[PATCH 6 of 7 V2 stable] merge: add "other" file node in the merge state file
pierre-yves.david at ens-lyon.org
pierre-yves.david at ens-lyon.org
Thu Feb 27 17:25:22 CST 2014
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david at fb.com>
# Date 1393383287 28800
# Tue Feb 25 18:54:47 2014 -0800
# Branch stable
# Node ID 219c3064c7763c1adb56e82a946fd9ab776a8a1d
# Parent 45a3436571efbbf33d4d5ed0c4a31af8950ece4c
merge: add "other" file node in the merge state file
This data is mostly redundant with the "other" changeset node (+ other changeset
file path). However, more data never hurt.
The old format do not store it so this require some dancing to add and remove it
on demand.
diff --git a/mercurial/merge.py b/mercurial/merge.py
--- a/mercurial/merge.py
+++ b/mercurial/merge.py
@@ -14,10 +14,16 @@ import error, util, filemerge, copies, s
import errno, os, shutil
_pack = struct.pack
_unpack = struct.unpack
+def _droponode(data):
+ # used for compatibility for v1
+ bits = data.split("\0")
+ bits = bits[:-2] + bits[-1:]
+ return "\0".join(bits)
+
class mergestate(object):
'''track 3-way merge state of individual files
it is stored on disk when needed. Two file are used, one with an old
format, one with a new format. Both contains similar data, but the new
@@ -68,18 +74,30 @@ class mergestate(object):
% rtype))
self._dirty = False
def _readrecords(self):
v1records = self._readrecordsv1()
v2records = self._readrecordsv2()
- allv2 = set(v2records)
- for rev in v1records:
- if rev not in allv2:
+ oldv2 = set() # old format version of v2 record
+ for rec in v2records:
+ if rec[0] == 'L':
+ oldv2.add(rec)
+ elif rec[0] == 'F':
+ # drop the onode data (not contained in v1)
+ oldv2.add(('F', _droponode(rec[1])))
+ for rec in v1records:
+ if rec not in oldv2:
# v1 file is newer than v2 file, use it
# we have to infer the "other" changeset of the merge
# we cannot do better than that with v1 of the format
mctx = self._repo[None].parents()[-1]
v1records.append(('O', mctx.hex()))
+ # add "other" file node information
+ for idx, r in enumerate(v1records):
+ if r[0] == 'F':
+ bits = r[1].split("\0")
+ bits.insert(-2, mctx[bits[-2]])
+ v1records[idx] = (r[0], "\0".join(bits))
return v1records
else:
return v2records
def _readrecordsv1(self):
records = []
@@ -133,11 +151,11 @@ class mergestate(object):
lrecords = irecords.next()
assert lrecords[0] == 'L'
f.write(hex(self._local) + "\n")
for rtype, data in irecords:
if rtype == "F":
- f.write("%s\n" % data)
+ f.write("%s\n" % _droponode(data))
f.close()
def _writerecordsv2(self, records):
f = self._repo.opener(self.statepathv2, "w")
for key, data in records:
assert len(key) == 1
@@ -145,12 +163,14 @@ class mergestate(object):
f.write(_pack(format, key, len(data), data))
f.close()
def add(self, fcl, fco, fca, fd):
hash = util.sha1(fcl.path()).hexdigest()
self._repo.opener.write("merge/" + hash, fcl.data())
- self._state[fd] = ['u', hash, fcl.path(), fca.path(),
- hex(fca.filenode()), fco.path(), fcl.flags()]
+ self._state[fd] = ['u', hash, fcl.path(),
+ fca.path(), hex(fca.filenode()),
+ fco.path(), hex(fco.filenode()),
+ fcl.flags()]
self._dirty = True
def __contains__(self, dfile):
return dfile in self._state
def __getitem__(self, dfile):
return self._state[dfile][0]
@@ -165,11 +185,12 @@ class mergestate(object):
self._state[dfile][0] = state
self._dirty = True
def resolve(self, dfile, wctx, octx):
if self[dfile] == 'r':
return 0
- state, hash, lfile, afile, anode, ofile, flags = self._state[dfile]
+ stateentry = self._state[dfile]
+ state, hash, lfile, afile, anode, ofile, onode, flags = stateentry
fcd = wctx[dfile]
fco = octx[ofile]
fca = self._repo.filectx(afile, fileid=anode)
# "premerge" x flags
flo = fco.flags()
More information about the Mercurial-devel
mailing list