Mercurial > hg
comparison mercurial/merge.py @ 45942:89a2afe31e82
formating: upgrade to black 20.8b1
This required a couple of small tweaks to un-confuse black, but now it
works. Big formatting changes come from:
* Dramatically improved collection-splitting logic upstream
* Black having a strong (correct IMO) opinion that """ is better than '''
Differential Revision: https://phab.mercurial-scm.org/D9430
author | Augie Fackler <raf@durin42.com> |
---|---|
date | Fri, 27 Nov 2020 17:03:29 -0500 |
parents | 10dbc80d4be7 |
children | dfca84970da8 39f23d20ea47 |
comparison
equal
deleted
inserted
replaced
45941:346af7687c6f | 45942:89a2afe31e82 |
---|---|
215 abortconflicts.add(f) | 215 abortconflicts.add(f) |
216 else: | 216 else: |
217 if config == b'warn': | 217 if config == b'warn': |
218 warnconflicts.add(f) | 218 warnconflicts.add(f) |
219 mresult.addfile( | 219 mresult.addfile( |
220 f, mergestatemod.ACTION_GET, (fl2, True), b'remote created', | 220 f, |
221 mergestatemod.ACTION_GET, | |
222 (fl2, True), | |
223 b'remote created', | |
221 ) | 224 ) |
222 | 225 |
223 for f in sorted(abortconflicts): | 226 for f in sorted(abortconflicts): |
224 warn = repo.ui.warn | 227 warn = repo.ui.warn |
225 if f in pathconflicts: | 228 if f in pathconflicts: |
279 | 282 |
280 if not branchmerge: | 283 if not branchmerge: |
281 for f in wctx.removed(): | 284 for f in wctx.removed(): |
282 if f not in mctx: | 285 if f not in mctx: |
283 mresult.addfile( | 286 mresult.addfile( |
284 f, mergestatemod.ACTION_FORGET, None, b"forget removed", | 287 f, |
288 mergestatemod.ACTION_FORGET, | |
289 None, | |
290 b"forget removed", | |
285 ) | 291 ) |
286 | 292 |
287 | 293 |
288 def _checkcollision(repo, wmf, mresult): | 294 def _checkcollision(repo, wmf, mresult): |
289 """ | 295 """ |
542 _(b'conflict in file \'%s\' is outside narrow clone') % f | 548 _(b'conflict in file \'%s\' is outside narrow clone') % f |
543 ) | 549 ) |
544 | 550 |
545 | 551 |
546 class mergeresult(object): | 552 class mergeresult(object): |
547 '''An object representing result of merging manifests. | 553 """An object representing result of merging manifests. |
548 | 554 |
549 It has information about what actions need to be performed on dirstate | 555 It has information about what actions need to be performed on dirstate |
550 mapping of divergent renames and other such cases.''' | 556 mapping of divergent renames and other such cases.""" |
551 | 557 |
552 def __init__(self): | 558 def __init__(self): |
553 """ | 559 """ |
554 filemapping: dict of filename as keys and action related info as values | 560 filemapping: dict of filename as keys and action related info as values |
555 diverge: mapping of source name -> list of dest name for | 561 diverge: mapping of source name -> list of dest name for |
570 def updatevalues(self, diverge, renamedelete): | 576 def updatevalues(self, diverge, renamedelete): |
571 self._diverge = diverge | 577 self._diverge = diverge |
572 self._renamedelete = renamedelete | 578 self._renamedelete = renamedelete |
573 | 579 |
574 def addfile(self, filename, action, data, message): | 580 def addfile(self, filename, action, data, message): |
575 """ adds a new file to the mergeresult object | 581 """adds a new file to the mergeresult object |
576 | 582 |
577 filename: file which we are adding | 583 filename: file which we are adding |
578 action: one of mergestatemod.ACTION_* | 584 action: one of mergestatemod.ACTION_* |
579 data: a tuple of information like fctx and ctx related to this merge | 585 data: a tuple of information like fctx and ctx related to this merge |
580 message: a message about the merge | 586 message: a message about the merge |
587 | 593 |
588 self._filemapping[filename] = (action, data, message) | 594 self._filemapping[filename] = (action, data, message) |
589 self._actionmapping[action][filename] = (data, message) | 595 self._actionmapping[action][filename] = (data, message) |
590 | 596 |
591 def getfile(self, filename, default_return=None): | 597 def getfile(self, filename, default_return=None): |
592 """ returns (action, args, msg) about this file | 598 """returns (action, args, msg) about this file |
593 | 599 |
594 returns default_return if the file is not present """ | 600 returns default_return if the file is not present""" |
595 if filename in self._filemapping: | 601 if filename in self._filemapping: |
596 return self._filemapping[filename] | 602 return self._filemapping[filename] |
597 return default_return | 603 return default_return |
598 | 604 |
599 def files(self, actions=None): | 605 def files(self, actions=None): |
600 """ returns files on which provided action needs to perfromed | 606 """returns files on which provided action needs to perfromed |
601 | 607 |
602 If actions is None, all files are returned | 608 If actions is None, all files are returned |
603 """ | 609 """ |
604 # TODO: think whether we should return renamedelete and | 610 # TODO: think whether we should return renamedelete and |
605 # diverge filenames also | 611 # diverge filenames also |
611 for a in actions: | 617 for a in actions: |
612 for f in self._actionmapping[a]: | 618 for f in self._actionmapping[a]: |
613 yield f | 619 yield f |
614 | 620 |
615 def removefile(self, filename): | 621 def removefile(self, filename): |
616 """ removes a file from the mergeresult object as the file might | 622 """removes a file from the mergeresult object as the file might |
617 not merging anymore """ | 623 not merging anymore""" |
618 action, data, message = self._filemapping[filename] | 624 action, data, message = self._filemapping[filename] |
619 del self._filemapping[filename] | 625 del self._filemapping[filename] |
620 del self._actionmapping[action][filename] | 626 del self._actionmapping[action][filename] |
621 | 627 |
622 def getactions(self, actions, sort=False): | 628 def getactions(self, actions, sort=False): |
623 """ get list of files which are marked with these actions | 629 """get list of files which are marked with these actions |
624 if sort is true, files for each action is sorted and then added | 630 if sort is true, files for each action is sorted and then added |
625 | 631 |
626 Returns a list of tuple of form (filename, data, message) | 632 Returns a list of tuple of form (filename, data, message) |
627 """ | 633 """ |
628 for a in actions: | 634 for a in actions: |
635 self._actionmapping[a] | 641 self._actionmapping[a] |
636 ): | 642 ): |
637 yield f, args, msg | 643 yield f, args, msg |
638 | 644 |
639 def len(self, actions=None): | 645 def len(self, actions=None): |
640 """ returns number of files which needs actions | 646 """returns number of files which needs actions |
641 | 647 |
642 if actions is passed, total of number of files in that action | 648 if actions is passed, total of number of files in that action |
643 only is returned """ | 649 only is returned""" |
644 | 650 |
645 if actions is None: | 651 if actions is None: |
646 return len(self._filemapping) | 652 return len(self._filemapping) |
647 | 653 |
648 return sum(len(self._actionmapping[a]) for a in actions) | 654 return sum(len(self._actionmapping[a]) for a in actions) |
654 else: | 660 else: |
655 for key, val in pycompat.iteritems(self._filemapping): | 661 for key, val in pycompat.iteritems(self._filemapping): |
656 yield key, val | 662 yield key, val |
657 | 663 |
658 def addcommitinfo(self, filename, key, value): | 664 def addcommitinfo(self, filename, key, value): |
659 """ adds key-value information about filename which will be required | 665 """adds key-value information about filename which will be required |
660 while committing this merge """ | 666 while committing this merge""" |
661 self._commitinfo[filename][key] = value | 667 self._commitinfo[filename][key] = value |
662 | 668 |
663 @property | 669 @property |
664 def diverge(self): | 670 def diverge(self): |
665 return self._diverge | 671 return self._diverge |
672 def commitinfo(self): | 678 def commitinfo(self): |
673 return self._commitinfo | 679 return self._commitinfo |
674 | 680 |
675 @property | 681 @property |
676 def actionsdict(self): | 682 def actionsdict(self): |
677 """ returns a dictionary of actions to be perfomed with action as key | 683 """returns a dictionary of actions to be perfomed with action as key |
678 and a list of files and related arguments as values """ | 684 and a list of files and related arguments as values""" |
679 res = collections.defaultdict(list) | 685 res = collections.defaultdict(list) |
680 for a, d in pycompat.iteritems(self._actionmapping): | 686 for a, d in pycompat.iteritems(self._actionmapping): |
681 for f, (args, msg) in pycompat.iteritems(d): | 687 for f, (args, msg) in pycompat.iteritems(d): |
682 res[a].append((f, args, msg)) | 688 res[a].append((f, args, msg)) |
683 return res | 689 return res |
687 self._actionmapping = collections.defaultdict(dict) | 693 self._actionmapping = collections.defaultdict(dict) |
688 for f, (act, data, msg) in pycompat.iteritems(self._filemapping): | 694 for f, (act, data, msg) in pycompat.iteritems(self._filemapping): |
689 self._actionmapping[act][f] = data, msg | 695 self._actionmapping[act][f] = data, msg |
690 | 696 |
691 def hasconflicts(self): | 697 def hasconflicts(self): |
692 """ tells whether this merge resulted in some actions which can | 698 """tells whether this merge resulted in some actions which can |
693 result in conflicts or not """ | 699 result in conflicts or not""" |
694 for a in self._actionmapping.keys(): | 700 for a in self._actionmapping.keys(): |
695 if ( | 701 if ( |
696 a | 702 a |
697 not in ( | 703 not in ( |
698 mergestatemod.ACTION_GET, | 704 mergestatemod.ACTION_GET, |
837 a = ma[f] | 843 a = ma[f] |
838 fla = ma.flags(f) | 844 fla = ma.flags(f) |
839 nol = b'l' not in fl1 + fl2 + fla | 845 nol = b'l' not in fl1 + fl2 + fla |
840 if n2 == a and fl2 == fla: | 846 if n2 == a and fl2 == fla: |
841 mresult.addfile( | 847 mresult.addfile( |
842 f, mergestatemod.ACTION_KEEP, (), b'remote unchanged', | 848 f, |
849 mergestatemod.ACTION_KEEP, | |
850 (), | |
851 b'remote unchanged', | |
843 ) | 852 ) |
844 elif n1 == a and fl1 == fla: # local unchanged - use remote | 853 elif n1 == a and fl1 == fla: # local unchanged - use remote |
845 if n1 == n2: # optimization: keep local content | 854 if n1 == n2: # optimization: keep local content |
846 mresult.addfile( | 855 mresult.addfile( |
847 f, | 856 f, |
934 ) | 943 ) |
935 elif n1 == addednodeid: | 944 elif n1 == addednodeid: |
936 # This file was locally added. We should forget it instead of | 945 # This file was locally added. We should forget it instead of |
937 # deleting it. | 946 # deleting it. |
938 mresult.addfile( | 947 mresult.addfile( |
939 f, mergestatemod.ACTION_FORGET, None, b'remote deleted', | 948 f, |
949 mergestatemod.ACTION_FORGET, | |
950 None, | |
951 b'remote deleted', | |
940 ) | 952 ) |
941 else: | 953 else: |
942 mresult.addfile( | 954 mresult.addfile( |
943 f, mergestatemod.ACTION_REMOVE, None, b'other deleted', | 955 f, |
956 mergestatemod.ACTION_REMOVE, | |
957 None, | |
958 b'other deleted', | |
944 ) | 959 ) |
945 if branchmerge: | 960 if branchmerge: |
946 # the file must be absent after merging, | 961 # the file must be absent after merging, |
947 # howeber the user might make | 962 # howeber the user might make |
948 # the file reappear using revert and if they does, | 963 # the file reappear using revert and if they does, |
1084 return mresult | 1099 return mresult |
1085 | 1100 |
1086 | 1101 |
1087 def _resolvetrivial(repo, wctx, mctx, ancestor, mresult): | 1102 def _resolvetrivial(repo, wctx, mctx, ancestor, mresult): |
1088 """Resolves false conflicts where the nodeid changed but the content | 1103 """Resolves false conflicts where the nodeid changed but the content |
1089 remained the same.""" | 1104 remained the same.""" |
1090 # We force a copy of actions.items() because we're going to mutate | 1105 # We force a copy of actions.items() because we're going to mutate |
1091 # actions as we resolve trivial conflicts. | 1106 # actions as we resolve trivial conflicts. |
1092 for f in list(mresult.files((mergestatemod.ACTION_CHANGED_DELETED,))): | 1107 for f in list(mresult.files((mergestatemod.ACTION_CHANGED_DELETED,))): |
1093 if f in ancestor and not wctx[f].cmp(ancestor[f]): | 1108 if f in ancestor and not wctx[f].cmp(ancestor[f]): |
1094 # local did change but ended up with same content | 1109 # local did change but ended up with same content |
1421 ) | 1436 ) |
1422 | 1437 |
1423 prefetch = scmutil.prefetchfiles | 1438 prefetch = scmutil.prefetchfiles |
1424 matchfiles = scmutil.matchfiles | 1439 matchfiles = scmutil.matchfiles |
1425 prefetch( | 1440 prefetch( |
1426 repo, [(ctx.rev(), matchfiles(repo, files),)], | 1441 repo, |
1442 [ | |
1443 ( | |
1444 ctx.rev(), | |
1445 matchfiles(repo, files), | |
1446 ) | |
1447 ], | |
1427 ) | 1448 ) |
1428 | 1449 |
1429 | 1450 |
1430 @attr.s(frozen=True) | 1451 @attr.s(frozen=True) |
1431 class updateresult(object): | 1452 class updateresult(object): |
1442 or self.unresolvedcount | 1463 or self.unresolvedcount |
1443 ) | 1464 ) |
1444 | 1465 |
1445 | 1466 |
1446 def applyupdates( | 1467 def applyupdates( |
1447 repo, mresult, wctx, mctx, overwrite, wantfiledata, labels=None, | 1468 repo, |
1469 mresult, | |
1470 wctx, | |
1471 mctx, | |
1472 overwrite, | |
1473 wantfiledata, | |
1474 labels=None, | |
1448 ): | 1475 ): |
1449 """apply the merge action list to the working directory | 1476 """apply the merge action list to the working directory |
1450 | 1477 |
1451 mresult is a mergeresult object representing result of the merge | 1478 mresult is a mergeresult object representing result of the merge |
1452 wctx is the working copy context | 1479 wctx is the working copy context |
1732 from . import dirstate | 1759 from . import dirstate |
1733 | 1760 |
1734 if dirstate.rustmod is not None: | 1761 if dirstate.rustmod is not None: |
1735 # When using rust status, fsmonitor becomes necessary at higher sizes | 1762 # When using rust status, fsmonitor becomes necessary at higher sizes |
1736 fsmonitorthreshold = repo.ui.configint( | 1763 fsmonitorthreshold = repo.ui.configint( |
1737 b'fsmonitor', b'warn_update_file_count_rust', | 1764 b'fsmonitor', |
1765 b'warn_update_file_count_rust', | |
1738 ) | 1766 ) |
1739 | 1767 |
1740 try: | 1768 try: |
1741 # avoid cycle: extensions -> cmdutil -> merge | 1769 # avoid cycle: extensions -> cmdutil -> merge |
1742 from . import extensions | 1770 from . import extensions |
1999 ) | 2027 ) |
2000 % prompts, | 2028 % prompts, |
2001 0, | 2029 0, |
2002 ): | 2030 ): |
2003 mresult.addfile( | 2031 mresult.addfile( |
2004 f, mergestatemod.ACTION_REMOVE, None, b'prompt delete', | 2032 f, |
2033 mergestatemod.ACTION_REMOVE, | |
2034 None, | |
2035 b'prompt delete', | |
2005 ) | 2036 ) |
2006 elif f in p1: | 2037 elif f in p1: |
2007 mresult.addfile( | 2038 mresult.addfile( |
2008 f, | 2039 f, |
2009 mergestatemod.ACTION_ADD_MODIFIED, | 2040 mergestatemod.ACTION_ADD_MODIFIED, |
2010 None, | 2041 None, |
2011 b'prompt keep', | 2042 b'prompt keep', |
2012 ) | 2043 ) |
2013 else: | 2044 else: |
2014 mresult.addfile( | 2045 mresult.addfile( |
2015 f, mergestatemod.ACTION_ADD, None, b'prompt keep', | 2046 f, |
2047 mergestatemod.ACTION_ADD, | |
2048 None, | |
2049 b'prompt keep', | |
2016 ) | 2050 ) |
2017 elif m == mergestatemod.ACTION_DELETED_CHANGED: | 2051 elif m == mergestatemod.ACTION_DELETED_CHANGED: |
2018 f1, f2, fa, move, anc = args | 2052 f1, f2, fa, move, anc = args |
2019 flags = p2[f2].flags() | 2053 flags = p2[f2].flags() |
2020 if ( | 2054 if ( |
2087 repo, mresult.len((mergestatemod.ACTION_GET,)), p1.node() | 2121 repo, mresult.len((mergestatemod.ACTION_GET,)), p1.node() |
2088 ) | 2122 ) |
2089 | 2123 |
2090 wantfiledata = updatedirstate and not branchmerge | 2124 wantfiledata = updatedirstate and not branchmerge |
2091 stats, getfiledata = applyupdates( | 2125 stats, getfiledata = applyupdates( |
2092 repo, mresult, wc, p2, overwrite, wantfiledata, labels=labels, | 2126 repo, |
2127 mresult, | |
2128 wc, | |
2129 p2, | |
2130 overwrite, | |
2131 wantfiledata, | |
2132 labels=labels, | |
2093 ) | 2133 ) |
2094 | 2134 |
2095 if updatedirstate: | 2135 if updatedirstate: |
2096 with repo.dirstate.parentchange(): | 2136 with repo.dirstate.parentchange(): |
2097 repo.setparents(fp1, fp2) | 2137 repo.setparents(fp1, fp2) |