Patchwork obsolete: consider successors along with descendants when updating

login
register
mail settings
Submitter Levi Bard
Date Feb. 10, 2013, 9:47 p.m.
Message ID <8d89080a98d69606ac26.1360532854@retina-monoteam>
Download mbox | patch
Permalink /patch/942/
State Changes Requested, archived
Delegated to: Pierre-Yves David
Headers show

Comments

Levi Bard - Feb. 10, 2013, 9:47 p.m.
# HG changeset patch
# User Levi Bard <levi@unity3d.com>
# Date 1360532614 -3600
# Node ID 8d89080a98d69606ac264282e2ba3e33b056bcac
# Parent  013fcd112f13f31a35ea6a40d8cd1c6923cdaf20
obsolete: consider successors along with descendants when updating

Currently, if you pull --update a group of changesets that obsoletes
the current changeset, mercurial refuses to update because the pulled tip
is not a descendant. This change causes mercurial to consider successors
as well as descendants when determining whether to update.
Pierre-Yves David - Feb. 11, 2013, 5:37 p.m.
On 11 févr. 2013, at 04:04, Kevin Bullock wrote:

> On 10 Feb 2013, at 9:47 PM, Levi Bard wrote:
> 
>> # HG changeset patch
>> # User Levi Bard <levi@unity3d.com>
>> # Date 1360532614 -3600
>> # Node ID 8d89080a98d69606ac264282e2ba3e33b056bcac
>> # Parent  013fcd112f13f31a35ea6a40d8cd1c6923cdaf20
>> obsolete: consider successors along with descendants when updating
>> 
>> Currently, if you pull --update a group of changesets that obsoletes
>> the current changeset, mercurial refuses to update because the pulled tip
>> is not a descendant. This change causes mercurial to consider successors
>> as well as descendants when determining whether to update.
>> 
>> diff -r 013fcd112f13 -r 8d89080a98d6 mercurial/merge.py
>> --- a/mercurial/merge.py	Sat Feb 09 11:00:42 2013 +0100
>> +++ b/mercurial/merge.py	Sun Feb 10 22:43:34 2013 +0100
>> @@ -7,6 +7,7 @@
>> 
>> from node import nullid, nullrev, hex, bin
>> from i18n import _
>> +from mercurial import obsolete
>> import error, util, filemerge, copies, subrepo
>> import errno, os, shutil
>> 
>> @@ -632,6 +633,9 @@
>>        elif not overwrite:
>>            if pa == p1 or pa == p2: # linear
>>                pass # all good
>> +            elif repo.obsstore and \
>> +             node in obsolete.allsuccessors(repo.obsstore, [p1.node()]):
> 
> Wrap condition in parens instead of continuing the line with \.
> 
>> +                pa = p1 # allow updating to successors of obsolete nodes
> 
> Huh, that's really all it takes?

The job was done for bookmark 6 months ago. If update target have the very same semantics than bookmarks target it should be good.

I'll have a closer look at this patch soon™.
Pierre-Yves David - Feb. 12, 2013, 1:08 a.m.
Status: Patches is currently "buggy" and need substantial rewrite

On 10 févr. 2013, at 22:47, Levi Bard wrote:

> # HG changeset patch
> # User Levi Bard <levi@unity3d.com>
> # Date 1360532614 -3600
> # Node ID 8d89080a98d69606ac264282e2ba3e33b056bcac
> # Parent  013fcd112f13f31a35ea6a40d8cd1c6923cdaf20
> obsolete: consider successors along with descendants when updating
> 
> Currently, if you pull --update a group of changesets that obsoletes
> the current changeset, mercurial refuses to update because the pulled tip
> is not a descendant. This change causes mercurial to consider successors
> as well as descendants when determining whether to update.

You should probably mentions that bookmarks are doing the same.

During our discussion about exchanging obsolescence marker we call the set of possible target "foreground", it is all possible descendant of all possible successors (recursively). This "foreground" is also were we what to be able to update to.

You actually got that part wrong because you are not doing it recursively

In this situation:

  A - B
    \ B' - C
         \ C' -D

If you are on B you want to be able to update to D. I do not think your code handles that

You needs to extract the while loop in bookmarks that contains `obsolete.allsuccessors` into a function and use that.

note: We also have "background" which is all possibles ancestors of all possible descendant (recursively) but we do not care about it here.

Thanks for working on that! Thats really very helpful for me to see such issue being resolved

> 
> diff -r 013fcd112f13 -r 8d89080a98d6 mercurial/merge.py
> --- a/mercurial/merge.py	Sat Feb 09 11:00:42 2013 +0100
> +++ b/mercurial/merge.py	Sun Feb 10 22:43:34 2013 +0100
> @@ -7,6 +7,7 @@
> 
> from node import nullid, nullrev, hex, bin
> from i18n import _
> +from mercurial import obsolete
> import error, util, filemerge, copies, subrepo
> import errno, os, shutil
> 
> @@ -632,6 +633,9 @@
>         elif not overwrite:
>             if pa == p1 or pa == p2: # linear
>                 pass # all good
> +            elif repo.obsstore and \
> +             node in obsolete.allsuccessors(repo.obsstore, [p1.node()]):
> +                pa = p1 # allow updating to successors of obsolete nodes
>             elif wc.dirty(missing=True):
>                 raise util.Abort(_("crosses branches (merge branches or use"
>                                    " --clean to discard changes)"))
> diff -r 013fcd112f13 -r 8d89080a98d6 tests/test-pull-update.t
> --- a/tests/test-pull-update.t	Sat Feb 09 11:00:42 2013 +0100
> +++ b/tests/test-pull-update.t	Sun Feb 10 22:43:34 2013 +0100
> @@ -1,3 +1,12 @@
> +  $ cat << EOF >> $HGRCPATH
> +  > [extensions]
> +  > obs=$TESTTMP/obs.py
> +  > EOF
> +  $ cat > obs.py << EOF
> +  > import mercurial.obsolete
> +  > mercurial.obsolete._enabled = True
> +  > EOF
> +
>   $ hg init t
>   $ cd t
>   $ echo 1 > foo
> @@ -60,3 +69,64 @@
>   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
> 
>   $ cd ..
> +
> +Test no-argument update to a successor of an obsoleted changeset

