##// END OF EJS Templates
merge: introduce new format for the state file...
Pierre-Yves David -
r20590:2b7d54e9 stable
parent child Browse files
Show More
@@ -5,15 +5,41 b''
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 import struct
9
8 10 from node import nullid, nullrev, hex, bin
9 11 from i18n import _
10 12 from mercurial import obsolete
11 13 import error, util, filemerge, copies, subrepo, worker, dicthelpers
12 14 import errno, os, shutil
13 15
16 _pack = struct.pack
17 _unpack = struct.unpack
18
14 19 class mergestate(object):
15 '''track 3-way merge state of individual files'''
16 statepath = "merge/state"
20 '''track 3-way merge state of individual files
21
22 it is stored on disk when needed. Two file are used, one with an old
23 format, one with a new format. Both contains similar data, but the new
24 format can store new kind of field.
25
26 Current new format is a list of arbitrary record of the form:
27
28 [type][length][content]
29
30 Type is a single character, length is a 4 bytes integer, content is an
31 arbitrary suites of bytes of lenght `length`.
32
33 Type should be a letter. Capital letter are mandatory record, Mercurial
34 should abort if they are unknown. lower case record can be safely ignored.
35
36 Currently known record:
37
38 L: the node of the "local" part of the merge (hexified version)
39 F: a file to be merged entry
40 '''
41 statepathv1 = "merge/state"
42 statepathv2 = "merge/state2"
17 43 def __init__(self, repo):
18 44 self._repo = repo
19 45 self._dirty = False
@@ -38,9 +64,19 b' class mergestate(object):'
38 64 % rtype))
39 65 self._dirty = False
40 66 def _readrecords(self):
67 v1records = self._readrecordsv1()
68 v2records = self._readrecordsv2()
69 allv2 = set(v2records)
70 for rev in v1records:
71 if rev not in allv2:
72 # v1 file is newer than v2 file, use it
73 return v1records
74 else:
75 return v2records
76 def _readrecordsv1(self):
41 77 records = []
42 78 try:
43 f = self._repo.opener(self.statepath)
79 f = self._repo.opener(self.statepathv1)
44 80 for i, l in enumerate(f):
45 81 if i == 0:
46 82 records.append(('L', l[:-1]))
@@ -51,6 +87,26 b' class mergestate(object):'
51 87 if err.errno != errno.ENOENT:
52 88 raise
53 89 return records
90 def _readrecordsv2(self):
91 records = []
92 try:
93 f = self._repo.opener(self.statepathv2)
94 data = f.read()
95 off = 0
96 end = len(data)
97 while off < end:
98 rtype = data[off]
99 off += 1
100 lenght = _unpack('>I', data[off:(off + 4)])[0]
101 off += 4
102 record = data[off:(off + lenght)]
103 off += lenght
104 records.append((rtype, record))
105 f.close()
106 except IOError, err:
107 if err.errno != errno.ENOENT:
108 raise
109 return records
54 110 def commit(self):
55 111 if self._dirty:
56 112 records = []
@@ -60,7 +116,10 b' class mergestate(object):'
60 116 self._writerecords(records)
61 117 self._dirty = False
62 118 def _writerecords(self, records):
63 f = self._repo.opener(self.statepath, "w")
119 self._writerecordsv1(records)
120 self._writerecordsv2(records)
121 def _writerecordsv1(self, records):
122 f = self._repo.opener(self.statepathv1, "w")
64 123 irecords = iter(records)
65 124 lrecords = irecords.next()
66 125 assert lrecords[0] == 'L'
@@ -69,6 +128,13 b' class mergestate(object):'
69 128 if rtype == "F":
70 129 f.write("%s\n" % data)
71 130 f.close()
131 def _writerecordsv2(self, records):
132 f = self._repo.opener(self.statepathv2, "w")
133 for key, data in records:
134 assert len(key) == 1
135 format = ">sI%is" % len(data)
136 f.write(_pack(format, key, len(data), data))
137 f.close()
72 138 def add(self, fcl, fco, fca, fd):
73 139 hash = util.sha1(fcl.path()).hexdigest()
74 140 self._repo.opener.write("merge/" + hash, fcl.data())
General Comments 0
You need to be logged in to leave comments. Login now