##// END OF EJS Templates
merge: start using the per-side copy dicts...
Martin von Zweigbergk -
r44682:fa9ad1da default
parent child Browse files
Show More
@@ -463,19 +463,23 b' def mergecopies(repo, c1, c2, base):'
463 """
463 """
464 # avoid silly behavior for update from empty dir
464 # avoid silly behavior for update from empty dir
465 if not c1 or not c2 or c1 == c2:
465 if not c1 or not c2 or c1 == c2:
466 return branch_copies(), {}
466 return branch_copies(), branch_copies(), {}
467
467
468 narrowmatch = c1.repo().narrowmatch()
468 narrowmatch = c1.repo().narrowmatch()
469
469
470 # avoid silly behavior for parent -> working dir
470 # avoid silly behavior for parent -> working dir
471 if c2.node() is None and c1.node() == repo.dirstate.p1():
471 if c2.node() is None and c1.node() == repo.dirstate.p1():
472 return branch_copies(_dirstatecopies(repo, narrowmatch)), {}
472 return (
473 branch_copies(_dirstatecopies(repo, narrowmatch)),
474 branch_copies(),
475 {},
476 )
473
477
474 copytracing = repo.ui.config(b'experimental', b'copytrace')
478 copytracing = repo.ui.config(b'experimental', b'copytrace')
475 if stringutil.parsebool(copytracing) is False:
479 if stringutil.parsebool(copytracing) is False:
476 # stringutil.parsebool() returns None when it is unable to parse the
480 # stringutil.parsebool() returns None when it is unable to parse the
477 # value, so we should rely on making sure copytracing is on such cases
481 # value, so we should rely on making sure copytracing is on such cases
478 return branch_copies(), {}
482 return branch_copies(), branch_copies(), {}
479
483
480 if usechangesetcentricalgo(repo):
484 if usechangesetcentricalgo(repo):
481 # The heuristics don't make sense when we need changeset-centric algos
485 # The heuristics don't make sense when we need changeset-centric algos
@@ -578,7 +582,7 b' def _fullcopytracing(repo, c1, c2, base)'
578 copies2 = pathcopies(base, c2)
582 copies2 = pathcopies(base, c2)
579
583
580 if not (copies1 or copies2):
584 if not (copies1 or copies2):
581 return branch_copies(), {}
585 return branch_copies(), branch_copies(), {}
582
586
583 inversecopies1 = {}
587 inversecopies1 = {}
584 inversecopies2 = {}
588 inversecopies2 = {}
@@ -681,12 +685,10 b' def _fullcopytracing(repo, c1, c2, base)'
681 dirmove1, movewithdir2 = _dir_renames(repo, c1, copy1, copies1, u2)
685 dirmove1, movewithdir2 = _dir_renames(repo, c1, copy1, copies1, u2)
682 dirmove2, movewithdir1 = _dir_renames(repo, c2, copy2, copies2, u1)
686 dirmove2, movewithdir1 = _dir_renames(repo, c2, copy2, copies2, u1)
683
687
684 copy1.update(copy2)
688 branch_copies1 = branch_copies(copy1, renamedelete1, dirmove1, movewithdir1)
685 renamedelete1.update(renamedelete2)
689 branch_copies2 = branch_copies(copy2, renamedelete2, dirmove2, movewithdir2)
686 movewithdir1.update(movewithdir2)
687 dirmove1.update(dirmove2)
688
690
689 return branch_copies(copy1, renamedelete1, dirmove1, movewithdir1), diverge
691 return branch_copies1, branch_copies2, diverge
690
692
691
693
692 def _dir_renames(repo, ctx, copy, fullcopy, addedfiles):
694 def _dir_renames(repo, ctx, copy, fullcopy, addedfiles):
@@ -784,8 +786,6 b' def _heuristicscopytracing(repo, c1, c2,'
784 if c2.rev() is None:
786 if c2.rev() is None:
785 c2 = c2.p1()
787 c2 = c2.p1()
786
788
787 copies = {}
788
789 changedfiles = set()
789 changedfiles = set()
790 m1 = c1.manifest()
790 m1 = c1.manifest()
791 if not repo.revs(b'%d::%d', base.rev(), c2.rev()):
791 if not repo.revs(b'%d::%d', base.rev(), c2.rev()):
@@ -805,10 +805,11 b' def _heuristicscopytracing(repo, c1, c2,'
805 changedfiles.update(ctx.files())
805 changedfiles.update(ctx.files())
806 ctx = ctx.p1()
806 ctx = ctx.p1()
807
807
808 copies2 = {}
808 cp = _forwardcopies(base, c2)
809 cp = _forwardcopies(base, c2)
809 for dst, src in pycompat.iteritems(cp):
810 for dst, src in pycompat.iteritems(cp):
810 if src in m1:
811 if src in m1:
811 copies[dst] = src
812 copies2[dst] = src
812
813
813 # file is missing if it isn't present in the destination, but is present in
814 # file is missing if it isn't present in the destination, but is present in
814 # the base and present in the source.
815 # the base and present in the source.
@@ -817,6 +818,7 b' def _heuristicscopytracing(repo, c1, c2,'
817 filt = lambda f: f not in m1 and f in base and f in c2
818 filt = lambda f: f not in m1 and f in base and f in c2
818 missingfiles = [f for f in changedfiles if filt(f)]
819 missingfiles = [f for f in changedfiles if filt(f)]
819
820
821 copies1 = {}
820 if missingfiles:
822 if missingfiles:
821 basenametofilename = collections.defaultdict(list)
823 basenametofilename = collections.defaultdict(list)
822 dirnametofilename = collections.defaultdict(list)
824 dirnametofilename = collections.defaultdict(list)
@@ -858,9 +860,9 b' def _heuristicscopytracing(repo, c1, c2,'
858 # if there are a few related copies then we'll merge
860 # if there are a few related copies then we'll merge
859 # changes into all of them. This matches the behaviour
861 # changes into all of them. This matches the behaviour
860 # of upstream copytracing
862 # of upstream copytracing
861 copies[candidate] = f
863 copies1[candidate] = f
862
864
863 return branch_copies(copies), {}
865 return branch_copies(copies1), branch_copies(copies2), {}
864
866
865
867
866 def _related(f1, f2):
868 def _related(f1, f2):
@@ -1262,13 +1262,13 b' def manifestmerge('
1262 for x in sorted(wctx.parents() + [p2, pa], key=scmutil.intrev)
1262 for x in sorted(wctx.parents() + [p2, pa], key=scmutil.intrev)
1263 ]
1263 ]
1264
1264
1265 copy, movewithdir, diverge, renamedelete, dirmove = {}, {}, {}, {}, {}
1265 branch_copies1 = copies.branch_copies()
1266 branch_copies2 = copies.branch_copies()
1267 diverge = {}
1266 if followcopies:
1268 if followcopies:
1267 branch_copies, diverge = copies.mergecopies(repo, wctx, p2, pa)
1269 branch_copies1, branch_copies2, diverge = copies.mergecopies(
1268 copy = branch_copies.copy
1270 repo, wctx, p2, pa
1269 renamedelete = branch_copies.renamedelete
1271 )
1270 dirmove = branch_copies.dirmove
1271 movewithdir = branch_copies.movewithdir
1272
1272
1273 boolbm = pycompat.bytestr(bool(branchmerge))
1273 boolbm = pycompat.bytestr(bool(branchmerge))
1274 boolf = pycompat.bytestr(bool(force))
1274 boolf = pycompat.bytestr(bool(force))
@@ -1280,8 +1280,10 b' def manifestmerge('
1280 repo.ui.debug(b" ancestor: %s, local: %s, remote: %s\n" % (pa, wctx, p2))
1280 repo.ui.debug(b" ancestor: %s, local: %s, remote: %s\n" % (pa, wctx, p2))
1281
1281
1282 m1, m2, ma = wctx.manifest(), p2.manifest(), pa.manifest()
1282 m1, m2, ma = wctx.manifest(), p2.manifest(), pa.manifest()
1283 copied = set(copy.values())
1283 copied1 = set(branch_copies1.copy.values())
1284 copied.update(movewithdir.values())
1284 copied1.update(branch_copies1.movewithdir.values())
1285 copied2 = set(branch_copies2.copy.values())
1286 copied2.update(branch_copies2.movewithdir.values())
1285
1287
1286 if b'.hgsubstate' in m1 and wctx.rev() is None:
1288 if b'.hgsubstate' in m1 and wctx.rev() is None:
1287 # Check whether sub state is modified, and overwrite the manifest
1289 # Check whether sub state is modified, and overwrite the manifest
@@ -1301,10 +1303,10 b' def manifestmerge('
1301 relevantfiles = set(ma.diff(m2).keys())
1303 relevantfiles = set(ma.diff(m2).keys())
1302
1304
1303 # For copied and moved files, we need to add the source file too.
1305 # For copied and moved files, we need to add the source file too.
1304 for copykey, copyvalue in pycompat.iteritems(copy):
1306 for copykey, copyvalue in pycompat.iteritems(branch_copies1.copy):
1305 if copyvalue in relevantfiles:
1307 if copyvalue in relevantfiles:
1306 relevantfiles.add(copykey)
1308 relevantfiles.add(copykey)
1307 for movedirkey in movewithdir:
1309 for movedirkey in branch_copies1.movewithdir:
1308 relevantfiles.add(movedirkey)
1310 relevantfiles.add(movedirkey)
1309 filesmatcher = scmutil.matchfiles(repo, relevantfiles)
1311 filesmatcher = scmutil.matchfiles(repo, relevantfiles)
1310 matcher = matchmod.intersectmatchers(matcher, filesmatcher)
1312 matcher = matchmod.intersectmatchers(matcher, filesmatcher)
@@ -1315,7 +1317,10 b' def manifestmerge('
1315 for f, ((n1, fl1), (n2, fl2)) in pycompat.iteritems(diff):
1317 for f, ((n1, fl1), (n2, fl2)) in pycompat.iteritems(diff):
1316 if n1 and n2: # file exists on both local and remote side
1318 if n1 and n2: # file exists on both local and remote side
1317 if f not in ma:
1319 if f not in ma:
1318 fa = copy.get(f, None)
1320 # TODO: what if they're renamed from different sources?
1321 fa = branch_copies1.copy.get(
1322 f, None
1323 ) or branch_copies2.copy.get(f, None)
1319 if fa is not None:
1324 if fa is not None:
1320 actions[f] = (
1325 actions[f] = (
1321 ACTION_MERGE,
1326 ACTION_MERGE,
@@ -1358,10 +1363,12 b' def manifestmerge('
1358 b'versions differ',
1363 b'versions differ',
1359 )
1364 )
1360 elif n1: # file exists only on local side
1365 elif n1: # file exists only on local side
1361 if f in copied:
1366 if f in copied2:
1362 pass # we'll deal with it on m2 side
1367 pass # we'll deal with it on m2 side
1363 elif f in movewithdir: # directory rename, move local
1368 elif (
1364 f2 = movewithdir[f]
1369 f in branch_copies1.movewithdir
1370 ): # directory rename, move local
1371 f2 = branch_copies1.movewithdir[f]
1365 if f2 in m2:
1372 if f2 in m2:
1366 actions[f2] = (
1373 actions[f2] = (
1367 ACTION_MERGE,
1374 ACTION_MERGE,
@@ -1374,8 +1381,8 b' def manifestmerge('
1374 (f, fl1),
1381 (f, fl1),
1375 b'remote directory rename - move from %s' % f,
1382 b'remote directory rename - move from %s' % f,
1376 )
1383 )
1377 elif f in copy:
1384 elif f in branch_copies1.copy:
1378 f2 = copy[f]
1385 f2 = branch_copies1.copy[f]
1379 actions[f] = (
1386 actions[f] = (
1380 ACTION_MERGE,
1387 ACTION_MERGE,
1381 (f, f2, f2, False, pa.node()),
1388 (f, f2, f2, False, pa.node()),
@@ -1399,10 +1406,10 b' def manifestmerge('
1399 else:
1406 else:
1400 actions[f] = (ACTION_REMOVE, None, b'other deleted')
1407 actions[f] = (ACTION_REMOVE, None, b'other deleted')
1401 elif n2: # file exists only on remote side
1408 elif n2: # file exists only on remote side
1402 if f in copied:
1409 if f in copied1:
1403 pass # we'll deal with it on m1 side
1410 pass # we'll deal with it on m1 side
1404 elif f in movewithdir:
1411 elif f in branch_copies2.movewithdir:
1405 f2 = movewithdir[f]
1412 f2 = branch_copies2.movewithdir[f]
1406 if f2 in m1:
1413 if f2 in m1:
1407 actions[f2] = (
1414 actions[f2] = (
1408 ACTION_MERGE,
1415 ACTION_MERGE,
@@ -1415,8 +1422,8 b' def manifestmerge('
1415 (f, fl2),
1422 (f, fl2),
1416 b'local directory rename - get from %s' % f,
1423 b'local directory rename - get from %s' % f,
1417 )
1424 )
1418 elif f in copy:
1425 elif f in branch_copies2.copy:
1419 f2 = copy[f]
1426 f2 = branch_copies2.copy[f]
1420 if f2 in m2:
1427 if f2 in m2:
1421 actions[f] = (
1428 actions[f] = (
1422 ACTION_MERGE,
1429 ACTION_MERGE,
@@ -1453,10 +1460,10 b' def manifestmerge('
1453 )
1460 )
1454 elif n2 != ma[f]:
1461 elif n2 != ma[f]:
1455 df = None
1462 df = None
1456 for d in dirmove:
1463 for d in branch_copies1.dirmove:
1457 if f.startswith(d):
1464 if f.startswith(d):
1458 # new file added in a directory that was moved
1465 # new file added in a directory that was moved
1459 df = dirmove[d] + f[len(d) :]
1466 df = branch_copies1.dirmove[d] + f[len(d) :]
1460 break
1467 break
1461 if df is not None and df in m1:
1468 if df is not None and df in m1:
1462 actions[df] = (
1469 actions[df] = (
@@ -1483,6 +1490,9 b' def manifestmerge('
1483 # Updates "actions" in place
1490 # Updates "actions" in place
1484 _filternarrowactions(narrowmatch, branchmerge, actions)
1491 _filternarrowactions(narrowmatch, branchmerge, actions)
1485
1492
1493 renamedelete = branch_copies1.renamedelete
1494 renamedelete.update(branch_copies2.renamedelete)
1495
1486 return actions, diverge, renamedelete
1496 return actions, diverge, renamedelete
1487
1497
1488
1498
General Comments 0
You need to be logged in to leave comments. Login now