<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>