[PATCH 4 of 4] obsolete: allow cycles

Jun Wu quark at fb.com
Mon Mar 13 05:44:41 EDT 2017


Excerpts from Jun Wu's message of 2017-03-13 02:34:19 -0700:
> # HG changeset patch
> # User Jun Wu <quark at fb.com>
> # Date 1489395002 25200
> #      Mon Mar 13 01:50:02 2017 -0700
> # Node ID 5cf846db23cddc36b01acf0211d52f8d50f36dcd
> # Parent  83288095bc38cef4b9e8bb9c69914b981115aaab
> # Available At https://bitbucket.org/quark-zju/hg-draft 
> #              hg pull https://bitbucket.org/quark-zju/hg-draft  -r 5cf846db23cd
> obsolete: allow cycles
> 
> Now we can handle cycles nicely, allow them to be created. Some practical
> examples:
> 
>   - To revive X, just create a marker X -> X, with a newer date.
>   - To prune X again, just create a marker X -> (), with a newer date.
>   - The above two could be repeated.
> 
>   - To unamend A -> B, just create a marker B -> A, with a newer date.
> 
> It's now possible for "touch" and "unamend" to reuse hashes (therefore more
> user-friendly). And it's no longer necessary to write "*_source" in commit
> metadata to workarounds obs cycles. The hacky inhibit extension also becomes
> unnecessary.
> 
> Finally. I have been wanting all these for a long time.
> 
> diff --git a/mercurial/obsolete.py b/mercurial/obsolete.py
> --- a/mercurial/obsolete.py
> +++ b/mercurial/obsolete.py
> @@ -638,6 +638,4 @@ class obsstore(object):
>              if len(succ) != 20:
>                  raise ValueError(succ)
> -        if prec in succs:
> -            raise ValueError(_('in-marker cycle with %s') % node.hex(prec))
>  
>          metadata = tuple(sorted(metadata.iteritems()))
> @@ -1296,7 +1294,4 @@ def createmarkers(repo, relations, flag=
>              if not nsucs:
>                  npare = tuple(p.node() for p in prec.parents())
> -            if nprec in nsucs:
> -                raise error.Abort(_("changeset %s cannot obsolete itself")
> -                                  % prec)
>  
>              # Creating the marker causes the hidden cache to become invalid,
> diff --git a/tests/test-obsolete-cycle.t b/tests/test-obsolete-cycle.t
> new file mode 100644
> --- /dev/null
> +++ b/tests/test-obsolete-cycle.t
> @@ -0,0 +1,153 @@
> +  $ cat >> $HGRCPATH << EOF
> +  > [ui]
> +  > logtemplate="{rev} {desc}\n"
> +  > [phases]
> +  > publish=false
> +  > [experimental]
> +  > evolution=createmarkers
> +  > [extensions]
> +  > drawdag=$TESTDIR/drawdag.py
> +  > EOF
> +
> +  $ getid() {
> +  >    hg log -T "{node}\n" --hidden -r "desc('$1')"
> +  > }
> +  $ assignnames() {
> +  >   for i in "$@"; do
> +  >       eval $i=`getid $i`
> +  >       # remove local tags created by drawdag
> +  >       hg tag --remove -l $i
> +  >   done
> +  > }
> +
> +Cycle of 2 changesets
> +
> +  $ hg init repo1
> +  $ cd repo1
> +
> +  $ hg debugdrawdag << EOF
> +  >   B C
> +  >   |/
> +  >   A
> +  > EOF
> +
> +  $ assignnames A B C
> +
> +  $ hg debugobsolete -d '0 0' $B $C
> +  $ hg log -G
> +  o  2 C
> +  |
> +  o  0 A
> +  
> +
> +  $ hg debugobsolete -d '1 0' $C $B
> +  $ hg log -G
> +  o  1 B
> +  |
> +  o  0 A
> +  
> +
> +  $ hg debugobsolete -d '2 0' $B $C
> +  $ hg log -G
> +  o  2 C
> +  |
> +  o  0 A
> +  
> +
> +  $ hg debugobsolete -d '3 0' $B $B
> +  $ hg log -G
> +  o  2 C
> +  |
> +  | o  1 B
> +  |/
> +  o  0 A
> +  
> +
> +  $ hg debugobsolete -d '4 0' $B
> +  $ hg debugobsolete -d '6 0' $C
> +  $ hg log -G
> +  o  0 A
> +  
> +
> +  $ hg debugobsolete -d '7 0' $B $B
> +  $ hg debugobsolete -d '5 0' $C $C
> +  $ hg log -G
> +  o  1 B
> +  |
> +  o  0 A
> +  
> +
> +  $ hg debugobsolete -d '8 0' $C $C
> +  $ hg log -G
> +  o  2 C
> +  |
> +  | o  1 B
> +  |/
> +  o  0 A
> +  
> +
> +  $ cd ..
> +
> +Cycle of 3 changesets
> +  $ hg init repo2
> +  $ cd repo2
> +
> +  $ hg debugdrawdag << EOF
> +  > D B C
> +  >  \|/
> +  >   A
> +  > EOF
> +
> +  $ assignnames A B C D
> +
> +  $ hg debugobsolete -d '2 0' $C $D
> +  $ hg debugobsolete -d '3 0' $D $C
> +  $ hg debugobsolete -d '1 0' $B $C
> +
> +  $ hg log -G
> +  o  2 C
> +  |
> +  o  0 A
> +  
> +
> +  $ hg debugobsolete -d '4 0' $D $D
> +  $ hg log -G
> +  o  3 D
> +  |
> +  | o  2 C
> +  |/
> +  o  0 A
> +  
> +
> +  $ hg debugobsolete -d '5 0' $B $B
> +  $ hg log -G
> +  o  3 D
> +  |
> +  | o  2 C
> +  |/
> +  | o  1 B
> +  |/
> +  o  0 A
> +  
> +
> +  $ hg debugobsolete -d '6 0' $D $B
> +  $ hg log -G
> +  o  2 C
> +  |
> +  | o  1 B
> +  |/
> +  o  0 A
> +  
> +  $ hg debugobsolete -d '9 0' $C
> +  $ hg log -G
> +  o  1 B
> +  |
> +  o  0 A
> +  
> +
> +  $ hg debugobsolete -d '8 0' $B $C
> +  $ hg log -G
> +  o  0 A
> +  
> +
> +  $ cd ..
> diff --git a/tests/test-obsolete.t b/tests/test-obsolete.t
> --- a/tests/test-obsolete.t
> +++ b/tests/test-obsolete.t
> @@ -30,10 +30,4 @@
>    $ mkcommit kill_me
>  
> -Checking that the feature is properly disabled
> -
> -  $ hg debugobsolete -d '0 0' `getid kill_me` -u babar
> -  abort: creating obsolete markers is not enabled on this repo
> -  [255]
> -
>  Enabling it

This seems to be a mistake. I'll resend a V2.

>  
> @@ -62,11 +56,4 @@ Killing a single changeset without repla
>    $ hg up --hidden tip --quiet
>  
> -Killing a single changeset with itself should fail
> -(simple local safeguard)
> -
> -  $ hg debugobsolete `getid kill_me` `getid kill_me`
> -  abort: bad obsmarker input: in-marker cycle with 97b7c2d76b1845ed3eb988cd612611e72406cef0
> -  [255]
> -
>    $ cd ..
>  


More information about the Mercurial-devel mailing list