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()