Patchwork [4,of,7,V2,stable] merge: record the "other" node in merge state

login
register
mail settings
Submitter Pierre-Yves David
Date Feb. 27, 2014, 11:25 p.m.
Message ID <d755e15d6e239d427371.1393543520@marginatus.alto.octopoid.net>
Download mbox | patch
Permalink /patch/3793/
State Accepted
Commit 02c60e380fd041d9767d144fdf2ab398275c16d2
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 1393382531 28800
#      Tue Feb 25 18:42:11 2014 -0800
# Branch stable
# Node ID d755e15d6e239d4273714d9194482719946732fa
# Parent  c54808809e40a0e75fc2ad64ffd76c9e1b05760b
merge: record the "other" node in merge state

We need to record the merge we were merging with. This solve multiple bug with
resolve when dropping the second parent after a merge. This happen a lot when
doing special merge (overriding the ancestor). Backout, shelve, rebase, etc… can
takes advantage of it.

This changeset just add the information in the merge state. We'll use it in the
resolve process in a later changeset.

Patch

diff --git a/mercurial/merge.py b/mercurial/merge.py
--- a/mercurial/merge.py
+++ b/mercurial/merge.py
@@ -34,30 +34,34 @@  class mergestate(object):
     should abort if they are unknown. lower case record can be safely ignored.
 
     Currently known record:
 
     L: the node of the "local" part of the merge (hexified version)
+    O: the node of the "other" part of the merge (hexified version)
     F: a file to be merged entry
     '''
     statepathv1 = "merge/state"
     statepathv2 = "merge/state2"
     def __init__(self, repo):
         self._repo = repo
         self._dirty = False
         self._read()
-    def reset(self, node=None):
+    def reset(self, node=None, other=None):
         self._state = {}
         if node:
             self._local = node
+            self._other = other
         shutil.rmtree(self._repo.join("merge"), True)
         self._dirty = False
     def _read(self):
         self._state = {}
         records = self._readrecords()
         for rtype, record in records:
             if rtype == 'L':
                 self._local = bin(record)
+            elif rtype == 'O':
+                self._other = bin(record)
             elif rtype == "F":
                 bits = record.split("\0")
                 self._state[bits[0]] = bits[1:]
             elif not rtype.islower():
                 raise util.Abort(_('unsupported merge state record:'
@@ -109,10 +113,11 @@  class mergestate(object):
         return records
     def commit(self):
         if self._dirty:
             records = []
             records.append(("L", hex(self._local)))
+            records.append(("O", hex(self._other)))
             for d, v in self._state.iteritems():
                 records.append(("F", "\0".join([d] + v)))
             self._writerecords(records)
             self._dirty = False
     def _writerecords(self, records):
@@ -527,11 +532,11 @@  def applyupdates(repo, actions, wctx, mc
     describes how many files were affected by the update.
     """
 
     updated, merged, removed, unresolved = 0, 0, 0, 0
     ms = mergestate(repo)
-    ms.reset(wctx.p1().node())
+    ms.reset(wctx.p1().node(), mctx.node())
     moves = []
     actions.sort(key=actionkey)
 
     # prescan for merges
     for a in actions: