##// END OF EJS Templates
graft: support grafting changes to new file in renamed directory (issue5436)
Gábor Stefanik -
r30581:43a9e02a default
parent child Browse files
Show More
@@ -310,8 +310,8 b' def mergecopies(repo, c1, c2, base):'
310 310 Find moves and copies between context c1 and c2 that are relevant
311 311 for merging. 'base' will be used as the merge base.
312 312
313 Returns four dicts: "copy", "movewithdir", "diverge", and
314 "renamedelete".
313 Returns five dicts: "copy", "movewithdir", "diverge", "renamedelete" and
314 "dirmove".
315 315
316 316 "copy" is a mapping from destination name -> source name,
317 317 where source is in c1 and destination is in c2 or vice-versa.
@@ -326,20 +326,24 b' def mergecopies(repo, c1, c2, base):'
326 326
327 327 "renamedelete" is a mapping of source name -> list of destination
328 328 names for files deleted in c1 that were renamed in c2 or vice-versa.
329
330 "dirmove" is a mapping of detected source dir -> destination dir renames.
331 This is needed for handling changes to new files previously grafted into
332 renamed directories.
329 333 """
330 334 # avoid silly behavior for update from empty dir
331 335 if not c1 or not c2 or c1 == c2:
332 return {}, {}, {}, {}
336 return {}, {}, {}, {}, {}
333 337
334 338 # avoid silly behavior for parent -> working dir
335 339 if c2.node() is None and c1.node() == repo.dirstate.p1():
336 return repo.dirstate.copies(), {}, {}, {}
340 return repo.dirstate.copies(), {}, {}, {}, {}
337 341
338 342 # Copy trace disabling is explicitly below the node == p1 logic above
339 343 # because the logic above is required for a simple copy to be kept across a
340 344 # rebase.
341 345 if repo.ui.configbool('experimental', 'disablecopytrace'):
342 return {}, {}, {}, {}
346 return {}, {}, {}, {}, {}
343 347
344 348 # In certain scenarios (e.g. graft, update or rebase), base can be
345 349 # overridden We still need to know a real common ancestor in this case We
@@ -365,7 +369,7 b' def mergecopies(repo, c1, c2, base):'
365 369 limit = _findlimit(repo, c1.rev(), c2.rev())
366 370 if limit is None:
367 371 # no common ancestor, no copies
368 return {}, {}, {}, {}
372 return {}, {}, {}, {}, {}
369 373 repo.ui.debug(" searching for copies back to rev %d\n" % limit)
370 374
371 375 m1 = c1.manifest()
@@ -503,7 +507,7 b' def mergecopies(repo, c1, c2, base):'
503 507 del divergeset
504 508
505 509 if not fullcopy:
506 return copy, {}, diverge, renamedelete
510 return copy, {}, diverge, renamedelete, {}
507 511
508 512 repo.ui.debug(" checking for directory renames\n")
509 513
@@ -541,7 +545,7 b' def mergecopies(repo, c1, c2, base):'
541 545 del d1, d2, invalid
542 546
543 547 if not dirmove:
544 return copy, {}, diverge, renamedelete
548 return copy, {}, diverge, renamedelete, {}
545 549
546 550 for d in dirmove:
547 551 repo.ui.debug(" discovered dir src: '%s' -> dst: '%s'\n" %
@@ -561,7 +565,7 b' def mergecopies(repo, c1, c2, base):'
561 565 "dst: '%s'\n") % (f, df))
562 566 break
563 567
564 return copy, movewithdir, diverge, renamedelete
568 return copy, movewithdir, diverge, renamedelete, dirmove
565 569
566 570 def _related(f1, f2, limit):
567 571 """return True if f1 and f2 filectx have a common ancestor
@@ -794,7 +794,7 b' def manifestmerge(repo, wctx, p2, pa, br'
794 794 if matcher is not None and matcher.always():
795 795 matcher = None
796 796
797 copy, movewithdir, diverge, renamedelete = {}, {}, {}, {}
797 copy, movewithdir, diverge, renamedelete, dirmove = {}, {}, {}, {}, {}
798 798
799 799 # manifests fetched in order are going to be faster, so prime the caches
800 800 [x.manifest() for x in
@@ -802,7 +802,7 b' def manifestmerge(repo, wctx, p2, pa, br'
802 802
803 803 if followcopies:
804 804 ret = copies.mergecopies(repo, wctx, p2, pa)
805 copy, movewithdir, diverge, renamedelete = ret
805 copy, movewithdir, diverge, renamedelete, dirmove = ret
806 806
807 807 repo.ui.note(_("resolving manifests\n"))
808 808 repo.ui.debug(" branchmerge: %s, force: %s, partial: %s\n"
@@ -921,7 +921,16 b' def manifestmerge(repo, wctx, p2, pa, br'
921 921 actions[f] = ('cm', (fl2, pa.node()),
922 922 "remote created, get or merge")
923 923 elif n2 != ma[f]:
924 if acceptremote:
924 df = None
925 for d in dirmove:
926 if f.startswith(d):
927 # new file added in a directory that was moved
928 df = dirmove[d] + f[len(d):]
929 break
930 if df in m1:
931 actions[df] = ('m', (df, f, f, False, pa.node()),
932 "local directory rename - respect move from " + f)
933 elif acceptremote:
925 934 actions[f] = ('c', (fl2,), "remote recreating")
926 935 else:
927 936 actions[f] = ('dc', (None, f, f, False, pa.node()),
@@ -1286,3 +1286,28 b' Check superfluous filemerge of files ren'
1286 1286 $ hg ci -qAmc
1287 1287 $ hg up -q .~2
1288 1288 $ hg graft tip -qt:fail
1289
1290 $ cd ..
1291
1292 Graft a change into a new file previously grafted into a renamed directory
1293
1294 $ hg init dirmovenewfile
1295 $ cd dirmovenewfile
1296 $ mkdir a
1297 $ echo a > a/a
1298 $ hg ci -qAma
1299 $ echo x > a/x
1300 $ hg ci -qAmx
1301 $ hg up -q 0
1302 $ hg mv -q a b
1303 $ hg ci -qAmb
1304 $ hg graft -q 1 # a/x grafted as b/x, but no copy information recorded
1305 $ hg up -q 1
1306 $ echo y > a/x
1307 $ hg ci -qAmy
1308 $ hg up -q 3
1309 $ hg graft -q 4
1310 $ hg status --change .
1311 M b/x
1312
1313 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now