Patchwork [2,of,2,V2] update: allow dirty update to foreground (successors)

login
register
mail settings
Submitter Pierre-Yves David
Date April 16, 2013, 1:44 p.m.
Message ID <96cf0ef42888242446c1.1366119896@crater2.logilab.fr>
Download mbox | patch
Permalink /patch/1346/
State Accepted
Commit a59e575c6ff87b517a8bb167c509a93003bfef53
Headers show

Comments

Pierre-Yves David - April 16, 2013, 1:44 p.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@logilab.fr>
# Date 1366119198 -7200
#      Tue Apr 16 15:33:18 2013 +0200
# Node ID 96cf0ef42888242446c105e978f4a97e7bb58555
# Parent  36fe662305fa1ec8a34c14e550f76afb47577455
update: allow dirty update to foreground (successors)

Update to "foreground" are no longer seen as cross branch update. "Foreground"
are descendants or successors (or successors of descendants (or descendant of
successors (etc))). This allows to update with uncommited changes that get
automatically merged.

This changeset is a small step forward. We want to allow dirty update to
"background" (precursors) and takes obsolescence in account when finding the
default update destination. But those requires deeper changes and will comes in
later changesets.
Matt Mackall - April 16, 2013, 4:52 p.m.
On Tue, 2013-04-16 at 15:44 +0200, pierre-yves.david@logilab.fr wrote:
> # HG changeset patch
> # User Pierre-Yves David <pierre-yves.david@logilab.fr>
> # Date 1366119198 -7200
> #      Tue Apr 16 15:33:18 2013 +0200
> # Node ID 96cf0ef42888242446c105e978f4a97e7bb58555
> # Parent  36fe662305fa1ec8a34c14e550f76afb47577455
> update: allow dirty update to foreground (successors)

These are queued for default, thanks.

Patch

diff --git a/mercurial/merge.py b/mercurial/merge.py
--- a/mercurial/merge.py
+++ b/mercurial/merge.py
@@ -5,10 +5,11 @@ 
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
 from node import nullid, nullrev, hex, bin
 from i18n import _
+from mercurial import obsolete
 import error, util, filemerge, copies, subrepo, worker, dicthelpers
 import errno, os, shutil
 
 class mergestate(object):
     '''track 3-way merge state of individual files'''
@@ -695,21 +696,30 @@  def update(repo, node, branchmerge, forc
                 if wc.sub(s).dirty():
                     raise util.Abort(_("outstanding uncommitted changes in "
                                        "subrepository '%s'") % s)
 
         elif not overwrite:
-            if pa == p1 or pa == p2: # linear
-                pass # all good
-            elif wc.dirty(missing=True):
-                raise util.Abort(_("crosses branches (merge branches or use"
-                                   " --clean to discard changes)"))
-            elif onode is None:
-                raise util.Abort(_("crosses branches (merge branches or update"
-                                   " --check to force update)"))
-            else:
-                # Allow jumping branches if clean and specific rev given
-                pa = p1
+            if pa not in (p1, p2):  # nolinear
+                dirty = wc.dirty(missing=True)
+                if dirty or onode is None:
+                    # Branching is a bit strange to ensure we do the minimal
+                    # amount of call to obsolete.background.
+                    foreground = obsolete.foreground(repo, [p1.node()])
+                    # note: the <node> variable contains a random identifier
+                    if repo[node].node() in foreground:
+                        pa = p1  # allow updating to successors
+                    elif dirty:
+                        msg = _("crosses branches (merge branches or use"
+                                " --clean to discard changes)")
+                        raise util.Abort(msg)
+                    else:  # node is none
+                        msg = _("crosses branches (merge branches or update"
+                                " --check to force update)")
+                        raise util.Abort(msg)
+                else:
+                    # Allow jumping branches if clean and specific rev given
+                    pa = p1
 
         ### calculate phase
         actions = calculateupdates(repo, wc, p2, pa,
                                    branchmerge, force, partial, mergeancestor)
 
diff --git a/tests/test-update-branches.t b/tests/test-update-branches.t
--- a/tests/test-update-branches.t
+++ b/tests/test-update-branches.t
@@ -162,5 +162,65 @@  Cases are run as shown in that table, ro
   $ revtest '-cC dirty linear'  dirty 1 2 -cC
   abort: cannot specify both -c/--check and -C/--clean
   parent=1
   M foo
 
+Test obsolescence behavior
+---------------------------------------------------------------------
+
+successors should be taken in account when checking head destination
+
+  $ cat << EOF >> $HGRCPATH
+  > [extensions]
+  > obs=$TESTTMP/obs.py
+  > [ui]
+  > logtemplate={rev}:{node|short} {desc|firstline}
+  > EOF
+  $ cat > $TESTTMP/obs.py << EOF
+  > import mercurial.obsolete
+  > mercurial.obsolete._enabled = True
+  > EOF
+
+Test no-argument update to a successor of an obsoleted changeset
+
+  $ hg log -G
+  o  5:ff252e8273df 5
+  |
+  o  4:d047485b3896 4
+  |
+  | o  3:6efa171f091b 3
+  | |
+  | | o  2:bd10386d478c 2
+  | |/
+  | @  1:0786582aa4b1 1
+  |/
+  o  0:60829823a42a 0
+  
+  $ hg status
+  M foo
+
+We add simple obsolescence marker between 3 and 4 (indirect successors)
+
+  $ hg id --debug -i -r 3
+  6efa171f091b00a3c35edc15d48c52a498929953
+  $ hg id --debug -i -r 4
+  d047485b3896813b2a624e86201983520f003206
+  $ hg debugobsolete 6efa171f091b00a3c35edc15d48c52a498929953 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+  $ hg debugobsolete aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa d047485b3896813b2a624e86201983520f003206
+
+Test that 5 is detected as a valid destination from 3
+  $ hg up --quiet --hidden 3
+  $ hg up 5
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+Test that 5 is detected as a valid destination from 1
+  $ hg up --quiet 0          # we should be able to update to 3 directly
+  $ hg up --quiet --hidden 3 # but not implemented yet.
+  $ hg up 5
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+Test that 5 is not detected as a valid destination from 2
+  $ hg up --quiet 0
+  $ hg up --quiet 2
+  $ hg up 5
+  abort: crosses branches (merge branches or use --clean to discard changes)
+  [255]