##// 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 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 import struct
9
8 from node import nullid, nullrev, hex, bin
10 from node import nullid, nullrev, hex, bin
9 from i18n import _
11 from i18n import _
10 from mercurial import obsolete
12 from mercurial import obsolete
11 import error, util, filemerge, copies, subrepo, worker, dicthelpers
13 import error, util, filemerge, copies, subrepo, worker, dicthelpers
12 import errno, os, shutil
14 import errno, os, shutil
13
15
16 _pack = struct.pack
17 _unpack = struct.unpack
18
14 class mergestate(object):
19 class mergestate(object):
15 '''track 3-way merge state of individual files'''
20 '''track 3-way merge state of individual files
16 statepath = "merge/state"
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 def __init__(self, repo):
43 def __init__(self, repo):
18 self._repo = repo
44 self._repo = repo
19 self._dirty = False
45 self._dirty = False
@@ -38,9 +64,19 b' class mergestate(object):'
38 % rtype))
64 % rtype))
39 self._dirty = False
65 self._dirty = False
40 def _readrecords(self):
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 records = []
77 records = []
42 try:
78 try:
43 f = self._repo.opener(self.statepath)
79 f = self._repo.opener(self.statepathv1)
44 for i, l in enumerate(f):
80 for i, l in enumerate(f):
45 if i == 0:
81 if i == 0:
46 records.append(('L', l[:-1]))
82 records.append(('L', l[:-1]))
@@ -51,6 +87,26 b' class mergestate(object):'
51 if err.errno != errno.ENOENT:
87 if err.errno != errno.ENOENT:
52 raise
88 raise
53 return records
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 def commit(self):
110 def commit(self):
55 if self._dirty:
111 if self._dirty:
56 records = []
112 records = []
@@ -60,7 +116,10 b' class mergestate(object):'
60 self._writerecords(records)
116 self._writerecords(records)
61 self._dirty = False
117 self._dirty = False
62 def _writerecords(self, records):
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 irecords = iter(records)
123 irecords = iter(records)
65 lrecords = irecords.next()
124 lrecords = irecords.next()
66 assert lrecords[0] == 'L'
125 assert lrecords[0] == 'L'
@@ -69,6 +128,13 b' class mergestate(object):'
69 if rtype == "F":
128 if rtype == "F":
70 f.write("%s\n" % data)
129 f.write("%s\n" % data)
71 f.close()
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 def add(self, fcl, fco, fca, fd):
138 def add(self, fcl, fco, fca, fd):
73 hash = util.sha1(fcl.path()).hexdigest()
139 hash = util.sha1(fcl.path()).hexdigest()
74 self._repo.opener.write("merge/" + hash, fcl.data())
140 self._repo.opener.write("merge/" + hash, fcl.data())
General Comments 0
You need to be logged in to leave comments. Login now