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( |
|
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 |
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