Patchwork [2,of,7,V2,stable] merge: change the merge state serialisation to use a record based logic

login
register
mail settings
Submitter Pierre-Yves David
Date Feb. 27, 2014, 11:25 p.m.
Message ID <fb9472f3f87499c67307.1393543518@marginatus.alto.octopoid.net>
Download mbox | patch
Permalink /patch/3791/
State Accepted
Commit 31993cd23b11334e1f323b2e4488ad038d4b4137
Headers show

Comments

Pierre-Yves David - Feb. 27, 2014, 11:25 p.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@fb.com>
# Date 1393534781 28800
#      Thu Feb 27 12:59:41 2014 -0800
# Branch stable
# Node ID fb9472f3f87499c67307304c76fa34735e581230
# Parent  9325d58e8471377755af36333d42d2a683794c60
merge: change the merge state serialisation to use a record based logic

The format of the file is unchanged. But we are preparing a new file with a new
format that would be record based. So we change all the read/write logic to
handle a list of record until a very low level. This will allow simple plugging
of the new format in the current code.

Patch

diff --git a/mercurial/merge.py b/mercurial/merge.py
--- a/mercurial/merge.py
+++ b/mercurial/merge.py
@@ -24,31 +24,53 @@  class mergestate(object):
             self._local = node
         shutil.rmtree(self._repo.join("merge"), True)
         self._dirty = False
     def _read(self):
         self._state = {}
+        records = self._readrecords()
+        for rtype, record in records:
+            if rtype == 'L':
+                self._local = bin(record)
+            elif rtype == "F":
+                bits = record.split("\0")
+                self._state[bits[0]] = bits[1:]
+            elif not rtype.islower():
+                raise util.Abort(_('unsupported merge state record:'
+                                   % rtype))
+        self._dirty = False
+    def _readrecords(self):
+        records = []
         try:
             f = self._repo.opener(self.statepath)
             for i, l in enumerate(f):
                 if i == 0:
-                    self._local = bin(l[:-1])
+                    records.append(('L', l[:-1]))
                 else:
-                    bits = l[:-1].split("\0")
-                    self._state[bits[0]] = bits[1:]
+                    records.append(('F', l[:-1]))
             f.close()
         except IOError, err:
             if err.errno != errno.ENOENT:
                 raise
-        self._dirty = False
+        return records
     def commit(self):
         if self._dirty:
-            f = self._repo.opener(self.statepath, "w")
-            f.write(hex(self._local) + "\n")
+            records = []
+            records.append(("L", hex(self._local)))
             for d, v in self._state.iteritems():
-                f.write("\0".join([d] + v) + "\n")
-            f.close()
+                records.append(("F", "\0".join([d] + v)))
+            self._writerecords(records)
             self._dirty = False
+    def _writerecords(self, records):
+        f = self._repo.opener(self.statepath, "w")
+        irecords = iter(records)
+        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.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()]