##// END OF EJS Templates
copies: separate moves via directory renames from explicit copies...
Siddharth Agarwal -
r18134:6c35b53c default
parent child Browse files
Show More
@@ -170,11 +170,17 def mergecopies(repo, c1, c2, ca):
170 170 Find moves and copies between context c1 and c2 that are relevant
171 171 for merging.
172 172
173 Returns two dicts, "copy" and "diverge".
173 Returns four dicts: "copy", "movewithdir", "diverge", and
174 "renamedelete".
174 175
175 176 "copy" is a mapping from destination name -> source name,
176 177 where source is in c1 and destination is in c2 or vice-versa.
177 178
179 "movewithdir" is a mapping from source name -> destination name,
180 where the file at source present in one context but not the other
181 needs to be moved to destination by the merge process, because the
182 other context moved the directory it is in.
183
178 184 "diverge" is a mapping of source name -> list of destination names
179 185 for divergent renames.
180 186
@@ -183,16 +189,16 def mergecopies(repo, c1, c2, ca):
183 189 """
184 190 # avoid silly behavior for update from empty dir
185 191 if not c1 or not c2 or c1 == c2:
186 return {}, {}, {}
192 return {}, {}, {}, {}
187 193
188 194 # avoid silly behavior for parent -> working dir
189 195 if c2.node() is None and c1.node() == repo.dirstate.p1():
190 return repo.dirstate.copies(), {}, {}
196 return repo.dirstate.copies(), {}, {}, {}
191 197
192 198 limit = _findlimit(repo, c1.rev(), c2.rev())
193 199 if limit is None:
194 200 # no common ancestor, no copies
195 return {}, {}, {}
201 return {}, {}, {}, {}
196 202 m1 = c1.manifest()
197 203 m2 = c2.manifest()
198 204 ma = ca.manifest()
@@ -206,6 +212,7 def mergecopies(repo, c1, c2, ca):
206 212
207 213 ctx = util.lrucachefunc(makectx)
208 214 copy = {}
215 movewithdir = {}
209 216 fullcopy = {}
210 217 diverge = {}
211 218
@@ -315,7 +322,7 def mergecopies(repo, c1, c2, ca):
315 322 del diverge2
316 323
317 324 if not fullcopy:
318 return copy, diverge, renamedelete
325 return copy, movewithdir, diverge, renamedelete
319 326
320 327 repo.ui.debug(" checking for directory renames\n")
321 328
@@ -352,7 +359,7 def mergecopies(repo, c1, c2, ca):
352 359 del d1, d2, invalid
353 360
354 361 if not dirmove:
355 return copy, diverge, renamedelete
362 return copy, movewithdir, diverge, renamedelete
356 363
357 364 for d in dirmove:
358 365 repo.ui.debug(" dir %s -> %s\n" % (d, dirmove[d]))
@@ -365,8 +372,8 def mergecopies(repo, c1, c2, ca):
365 372 # new file added in a directory that was moved, move it
366 373 df = dirmove[d] + f[len(d):]
367 374 if df not in copy:
368 copy[f] = df
369 repo.ui.debug(" file %s -> %s\n" % (f, copy[f]))
375 movewithdir[f] = df
376 repo.ui.debug(" file %s -> %s\n" % (f, df))
370 377 break
371 378
372 return copy, diverge, renamedelete
379 return copy, movewithdir, diverge, renamedelete
@@ -213,14 +213,15 def manifestmerge(repo, p1, p2, pa, over
213 213 repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
214 214 action.append((f, m) + args)
215 215
216 action, copy = [], {}
216 action, copy, movewithdir = [], {}, {}
217 217
218 218 if overwrite:
219 219 pa = p1
220 220 elif pa == p2: # backwards
221 221 pa = p1.p1()
222 222 elif pa and repo.ui.configbool("merge", "followcopies", True):
223 copy, diverge, renamedelete = copies.mergecopies(repo, p1, p2, pa)
223 ret = copies.mergecopies(repo, p1, p2, pa)
224 copy, movewithdir, diverge, renamedelete = ret
224 225 for of, fl in diverge.iteritems():
225 226 act("divergent renames", "dr", of, fl)
226 227 for of, fl in renamedelete.iteritems():
@@ -233,6 +234,7 def manifestmerge(repo, p1, p2, pa, over
233 234
234 235 m1, m2, ma = p1.manifest(), p2.manifest(), pa.manifest()
235 236 copied = set(copy.values())
237 copied.update(movewithdir.values())
236 238
237 239 if '.hgsubstate' in m1:
238 240 # check whether sub state is modified
@@ -259,14 +261,14 def manifestmerge(repo, p1, p2, pa, over
259 261 act("versions differ", "m", f, f, f, rflags, False)
260 262 elif f in copied: # files we'll deal with on m2 side
261 263 pass
262 elif f in copy:
264 elif f in movewithdir: # directory rename
265 f2 = movewithdir[f]
266 act("remote renamed directory to " + f2, "d", f, None, f2,
267 m1.flags(f))
268 elif f in copy: # case 2 A,B/B/B or case 4,21 A/B/B
263 269 f2 = copy[f]
264 if f2 not in m2: # directory rename
265 act("remote renamed directory to " + f2, "d",
266 f, None, f2, m1.flags(f))
267 else: # case 2 A,B/B/B or case 4,21 A/B/B
268 act("local copied/moved to " + f2, "m",
269 f, f2, f, fmerge(f, f2, f2), False)
270 act("local copied/moved to " + f2, "m", f, f2, f,
271 fmerge(f, f2, f2), False)
270 272 elif f in ma: # clean, a different, no remote
271 273 if n != ma[f]:
272 274 if repo.ui.promptchoice(
@@ -286,12 +288,13 def manifestmerge(repo, p1, p2, pa, over
286 288 continue
287 289 if f in m1 or f in copied: # files already visited
288 290 continue
289 if f in copy:
291 if f in movewithdir:
292 f2 = movewithdir[f]
293 act("local renamed directory to " + f2, "d", None, f, f2,
294 m2.flags(f))
295 elif f in copy:
290 296 f2 = copy[f]
291 if f2 not in m1: # directory rename
292 act("local renamed directory to " + f2, "d",
293 None, f, f2, m2.flags(f))
294 elif f2 in m2: # rename case 1, A/A,B/A
297 if f2 in m2: # rename case 1, A/A,B/A
295 298 act("remote copied to " + f, "m",
296 299 f2, f, f, fmerge(f2, f, f2), False)
297 300 else: # case 3,20 A/B/A
General Comments 0
You need to be logged in to leave comments. Login now