comparison mercurial/merge.py @ 45345:e5b4061f32be

mergeresult: add `files()` and use it `files()` will return a list of files on which an action needs to be performed. This is a step to stop exposing the underlying map to the user of this object. Differential Revision: https://phab.mercurial-scm.org/D8887
author Pulkit Goyal <7895pulkit@gmail.com>
date Wed, 05 Aug 2020 15:41:23 +0530
parents 4c6004afd836
children 3c783ff08d40
comparison
equal deleted inserted replaced
45344:4c6004afd836 45345:e5b4061f32be
149 abortconflicts.update(conflicts) 149 abortconflicts.update(conflicts)
150 elif config == b'warn': 150 elif config == b'warn':
151 warnconflicts.update(conflicts) 151 warnconflicts.update(conflicts)
152 152
153 checkunknowndirs = _unknowndirschecker() 153 checkunknowndirs = _unknowndirschecker()
154 for f, args, msg in mresult.getactions( 154 for f in mresult.files(
155 [ 155 (
156 mergestatemod.ACTION_CREATED, 156 mergestatemod.ACTION_CREATED,
157 mergestatemod.ACTION_DELETED_CHANGED, 157 mergestatemod.ACTION_DELETED_CHANGED,
158 ] 158 )
159 ): 159 ):
160 if _checkunknownfile(repo, wctx, mctx, f): 160 if _checkunknownfile(repo, wctx, mctx, f):
161 fileconflicts.add(f) 161 fileconflicts.add(f)
162 elif pathconfig and f not in wctx: 162 elif pathconfig and f not in wctx:
163 path = checkunknowndirs(repo, wctx, f) 163 path = checkunknowndirs(repo, wctx, f)
297 # If the repo is narrowed, filter out files outside the narrowspec. 297 # If the repo is narrowed, filter out files outside the narrowspec.
298 narrowmatch = repo.narrowmatch() 298 narrowmatch = repo.narrowmatch()
299 if not narrowmatch.always(): 299 if not narrowmatch.always():
300 pmmf = set(wmf.walk(narrowmatch)) 300 pmmf = set(wmf.walk(narrowmatch))
301 if mresult: 301 if mresult:
302 for f, actionsfortype in pycompat.iteritems(mresult.actions): 302 for f in list(mresult.files()):
303 if not narrowmatch(f): 303 if not narrowmatch(f):
304 mresult.removefile(f) 304 mresult.removefile(f)
305 else: 305 else:
306 # build provisional merged manifest up 306 # build provisional merged manifest up
307 pmmf = set(wmf) 307 pmmf = set(wmf)
308 308
309 if mresult: 309 if mresult:
310 # KEEP and EXEC are no-op 310 # KEEP and EXEC are no-op
311 for f, args, msg in mresult.getactions( 311 for f in mresult.files(
312 ( 312 (
313 mergestatemod.ACTION_ADD, 313 mergestatemod.ACTION_ADD,
314 mergestatemod.ACTION_ADD_MODIFIED, 314 mergestatemod.ACTION_ADD_MODIFIED,
315 mergestatemod.ACTION_FORGET, 315 mergestatemod.ACTION_FORGET,
316 mergestatemod.ACTION_GET, 316 mergestatemod.ACTION_GET,
317 mergestatemod.ACTION_CHANGED_DELETED, 317 mergestatemod.ACTION_CHANGED_DELETED,
318 mergestatemod.ACTION_DELETED_CHANGED, 318 mergestatemod.ACTION_DELETED_CHANGED,
319 ) 319 )
320 ): 320 ):
321 pmmf.add(f) 321 pmmf.add(f)
322 for f, args, msg in mresult.getactions([mergestatemod.ACTION_REMOVE]): 322 for f in mresult.files((mergestatemod.ACTION_REMOVE,)):
323 pmmf.discard(f) 323 pmmf.discard(f)
324 for f, args, msg in mresult.getactions( 324 for f, args, msg in mresult.getactions(
325 [mergestatemod.ACTION_DIR_RENAME_MOVE_LOCAL] 325 [mergestatemod.ACTION_DIR_RENAME_MOVE_LOCAL]
326 ): 326 ):
327 f2, flags = args 327 f2, flags = args
328 pmmf.discard(f2) 328 pmmf.discard(f2)
329 pmmf.add(f) 329 pmmf.add(f)
330 for f, args, msg in mresult.getactions( 330 for f in mresult.files((mergestatemod.ACTION_LOCAL_DIR_RENAME_GET,)):
331 [mergestatemod.ACTION_LOCAL_DIR_RENAME_GET]
332 ):
333 pmmf.add(f) 331 pmmf.add(f)
334 for f, args, msg in mresult.getactions([mergestatemod.ACTION_MERGE]): 332 for f, args, msg in mresult.getactions([mergestatemod.ACTION_MERGE]):
335 f1, f2, fa, move, anc = args 333 f1, f2, fa, move, anc = args
336 if move: 334 if move:
337 pmmf.discard(f1) 335 pmmf.discard(f1)
412 createdfiledirs = set() 410 createdfiledirs = set()
413 411
414 # The set of files deleted by all the actions. 412 # The set of files deleted by all the actions.
415 deletedfiles = set() 413 deletedfiles = set()
416 414
417 for (f, args, msg) in mresult.getactions( 415 for f in mresult.files(
418 ( 416 (
419 mergestatemod.ACTION_CREATED, 417 mergestatemod.ACTION_CREATED,
420 mergestatemod.ACTION_DELETED_CHANGED, 418 mergestatemod.ACTION_DELETED_CHANGED,
421 mergestatemod.ACTION_MERGE, 419 mergestatemod.ACTION_MERGE,
422 mergestatemod.ACTION_CREATED_MERGE, 420 mergestatemod.ACTION_CREATED_MERGE,
428 # The file aliases a local directory. This might be ok if all 426 # The file aliases a local directory. This might be ok if all
429 # the files in the local directory are being deleted. This 427 # the files in the local directory are being deleted. This
430 # will be checked once we know what all the deleted files are. 428 # will be checked once we know what all the deleted files are.
431 remoteconflicts.add(f) 429 remoteconflicts.add(f)
432 # Track the names of all deleted files. 430 # Track the names of all deleted files.
433 for (f, args, msg) in mresult.getactions((mergestatemod.ACTION_REMOVE,)): 431 for f in mresult.files((mergestatemod.ACTION_REMOVE,)):
434 deletedfiles.add(f) 432 deletedfiles.add(f)
435 for (f, args, msg) in mresult.getactions((mergestatemod.ACTION_MERGE,)): 433 for (f, args, msg) in mresult.getactions((mergestatemod.ACTION_MERGE,)):
436 f1, f2, fa, move, anc = args 434 f1, f2, fa, move, anc = args
437 if move: 435 if move:
438 deletedfiles.add(f1) 436 deletedfiles.add(f1)
468 466
469 # Rename all local conflicting files that have not been deleted. 467 # Rename all local conflicting files that have not been deleted.
470 for p in localconflicts: 468 for p in localconflicts:
471 if p not in deletedfiles: 469 if p not in deletedfiles:
472 ctxname = bytes(wctx).rstrip(b'+') 470 ctxname = bytes(wctx).rstrip(b'+')
473 pnew = util.safename(p, ctxname, wctx, set(mresult.actions.keys())) 471 pnew = util.safename(p, ctxname, wctx, set(mresult.files()))
474 porig = wctx[p].copysource() or p 472 porig = wctx[p].copysource() or p
475 mresult.addfile( 473 mresult.addfile(
476 pnew, 474 pnew,
477 mergestatemod.ACTION_PATH_CONFLICT_RESOLVE, 475 mergestatemod.ACTION_PATH_CONFLICT_RESOLVE,
478 (p, porig), 476 (p, porig),
489 # Check if all files in the conflicting directories have been removed. 487 # Check if all files in the conflicting directories have been removed.
490 ctxname = bytes(mctx).rstrip(b'+') 488 ctxname = bytes(mctx).rstrip(b'+')
491 for f, p in _filesindirs(repo, mf, remoteconflicts): 489 for f, p in _filesindirs(repo, mf, remoteconflicts):
492 if f not in deletedfiles: 490 if f not in deletedfiles:
493 m, args, msg = mresult.getfile(p) 491 m, args, msg = mresult.getfile(p)
494 pnew = util.safename( 492 pnew = util.safename(p, ctxname, wctx, set(mresult.files()))
495 p, ctxname, wctx, set(mresult.actions.keys())
496 )
497 if m in ( 493 if m in (
498 mergestatemod.ACTION_DELETED_CHANGED, 494 mergestatemod.ACTION_DELETED_CHANGED,
499 mergestatemod.ACTION_MERGE, 495 mergestatemod.ACTION_MERGE,
500 ): 496 ):
501 # Action was merge, just update target. 497 # Action was merge, just update target.
619 returns default_return if the file is not present """ 615 returns default_return if the file is not present """
620 if filename in self._filemapping: 616 if filename in self._filemapping:
621 return self._filemapping[filename] 617 return self._filemapping[filename]
622 return default_return 618 return default_return
623 619
620 def files(self, actions=None):
621 """ returns files on which provided action needs to perfromed
622
623 If actions is None, all files are returned
624 """
625 # TODO: think whether we should return renamedelete and
626 # diverge filenames also
627 if actions is None:
628 for f in self._filemapping:
629 yield f
630
631 else:
632 for a in actions:
633 for f in self._actionmapping[a]:
634 yield f
635
624 def removefile(self, filename): 636 def removefile(self, filename):
625 """ removes a file from the mergeresult object as the file might 637 """ removes a file from the mergeresult object as the file might
626 not merging anymore """ 638 not merging anymore """
627 action, data, message = self._filemapping[filename] 639 action, data, message = self._filemapping[filename]
628 del self._filemapping[filename] 640 del self._filemapping[filename]
1027 def _resolvetrivial(repo, wctx, mctx, ancestor, mresult): 1039 def _resolvetrivial(repo, wctx, mctx, ancestor, mresult):
1028 """Resolves false conflicts where the nodeid changed but the content 1040 """Resolves false conflicts where the nodeid changed but the content
1029 remained the same.""" 1041 remained the same."""
1030 # We force a copy of actions.items() because we're going to mutate 1042 # We force a copy of actions.items() because we're going to mutate
1031 # actions as we resolve trivial conflicts. 1043 # actions as we resolve trivial conflicts.
1032 for f, args, msg in list( 1044 for f in list(mresult.files((mergestatemod.ACTION_CHANGED_DELETED,))):
1033 mresult.getactions([mergestatemod.ACTION_CHANGED_DELETED])
1034 ):
1035 if f in ancestor and not wctx[f].cmp(ancestor[f]): 1045 if f in ancestor and not wctx[f].cmp(ancestor[f]):
1036 # local did change but ended up with same content 1046 # local did change but ended up with same content
1037 mresult.addfile( 1047 mresult.addfile(
1038 f, mergestatemod.ACTION_REMOVE, None, b'prompt same' 1048 f, mergestatemod.ACTION_REMOVE, None, b'prompt same'
1039 ) 1049 )
1040 1050
1041 for f, args, msg in list( 1051 for f in list(mresult.files((mergestatemod.ACTION_DELETED_CHANGED,))):
1042 mresult.getactions([mergestatemod.ACTION_DELETED_CHANGED])
1043 ):
1044 if f in ancestor and not mctx[f].cmp(ancestor[f]): 1052 if f in ancestor and not mctx[f].cmp(ancestor[f]):
1045 # remote did change but ended up with same content 1053 # remote did change but ended up with same content
1046 mresult.removefile(f) # don't get = keep local deleted 1054 mresult.removefile(f) # don't get = keep local deleted
1047 1055
1048 1056
1302 of merge actions. ``ctx`` is the context being merged in.""" 1310 of merge actions. ``ctx`` is the context being merged in."""
1303 1311
1304 # Skipping 'a', 'am', 'f', 'r', 'dm', 'e', 'k', 'p' and 'pr', because they 1312 # Skipping 'a', 'am', 'f', 'r', 'dm', 'e', 'k', 'p' and 'pr', because they
1305 # don't touch the context to be merged in. 'cd' is skipped, because 1313 # don't touch the context to be merged in. 'cd' is skipped, because
1306 # changed/deleted never resolves to something from the remote side. 1314 # changed/deleted never resolves to something from the remote side.
1307 files = [] 1315 files = mresult.files(
1308 for f, args, msg in mresult.getactions(
1309 [ 1316 [
1310 mergestatemod.ACTION_GET, 1317 mergestatemod.ACTION_GET,
1311 mergestatemod.ACTION_DELETED_CHANGED, 1318 mergestatemod.ACTION_DELETED_CHANGED,
1312 mergestatemod.ACTION_LOCAL_DIR_RENAME_GET, 1319 mergestatemod.ACTION_LOCAL_DIR_RENAME_GET,
1313 mergestatemod.ACTION_MERGE, 1320 mergestatemod.ACTION_MERGE,
1314 ] 1321 ]
1315 ): 1322 )
1316 files.append(f)
1317 1323
1318 prefetch = scmutil.prefetchfiles 1324 prefetch = scmutil.prefetchfiles
1319 matchfiles = scmutil.matchfiles 1325 matchfiles = scmutil.matchfiles
1320 prefetch( 1326 prefetch(
1321 repo, [(ctx.rev(), matchfiles(repo, files),)], 1327 repo, [(ctx.rev(), matchfiles(repo, files),)],