From patchwork Tue Oct 24 17:57:55 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: D1226: merge: check created file dirs for path conflicts only once From: phabricator X-Patchwork-Id: 25277 Message-Id: To: mercurial-devel@mercurial-scm.org Date: Tue, 24 Oct 2017 17:57:55 +0000 mbthomas created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY In large repositories, updates involving the creation of many files check the same directories repeatedly. Move these checks out to a separate loop to avoid repeated checks that hit the filesystem. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D1226 AFFECTED FILES mercurial/merge.py CHANGE DETAILS To: mbthomas, #hg-reviewers Cc: mercurial-devel diff --git a/mercurial/merge.py b/mercurial/merge.py --- a/mercurial/merge.py +++ b/mercurial/merge.py @@ -914,34 +914,21 @@ # 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) @@ -953,6 +940,24 @@ 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: