copies: avoid materializing a full directory map during copy tracing
Materializing a full copy of every directory in a treemanifest repo can be quite
expensive, even with a narrow matcher. For flat manifest repos, this should be
equivalent - it will still materialize (and cache) a dict of all of the dirs
inside of the manifest object, we just don't get a copy of it.
In a repo I have here, this brings the time for a simple rebase from 11.197s to
4.609s.
Differential Revision: https://phab.mercurial-scm.org/D9503
--- a/mercurial/copies.py Wed Dec 02 15:39:01 2020 -0800
+++ b/mercurial/copies.py Wed Dec 02 11:05:53 2020 -0800
@@ -930,7 +930,6 @@
addedfiles: added files on the other side (compared to ctx)
"""
# generate a directory move map
- d = ctx.dirs()
invalid = set()
dirmove = {}
@@ -941,7 +940,7 @@
if dsrc in invalid:
# already seen to be uninteresting
continue
- elif dsrc in d and ddst in d:
+ elif ctx.hasdir(dsrc) and ctx.hasdir(ddst):
# directory wasn't entirely moved locally
invalid.add(dsrc)
elif dsrc in dirmove and dirmove[dsrc] != ddst:
@@ -954,7 +953,7 @@
for i in invalid:
if i in dirmove:
del dirmove[i]
- del d, invalid
+ del invalid
if not dirmove:
return {}, {}