# HG changeset patch
# User Jun Wu <qu...@fb.com>
# Date 1489395002 25200
#      Mon Mar 13 01:50:02 2017 -0700
# Node ID 6ae6d1069ba1d4089afaeb0bb8ef2411983a1292
# Parent  0280ee091bd0ae33aa0a67b0c8a55ccffd2e0718
# Available At https://bitbucket.org/quark-zju/hg-draft
#              hg pull https://bitbucket.org/quark-zju/hg-draft -r 6ae6d1069ba1
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
@@ -62,11 +62,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 ..
 
_______________________________________________
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel

Reply via email to