##// 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 Find moves and copies between context c1 and c2 that are relevant
310 Find moves and copies between context c1 and c2 that are relevant
311 for merging. 'base' will be used as the merge base.
311 for merging. 'base' will be used as the merge base.
312
312
313 Returns four dicts: "copy", "movewithdir", "diverge", and
313 Returns five dicts: "copy", "movewithdir", "diverge", "renamedelete" and
314 "renamedelete".
314 "dirmove".
315
315
316 "copy" is a mapping from destination name -> source name,
316 "copy" is a mapping from destination name -> source name,
317 where source is in c1 and destination is in c2 or vice-versa.
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 "renamedelete" is a mapping of source name -> list of destination
327 "renamedelete" is a mapping of source name -> list of destination
328 names for files deleted in c1 that were renamed in c2 or vice-versa.
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 # avoid silly behavior for update from empty dir
334 # avoid silly behavior for update from empty dir
331 if not c1 or not c2 or c1 == c2:
335 if not c1 or not c2 or c1 == c2:
332 return {}, {}, {}, {}
336 return {}, {}, {}, {}, {}
333
337
334 # avoid silly behavior for parent -> working dir
338 # avoid silly behavior for parent -> working dir
335 if c2.node() is None and c1.node() == repo.dirstate.p1():
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 # Copy trace disabling is explicitly below the node == p1 logic above
342 # Copy trace disabling is explicitly below the node == p1 logic above
339 # because the logic above is required for a simple copy to be kept across a
343 # because the logic above is required for a simple copy to be kept across a
340 # rebase.
344 # rebase.
341 if repo.ui.configbool('experimental', 'disablecopytrace'):
345 if repo.ui.configbool('experimental', 'disablecopytrace'):
342 return {}, {}, {}, {}
346 return {}, {}, {}, {}, {}
343
347
344 # In certain scenarios (e.g. graft, update or rebase), base can be
348 # In certain scenarios (e.g. graft, update or rebase), base can be
345 # overridden We still need to know a real common ancestor in this case We
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 limit = _findlimit(repo, c1.rev(), c2.rev())
369 limit = _findlimit(repo, c1.rev(), c2.rev())
366 if limit is None:
370 if limit is None:
367 # no common ancestor, no copies
371 # no common ancestor, no copies
368 return {}, {}, {}, {}
372 return {}, {}, {}, {}, {}
369 repo.ui.debug(" searching for copies back to rev %d\n" % limit)
373 repo.ui.debug(" searching for copies back to rev %d\n" % limit)
370
374
371 m1 = c1.manifest()
375 m1 = c1.manifest()
@@ -503,7 +507,7 b' def mergecopies(repo, c1, c2, base):'
503 del divergeset
507 del divergeset
504
508
505 if not fullcopy:
509 if not fullcopy:
506 return copy, {}, diverge, renamedelete
510 return copy, {}, diverge, renamedelete, {}
507
511
508 repo.ui.debug(" checking for directory renames\n")
512 repo.ui.debug(" checking for directory renames\n")
509
513
@@ -541,7 +545,7 b' def mergecopies(repo, c1, c2, base):'
541 del d1, d2, invalid
545 del d1, d2, invalid
542
546
543 if not dirmove:
547 if not dirmove:
544 return copy, {}, diverge, renamedelete
548 return copy, {}, diverge, renamedelete, {}
545
549
546 for d in dirmove:
550 for d in dirmove:
547 repo.ui.debug(" discovered dir src: '%s' -> dst: '%s'\n" %
551 repo.ui.debug(" discovered dir src: '%s' -> dst: '%s'\n" %
@@ -561,7 +565,7 b' def mergecopies(repo, c1, c2, base):'
561 "dst: '%s'\n") % (f, df))
565 "dst: '%s'\n") % (f, df))
562 break
566 break
563
567
564 return copy, movewithdir, diverge, renamedelete
568 return copy, movewithdir, diverge, renamedelete, dirmove
565
569
566 def _related(f1, f2, limit):
570 def _related(f1, f2, limit):
567 """return True if f1 and f2 filectx have a common ancestor
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 if matcher is not None and matcher.always():
794 if matcher is not None and matcher.always():
795 matcher = None
795 matcher = None
796
796
797 copy, movewithdir, diverge, renamedelete = {}, {}, {}, {}
797 copy, movewithdir, diverge, renamedelete, dirmove = {}, {}, {}, {}, {}
798
798
799 # manifests fetched in order are going to be faster, so prime the caches
799 # manifests fetched in order are going to be faster, so prime the caches
800 [x.manifest() for x in
800 [x.manifest() for x in
@@ -802,7 +802,7 b' def manifestmerge(repo, wctx, p2, pa, br'
802
802
803 if followcopies:
803 if followcopies:
804 ret = copies.mergecopies(repo, wctx, p2, pa)
804 ret = copies.mergecopies(repo, wctx, p2, pa)
805 copy, movewithdir, diverge, renamedelete = ret
805 copy, movewithdir, diverge, renamedelete, dirmove = ret
806
806
807 repo.ui.note(_("resolving manifests\n"))
807 repo.ui.note(_("resolving manifests\n"))
808 repo.ui.debug(" branchmerge: %s, force: %s, partial: %s\n"
808 repo.ui.debug(" branchmerge: %s, force: %s, partial: %s\n"
@@ -921,7 +921,16 b' def manifestmerge(repo, wctx, p2, pa, br'
921 actions[f] = ('cm', (fl2, pa.node()),
921 actions[f] = ('cm', (fl2, pa.node()),
922 "remote created, get or merge")
922 "remote created, get or merge")
923 elif n2 != ma[f]:
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 actions[f] = ('c', (fl2,), "remote recreating")
934 actions[f] = ('c', (fl2,), "remote recreating")
926 else:
935 else:
927 actions[f] = ('dc', (None, f, f, False, pa.node()),
936 actions[f] = ('dc', (None, f, f, False, pa.node()),
@@ -1286,3 +1286,28 b' Check superfluous filemerge of files ren'
1286 $ hg ci -qAmc
1286 $ hg ci -qAmc
1287 $ hg up -q .~2
1287 $ hg up -q .~2
1288 $ hg graft tip -qt:fail
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