##// END OF EJS Templates
merge: use constants for actions...
Gregory Szorc -
r37130:43ffd907 default
parent child Browse files
Show More
@@ -71,6 +71,23 b" MERGE_RECORD_UNRESOLVED_PATH = b'pu'"
71 71 MERGE_RECORD_RESOLVED_PATH = b'pr'
72 72 MERGE_RECORD_DRIVER_RESOLVED = b'd'
73 73
74 ACTION_FORGET = b'f'
75 ACTION_REMOVE = b'r'
76 ACTION_ADD = b'a'
77 ACTION_GET = b'g'
78 ACTION_PATH_CONFLICT = b'p'
79 ACTION_PATH_CONFLICT_RESOLVE = b'pr'
80 ACTION_ADD_MODIFIED = b'am'
81 ACTION_CREATED = b'c'
82 ACTION_DELETED_CHANGED = b'dc'
83 ACTION_CHANGED_DELETED = b'cd'
84 ACTION_MERGE = b'm'
85 ACTION_LOCAL_DIR_RENAME_GET = b'dg'
86 ACTION_DIR_RENAME_MOVE_LOCAL = b'dm'
87 ACTION_KEEP = b'k'
88 ACTION_EXEC = b'e'
89 ACTION_CREATED_MERGE = b'cm'
90
74 91 class mergestate(object):
75 92 '''track 3-way merge state of individual files
76 93
@@ -588,18 +605,18 b' class mergestate(object):'
588 605 if fcd.isabsent():
589 606 # dc: local picked. Need to drop if present, which may
590 607 # happen on re-resolves.
591 action = 'f'
608 action = ACTION_FORGET
592 609 else:
593 610 # cd: remote picked (or otherwise deleted)
594 action = 'r'
611 action = ACTION_REMOVE
595 612 else:
596 613 if fcd.isabsent(): # dc: remote picked
597 action = 'g'
614 action = ACTION_GET
598 615 elif fco.isabsent(): # cd: local picked
599 616 if dfile in self.localctx:
600 action = 'am'
617 action = ACTION_ADD_MODIFIED
601 618 else:
602 action = 'a'
619 action = ACTION_ADD
603 620 # else: regular merges (no action necessary)
604 621 self._results[dfile] = r, action
605 622
@@ -631,7 +648,7 b' class mergestate(object):'
631 648 if r is None:
632 649 updated += 1
633 650 elif r == 0:
634 if action == 'r':
651 if action == ACTION_REMOVE:
635 652 removed += 1
636 653 else:
637 654 merged += 1
@@ -643,7 +660,13 b' class mergestate(object):'
643 660
644 661 def actions(self):
645 662 """return lists of actions to perform on the dirstate"""
646 actions = {'r': [], 'f': [], 'a': [], 'am': [], 'g': []}
663 actions = {
664 ACTION_REMOVE: [],
665 ACTION_FORGET: [],
666 ACTION_ADD: [],
667 ACTION_ADD_MODIFIED: [],
668 ACTION_GET: [],
669 }
647 670 for f, (r, action) in self._results.iteritems():
648 671 if action is not None:
649 672 actions[action].append((f, None, "merge result"))
@@ -658,19 +681,19 b' class mergestate(object):'
658 681 """queues a file to be removed from the dirstate
659 682
660 683 Meant for use by custom merge drivers."""
661 self._results[f] = 0, 'r'
684 self._results[f] = 0, ACTION_REMOVE
662 685
663 686 def queueadd(self, f):
664 687 """queues a file to be added to the dirstate
665 688
666 689 Meant for use by custom merge drivers."""
667 self._results[f] = 0, 'a'
690 self._results[f] = 0, ACTION_ADD
668 691
669 692 def queueget(self, f):
670 693 """queues a file to be marked modified in the dirstate
671 694
672 695 Meant for use by custom merge drivers."""
673 self._results[f] = 0, 'g'
696 self._results[f] = 0, ACTION_GET
674 697
675 698 def _getcheckunknownconfig(repo, section, name):
676 699 config = repo.ui.config(section, name)
@@ -772,14 +795,14 b' def _checkunknownfiles(repo, wctx, mctx,'
772 795
773 796 checkunknowndirs = _unknowndirschecker()
774 797 for f, (m, args, msg) in actions.iteritems():
775 if m in ('c', 'dc'):
798 if m in (ACTION_CREATED, ACTION_DELETED_CHANGED):
776 799 if _checkunknownfile(repo, wctx, mctx, f):
777 800 fileconflicts.add(f)
778 801 elif pathconfig and f not in wctx:
779 802 path = checkunknowndirs(repo, wctx, f)
780 803 if path is not None:
781 804 pathconflicts.add(path)
782 elif m == 'dg':
805 elif m == ACTION_LOCAL_DIR_RENAME_GET:
783 806 if _checkunknownfile(repo, wctx, mctx, f, args[0]):
784 807 fileconflicts.add(f)
785 808
@@ -791,7 +814,7 b' def _checkunknownfiles(repo, wctx, mctx,'
791 814 collectconflicts(unknownconflicts, unknownconfig)
792 815 else:
793 816 for f, (m, args, msg) in actions.iteritems():
794 if m == 'cm':
817 if m == ACTION_CREATED_MERGE:
795 818 fl2, anc = args
796 819 different = _checkunknownfile(repo, wctx, mctx, f)
797 820 if repo.dirstate._ignore(f):
@@ -812,16 +835,16 b' def _checkunknownfiles(repo, wctx, mctx,'
812 835 # don't like an abort happening in the middle of
813 836 # merge.update.
814 837 if not different:
815 actions[f] = ('g', (fl2, False), "remote created")
838 actions[f] = (ACTION_GET, (fl2, False), 'remote created')
816 839 elif mergeforce or config == 'abort':
817 actions[f] = ('m', (f, f, None, False, anc),
818 "remote differs from untracked local")
840 actions[f] = (ACTION_MERGE, (f, f, None, False, anc),
841 'remote differs from untracked local')
819 842 elif config == 'abort':
820 843 abortconflicts.add(f)
821 844 else:
822 845 if config == 'warn':
823 846 warnconflicts.add(f)
824 actions[f] = ('g', (fl2, True), "remote created")
847 actions[f] = (ACTION_GET, (fl2, True), 'remote created')
825 848
826 849 for f in sorted(abortconflicts):
827 850 warn = repo.ui.warn
@@ -843,11 +866,11 b' def _checkunknownfiles(repo, wctx, mctx,'
843 866 repo.ui.warn(_("%s: replacing untracked files in directory\n") % f)
844 867
845 868 for f, (m, args, msg) in actions.iteritems():
846 if m == 'c':
869 if m == ACTION_CREATED:
847 870 backup = (f in fileconflicts or f in pathconflicts or
848 871 any(p in pathconflicts for p in util.finddirs(f)))
849 872 flags, = args
850 actions[f] = ('g', (flags, backup), msg)
873 actions[f] = (ACTION_GET, (flags, backup), msg)
851 874
852 875 def _forgetremoved(wctx, mctx, branchmerge):
853 876 """
@@ -865,9 +888,9 b' def _forgetremoved(wctx, mctx, branchmer'
865 888 """
866 889
867 890 actions = {}
868 m = 'f'
891 m = ACTION_FORGET
869 892 if branchmerge:
870 m = 'r'
893 m = ACTION_REMOVE
871 894 for f in wctx.deleted():
872 895 if f not in mctx:
873 896 actions[f] = m, None, "forget deleted"
@@ -875,7 +898,7 b' def _forgetremoved(wctx, mctx, branchmer'
875 898 if not branchmerge:
876 899 for f in wctx.removed():
877 900 if f not in mctx:
878 actions[f] = 'f', None, "forget removed"
901 actions[f] = ACTION_FORGET, None, "forget removed"
879 902
880 903 return actions
881 904
@@ -884,19 +907,20 b' def _checkcollision(repo, wmf, actions):'
884 907 pmmf = set(wmf)
885 908
886 909 if actions:
887 # k, dr, e and rd are no-op
888 for m in 'a', 'am', 'f', 'g', 'cd', 'dc':
910 # KEEP and EXEC are no-op
911 for m in (ACTION_ADD, ACTION_ADD_MODIFIED, ACTION_FORGET, ACTION_GET,
912 ACTION_CHANGED_DELETED, ACTION_DELETED_CHANGED):
889 913 for f, args, msg in actions[m]:
890 914 pmmf.add(f)
891 for f, args, msg in actions['r']:
915 for f, args, msg in actions[ACTION_REMOVE]:
892 916 pmmf.discard(f)
893 for f, args, msg in actions['dm']:
917 for f, args, msg in actions[ACTION_DIR_RENAME_MOVE_LOCAL]:
894 918 f2, flags = args
895 919 pmmf.discard(f2)
896 920 pmmf.add(f)
897 for f, args, msg in actions['dg']:
921 for f, args, msg in actions[ACTION_LOCAL_DIR_RENAME_GET]:
898 922 pmmf.add(f)
899 for f, args, msg in actions['m']:
923 for f, args, msg in actions[ACTION_MERGE]:
900 924 f1, f2, fa, move, anc = args
901 925 if move:
902 926 pmmf.discard(f1)
@@ -972,7 +996,8 b' def checkpathconflicts(repo, wctx, mctx,'
972 996 deletedfiles = set()
973 997
974 998 for f, (m, args, msg) in actions.items():
975 if m in ('c', 'dc', 'm', 'cm'):
999 if m in (ACTION_CREATED, ACTION_DELETED_CHANGED, ACTION_MERGE,
1000 ACTION_CREATED_MERGE):
976 1001 # This action may create a new local file.
977 1002 createdfiledirs.update(util.finddirs(f))
978 1003 if mf.hasdir(f):
@@ -981,13 +1006,13 b' def checkpathconflicts(repo, wctx, mctx,'
981 1006 # will be checked once we know what all the deleted files are.
982 1007 remoteconflicts.add(f)
983 1008 # Track the names of all deleted files.
984 if m == 'r':
1009 if m == ACTION_REMOVE:
985 1010 deletedfiles.add(f)
986 if m == 'm':
1011 if m == ACTION_MERGE:
987 1012 f1, f2, fa, move, anc = args
988 1013 if move:
989 1014 deletedfiles.add(f1)
990 if m == 'dm':
1015 if m == ACTION_DIR_RENAME_MOVE_LOCAL:
991 1016 f2, flags = args
992 1017 deletedfiles.add(f2)
993 1018
@@ -1003,7 +1028,10 b' def checkpathconflicts(repo, wctx, mctx,'
1003 1028 # A file is in a directory which aliases a local file.
1004 1029 # We will need to rename the local file.
1005 1030 localconflicts.add(p)
1006 if p in actions and actions[p][0] in ('c', 'dc', 'm', 'cm'):
1031 if p in actions and actions[p][0] in (ACTION_CREATED,
1032 ACTION_DELETED_CHANGED,
1033 ACTION_MERGE,
1034 ACTION_CREATED_MERGE):
1007 1035 # The file is in a directory which aliases a remote file.
1008 1036 # This is an internal inconsistency within the remote
1009 1037 # manifest.
@@ -1014,8 +1042,10 b' def checkpathconflicts(repo, wctx, mctx,'
1014 1042 if p not in deletedfiles:
1015 1043 ctxname = bytes(wctx).rstrip('+')
1016 1044 pnew = util.safename(p, ctxname, wctx, set(actions.keys()))
1017 actions[pnew] = ('pr', (p,), "local path conflict")
1018 actions[p] = ('p', (pnew, 'l'), "path conflict")
1045 actions[pnew] = (ACTION_PATH_CONFLICT_RESOLVE, (p,),
1046 'local path conflict')
1047 actions[p] = (ACTION_PATH_CONFLICT, (pnew, 'l'),
1048 'path conflict')
1019 1049
1020 1050 if remoteconflicts:
1021 1051 # Check if all files in the conflicting directories have been removed.
@@ -1024,14 +1054,16 b' def checkpathconflicts(repo, wctx, mctx,'
1024 1054 if f not in deletedfiles:
1025 1055 m, args, msg = actions[p]
1026 1056 pnew = util.safename(p, ctxname, wctx, set(actions.keys()))
1027 if m in ('dc', 'm'):
1057 if m in (ACTION_DELETED_CHANGED, ACTION_MERGE):
1028 1058 # Action was merge, just update target.
1029 1059 actions[pnew] = (m, args, msg)
1030 1060 else:
1031 1061 # Action was create, change to renamed get action.
1032 1062 fl = args[0]
1033 actions[pnew] = ('dg', (p, fl), "remote path conflict")
1034 actions[p] = ('p', (pnew, 'r'), "path conflict")
1063 actions[pnew] = (ACTION_LOCAL_DIR_RENAME_GET, (p, fl),
1064 'remote path conflict')
1065 actions[p] = (ACTION_PATH_CONFLICT, (pnew, ACTION_REMOVE),
1066 'path conflict')
1035 1067 remoteconflicts.remove(p)
1036 1068 break
1037 1069
@@ -1109,77 +1141,80 b' def manifestmerge(repo, wctx, p2, pa, br'
1109 1141 if f not in ma:
1110 1142 fa = copy.get(f, None)
1111 1143 if fa is not None:
1112 actions[f] = ('m', (f, f, fa, False, pa.node()),
1113 "both renamed from " + fa)
1144 actions[f] = (ACTION_MERGE, (f, f, fa, False, pa.node()),
1145 'both renamed from %s' % fa)
1114 1146 else:
1115 actions[f] = ('m', (f, f, None, False, pa.node()),
1116 "both created")
1147 actions[f] = (ACTION_MERGE, (f, f, None, False, pa.node()),
1148 'both created')
1117 1149 else:
1118 1150 a = ma[f]
1119 1151 fla = ma.flags(f)
1120 1152 nol = 'l' not in fl1 + fl2 + fla
1121 1153 if n2 == a and fl2 == fla:
1122 actions[f] = ('k', (), "remote unchanged")
1154 actions[f] = (ACTION_KEEP, (), 'remote unchanged')
1123 1155 elif n1 == a and fl1 == fla: # local unchanged - use remote
1124 1156 if n1 == n2: # optimization: keep local content
1125 actions[f] = ('e', (fl2,), "update permissions")
1157 actions[f] = (ACTION_EXEC, (fl2,), 'update permissions')
1126 1158 else:
1127 actions[f] = ('g', (fl2, False), "remote is newer")
1159 actions[f] = (ACTION_GET, (fl2, False),
1160 'remote is newer')
1128 1161 elif nol and n2 == a: # remote only changed 'x'
1129 actions[f] = ('e', (fl2,), "update permissions")
1162 actions[f] = (ACTION_EXEC, (fl2,), 'update permissions')
1130 1163 elif nol and n1 == a: # local only changed 'x'
1131 actions[f] = ('g', (fl1, False), "remote is newer")
1164 actions[f] = (ACTION_GET, (fl1, False), 'remote is newer')
1132 1165 else: # both changed something
1133 actions[f] = ('m', (f, f, f, False, pa.node()),
1134 "versions differ")
1166 actions[f] = (ACTION_MERGE, (f, f, f, False, pa.node()),
1167 'versions differ')
1135 1168 elif n1: # file exists only on local side
1136 1169 if f in copied:
1137 1170 pass # we'll deal with it on m2 side
1138 1171 elif f in movewithdir: # directory rename, move local
1139 1172 f2 = movewithdir[f]
1140 1173 if f2 in m2:
1141 actions[f2] = ('m', (f, f2, None, True, pa.node()),
1142 "remote directory rename, both created")
1174 actions[f2] = (ACTION_MERGE, (f, f2, None, True, pa.node()),
1175 'remote directory rename, both created')
1143 1176 else:
1144 actions[f2] = ('dm', (f, fl1),
1145 "remote directory rename - move from " + f)
1177 actions[f2] = (ACTION_DIR_RENAME_MOVE_LOCAL, (f, fl1),
1178 'remote directory rename - move from %s' % f)
1146 1179 elif f in copy:
1147 1180 f2 = copy[f]
1148 actions[f] = ('m', (f, f2, f2, False, pa.node()),
1149 "local copied/moved from " + f2)
1181 actions[f] = (ACTION_MERGE, (f, f2, f2, False, pa.node()),
1182 'local copied/moved from %s' % f2)
1150 1183 elif f in ma: # clean, a different, no remote
1151 1184 if n1 != ma[f]:
1152 1185 if acceptremote:
1153 actions[f] = ('r', None, "remote delete")
1186 actions[f] = (ACTION_REMOVE, None, 'remote delete')
1154 1187 else:
1155 actions[f] = ('cd', (f, None, f, False, pa.node()),
1156 "prompt changed/deleted")
1188 actions[f] = (ACTION_CHANGED_DELETED,
1189 (f, None, f, False, pa.node()),
1190 'prompt changed/deleted')
1157 1191 elif n1 == addednodeid:
1158 1192 # This extra 'a' is added by working copy manifest to mark
1159 1193 # the file as locally added. We should forget it instead of
1160 1194 # deleting it.
1161 actions[f] = ('f', None, "remote deleted")
1195 actions[f] = (ACTION_FORGET, None, 'remote deleted')
1162 1196 else:
1163 actions[f] = ('r', None, "other deleted")
1197 actions[f] = (ACTION_REMOVE, None, 'other deleted')
1164 1198 elif n2: # file exists only on remote side
1165 1199 if f in copied:
1166 1200 pass # we'll deal with it on m1 side
1167 1201 elif f in movewithdir:
1168 1202 f2 = movewithdir[f]
1169 1203 if f2 in m1:
1170 actions[f2] = ('m', (f2, f, None, False, pa.node()),
1171 "local directory rename, both created")
1204 actions[f2] = (ACTION_MERGE,
1205 (f2, f, None, False, pa.node()),
1206 'local directory rename, both created')
1172 1207 else:
1173 actions[f2] = ('dg', (f, fl2),
1174 "local directory rename - get from " + f)
1208 actions[f2] = (ACTION_LOCAL_DIR_RENAME_GET, (f, fl2),
1209 'local directory rename - get from %s' % f)
1175 1210 elif f in copy:
1176 1211 f2 = copy[f]
1177 1212 if f2 in m2:
1178 actions[f] = ('m', (f2, f, f2, False, pa.node()),
1179 "remote copied from " + f2)
1213 actions[f] = (ACTION_MERGE, (f2, f, f2, False, pa.node()),
1214 'remote copied from %s' % f2)
1180 1215 else:
1181 actions[f] = ('m', (f2, f, f2, True, pa.node()),
1182 "remote moved from " + f2)
1216 actions[f] = (ACTION_MERGE, (f2, f, f2, True, pa.node()),
1217 'remote moved from %s' % f2)
1183 1218 elif f not in ma:
1184 1219 # local unknown, remote created: the logic is described by the
1185 1220 # following table:
@@ -1193,12 +1228,12 b' def manifestmerge(repo, wctx, p2, pa, br'
1193 1228 # Checking whether the files are different is expensive, so we
1194 1229 # don't do that when we can avoid it.
1195 1230 if not force:
1196 actions[f] = ('c', (fl2,), "remote created")
1231 actions[f] = (ACTION_CREATED, (fl2,), 'remote created')
1197 1232 elif not branchmerge:
1198 actions[f] = ('c', (fl2,), "remote created")
1233 actions[f] = (ACTION_CREATED, (fl2,), 'remote created')
1199 1234 else:
1200 actions[f] = ('cm', (fl2, pa.node()),
1201 "remote created, get or merge")
1235 actions[f] = (ACTION_CREATED_MERGE, (fl2, pa.node()),
1236 'remote created, get or merge')
1202 1237 elif n2 != ma[f]:
1203 1238 df = None
1204 1239 for d in dirmove:
@@ -1207,13 +1242,15 b' def manifestmerge(repo, wctx, p2, pa, br'
1207 1242 df = dirmove[d] + f[len(d):]
1208 1243 break
1209 1244 if df is not None and df in m1:
1210 actions[df] = ('m', (df, f, f, False, pa.node()),
1211 "local directory rename - respect move from " + f)
1245 actions[df] = (ACTION_MERGE, (df, f, f, False, pa.node()),
1246 'local directory rename - respect move '
1247 'from %s' % f)
1212 1248 elif acceptremote:
1213 actions[f] = ('c', (fl2,), "remote recreating")
1249 actions[f] = (ACTION_CREATED, (fl2,), 'remote recreating')
1214 1250 else:
1215 actions[f] = ('dc', (None, f, f, False, pa.node()),
1216 "prompt deleted/changed")
1251 actions[f] = (ACTION_DELETED_CHANGED,
1252 (None, f, f, False, pa.node()),
1253 'prompt deleted/changed')
1217 1254
1218 1255 if repo.ui.configbool('experimental', 'merge.checkpathconflicts'):
1219 1256 # If we are merging, look for path conflicts.
@@ -1227,10 +1264,12 b' def _resolvetrivial(repo, wctx, mctx, an'
1227 1264 # We force a copy of actions.items() because we're going to mutate
1228 1265 # actions as we resolve trivial conflicts.
1229 1266 for f, (m, args, msg) in list(actions.items()):
1230 if m == 'cd' and f in ancestor and not wctx[f].cmp(ancestor[f]):
1267 if (m == ACTION_CHANGED_DELETED and f in ancestor
1268 and not wctx[f].cmp(ancestor[f])):
1231 1269 # local did change but ended up with same content
1232 actions[f] = 'r', None, "prompt same"
1233 elif m == 'dc' and f in ancestor and not mctx[f].cmp(ancestor[f]):
1270 actions[f] = ACTION_REMOVE, None, 'prompt same'
1271 elif (m == ACTION_DELETED_CHANGED and f in ancestor
1272 and not mctx[f].cmp(ancestor[f])):
1234 1273 # remote did change but ended up with same content
1235 1274 del actions[f] # don't get = keep local deleted
1236 1275
@@ -1294,18 +1333,18 b' def calculateupdates(repo, wctx, mctx, a'
1294 1333 if all(a == l[0] for a in l[1:]): # len(bids) is > 1
1295 1334 repo.ui.note(_(" %s: consensus for %s\n") % (f, m))
1296 1335 actions[f] = l[0]
1297 if m == 'dm':
1336 if m == ACTION_DIR_RENAME_MOVE_LOCAL:
1298 1337 dms.append(f)
1299 1338 continue
1300 1339 # If keep is an option, just do it.
1301 if 'k' in bids:
1340 if ACTION_KEEP in bids:
1302 1341 repo.ui.note(_(" %s: picking 'keep' action\n") % f)
1303 actions[f] = bids['k'][0]
1342 actions[f] = bids[ACTION_KEEP][0]
1304 1343 continue
1305 1344 # If there are gets and they all agree [how could they not?], do it.
1306 if 'g' in bids:
1307 ga0 = bids['g'][0]
1308 if all(a == ga0 for a in bids['g'][1:]):
1345 if ACTION_GET in bids:
1346 ga0 = bids[ACTION_GET][0]
1347 if all(a == ga0 for a in bids[ACTION_GET][1:]):
1309 1348 repo.ui.note(_(" %s: picking 'get' action\n") % f)
1310 1349 actions[f] = ga0
1311 1350 continue
@@ -1320,14 +1359,14 b' def calculateupdates(repo, wctx, mctx, a'
1320 1359 repo.ui.warn(_(' %s: ambiguous merge - picked %s action\n') %
1321 1360 (f, m))
1322 1361 actions[f] = l[0]
1323 if m == 'dm':
1362 if m == ACTION_DIR_RENAME_MOVE_LOCAL:
1324 1363 dms.append(f)
1325 1364 continue
1326 1365 # Work around 'dm' that can cause multiple actions for the same file
1327 1366 for f in dms:
1328 1367 dm, (f0, flags), msg = actions[f]
1329 assert dm == 'dm', dm
1330 if f0 in actions and actions[f0][0] == 'r':
1368 assert dm == ACTION_DIR_RENAME_MOVE_LOCAL, dm
1369 if f0 in actions and actions[f0][0] == ACTION_REMOVE:
1331 1370 # We have one bid for removing a file and another for moving it.
1332 1371 # These two could be merged as first move and then delete ...
1333 1372 # but instead drop moving and just delete.
@@ -1432,7 +1471,8 b' def _prefetchfiles(repo, ctx, actions):'
1432 1471 # Skipping 'a', 'am', 'f', 'r', 'dm', 'e', 'k', 'p' and 'pr', because they
1433 1472 # don't touch the context to be merged in. 'cd' is skipped, because
1434 1473 # changed/deleted never resolves to something from the remote side.
1435 oplist = [actions[a] for a in 'g dc dg m'.split()]
1474 oplist = [actions[a] for a in (ACTION_GET, ACTION_DELETED_CHANGED,
1475 ACTION_LOCAL_DIR_RENAME_GET, ACTION_MERGE)]
1436 1476 prefetch = scmutil.fileprefetchhooks
1437 1477 prefetch(repo, ctx, [f for sublist in oplist for f, args, msg in sublist])
1438 1478
@@ -1479,9 +1519,9 b' def applyupdates(repo, actions, wctx, mc'
1479 1519 l.sort()
1480 1520
1481 1521 # 'cd' and 'dc' actions are treated like other merge conflicts
1482 mergeactions = sorted(actions['cd'])
1483 mergeactions.extend(sorted(actions['dc']))
1484 mergeactions.extend(actions['m'])
1522 mergeactions = sorted(actions[ACTION_CHANGED_DELETED])
1523 mergeactions.extend(sorted(actions[ACTION_DELETED_CHANGED]))
1524 mergeactions.extend(actions[ACTION_MERGE])
1485 1525 for f, args, msg in mergeactions:
1486 1526 f1, f2, fa, move, anc = args
1487 1527 if f == '.hgsubstate': # merged internally
@@ -1516,14 +1556,15 b' def applyupdates(repo, actions, wctx, mc'
1516 1556 wctx[f].audit()
1517 1557 wctx[f].remove()
1518 1558
1519 numupdates = sum(len(l) for m, l in actions.items() if m != 'k')
1559 numupdates = sum(len(l) for m, l in actions.items()
1560 if m != ACTION_KEEP)
1520 1561 z = 0
1521 1562
1522 if [a for a in actions['r'] if a[0] == '.hgsubstate']:
1563 if [a for a in actions[ACTION_REMOVE] if a[0] == '.hgsubstate']:
1523 1564 subrepoutil.submerge(repo, wctx, mctx, wctx, overwrite, labels)
1524 1565
1525 1566 # record path conflicts
1526 for f, args, msg in actions['p']:
1567 for f, args, msg in actions[ACTION_PATH_CONFLICT]:
1527 1568 f1, fo = args
1528 1569 s = repo.ui.status
1529 1570 s(_("%s: path conflict - a file or link has the same name as a "
@@ -1543,14 +1584,14 b' def applyupdates(repo, actions, wctx, mc'
1543 1584
1544 1585 # remove in parallel (must come before resolving path conflicts and getting)
1545 1586 prog = worker.worker(repo.ui, cost, batchremove, (repo, wctx),
1546 actions['r'])
1587 actions[ACTION_REMOVE])
1547 1588 for i, item in prog:
1548 1589 z += i
1549 1590 progress(_updating, z, item=item, total=numupdates, unit=_files)
1550 removed = len(actions['r'])
1591 removed = len(actions[ACTION_REMOVE])
1551 1592
1552 1593 # resolve path conflicts (must come before getting)
1553 for f, args, msg in actions['pr']:
1594 for f, args, msg in actions[ACTION_PATH_CONFLICT_RESOLVE]:
1554 1595 repo.ui.debug(" %s: %s -> pr\n" % (f, msg))
1555 1596 f0, = args
1556 1597 if wctx[f0].lexists():
@@ -1563,40 +1604,40 b' def applyupdates(repo, actions, wctx, mc'
1563 1604
1564 1605 # get in parallel
1565 1606 prog = worker.worker(repo.ui, cost, batchget, (repo, mctx, wctx),
1566 actions['g'])
1607 actions[ACTION_GET])
1567 1608 for i, item in prog:
1568 1609 z += i
1569 1610 progress(_updating, z, item=item, total=numupdates, unit=_files)
1570 updated = len(actions['g'])
1611 updated = len(actions[ACTION_GET])
1571 1612
1572 if [a for a in actions['g'] if a[0] == '.hgsubstate']:
1613 if [a for a in actions[ACTION_GET] if a[0] == '.hgsubstate']:
1573 1614 subrepoutil.submerge(repo, wctx, mctx, wctx, overwrite, labels)
1574 1615
1575 1616 # forget (manifest only, just log it) (must come first)
1576 for f, args, msg in actions['f']:
1617 for f, args, msg in actions[ACTION_FORGET]:
1577 1618 repo.ui.debug(" %s: %s -> f\n" % (f, msg))
1578 1619 z += 1
1579 1620 progress(_updating, z, item=f, total=numupdates, unit=_files)
1580 1621
1581 1622 # re-add (manifest only, just log it)
1582 for f, args, msg in actions['a']:
1623 for f, args, msg in actions[ACTION_ADD]:
1583 1624 repo.ui.debug(" %s: %s -> a\n" % (f, msg))
1584 1625 z += 1
1585 1626 progress(_updating, z, item=f, total=numupdates, unit=_files)
1586 1627
1587 1628 # re-add/mark as modified (manifest only, just log it)
1588 for f, args, msg in actions['am']:
1629 for f, args, msg in actions[ACTION_ADD_MODIFIED]:
1589 1630 repo.ui.debug(" %s: %s -> am\n" % (f, msg))
1590 1631 z += 1
1591 1632 progress(_updating, z, item=f, total=numupdates, unit=_files)
1592 1633
1593 1634 # keep (noop, just log it)
1594 for f, args, msg in actions['k']:
1635 for f, args, msg in actions[ACTION_KEEP]:
1595 1636 repo.ui.debug(" %s: %s -> k\n" % (f, msg))
1596 1637 # no progress
1597 1638
1598 1639 # directory rename, move local
1599 for f, args, msg in actions['dm']:
1640 for f, args, msg in actions[ACTION_DIR_RENAME_MOVE_LOCAL]:
1600 1641 repo.ui.debug(" %s: %s -> dm\n" % (f, msg))
1601 1642 z += 1
1602 1643 progress(_updating, z, item=f, total=numupdates, unit=_files)
@@ -1608,7 +1649,7 b' def applyupdates(repo, actions, wctx, mc'
1608 1649 updated += 1
1609 1650
1610 1651 # local directory rename, get
1611 for f, args, msg in actions['dg']:
1652 for f, args, msg in actions[ACTION_LOCAL_DIR_RENAME_GET]:
1612 1653 repo.ui.debug(" %s: %s -> dg\n" % (f, msg))
1613 1654 z += 1
1614 1655 progress(_updating, z, item=f, total=numupdates, unit=_files)
@@ -1618,7 +1659,7 b' def applyupdates(repo, actions, wctx, mc'
1618 1659 updated += 1
1619 1660
1620 1661 # exec
1621 for f, args, msg in actions['e']:
1662 for f, args, msg in actions[ACTION_EXEC]:
1622 1663 repo.ui.debug(" %s: %s -> e\n" % (f, msg))
1623 1664 z += 1
1624 1665 progress(_updating, z, item=f, total=numupdates, unit=_files)
@@ -1696,17 +1737,17 b' def applyupdates(repo, actions, wctx, mc'
1696 1737
1697 1738 extraactions = ms.actions()
1698 1739 if extraactions:
1699 mfiles = set(a[0] for a in actions['m'])
1740 mfiles = set(a[0] for a in actions[ACTION_MERGE])
1700 1741 for k, acts in extraactions.iteritems():
1701 1742 actions[k].extend(acts)
1702 # Remove these files from actions['m'] as well. This is important
1703 # because in recordupdates, files in actions['m'] are processed
1704 # after files in other actions, and the merge driver might add
1705 # files to those actions via extraactions above. This can lead to a
1706 # file being recorded twice, with poor results. This is especially
1707 # problematic for actions['r'] (currently only possible with the
1708 # merge driver in the initial merge process; interrupted merges
1709 # don't go through this flow).
1743 # Remove these files from actions[ACTION_MERGE] as well. This is
1744 # important because in recordupdates, files in actions[ACTION_MERGE]
1745 # are processed after files in other actions, and the merge driver
1746 # might add files to those actions via extraactions above. This can
1747 # lead to a file being recorded twice, with poor results. This is
1748 # especially problematic for actions[ACTION_REMOVE] (currently only
1749 # possible with the merge driver in the initial merge process;
1750 # interrupted merges don't go through this flow).
1710 1751 #
1711 1752 # The real fix here is to have indexes by both file and action so
1712 1753 # that when the action for a file is changed it is automatically
@@ -1717,7 +1758,8 b' def applyupdates(repo, actions, wctx, mc'
1717 1758 # those lists aren't consulted again.
1718 1759 mfiles.difference_update(a[0] for a in acts)
1719 1760
1720 actions['m'] = [a for a in actions['m'] if a[0] in mfiles]
1761 actions[ACTION_MERGE] = [a for a in actions[ACTION_MERGE]
1762 if a[0] in mfiles]
1721 1763
1722 1764 progress(_updating, None, total=numupdates, unit=_files)
1723 1765 return updateresult(updated, merged, removed, unresolved)
@@ -1725,18 +1767,18 b' def applyupdates(repo, actions, wctx, mc'
1725 1767 def recordupdates(repo, actions, branchmerge):
1726 1768 "record merge actions to the dirstate"
1727 1769 # remove (must come first)
1728 for f, args, msg in actions.get('r', []):
1770 for f, args, msg in actions.get(ACTION_REMOVE, []):
1729 1771 if branchmerge:
1730 1772 repo.dirstate.remove(f)
1731 1773 else:
1732 1774 repo.dirstate.drop(f)
1733 1775
1734 1776 # forget (must come first)
1735 for f, args, msg in actions.get('f', []):
1777 for f, args, msg in actions.get(ACTION_FORGET, []):
1736 1778 repo.dirstate.drop(f)
1737 1779
1738 1780 # resolve path conflicts
1739 for f, args, msg in actions.get('pr', []):
1781 for f, args, msg in actions.get(ACTION_PATH_CONFLICT_RESOLVE, []):
1740 1782 f0, = args
1741 1783 origf0 = repo.dirstate.copied(f0) or f0
1742 1784 repo.dirstate.add(f)
@@ -1747,33 +1789,33 b' def recordupdates(repo, actions, branchm'
1747 1789 repo.dirstate.drop(f0)
1748 1790
1749 1791 # re-add
1750 for f, args, msg in actions.get('a', []):
1792 for f, args, msg in actions.get(ACTION_ADD, []):
1751 1793 repo.dirstate.add(f)
1752 1794
1753 1795 # re-add/mark as modified
1754 for f, args, msg in actions.get('am', []):
1796 for f, args, msg in actions.get(ACTION_ADD_MODIFIED, []):
1755 1797 if branchmerge:
1756 1798 repo.dirstate.normallookup(f)
1757 1799 else:
1758 1800 repo.dirstate.add(f)
1759 1801
1760 1802 # exec change
1761 for f, args, msg in actions.get('e', []):
1803 for f, args, msg in actions.get(ACTION_EXEC, []):
1762 1804 repo.dirstate.normallookup(f)
1763 1805
1764 1806 # keep
1765 for f, args, msg in actions.get('k', []):
1807 for f, args, msg in actions.get(ACTION_KEEP, []):
1766 1808 pass
1767 1809
1768 1810 # get
1769 for f, args, msg in actions.get('g', []):
1811 for f, args, msg in actions.get(ACTION_GET, []):
1770 1812 if branchmerge:
1771 1813 repo.dirstate.otherparent(f)
1772 1814 else:
1773 1815 repo.dirstate.normal(f)
1774 1816
1775 1817 # merge
1776 for f, args, msg in actions.get('m', []):
1818 for f, args, msg in actions.get(ACTION_MERGE, []):
1777 1819 f1, f2, fa, move, anc = args
1778 1820 if branchmerge:
1779 1821 # We've done a branch merge, mark this file as merged
@@ -1798,7 +1840,7 b' def recordupdates(repo, actions, branchm'
1798 1840 repo.dirstate.drop(f1)
1799 1841
1800 1842 # directory rename, move local
1801 for f, args, msg in actions.get('dm', []):
1843 for f, args, msg in actions.get(ACTION_DIR_RENAME_MOVE_LOCAL, []):
1802 1844 f0, flag = args
1803 1845 if branchmerge:
1804 1846 repo.dirstate.add(f)
@@ -1809,7 +1851,7 b' def recordupdates(repo, actions, branchm'
1809 1851 repo.dirstate.drop(f0)
1810 1852
1811 1853 # directory rename, get
1812 for f, args, msg in actions.get('dg', []):
1854 for f, args, msg in actions.get(ACTION_LOCAL_DIR_RENAME_GET, []):
1813 1855 f0, flag = args
1814 1856 if branchmerge:
1815 1857 repo.dirstate.add(f)
@@ -1982,7 +2024,8 b' def update(repo, node, branchmerge, forc'
1982 2024
1983 2025 if updatecheck == 'noconflict':
1984 2026 for f, (m, args, msg) in actionbyfile.iteritems():
1985 if m not in ('g', 'k', 'e', 'r', 'pr'):
2027 if m not in (ACTION_GET, ACTION_KEEP, ACTION_EXEC,
2028 ACTION_REMOVE, ACTION_PATH_CONFLICT_RESOLVE):
1986 2029 msg = _("conflicting changes")
1987 2030 hint = _("commit or update --clean to discard changes")
1988 2031 raise error.Abort(msg, hint=hint)
@@ -1995,30 +2038,45 b' def update(repo, node, branchmerge, forc'
1995 2038 m, args, msg = actionbyfile[f]
1996 2039 prompts = filemerge.partextras(labels)
1997 2040 prompts['f'] = f
1998 if m == 'cd':
2041 if m == ACTION_CHANGED_DELETED:
1999 2042 if repo.ui.promptchoice(
2000 2043 _("local%(l)s changed %(f)s which other%(o)s deleted\n"
2001 2044 "use (c)hanged version or (d)elete?"
2002 2045 "$$ &Changed $$ &Delete") % prompts, 0):
2003 actionbyfile[f] = ('r', None, "prompt delete")
2046 actionbyfile[f] = (ACTION_REMOVE, None, 'prompt delete')
2004 2047 elif f in p1:
2005 actionbyfile[f] = ('am', None, "prompt keep")
2048 actionbyfile[f] = (ACTION_ADD_MODIFIED, None, 'prompt keep')
2006 2049 else:
2007 actionbyfile[f] = ('a', None, "prompt keep")
2008 elif m == 'dc':
2050 actionbyfile[f] = (ACTION_ADD, None, 'prompt keep')
2051 elif m == ACTION_DELETED_CHANGED:
2009 2052 f1, f2, fa, move, anc = args
2010 2053 flags = p2[f2].flags()
2011 2054 if repo.ui.promptchoice(
2012 2055 _("other%(o)s changed %(f)s which local%(l)s deleted\n"
2013 2056 "use (c)hanged version or leave (d)eleted?"
2014 2057 "$$ &Changed $$ &Deleted") % prompts, 0) == 0:
2015 actionbyfile[f] = ('g', (flags, False), "prompt recreating")
2058 actionbyfile[f] = (ACTION_GET, (flags, False),
2059 'prompt recreating')
2016 2060 else:
2017 2061 del actionbyfile[f]
2018 2062
2019 2063 # Convert to dictionary-of-lists format
2020 2064 actions = dict((m, [])
2021 for m in 'a am f g cd dc r dm dg m e k p pr'.split())
2065 for m in (
2066 ACTION_ADD,
2067 ACTION_ADD_MODIFIED,
2068 ACTION_FORGET,
2069 ACTION_GET,
2070 ACTION_CHANGED_DELETED,
2071 ACTION_DELETED_CHANGED,
2072 ACTION_REMOVE,
2073 ACTION_DIR_RENAME_MOVE_LOCAL,
2074 ACTION_LOCAL_DIR_RENAME_GET,
2075 ACTION_MERGE,
2076 ACTION_EXEC,
2077 ACTION_KEEP,
2078 ACTION_PATH_CONFLICT,
2079 ACTION_PATH_CONFLICT_RESOLVE))
2022 2080 for f, (m, args, msg) in actionbyfile.iteritems():
2023 2081 if m not in actions:
2024 2082 actions[m] = []
@@ -2081,7 +2139,7 b' def update(repo, node, branchmerge, forc'
2081 2139 if (fsmonitorwarning
2082 2140 and not fsmonitorenabled
2083 2141 and p1.node() == nullid
2084 and len(actions['g']) >= fsmonitorthreshold
2142 and len(actions[ACTION_GET]) >= fsmonitorthreshold
2085 2143 and pycompat.sysplatform.startswith(('linux', 'darwin'))):
2086 2144 repo.ui.warn(
2087 2145 _('(warning: large working directory being used without '
General Comments 0
You need to be logged in to leave comments. Login now