You want to add hg log -G output in your test so that people can understand what's going on without compiling the whole test.

> +
> +  $ hg init blah
> +  $ cd blah
> +  $ echo 1 > a
> +  $ hg add a
> +  $ hg commit -m0
> +  $ echo 2 > a
> +  $ hg commit -m1
> +  $ cd ..
> +  $ hg clone blah meh
> +  updating to branch default
> +  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
> +  $ cd blah
> +  $ echo 3 > a
> +  $ hg commit --amend -m3
> +  $ cd ../meh
> +  $ hg pull --update ../blah
> +  pulling from ../blah
> +  searching for changes
> +  adding changesets
> +  adding manifests
> +  adding file changes
> +  added 1 changesets with 1 changes to 1 files (+1 heads)
> +  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
> +  $ cd ..
> +
> +Test refusal to update to a non-successor of an obsoleted changeset
> +
> +  $ rm -rf blah meh
> +  $ hg init blah
> +  $ cd blah
> +  $ echo 1 > a
> +  $ hg add a
> +  $ hg commit -m0
> +  $ echo 2 > a
> +  $ hg commit -m1
> +  $ cd ..
> +  $ hg clone blah meh
> +  updating to branch default
> +  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
> +  $ cd blah
> +  $ echo 3 > a
> +  $ hg commit --amend -m3
> +  $ hg update 0
> +  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
> +  $ echo 4 > a
> +  $ hg commit -m4
> +  created new head
> +  $ cd ../meh
> +  $ hg pull --update ../blah
> +  pulling from ../blah
> +  searching for changes
> +  adding changesets
> +  adding manifests
> +  adding file changes
> +  added 2 changesets with 2 changes to 1 files (+2 heads)
> +  not updating: crosses branches (merge branches or update --check to force update)
> +  $ cd ..
> +
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel

Patch

diff -r 013fcd112f13 -r 8d89080a98d6 mercurial/merge.py
--- a/mercurial/merge.py	Sat Feb 09 11:00:42 2013 +0100
+++ b/mercurial/merge.py	Sun Feb 10 22:43:34 2013 +0100
@@ -7,6 +7,7 @@ 
 
 from node import nullid, nullrev, hex, bin
 from i18n import _
+from mercurial import obsolete
 import error, util, filemerge, copies, subrepo
 import errno, os, shutil
 
@@ -632,6 +633,9 @@ 
         elif not overwrite:
             if pa == p1 or pa == p2: # linear
                 pass # all good
+            elif repo.obsstore and \
+             node in obsolete.allsuccessors(repo.obsstore, [p1.node()]):
+                pa = p1 # allow updating to successors of obsolete nodes
             elif wc.dirty(missing=True):
                 raise util.Abort(_("crosses branches (merge branches or use"
                                    " --clean to discard changes)"))
diff -r 013fcd112f13 -r 8d89080a98d6 tests/test-pull-update.t
--- a/tests/test-pull-update.t	Sat Feb 09 11:00:42 2013 +0100
+++ b/tests/test-pull-update.t	Sun Feb 10 22:43:34 2013 +0100
@@ -1,3 +1,12 @@ 
+  $ cat << EOF >> $HGRCPATH
+  > [extensions]
+  > obs=$TESTTMP/obs.py
+  > EOF
+  $ cat > obs.py << EOF
+  > import mercurial.obsolete
+  > mercurial.obsolete._enabled = True
+  > EOF
+
   $ hg init t
   $ cd t
   $ echo 1 > foo
@@ -60,3 +69,64 @@ 
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
   $ cd ..
+
+Test no-argument update to a successor of an obsoleted changeset
+
+  $ hg init blah
+  $ cd blah
+  $ echo 1 > a
+  $ hg add a
+  $ hg commit -m0
+  $ echo 2 > a
+  $ hg commit -m1
+  $ cd ..
+  $ hg clone blah meh
+  updating to branch default
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ cd blah
+  $ echo 3 > a
+  $ hg commit --amend -m3
+  $ cd ../meh
+  $ hg pull --update ../blah
+  pulling from ../blah
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files (+1 heads)
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ cd ..
+
+Test refusal to update to a non-successor of an obsoleted changeset
+
+  $ rm -rf blah meh
+  $ hg init blah
+  $ cd blah
+  $ echo 1 > a
+  $ hg add a
+  $ hg commit -m0
+  $ echo 2 > a
+  $ hg commit -m1
+  $ cd ..
+  $ hg clone blah meh
+  updating to branch default
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ cd blah
+  $ echo 3 > a
+  $ hg commit --amend -m3
+  $ hg update 0
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ echo 4 > a
+  $ hg commit -m4
+  created new head
+  $ cd ../meh
+  $ hg pull --update ../blah
+  pulling from ../blah
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 2 changesets with 2 changes to 1 files (+2 heads)
+  not updating: crosses branches (merge branches or update --check to force update)
+  $ cd ..
+