# HG changeset patch # User Anton Shestakov # Date 1671104679 -14400 # Node ID 5c8196a550b66218c3f74e228624f0dbe7b5facc # Parent fcbca44dd0df2d0d5dddc3792d18020bb2c3c4ac topic: make hg stack work for branches with double slashes in them Other commands are likely affected as well. Things to note: we're using FQBN-formatted branch instead of full branch//namespace/topic in the workingctx.dirty() check because otherwise, if you had no topic active and were trying to update to a topic, wdir would be considered to be dirty and update would abort (same with unset topic namespace and trying to update to a changeset with topic namespace set). With just a bare branch, this doesn't happen, because you can't deactivate a branch. This is caught by test-topic.t. diff -r fcbca44dd0df -r 5c8196a550b6 hgext3rd/topic/__init__.py --- a/hgext3rd/topic/__init__.py Mon Jan 30 19:19:52 2023 +0400 +++ b/hgext3rd/topic/__init__.py Thu Dec 15 15:44:39 2022 +0400 @@ -410,6 +410,26 @@ with discovery.override_context_branch(repo) as repo: return orig(ui, repo, *args, **kwargs) +def wrapwctxbranch(orig, self): + branch = orig(self) + return common.formatfqbn(branch=branch) + +def wrapwctxdirty(orig, self, missing=False, merge=True, branch=True): + """check whether a working directory is modified""" + # check subrepos first + for s in sorted(self.substate): + if self.sub(s).dirty(missing=missing): + return True + # check current working dir + return ( + (merge and self.p2()) + or (branch and self.branch() != common.formatfqbn(branch=self.p1().branch())) + or self.modified() + or self.added() + or self.removed() + or (missing and self.deleted()) + ) + def uisetup(ui): destination.modsetup(ui) discovery.modsetup(ui) @@ -458,6 +478,10 @@ # Wrap workingctx extra to return the topic name extensions.wrapfunction(context.workingctx, '__init__', wrapinit) + # Wrap workingctx.branch() to return branch name in the "//" format + extensions.wrapfunction(context.workingctx, 'branch', wrapwctxbranch) + # Wrap workingctx.dirty() to check branch//namespace/topic + extensions.wrapfunction(context.workingctx, 'dirty', wrapwctxdirty) # Wrap changelog.add to drop empty topic extensions.wrapfunction(changelog.changelog, 'add', wrapadd) # Make exchange._checkpublish handle experimental.topic.publish-bare-branch diff -r fcbca44dd0df -r 5c8196a550b6 hgext3rd/topic/topicmap.py --- a/hgext3rd/topic/topicmap.py Mon Jan 30 19:19:52 2023 +0400 +++ b/hgext3rd/topic/topicmap.py Thu Dec 15 15:44:39 2022 +0400 @@ -14,6 +14,7 @@ from . import ( common, compat, + discovery, ) basefilter = set([b'base', b'immutable']) @@ -98,10 +99,12 @@ def commitstatus(orig, repo, node, branch, bheads=None, tip=None, opts=None): # wrap commit status use the topic branch heads ctx = repo[node] - if ctx.topic() and ctx.branch() == branch: + ctxbranch = common.formatfqbn(branch=ctx.branch()) + if ctx.topic() and ctxbranch == branch: bheads = repo.branchheads(b"%s:%s" % (branch, ctx.topic())) - ret = orig(repo, node, branch, bheads=bheads, tip=tip, opts=opts) + with discovery.override_context_branch(repo) as repo: + ret = orig(repo, node, branch, bheads=bheads, tip=tip, opts=opts) # logic copy-pasted from cmdutil.commitstatus() if opts is None: @@ -111,7 +114,8 @@ parents = ctx.parents() if (not opts.get(b'amend') and bheads and node not in bheads and not any( - p.node() in bheads and p.branch() == branch for p in parents + p.node() in bheads and common.formatfqbn(branch=p.branch()) == branch + for p in parents )): repo.ui.status(_(b"(consider using topic for lightweight branches." b" See 'hg help topic')\n")) diff -r fcbca44dd0df -r 5c8196a550b6 tests/test-stack-branch.t --- a/tests/test-stack-branch.t Mon Jan 30 19:19:52 2023 +0400 +++ b/tests/test-stack-branch.t Thu Dec 15 15:44:39 2022 +0400 @@ -12,8 +12,8 @@ $ hg init main $ cd main - $ hg branch other - marked working directory as branch other + $ hg branch double//slash + marked working directory as branch double//slash (branches are permanent and global, did you want a bookmark?) $ echo aaa > aaa $ hg add aaa @@ -21,8 +21,8 @@ $ echo aaa > bbb $ hg add bbb $ hg commit -m c_b - $ hg branch foo - marked working directory as branch foo + $ hg branch foo//bar + marked working directory as branch foo//bar $ echo aaa > ccc $ hg add ccc $ hg commit -m c_c @@ -36,30 +36,30 @@ $ hg add fff $ hg commit -m c_f $ hg log -G - @ 5 foo {} draft c_f + @ 5 foo//bar {} draft c_f | - o 4 foo {} draft c_e + o 4 foo//bar {} draft c_e | - o 3 foo {} draft c_d + o 3 foo//bar {} draft c_d | - o 2 foo {} draft c_c + o 2 foo//bar {} draft c_c | - o 1 other {} draft c_b + o 1 double//slash {} draft c_b | - o 0 other {} draft c_a + o 0 double//slash {} draft c_a Check that topic without any parent does not crash --list --------------------------------------------------------- - $ hg up other + $ hg up double//slash// 0 files updated, 0 files merged, 4 files removed, 0 files unresolved $ hg stack - ### target: other (branch) + ### target: double//slash (branch) s2@ c_b (current) s1: c_a - $ hg phase --public 'branch("other")' - $ hg up foo + $ hg phase --public 'branch("double//slash//")' + $ hg up foo//bar// 4 files updated, 0 files merged, 0 files removed, 0 files unresolved Simple test @@ -68,38 +68,38 @@ 'hg stack' list all changeset in the topic $ hg branch - foo + foo//bar $ hg stack - ### target: foo (branch) + ### target: foo//bar (branch) s4@ c_f (current) s3: c_e s2: c_d s1: c_c s0^ c_b (base) $ hg stack -v - ### target: foo (branch) - s4(913c298d8b0a)@ c_f (current) - s3(4f2a69f6d380): c_e - s2(f61adbacd17a): c_d - s1(3e9313bc4b71): c_c - s0(4a04f1104a27)^ c_b (base) + ### target: foo//bar (branch) + s4(18b3ff044de9)@ c_f (current) + s3(b1913e064ca1): c_e + s2(8fad7e98adf6): c_d + s1(da14ac95d156): c_c + s0(2450a061c0f0)^ c_b (base) Test "t#" reference ------------------- $ hg up s2 0 files updated, 0 files merged, 2 files removed, 0 files unresolved - $ hg up foo + $ hg up foo//bar// 2 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg up s42 - abort: cannot resolve "s42": branch "foo" has only 4 non-public changesets + abort: cannot resolve "s42": branch "foo//bar//" has only 4 non-public changesets [255] $ hg up s2 0 files updated, 0 files merged, 2 files removed, 0 files unresolved $ hg summary - parent: 3:f61adbacd17a + parent: 3:8fad7e98adf6 c_d - branch: foo + branch: foo//bar// commit: (clean) update: 2 new changesets (update) phases: 4 draft @@ -111,22 +111,22 @@ $ hg commit --amend 2 new orphan changesets $ hg log -G - @ 6 foo {} draft c_d + @ 6 foo//bar {} draft c_d | - | * 5 foo {} draft c_f + | * 5 foo//bar {} draft c_f | | - | * 4 foo {} draft c_e + | * 4 foo//bar {} draft c_e | | - | x 3 foo {} draft c_d + | x 3 foo//bar {} draft c_d |/ - o 2 foo {} draft c_c + o 2 foo//bar {} draft c_c | - o 1 other {} public c_b + o 1 double//slash {} public c_b | - o 0 other {} public c_a + o 0 double//slash {} public c_a $ hg stack - ### target: foo (branch) + ### target: foo//bar (branch) s4$ c_f (orphan) s3$ c_e (orphan) s2@ c_d (current) @@ -135,7 +135,7 @@ $ hg up s3 2 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg stack - ### target: foo (branch) + ### target: foo//bar (branch) s4$ c_f (orphan) s3@ c_e (current orphan) s2: c_d @@ -147,10 +147,10 @@ Also test the revset: $ hg log -r 'stack()' - 2 foo {} draft c_c - 6 foo {} draft c_d - 4 foo {} draft c_e - 5 foo {} draft c_f + 2 foo//bar {} draft c_c + 6 foo//bar {} draft c_d + 4 foo//bar {} draft c_e + 5 foo//bar {} draft c_f Case with multiple heads on the topic ------------------------------------- @@ -158,20 +158,20 @@ Make things linear again $ hg rebase -s 'desc(c_e)' -d 'desc(c_d) - obsolete()' - rebasing 4:4f2a69f6d380 "c_e" - rebasing 5:913c298d8b0a "c_f" + rebasing 4:b1913e064ca1 "c_e" + rebasing 5:18b3ff044de9 "c_f" $ hg log -G - o 8 foo {} draft c_f + o 8 foo//bar {} draft c_f | - o 7 foo {} draft c_e + o 7 foo//bar {} draft c_e | - @ 6 foo {} draft c_d + @ 6 foo//bar {} draft c_d | - o 2 foo {} draft c_c + o 2 foo//bar {} draft c_c | - o 1 other {} public c_b + o 1 double//slash {} public c_b | - o 0 other {} public c_a + o 0 double//slash {} public c_a Create the second branch @@ -187,27 +187,27 @@ $ hg add hhh $ hg commit -m c_h $ hg log -G - @ 10 foo {} draft c_h + @ 10 foo//bar {} draft c_h | - o 9 foo {} draft c_g + o 9 foo//bar {} draft c_g | - | o 8 foo {} draft c_f + | o 8 foo//bar {} draft c_f | | - | o 7 foo {} draft c_e + | o 7 foo//bar {} draft c_e |/ - o 6 foo {} draft c_d + o 6 foo//bar {} draft c_d | - o 2 foo {} draft c_c + o 2 foo//bar {} draft c_c | - o 1 other {} public c_b + o 1 double//slash {} public c_b | - o 0 other {} public c_a + o 0 double//slash {} public c_a Test output $ hg stack - ### target: foo (branch) (2 heads) + ### target: foo//bar (branch) (2 heads) s6@ c_h (current) s5: c_g s2^ c_d (base) @@ -228,30 +228,30 @@ $ hg commit --amend -m 'c_D' 4 new orphan changesets $ hg rebase -d . -s 'desc(c_g)' - rebasing 9:2ebb6e48ab8a "c_g" - rebasing 10:634f38e27a1d "c_h" + rebasing 9:8c1819a4441f "c_g" + rebasing 10:e255b784f0e9 "c_h" $ hg log -G - o 13 foo {} draft c_h + o 13 foo//bar {} draft c_h | - o 12 foo {} draft c_g + o 12 foo//bar {} draft c_g | - @ 11 foo {} draft c_D + @ 11 foo//bar {} draft c_D | - | * 8 foo {} draft c_f + | * 8 foo//bar {} draft c_f | | - | * 7 foo {} draft c_e + | * 7 foo//bar {} draft c_e | | - | x 6 foo {} draft c_d + | x 6 foo//bar {} draft c_d |/ - o 2 foo {} draft c_c + o 2 foo//bar {} draft c_c | - o 1 other {} public c_b + o 1 double//slash {} public c_b | - o 0 other {} public c_a + o 0 double//slash {} public c_a $ hg stack - ### target: foo (branch) (2 heads) + ### target: foo//bar (branch) (2 heads) s6: c_h s5: c_g s2^ c_D (base current) @@ -265,27 +265,27 @@ ---------------------------------------------------------- $ hg log --graph - o 13 foo {} draft c_h + o 13 foo//bar {} draft c_h | - o 12 foo {} draft c_g + o 12 foo//bar {} draft c_g | - @ 11 foo {} draft c_D + @ 11 foo//bar {} draft c_D | - | * 8 foo {} draft c_f + | * 8 foo//bar {} draft c_f | | - | * 7 foo {} draft c_e + | * 7 foo//bar {} draft c_e | | - | x 6 foo {} draft c_d + | x 6 foo//bar {} draft c_d |/ - o 2 foo {} draft c_c + o 2 foo//bar {} draft c_c | - o 1 other {} public c_b + o 1 double//slash {} public c_b | - o 0 other {} public c_a + o 0 double//slash {} public c_a $ hg stack - ### target: foo (branch) (2 heads) + ### target: foo//bar (branch) (2 heads) s6: c_h s5: c_g s2^ c_D (base current) @@ -296,7 +296,7 @@ s0^ c_b (base) $ hg phase --public s1 $ hg stack - ### target: foo (branch) (2 heads) + ### target: foo//bar (branch) (2 heads) s5: c_h s4: c_g s1^ c_D (base current) @@ -311,7 +311,7 @@ $ hg topic --rev s4::s5 sometopic changed topic on 2 changesets to "sometopic" $ hg stack - ### target: foo (branch) + ### target: foo//bar (branch) s3$ c_f (orphan) s2$ c_e (orphan) s1@ c_D (current)