merge: save merge part labels for later reuse

We permit the caller of merge operations to supply labels for the merge
parts ("local", "other", and optionally "base"). These labels are used in
conflict markers to reduce confusion; however, the labels were not
persistent, so 'hg resolve' would lose the labels.

Store the labels in the mergestate.
This commit is contained in:
Simon Farnsworth 2016-03-19 18:37:10 -07:00
parent 45450b6576
commit 74ca86ac73
6 changed files with 62 additions and 15 deletions

View File

@ -2896,6 +2896,14 @@ def debugmergestate(ui, repo, *args):
ui.write(('file extras: %s (%s)\n')
% (filename, ', '.join(extrastrings)))
elif rtype == 'l':
labels = record.split('\0', 2)
labels = [l for l in labels if len(l) > 0]
ui.write(('labels:\n'))
ui.write((' local: %s\n' % labels[0]))
ui.write((' other: %s\n' % labels[1]))
if len(labels) > 2:
ui.write((' base: %s\n' % labels[2]))
else:
ui.write(('unrecognized entry: %s\t%s\n')
% (rtype, record.replace('\0', '\t')))
@ -2908,7 +2916,7 @@ def debugmergestate(ui, repo, *args):
# sort so that reasonable information is on top
v1records = ms._readrecordsv1()
v2records = ms._readrecordsv2()
order = 'LOm'
order = 'LOml'
def key(r):
idx = order.find(r[0])
if idx == -1:

View File

