Patchwork [7,of,7,V2,stable] resolve: use "other" changeset from merge state (issue4163)

login
register
mail settings
Submitter Pierre-Yves David
Date Feb. 27, 2014, 11:25 p.m.
Message ID <e9c7a904463947c37c21.1393543523@marginatus.alto.octopoid.net>
Download mbox | patch
Permalink /patch/3796/
State Accepted
Commit ba619c50a355c3946cdb07add520ff260034549d
Headers show

Comments

Pierre-Yves David - Feb. 27, 2014, 11:25 p.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@fb.com>
# Date 1393382701 28800
#      Tue Feb 25 18:45:01 2014 -0800
# Branch stable
# Node ID e9c7a904463947c37c21a8d195b535f667b35f19
# Parent  219c3064c7763c1adb56e82a946fd9ab776a8a1d
resolve: use "other" changeset from merge state (issue4163)

We can use the "other" data from the recorded merge state instead of inferring
what the other could be from working copy parent. This will allow resolve to
fulfil its duty even when the second parent have been dropped.

Most direct benefit is fixing a regression in backout.
Matt Mackall - Feb. 28, 2014, 12:15 a.m.
On Thu, 2014-02-27 at 15:25 -0800, pierre-yves.david@ens-lyon.org wrote:
> # HG changeset patch
> # User Pierre-Yves David <pierre-yves.david@fb.com>
> # Date 1393382701 28800
> #      Tue Feb 25 18:45:01 2014 -0800
> # Branch stable
> # Node ID e9c7a904463947c37c21a8d195b535f667b35f19
> # Parent  219c3064c7763c1adb56e82a946fd9ab776a8a1d
> resolve: use "other" changeset from merge state (issue4163)
> 
> We can use the "other" data from the recorded merge state instead of inferring
> what the other could be from working copy parent. This will allow resolve to
> fulfil its duty even when the second parent have been dropped.
> 
> Most direct benefit is fixing a regression in backout.

These are queued for stable, thanks.

This would normally be a bit too invasive for stable, but it's killing
off a large class of bugs, so it's probably worth it. Crossing fingers.

Patch

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -4959,20 +4959,19 @@  def resolve(ui, repo, *pats, **opts):
                 ms.mark(f, "r")
             elif unmark:
                 ms.mark(f, "u")
             else:
                 wctx = repo[None]
-                mctx = wctx.parents()[-1]
 
                 # backup pre-resolve (merge uses .orig for its own purposes)
                 a = repo.wjoin(f)
                 util.copyfile(a, a + ".resolve")
 
                 try:
                     # resolve file
                     ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
-                    if ms.resolve(f, wctx, mctx):
+                    if ms.resolve(f, wctx):
                         ret = 1
                 finally:
                     ui.setconfig('ui', 'forcemerge', '')
                     ms.commit()
 
diff --git a/mercurial/merge.py b/mercurial/merge.py
--- a/mercurial/merge.py
+++ b/mercurial/merge.py
@@ -182,15 +182,16 @@  class mergestate(object):
     def files(self):
         return self._state.keys()
     def mark(self, dfile, state):
         self._state[dfile][0] = state
         self._dirty = True
-    def resolve(self, dfile, wctx, octx):
+    def resolve(self, dfile, wctx):
         if self[dfile] == 'r':
             return 0
         stateentry = self._state[dfile]
         state, hash, lfile, afile, anode, ofile, onode, flags = stateentry
+        octx = self._repo[self._other]
         fcd = wctx[dfile]
         fco = octx[ofile]
         fca = self._repo.filectx(afile, fileid=anode)
         # "premerge" x flags
         flo = fco.flags()
@@ -637,11 +638,11 @@  def applyupdates(repo, actions, wctx, mc
             if fd == '.hgsubstate': # subrepo states need updating
                 subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx),
                                  overwrite)
                 continue
             audit(fd)
-            r = ms.resolve(fd, wctx, mctx)
+            r = ms.resolve(fd, wctx)
             if r is not None and r > 0:
                 unresolved += 1
             else:
                 if r is None:
                     updated += 1
diff --git a/tests/test-backout.t b/tests/test-backout.t
--- a/tests/test-backout.t
+++ b/tests/test-backout.t
@@ -406,5 +406,95 @@  on branch1, so no file1 and file2:
   branch: branch1
   commit: (clean)
   update: (current)
 
   $ cd ..
+
+
+Test usage of `hg resolve` in case of conflict
+(issue4163)
+
+  $ hg init issue4163
+  $ cd issue4163
+  $ touch foo
+  $ hg add foo
+  $ cat > foo << EOF
+  > one
+  > two
+  > three
+  > four
+  > five
+  > six
+  > seven
+  > height
+  > nine
+  > ten
+  > EOF
+  $ hg ci -m 'initial'
+  $ cat > foo << EOF
+  > one
+  > two
+  > THREE
+  > four
+  > five
+  > six
+  > seven
+  > height
+  > nine
+  > ten
+  > EOF
+  $ hg ci -m 'capital three'
+  $ cat > foo << EOF
+  > one
+  > two
+  > THREE
+  > four
+  > five
+  > six
+  > seven
+  > height
+  > nine
+  > TEN
+  > EOF
+  $ hg ci -m 'capital ten'
+  $ hg backout -r 'desc("capital three")' --tool internal:fail
+  0 files updated, 0 files merged, 0 files removed, 1 files unresolved
+  use 'hg resolve' to retry unresolved file merges
+  [1]
+  $ hg status
+  $ hg resolve -l  # still unresolved
+  U foo
+  $ hg summary
+  parent: 2:b71750c4b0fd tip
+   capital ten
+  branch: default
+  commit: 1 unresolved (clean)
+  update: (current)
+  $ hg resolve --all --debug
+  picked tool 'internal:merge' for foo (binary False symlink False)
+  merging foo
+  my foo@b71750c4b0fd+ other foo@a30dd8addae3 ancestor foo@913609522437
+   premerge successful
+  $ hg status
+  M foo
+  ? foo.orig
+  $ hg resolve -l
+  R foo
+  $ hg summary
+  parent: 2:b71750c4b0fd tip
+   capital ten
+  branch: default
+  commit: 1 modified, 1 unknown
+  update: (current)
+  $ cat foo
+  one
+  two
+  three
+  four
+  five
+  six
+  seven
+  height
+  nine
+  TEN
+
+