Mercurial > public > mercurial-scm > hg
comparison mercurial/merge.py @ 20593:3678707e4017 stable
merge: add "other" file node in the merge state file
This data is mostly redundant with the "other" changeset node (+ other changeset
file path). However, more data never hurt.
The old format do not store it so this require some dancing to add and remove it
on demand.
author | Pierre-Yves David <pierre-yves.david@fb.com> |
---|---|
date | Tue, 25 Feb 2014 18:54:47 -0800 |
parents | 303cbfe3dcc8 |
children | ba619c50a355 |
comparison
equal
deleted
inserted
replaced
20592:303cbfe3dcc8 | 20593:3678707e4017 |
---|---|
13 import error, util, filemerge, copies, subrepo, worker, dicthelpers | 13 import error, util, filemerge, copies, subrepo, worker, dicthelpers |
14 import errno, os, shutil | 14 import errno, os, shutil |
15 | 15 |
16 _pack = struct.pack | 16 _pack = struct.pack |
17 _unpack = struct.unpack | 17 _unpack = struct.unpack |
18 | |
19 def _droponode(data): | |
20 # used for compatibility for v1 | |
21 bits = data.split("\0") | |
22 bits = bits[:-2] + bits[-1:] | |
23 return "\0".join(bits) | |
18 | 24 |
19 class mergestate(object): | 25 class mergestate(object): |
20 '''track 3-way merge state of individual files | 26 '''track 3-way merge state of individual files |
21 | 27 |
22 it is stored on disk when needed. Two file are used, one with an old | 28 it is stored on disk when needed. Two file are used, one with an old |
68 % rtype)) | 74 % rtype)) |
69 self._dirty = False | 75 self._dirty = False |
70 def _readrecords(self): | 76 def _readrecords(self): |
71 v1records = self._readrecordsv1() | 77 v1records = self._readrecordsv1() |
72 v2records = self._readrecordsv2() | 78 v2records = self._readrecordsv2() |
73 allv2 = set(v2records) | 79 oldv2 = set() # old format version of v2 record |
74 for rev in v1records: | 80 for rec in v2records: |
75 if rev not in allv2: | 81 if rec[0] == 'L': |
82 oldv2.add(rec) | |
83 elif rec[0] == 'F': | |
84 # drop the onode data (not contained in v1) | |
85 oldv2.add(('F', _droponode(rec[1]))) | |
86 for rec in v1records: | |
87 if rec not in oldv2: | |
76 # v1 file is newer than v2 file, use it | 88 # v1 file is newer than v2 file, use it |
77 # we have to infer the "other" changeset of the merge | 89 # we have to infer the "other" changeset of the merge |
78 # we cannot do better than that with v1 of the format | 90 # we cannot do better than that with v1 of the format |
79 mctx = self._repo[None].parents()[-1] | 91 mctx = self._repo[None].parents()[-1] |
80 v1records.append(('O', mctx.hex())) | 92 v1records.append(('O', mctx.hex())) |
93 # add place holder "other" file node information | |
94 # nobody is using it yet so we do no need to fetch the data | |
95 # if mctx was wrong `mctx[bits[-2]]` may fails. | |
96 for idx, r in enumerate(v1records): | |
97 if r[0] == 'F': | |
98 bits = r[1].split("\0") | |
99 bits.insert(-2, '') | |
100 v1records[idx] = (r[0], "\0".join(bits)) | |
81 return v1records | 101 return v1records |
82 else: | 102 else: |
83 return v2records | 103 return v2records |
84 def _readrecordsv1(self): | 104 def _readrecordsv1(self): |
85 records = [] | 105 records = [] |
133 lrecords = irecords.next() | 153 lrecords = irecords.next() |
134 assert lrecords[0] == 'L' | 154 assert lrecords[0] == 'L' |
135 f.write(hex(self._local) + "\n") | 155 f.write(hex(self._local) + "\n") |
136 for rtype, data in irecords: | 156 for rtype, data in irecords: |
137 if rtype == "F": | 157 if rtype == "F": |
138 f.write("%s\n" % data) | 158 f.write("%s\n" % _droponode(data)) |
139 f.close() | 159 f.close() |
140 def _writerecordsv2(self, records): | 160 def _writerecordsv2(self, records): |
141 f = self._repo.opener(self.statepathv2, "w") | 161 f = self._repo.opener(self.statepathv2, "w") |
142 for key, data in records: | 162 for key, data in records: |
143 assert len(key) == 1 | 163 assert len(key) == 1 |
145 f.write(_pack(format, key, len(data), data)) | 165 f.write(_pack(format, key, len(data), data)) |
146 f.close() | 166 f.close() |
147 def add(self, fcl, fco, fca, fd): | 167 def add(self, fcl, fco, fca, fd): |
148 hash = util.sha1(fcl.path()).hexdigest() | 168 hash = util.sha1(fcl.path()).hexdigest() |
149 self._repo.opener.write("merge/" + hash, fcl.data()) | 169 self._repo.opener.write("merge/" + hash, fcl.data()) |
150 self._state[fd] = ['u', hash, fcl.path(), fca.path(), | 170 self._state[fd] = ['u', hash, fcl.path(), |
151 hex(fca.filenode()), fco.path(), fcl.flags()] | 171 fca.path(), hex(fca.filenode()), |
172 fco.path(), hex(fco.filenode()), | |
173 fcl.flags()] | |
152 self._dirty = True | 174 self._dirty = True |
153 def __contains__(self, dfile): | 175 def __contains__(self, dfile): |
154 return dfile in self._state | 176 return dfile in self._state |
155 def __getitem__(self, dfile): | 177 def __getitem__(self, dfile): |
156 return self._state[dfile][0] | 178 return self._state[dfile][0] |
165 self._state[dfile][0] = state | 187 self._state[dfile][0] = state |
166 self._dirty = True | 188 self._dirty = True |
167 def resolve(self, dfile, wctx, octx): | 189 def resolve(self, dfile, wctx, octx): |
168 if self[dfile] == 'r': | 190 if self[dfile] == 'r': |
169 return 0 | 191 return 0 |
170 state, hash, lfile, afile, anode, ofile, flags = self._state[dfile] | 192 stateentry = self._state[dfile] |
193 state, hash, lfile, afile, anode, ofile, onode, flags = stateentry | |
171 fcd = wctx[dfile] | 194 fcd = wctx[dfile] |
172 fco = octx[ofile] | 195 fco = octx[ofile] |
173 fca = self._repo.filectx(afile, fileid=anode) | 196 fca = self._repo.filectx(afile, fileid=anode) |
174 # "premerge" x flags | 197 # "premerge" x flags |
175 flo = fco.flags() | 198 flo = fco.flags() |