diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -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: diff --git a/mercurial/merge.py b/mercurial/merge.py --- a/mercurial/merge.py +++ b/mercurial/merge.py @@ -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, mc """ 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, mc 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, mc 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() diff --git a/tests/test-graft.t b/tests/test-graft.t --- a/tests/test-graft.t +++ b/tests/test-graft.t @@ -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) diff --git a/tests/test-histedit-non-commute-abort.t b/tests/test-histedit-non-commute-abort.t --- a/tests/test-histedit-non-commute-abort.t +++ b/tests/test-histedit-non-commute-abort.t @@ -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 recor * 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 "") diff --git a/tests/test-merge-changedelete.t b/tests/test-merge-changedelete.t --- a/tests/test-merge-changedelete.t +++ b/tests/test-merge-changedelete.t @@ -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 "") diff --git a/tests/test-rebase-abort.t b/tests/test-rebase-abort.t --- a/tests/test-rebase-abort.t +++ b/tests/test-rebase-abort.t @@ -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 recor * 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 "")