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)