[PATCH 2 of 2] update: allow dirty update to successors

Augie Fackler raf at durin42.com
Fri Apr 12 15:30:08 CDT 2013


On Fri, Apr 12, 2013 at 06:55:22PM +0200, pierre-yves.david at logilab.fr wrote:
> # HG changeset patch
> # User Pierre-Yves David <pierre-yves.david at logilab.fr>
> # Date 1365784871 -7200
> #      Fri Apr 12 18:41:11 2013 +0200
> # Node ID 0f44f99fb5c1d9b05fa0b703e11aa10d7dc0f926
> # Parent  5bd7702f8e9613a70b2dcf511aef85fd221eff78
> update: allow dirty update to successors
>

Behavior sounds reasonable, but I'd like someone else to agree with me
before I push, since I'm not wholly able to channel mpm on this kind
of thing.

One nit in this patch about import style, otherwise series LGTM.

>
>
> Update to successors are no longer seen as cross branch update. This allows to
> merge with uncommited changes.
>
> This changeset is a small step forward. We want to allow dirty update to
> precursors and takes obsolescence in account when finding the default update
> destination. But those requires deeper changes and will comes in later
> changesets.
>
> 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

stylistically, we generally prefer "import obsolete" to "from mercurial import obsolete" in hg

>  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,28 @@ 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.validdest as it may be costly.
> +                    if obsolete.validdest(repo, p1, repo[node]):
> +                        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/mercurial/obsolete.py b/mercurial/obsolete.py
> --- a/mercurial/obsolete.py
> +++ b/mercurial/obsolete.py
> @@ -404,11 +404,11 @@ def allsuccessors(obsstore, nodes, ignor
>                      remaining.add(suc)
>
>  def validdest(repo, old, new):
>      """Is <new> a valid destination from the <old> one
>
> -    Used by bookmark logic.
> +    Used by bookmark and update logic.
>      """
>      repo = repo.unfiltered()
>      if old == new:
>          # Old == new -> nothing to update.
>          return False
> 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,71 @@ 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 --hidden 3
> +  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
> +  $ 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 0 # we should be possible to update to 3 directly
> +  >         # but not implemented yet.
> +  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
> +  $ hg up --hidden 3
> +  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
> +  $ 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 0
> +  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
> +  $ hg up 2
> +  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
> +  $ hg up 5
> +  abort: crosses branches (merge branches or use --clean to discard changes)
> +  [255]
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel


More information about the Mercurial-devel mailing list