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),)], |