Patchwork [3,of,3] singlehead: introduce special handling of closed heads

login
register
mail settings
Submitter Pierre-Yves David
Date Sept. 25, 2019, 11:07 a.m.
Message ID <af71efbe73e62e427eeb.1569409640@nodosa.octobus.net>
Download mbox | patch
Permalink /patch/41754/
State Accepted
Headers show

Comments

Pierre-Yves David - Sept. 25, 2019, 11:07 a.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@octobus.net>
# Date 1569409166 -7200
#      Wed Sep 25 12:59:26 2019 +0200
# Node ID af71efbe73e62e427eeb559923057f950530fe40
# Parent  ddbb9bccf64e004e6e7ee5912b701c732f8a4435
# EXP-Topic enforce-single-head
# Available At https://bitbucket.org/octobus/mercurial-devel/
#              hg pull https://bitbucket.org/octobus/mercurial-devel/ -r af71efbe73e6
singlehead: introduce special handling of closed heads

Until now, the experimental option `single-head-per-branch` was also refusing
closed heads. The logic is now ignoring them by default and a suboption have
been added to refuse them too `single-head-per-branch:account-closed-heads`.
Augie Fackler - Sept. 25, 2019, 2:27 p.m.
queued, thanks

> On Sep 25, 2019, at 07:07, Pierre-Yves David <pierre-yves.david@ens-lyon.org> wrote:
> 
> # HG changeset patch
> # User Pierre-Yves David <pierre-yves.david@octobus.net>
> # Date 1569409166 -7200
> #      Wed Sep 25 12:59:26 2019 +0200
> # Node ID af71efbe73e62e427eeb559923057f950530fe40
> # Parent  ddbb9bccf64e004e6e7ee5912b701c732f8a4435
> # EXP-Topic enforce-single-head
> # Available At https://bitbucket.org/octobus/mercurial-devel/
> #              hg pull https://bitbucket.org/octobus/mercurial-devel/ -r af71efbe73e6
> singlehead: introduce special handling of closed heads
> 
> Until now, the experimental option `single-head-per-branch` was also refusing
> closed heads. The logic is now ignoring them by default and a suboption have
> been added to refuse them too `single-head-per-branch:account-closed-heads`.
> 
> diff --git a/mercurial/configitems.py b/mercurial/configitems.py
> --- a/mercurial/configitems.py
> +++ b/mercurial/configitems.py
> @@ -645,6 +645,9 @@ coreconfigitem('experimental', 'server.s
> coreconfigitem('experimental', 'single-head-per-branch',
>     default=False,
> )
> +coreconfigitem('experimental', 'single-head-perf-branch:account-closed-heads',
> +    default=False,
> +)
> coreconfigitem('experimental', 'sshserver.support-v2',
>     default=False,
> )
> diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
> --- a/mercurial/localrepo.py
> +++ b/mercurial/localrepo.py
> @@ -1920,8 +1920,13 @@ class localrepository(object):
>             # gating.
>             tracktags(tr2)
>             repo = reporef()
> -            if repo.ui.configbool('experimental', 'single-head-per-branch'):
> -                scmutil.enforcesinglehead(repo, tr2, desc)
> +
> +            r = repo.ui.configsuboptions('experimental',
> +                                         'single-head-per-branch')
> +            singlehead, singleheadsub = r
> +            if singlehead:
> +                accountclosed = singleheadsub.get("account-closed-heads", False)
> +                scmutil.enforcesinglehead(repo, tr2, desc, accountclosed)
>             if hook.hashook(repo.ui, 'pretxnclose-bookmark'):
>                 for name, (old, new) in sorted(tr.changes['bookmarks'].items()):
>                     args = tr.hookargs.copy()
> diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
> --- a/mercurial/scmutil.py
> +++ b/mercurial/scmutil.py
> @@ -1895,14 +1895,16 @@ def nodesummaries(repo, nodes, maxnumnod
>     first = ' '.join(short(h) for h in nodes[:maxnumnodes])
>     return _("%s and %d others") % (first, len(nodes) - maxnumnodes)
> 
> -def enforcesinglehead(repo, tr, desc):
> +def enforcesinglehead(repo, tr, desc, accountclosed=False):
>     """check that no named branch has multiple heads"""
>     if desc in ('strip', 'repair'):
>         # skip the logic during strip
>         return
>     visible = repo.filtered('visible')
>     # possible improvement: we could restrict the check to affected branch
> -    for name, heads in visible.branchmap().iteritems():
> +    bm = visible.branchmap()
> +    for name in bm:
> +        heads = bm.branchheads(name, closed=accountclosed)
>         if len(heads) > 1:
>             msg = _('rejecting multiple heads on branch "%s"')
>             msg %= name
> diff --git a/tests/test-single-head.t b/tests/test-single-head.t
> --- a/tests/test-single-head.t
> +++ b/tests/test-single-head.t
> @@ -200,3 +200,62 @@ actual stripping
>   $ hg strip --config extensions.strip= --rev 'desc("c_dH0")'
>   saved backup bundle to $TESTTMP/client/.hg/strip-backup/fe47ea669cea-a41bf5a9-backup.hg
> 
> +Test that closing heads are ignored by default
> +-----------------------------------------------
> +
> +  $ hg up 'desc("c_aG0")'
> +  0 files updated, 0 files merged, 2 files removed, 0 files unresolved
> +  $ mkcommit c_aJ0
> +  created new head
> +
> +pushing the new head should fails
> +
> +  $ hg push -f
> +  pushing to $TESTTMP/single-head-server
> +  searching for changes
> +  adding changesets
> +  adding manifests
> +  adding file changes
> +  transaction abort!
> +  rollback completed
> +  abort: rejecting multiple heads on branch "branch_A"
> +  (2 heads: 49003e504178 468bd81ccc5d)
> +  [255]
> +
> +
> +closing the head and pushing should succeed
> +
> +  $ mkcommit c_aK0 --close-branch
> +  $ hg push -f
> +  pushing to $TESTTMP/single-head-server
> +  searching for changes
> +  adding changesets
> +  adding manifests
> +  adding file changes
> +  added 4 changesets with 4 changes to 4 files (-1 heads)
> +
> +
> +Test that closing heads can be explicitly accounted for
> +-------------------------------------------------------
> +
> +  $ cat <<EOF >> $TESTTMP/single-head-server/.hg/hgrc
> +  > [experimental]
> +  > single-head-per-branch:account-closed-heads = yes
> +  > EOF
> +
> +  $ hg up 'desc("c_aG0")'
> +  0 files updated, 0 files merged, 2 files removed, 0 files unresolved
> +  $ mkcommit c_aL0
> +  created new head
> +  $ mkcommit c_aM0 --close-branch
> +  $ hg push -f
> +  pushing to $TESTTMP/single-head-server
> +  searching for changes
> +  adding changesets
> +  adding manifests
> +  adding file changes
> +  transaction abort!
> +  rollback completed
> +  abort: rejecting multiple heads on branch "branch_A"
> +  (3 heads: 49003e504178 5254bcccab93 42b9fe70a3c1)
> +  [255]
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Pulkit Goyal - Sept. 25, 2019, 3:29 p.m.
On Wed, Sep 25, 2019 at 2:17 PM Pierre-Yves David
<pierre-yves.david@ens-lyon.org> wrote:
>
> # HG changeset patch
> # User Pierre-Yves David <pierre-yves.david@octobus.net>
> # Date 1569409166 -7200
> #      Wed Sep 25 12:59:26 2019 +0200
> # Node ID af71efbe73e62e427eeb559923057f950530fe40
> # Parent  ddbb9bccf64e004e6e7ee5912b701c732f8a4435
> # EXP-Topic enforce-single-head
> # Available At https://bitbucket.org/octobus/mercurial-devel/
> #              hg pull https://bitbucket.org/octobus/mercurial-devel/ -r af71efbe73e6
> singlehead: introduce special handling of closed heads
>
> Until now, the experimental option `single-head-per-branch` was also refusing
> closed heads. The logic is now ignoring them by default and a suboption have
> been added to refuse them too `single-head-per-branch:account-closed-heads`.
>
> diff --git a/mercurial/configitems.py b/mercurial/configitems.py
> --- a/mercurial/configitems.py
> +++ b/mercurial/configitems.py
> @@ -645,6 +645,9 @@ coreconfigitem('experimental', 'server.s
>  coreconfigitem('experimental', 'single-head-per-branch',
>      default=False,
>  )
> +coreconfigitem('experimental', 'single-head-perf-branch:account-closed-heads',

s/perf/per in flight
Pierre-Yves David - Sept. 25, 2019, 3:54 p.m.
On 9/25/19 5:29 PM, Pulkit Goyal wrote:
> On Wed, Sep 25, 2019 at 2:17 PM Pierre-Yves David
> <pierre-yves.david@ens-lyon.org> wrote:
>>
>> # HG changeset patch
>> # User Pierre-Yves David <pierre-yves.david@octobus.net>
>> # Date 1569409166 -7200
>> #      Wed Sep 25 12:59:26 2019 +0200
>> # Node ID af71efbe73e62e427eeb559923057f950530fe40
>> # Parent  ddbb9bccf64e004e6e7ee5912b701c732f8a4435
>> # EXP-Topic enforce-single-head
>> # Available At https://bitbucket.org/octobus/mercurial-devel/
>> #              hg pull https://bitbucket.org/octobus/mercurial-devel/ -r af71efbe73e6
>> singlehead: introduce special handling of closed heads
>>
>> Until now, the experimental option `single-head-per-branch` was also refusing
>> closed heads. The logic is now ignoring them by default and a suboption have
>> been added to refuse them too `single-head-per-branch:account-closed-heads`.
>>
>> diff --git a/mercurial/configitems.py b/mercurial/configitems.py
>> --- a/mercurial/configitems.py
>> +++ b/mercurial/configitems.py
>> @@ -645,6 +645,9 @@ coreconfigitem('experimental', 'server.s
>>   coreconfigitem('experimental', 'single-head-per-branch',
>>       default=False,
>>   )
>> +coreconfigitem('experimental', 'single-head-perf-branch:account-closed-heads',
> 
> s/perf/per in flight

ha thanks, I must have spend too much time looking a perf stuff recently.

That said, this means the suboption logic does not triggers devel 
warning :-/

Patch

diff --git a/mercurial/configitems.py b/mercurial/configitems.py
--- a/mercurial/configitems.py
+++ b/mercurial/configitems.py
@@ -645,6 +645,9 @@  coreconfigitem('experimental', 'server.s
 coreconfigitem('experimental', 'single-head-per-branch',
     default=False,
 )
+coreconfigitem('experimental', 'single-head-perf-branch:account-closed-heads',
+    default=False,
+)
 coreconfigitem('experimental', 'sshserver.support-v2',
     default=False,
 )
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -1920,8 +1920,13 @@  class localrepository(object):
             # gating.
             tracktags(tr2)
             repo = reporef()
-            if repo.ui.configbool('experimental', 'single-head-per-branch'):
-                scmutil.enforcesinglehead(repo, tr2, desc)
+
+            r = repo.ui.configsuboptions('experimental',
+                                         'single-head-per-branch')
+            singlehead, singleheadsub = r
+            if singlehead:
+                accountclosed = singleheadsub.get("account-closed-heads", False)
+                scmutil.enforcesinglehead(repo, tr2, desc, accountclosed)
             if hook.hashook(repo.ui, 'pretxnclose-bookmark'):
                 for name, (old, new) in sorted(tr.changes['bookmarks'].items()):
                     args = tr.hookargs.copy()
diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -1895,14 +1895,16 @@  def nodesummaries(repo, nodes, maxnumnod
     first = ' '.join(short(h) for h in nodes[:maxnumnodes])
     return _("%s and %d others") % (first, len(nodes) - maxnumnodes)
 
-def enforcesinglehead(repo, tr, desc):
+def enforcesinglehead(repo, tr, desc, accountclosed=False):
     """check that no named branch has multiple heads"""
     if desc in ('strip', 'repair'):
         # skip the logic during strip
         return
     visible = repo.filtered('visible')
     # possible improvement: we could restrict the check to affected branch
-    for name, heads in visible.branchmap().iteritems():
+    bm = visible.branchmap()
+    for name in bm:
+        heads = bm.branchheads(name, closed=accountclosed)
         if len(heads) > 1:
             msg = _('rejecting multiple heads on branch "%s"')
             msg %= name
diff --git a/tests/test-single-head.t b/tests/test-single-head.t
--- a/tests/test-single-head.t
+++ b/tests/test-single-head.t
@@ -200,3 +200,62 @@  actual stripping
   $ hg strip --config extensions.strip= --rev 'desc("c_dH0")'
   saved backup bundle to $TESTTMP/client/.hg/strip-backup/fe47ea669cea-a41bf5a9-backup.hg
 
+Test that closing heads are ignored by default
+-----------------------------------------------
+
+  $ hg up 'desc("c_aG0")'
+  0 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  $ mkcommit c_aJ0
+  created new head
+
+pushing the new head should fails
+
+  $ hg push -f
+  pushing to $TESTTMP/single-head-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  transaction abort!
+  rollback completed
+  abort: rejecting multiple heads on branch "branch_A"
+  (2 heads: 49003e504178 468bd81ccc5d)
+  [255]
+
+
+closing the head and pushing should succeed
+
+  $ mkcommit c_aK0 --close-branch
+  $ hg push -f
+  pushing to $TESTTMP/single-head-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 4 changesets with 4 changes to 4 files (-1 heads)
+
+
+Test that closing heads can be explicitly accounted for
+-------------------------------------------------------
+
+  $ cat <<EOF >> $TESTTMP/single-head-server/.hg/hgrc
+  > [experimental]
+  > single-head-per-branch:account-closed-heads = yes
+  > EOF
+
+  $ hg up 'desc("c_aG0")'
+  0 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  $ mkcommit c_aL0
+  created new head
+  $ mkcommit c_aM0 --close-branch
+  $ hg push -f
+  pushing to $TESTTMP/single-head-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  transaction abort!
+  rollback completed
+  abort: rejecting multiple heads on branch "branch_A"
+  (3 heads: 49003e504178 5254bcccab93 42b9fe70a3c1)
+  [255]