comparison mercurial/merge.py @ 4397:c04c96504a12

merge: clarify the findcopies code
author Matt Mackall <mpm@selenic.com>
date Thu, 03 May 2007 17:24:43 -0500
parents 8aee687f0214
children 9fe267f77f56
comparison
equal deleted inserted replaced
4387:80d3f6f0d8e5 4397:c04c96504a12
131 return l 131 return l
132 132
133 def checkcopies(c, man): 133 def checkcopies(c, man):
134 '''check possible copies for filectx c''' 134 '''check possible copies for filectx c'''
135 for of in findold(c): 135 for of in findold(c):
136 if of not in man: 136 if of not in man: # original file not in other manifest?
137 continue 137 continue
138 c2 = ctx(of, man[of]) 138 c2 = ctx(of, man[of])
139 ca = c.ancestor(c2) 139 ca = c.ancestor(c2)
140 if not ca: # unrelated 140 if not ca: # unrelated?
141 continue 141 continue
142 # named changed on only one side?
142 if ca.path() == c.path() or ca.path() == c2.path(): 143 if ca.path() == c.path() or ca.path() == c2.path():
143 fullcopy[c.path()] = of 144 fullcopy[c.path()] = of # remember for dir rename detection
144 if c == ca and c2 == ca: # no merge needed, ignore copy 145 if c == ca and c2 == ca: # no merge needed, ignore copy
145 continue 146 continue
146 copy[c.path()] = of 147 copy[c.path()] = of
147 148
148 def dirs(files): 149 def dirs(files):
177 # generate a directory move map 178 # generate a directory move map
178 d1, d2 = dirs(m1), dirs(m2) 179 d1, d2 = dirs(m1), dirs(m2)
179 invalid = {} 180 invalid = {}
180 dirmove = {} 181 dirmove = {}
181 182
183 # examine each file copy for a potential directory move, which is
184 # when all the files in a directory are moved to a new directory
182 for dst, src in fullcopy.items(): 185 for dst, src in fullcopy.items():
183 dsrc, ddst = os.path.dirname(src), os.path.dirname(dst) 186 dsrc, ddst = os.path.dirname(src), os.path.dirname(dst)
184 if dsrc in invalid: 187 if dsrc in invalid:
185 continue 188 # already seen to be uninteresting
186 elif (dsrc in d1 and ddst in d1) or (dsrc in d2 and ddst in d2): 189 continue
190 elif dsrc in d1 and ddst in d1:
191 # directory wasn't entirely moved locally
192 invalid[dsrc] = True
193 elif dsrc in d2 and ddst in d2:
194 # directory wasn't entirely moved remotely
187 invalid[dsrc] = True 195 invalid[dsrc] = True
188 elif dsrc in dirmove and dirmove[dsrc] != ddst: 196 elif dsrc in dirmove and dirmove[dsrc] != ddst:
197 # files from the same directory moved to two different places
189 invalid[dsrc] = True 198 invalid[dsrc] = True
190 del dirmove[dsrc] 199 del dirmove[dsrc]
191 else: 200 else:
201 # looks good so far
192 dirmove[dsrc + "/"] = ddst + "/" 202 dirmove[dsrc + "/"] = ddst + "/"
193 203
194 del d1, d2, invalid 204 del d1, d2, invalid
195 205
196 if not dirmove: 206 if not dirmove:
197 return copy 207 return copy
198 208
199 # check unaccounted nonoverlapping files 209 # check unaccounted nonoverlapping files against directory moves
200 for f in u1 + u2: 210 for f in u1 + u2:
201 if f not in fullcopy: 211 if f not in fullcopy:
202 for d in dirmove: 212 for d in dirmove:
203 if f.startswith(d): 213 if f.startswith(d):
214 # new file added in a directory that was moved, move it
204 copy[f] = dirmove[d] + f[len(d):] 215 copy[f] = dirmove[d] + f[len(d):]
205 break 216 break
206 217
207 return copy 218 return copy
208 219