<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, Feb 26, 2014 at 11:58 PM, <span dir="ltr"><<a href="mailto:pierre-yves.david@ens-lyon.org" target="_blank">pierre-yves.david@ens-lyon.org</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"># HG changeset patch<br>
# User Pierre-Yves David <<a href="mailto:pierre-yves.david@fb.com">pierre-yves.david@fb.com</a>><br>
# Date 1393382226 28800<br>
# Tue Feb 25 18:37:06 2014 -0800<br>
# Branch stable<br>
# Node ID d229b5d2096e7fdcc362fe22ff049ae257365c51<br>
# Parent a0c9e2941511a01624a0a75c000190f4ce3ed467<br>
merge: new format for the state file<br>
<br>
This new format will allow use to address common bugs with doing special merge<br>
(graft, backout, rebase…) and record user choice during conflict resolution.<br>
<br>
The format is open so we can add more record for future usage.<br>
<br>
I'm keeping hexified version of node in this file to help human willing to debug<br>
it by hand. I do not expect the overhead or oversize to be an issue.<br>
<br>
diff --git a/mercurial/merge.py b/mercurial/merge.py<br>
--- a/mercurial/merge.py<br>
+++ b/mercurial/merge.py<br>
@@ -3,20 +3,40 @@<br>
# Copyright 2006, 2007 Matt Mackall <<a href="mailto:mpm@selenic.com">mpm@selenic.com</a>><br>
#<br>
# This software may be used and distributed according to the terms of the<br>
# GNU General Public License version 2 or any later version.<br>
<br>
+import struct<br>
+<br>
from node import nullid, nullrev, hex, bin<br>
from i18n import _<br>
from mercurial import obsolete<br>
import error, util, filemerge, copies, subrepo, worker, dicthelpers<br>
import errno, os, shutil<br>
<br>
+_pack = struct.pack<br>
+_unpack = struct.unpack<br>
+<br>
class mergestate(object):<br>
- '''track 3-way merge state of individual files'''<br>
- statepath = "merge/state"<br>
+ '''track 3-way merge state of individual files<br>
<br>
+ current format is a list of arbitrary record of the form:<br>
+<br>
+ [type][length][content]<br>
+<br>
+ Type is a single character, length is a 4 bytes integer, content is an<br>
+ arbitrary suites of bytes of lenght `length`.<br></blockquote><div>length </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+<br>
+ Type should be a letter. Capital letter are mandatory record, Mercurial<br>
+ should abort if they are unknown. lower case record can be safely ignored.<br>
+<br>
+ Currently known record:<br>
+<br>
+ L: the node of the "local" part of the merge (hexified version)<br>
+ F: a file to be merged entry<br>
+ '''<br>
+ statepath = "merge/state2"<br>
def __init__(self, repo):<br>
self._repo = repo<br>
self._dirty = False<br>
self._read()<br>
def reset(self, node=None):<br>
@@ -27,29 +47,52 @@ class mergestate(object):<br>
self._dirty = False<br>
def _read(self):<br>
self._state = {}<br>
try:<br>
f = self._repo.opener(self.statepath)<br>
- for i, l in enumerate(f):<br>
- if i == 0:<br>
- self._local = bin(l[:-1])<br>
- else:<br>
- bits = l[:-1].split("\0")<br>
+ for rtype, record in self._readrecords(f):<br>
+ if rtype == 'L':<br>
+ self._local = bin(record)<br>
+ elif rtype == "F":<br>
+ bits = record.split("\0")<br>
self._state[bits[0]] = bits[1:]<br>
+ elif not rtype.islower():<br>
+ raise util.Abort(_('unsupported merge state record:'<br>
+ % rtype))<br>
f.close()<br>
except IOError, err:<br>
if err.errno != errno.ENOENT:<br>
raise<br>
self._dirty = False<br>
+ def _readrecords(self, f):<br>
+ data = f.read()<br>
+ off = 0<br>
+ end = len(data)<br>
+ while off < end:<br>
+ rtype = data[off]<br>
+ off += 1<br>
+ lenght = _unpack('>I', data[off:(off + 4)])[0]<br></blockquote><div>length </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+ off += 4<br>
+ record = data[off:(off + lenght)]<br></blockquote><div>length </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+ off += lenght<br></blockquote><div>length </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+ yield rtype, record<br>
+<br>
def commit(self):<br>
if self._dirty:<br>
+ records = []<br>
+ records.append(("L", hex(self._local)))<br>
+ for d, v in self._state.iteritems():<br>
+ records.append(("F", "\0".join([d] + v)))<br>
+ self._writerecords(records)<br>
+ self._dirty = False<br>
+ def _writerecords(self, records):<br>
f = self._repo.opener(self.statepath, "w")<br>
- f.write(hex(self._local) + "\n")<br>
- for d, v in self._state.iteritems():<br>
- f.write("\0".join([d] + v) + "\n")<br>
+ for key, data in records:<br>
+ assert len(key) == 1<br>
+ format = ">sI%is" % len(data)<br>
+ f.write(_pack(format, key, len(data), data))<br>
f.close()<br>
- self._dirty = False<br>
def add(self, fcl, fco, fca, fd):<br>
hash = util.sha1(fcl.path()).hexdigest()<br>
self._repo.opener.write("merge/" + hash, fcl.data())<br>
self._state[fd] = ['u', hash, fcl.path(), fca.path(),<br>
hex(fca.filenode()), fco.path(), fcl.flags()]<br>
_______________________________________________<br>
Mercurial-devel mailing list<br>
<a href="mailto:Mercurial-devel@selenic.com">Mercurial-devel@selenic.com</a><br>
<a href="http://selenic.com/mailman/listinfo/mercurial-devel" target="_blank">http://selenic.com/mailman/listinfo/mercurial-devel</a><br>
</blockquote></div><br><br clear="all"><div><br></div>-- <br>Olle
</div></div>