Show More
@@ -5,15 +5,41 | |||
|
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 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 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 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 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