@ -68,6 +68,7 @@ class mergestate(object):
f: a (filename, dictonary) tuple of optional values for a given file
X: unsupported mandatory record type (used in tests)
x: unsupported advisory record type (used in tests)
l: the labels for the parts of the merge.
Merge driver run states (experimental):
u: driver-resolved files unmarked -- needs to be run next time we're about
@ -80,11 +81,11 @@ class mergestate(object):
statepathv2 = 'merge/state2'
@staticmethod
def clean(repo, node=None, other=None):
def clean(repo, node=None, other=None, labels=None):
"""Initialize a brand new merge state, removing any existing state on
disk."""
ms = mergestate(repo)
ms.reset(node, other)
ms.reset(node, other, labels)
return ms
@staticmethod
@ -100,12 +101,14 @@ class mergestate(object):
Do not use this directly! Instead call read() or clean()."""
self._repo = repo
self._dirty = False
self._labels = None
def reset(self, node=None, other=None):
def reset(self, node=None, other=None, labels=None):
self._state = {}
self._stateextras = {}
self._local = None
self._other = None
self._labels = labels
for var in ('localctx', 'otherctx'):
if var in vars(self):
delattr(self, var)
@ -165,6 +168,9 @@ class mergestate(object):
i += 2
self._stateextras[filename] = extras
elif rtype == 'l':
labels = record.split('\0', 2)
self._labels = [l for l in labels if len(l) > 0]
elif not rtype.islower():
unsupported.add(rtype)
self._results = {}
@ -353,6 +359,9 @@ class mergestate(object):
rawextras = '\0'.join('%s\0%s' % (k, v) for k, v in
extras.iteritems())
records.append(('f', '%s\0%s' % (filename, rawextras)))
if self._labels is not None:
labels = '\0'.join(self._labels)
records.append(('l', labels))
return records
def _writerecords(self, records):
@ -444,7 +453,7 @@ class mergestate(object):
def extras(self, filename):
return self._stateextras.setdefault(filename, {})
def _resolve(self, preresolve, dfile, wctx, labels=None):
def _resolve(self, preresolve, dfile, wctx):
"""rerun merge process for file path `dfile`"""
if self[dfile] in 'rd':
return True, 0
@ -481,11 +490,11 @@ class mergestate(object):
self._repo.wvfs.unlinkpath(dfile, ignoremissing=True)
complete, r, deleted = filemerge.premerge(self._repo, self._local,
lfile, fcd, fco, fca,
labels=labels)
labels=self._labels)
else:
complete, r, deleted = filemerge.filemerge(self._repo, self._local,
lfile, fcd, fco, fca,
labels=labels)
labels=self._labels)
if r is None:
# no real conflict
del self._state[dfile]
@ -523,17 +532,17 @@ class mergestate(object):
else:
return ctx[f]
def preresolve(self, dfile, wctx, labels=None):
def preresolve(self, dfile, wctx):
"""run premerge process for dfile
Returns whether the merge is complete, and the exit code."""
return self._resolve(True, dfile, wctx, labels=labels)
return self._resolve(True, dfile, wctx)
def resolve(self, dfile, wctx, labels=None):
def resolve(self, dfile, wctx):
"""run merge process (assuming premerge was run) for dfile
Returns the exit code of the merge."""
return self._resolve(False, dfile, wctx, labels=labels)[1]
return self._resolve(False, dfile, wctx)[1]
def counts(self):
"""return counts for updated, merged and removed files in this
@ -1094,7 +1103,7 @@ def applyupdates(repo, actions, wctx, mctx, overwrite, labels=None):
"""
updated, merged, removed = 0, 0, 0
ms = mergestate.clean(repo, wctx.p1().node(), mctx.node())
ms = mergestate.clean(repo, wctx.p1().node(), mctx.node(), labels)
moves = []
for m, l in actions.items():
l.sort()
@ -1247,7 +1256,7 @@ def applyupdates(repo, actions, wctx, mctx, overwrite, labels=None):
overwrite)
continue
audit(f)
complete, r = ms.preresolve(f, wctx, labels=labels)
complete, r = ms.preresolve(f, wctx)
if not complete:
numupdates += 1
tocomplete.append((f, args, msg))
@ -1257,7 +1266,7 @@ def applyupdates(repo, actions, wctx, mctx, overwrite, labels=None):
repo.ui.debug(" %s: %s -> m (merge)\n" % (f, msg))
z += 1
progress(_updating, z, item=f, total=numupdates, unit=_files)
ms.resolve(f, wctx, labels=labels)
ms.resolve(f, wctx)
ms.commit()

View File

@ -452,7 +452,7 @@ Resolve conflicted graft
c
=======
b
>>>>>>> other: 5d205f8b35b6 - bar: 1
>>>>>>> graft: 5d205f8b35b6 - bar: 1
$ echo b > a
$ hg resolve -m a
(no more unresolved files)

View File

@ -80,6 +80,9 @@ insert unsupported advisory merge record
* version 2 records
local: 8f7551c7e4a2f2efe0bc8c741baf7f227d65d758
other: e860deea161a2f77de56603b340ebbb4536308ae
labels:
local: local
other: histedit
unrecognized entry: x advisory record
file extras: e (ancestorlinknode = 0000000000000000000000000000000000000000)
file: e (record type "F", state "u", hash 58e6b3a414a1e090dfc6029add0f3555ccba127f)
@ -95,6 +98,9 @@ insert unsupported mandatory merge record
* version 2 records
local: 8f7551c7e4a2f2efe0bc8c741baf7f227d65d758
other: e860deea161a2f77de56603b340ebbb4536308ae
labels:
local: local
other: histedit
file extras: e (ancestorlinknode = 0000000000000000000000000000000000000000)
file: e (record type "F", state "u", hash 58e6b3a414a1e090dfc6029add0f3555ccba127f)
local path: e (flags "")

View File

@ -736,6 +736,9 @@ Non-interactive linear update
* version 2 records
local: ab57bf49aa276a22d35a473592d4c34b5abc3eff
other: 10f9a0a634e82080907e62f075ab119cbc565ea6
labels:
local: working copy
other: destination
file extras: file1 (ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff)
file: file1 (record type "C", state "u", hash 60b27f004e454aca81b0480209cce5081ec52390)
local path: file1 (flags "")
@ -776,6 +779,9 @@ Choose local versions of files
* version 2 records
local: ab57bf49aa276a22d35a473592d4c34b5abc3eff
other: 10f9a0a634e82080907e62f075ab119cbc565ea6
labels:
local: working copy
other: destination
file extras: file1 (ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff)
file: file1 (record type "C", state "r", hash 60b27f004e454aca81b0480209cce5081ec52390)
local path: file1 (flags "")
@ -814,6 +820,9 @@ Choose other versions of files
* version 2 records
local: ab57bf49aa276a22d35a473592d4c34b5abc3eff
other: 10f9a0a634e82080907e62f075ab119cbc565ea6
labels:
local: working copy
other: destination
file extras: file1 (ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff)
file: file1 (record type "C", state "r", hash 60b27f004e454aca81b0480209cce5081ec52390)
local path: file1 (flags "")
@ -854,6 +863,9 @@ Fail
* version 2 records
local: ab57bf49aa276a22d35a473592d4c34b5abc3eff
other: 10f9a0a634e82080907e62f075ab119cbc565ea6
labels:
local: working copy
other: destination
file extras: file1 (ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff)
file: file1 (record type "C", state "u", hash 60b27f004e454aca81b0480209cce5081ec52390)
local path: file1 (flags "")
@ -900,6 +912,9 @@ Force prompts with no input
* version 2 records
local: ab57bf49aa276a22d35a473592d4c34b5abc3eff
other: 10f9a0a634e82080907e62f075ab119cbc565ea6
labels:
local: working copy
other: destination
file extras: file1 (ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff)
file: file1 (record type "C", state "u", hash 60b27f004e454aca81b0480209cce5081ec52390)
local path: file1 (flags "")
@ -947,6 +962,9 @@ Choose to merge all files
* version 2 records
local: ab57bf49aa276a22d35a473592d4c34b5abc3eff
other: 10f9a0a634e82080907e62f075ab119cbc565ea6
labels:
local: working copy
other: destination
file extras: file1 (ancestorlinknode = ab57bf49aa276a22d35a473592d4c34b5abc3eff)
file: file1 (record type "C", state "u", hash 60b27f004e454aca81b0480209cce5081ec52390)
local path: file1 (flags "")

View File

@ -75,6 +75,9 @@ Insert unsupported advisory merge record:
* version 2 records
local: 3e046f2ecedb793b97ed32108086edd1a162f8bc
other: 46f0b057b5c061d276b91491c22151f78698abd2
labels:
local: dest
other: source
unrecognized entry: x advisory record
file extras: common (ancestorlinknode = 3163e20567cc93074fbb7a53c8b93312e59dbf2c)
file: common (record type "F", state "u", hash 94c8c21d08740f5da9eaa38d1f175c592692f0d1)
@ -91,6 +94,9 @@ Insert unsupported mandatory merge record:
* version 2 records
local: 3e046f2ecedb793b97ed32108086edd1a162f8bc
other: 46f0b057b5c061d276b91491c22151f78698abd2
labels:
local: dest
other: source
file extras: common (ancestorlinknode = 3163e20567cc93074fbb7a53c8b93312e59dbf2c)
file: common (record type "F", state "u", hash 94c8c21d08740f5da9eaa38d1f175c592692f0d1)
local path: common (flags "")