# HG changeset patch # User Mark Thomas # Date 2017-11-24 20:53:58 # Node ID a92b9f8e11ba330614cdfd6af0e03b15c1ff3797 # Parent b85962350bb31bc33c917866bea67918c24ff2b3 merge: check created file dirs for path conflicts only once (issue5716) In large repositories, updates involving the creation of many files check the same directories repeatedly in the wctx manifest. Move these checks out to a separate loop to avoid repeated checks hitting the manifest. Differential Revision: https://phab.mercurial-scm.org/D1226 diff --git a/mercurial/merge.py b/mercurial/merge.py --- a/mercurial/merge.py +++ b/mercurial/merge.py @@ -915,34 +915,21 @@ def checkpathconflicts(repo, wctx, mctx, # can't be updated to cleanly. invalidconflicts = set() + # The set of directories that contain files that are being created. + createdfiledirs = set() + # The set of files deleted by all the actions. deletedfiles = set() for f, (m, args, msg) in actions.items(): if m in ('c', 'dc', 'm', 'cm'): # This action may create a new local file. + createdfiledirs.update(util.finddirs(f)) if mf.hasdir(f): # The file aliases a local directory. This might be ok if all # the files in the local directory are being deleted. This # will be checked once we know what all the deleted files are. remoteconflicts.add(f) - for p in util.finddirs(f): - if p in mf: - if p in mctx: - # The file is in a directory which aliases both a local - # and a remote file. This is an internal inconsistency - # within the remote manifest. - invalidconflicts.add(p) - else: - # The file is in a directory which aliases a local file. - # We will need to rename the local file. - localconflicts.add(p) - if p in actions and actions[p][0] in ('c', 'dc', 'm', 'cm'): - # The file is in a directory which aliases a remote file. - # This is an internal inconsistency within the remote - # manifest. - invalidconflicts.add(p) - # Track the names of all deleted files. if m == 'r': deletedfiles.add(f) @@ -954,6 +941,24 @@ def checkpathconflicts(repo, wctx, mctx, f2, flags = args deletedfiles.add(f2) + # Check all directories that contain created files for path conflicts. + for p in createdfiledirs: + if p in mf: + if p in mctx: + # A file is in a directory which aliases both a local + # and a remote file. This is an internal inconsistency + # within the remote manifest. + invalidconflicts.add(p) + else: + # A file is in a directory which aliases a local file. + # We will need to rename the local file. + localconflicts.add(p) + if p in actions and actions[p][0] in ('c', 'dc', 'm', 'cm'): + # The file is in a directory which aliases a remote file. + # This is an internal inconsistency within the remote + # manifest. + invalidconflicts.add(p) + # Rename all local conflicting files that have not been deleted. for p in localconflicts: if p not in deletedfiles: