D4129: includematcher: separate "parents" from "dirs"
spectral (Kyle Lippincott)
phabricator at mercurial-scm.org
Mon Aug 6 18:50:14 UTC 2018
spectral created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.
REVISION SUMMARY
A future patch will make use of this separation so that we can make more
intelligent decisions about what to investigate/load when the matcher is in use.
Currently, even with this patch, we typically use the 'visitdir' call to identify if
we can skip some directory, something along the lines of:
for f in all_items:
if match.visitdir(f):
<do stuff>
This can be slower than we'd like if there are a lot of items; it requires N
calls to match.visitdir in the best case. Commonly, especially with 'narrow',
we have a situation where we do some work for the directory, possibly just
loading it from disk (when using treemanifests) and then check if we should be
interacting with it at all, which can be a huge slowdown in some pathological
cases.
REPOSITORY
rHG Mercurial
REVISION DETAIL
https://phab.mercurial-scm.org/D4129
AFFECTED FILES
mercurial/match.py
CHANGE DETAILS
diff --git a/mercurial/match.py b/mercurial/match.py
--- a/mercurial/match.py
+++ b/mercurial/match.py
@@ -445,18 +445,22 @@
self._pats, self.matchfn = _buildmatch(kindpats, '(?:/|$)',
listsubrepos, root)
self._prefix = _prefix(kindpats)
- roots, dirs = _rootsanddirs(kindpats)
+ roots, dirs, parents = _rootsdirsandparents(kindpats)
# roots are directories which are recursively included.
self._roots = set(roots)
# dirs are directories which are non-recursively included.
self._dirs = set(dirs)
+ # parents are directories which are non-recursively included because
+ # they are needed to get to items in _dirs or _roots.
+ self._parents = set(parents)
def visitdir(self, dir):
if self._prefix and dir in self._roots:
return 'all'
return ('.' in self._roots or
dir in self._roots or
dir in self._dirs or
+ dir in self._parents or
any(parentdir in self._roots
for parentdir in util.finddirs(dir)))
@@ -1004,40 +1008,41 @@
roots, dirs = _patternrootsanddirs(kindpats)
return roots
-def _rootsanddirs(kindpats):
+def _rootsdirsandparents(kindpats):
'''Returns roots and exact directories from patterns.
roots are directories to match recursively, whereas exact directories should
be matched non-recursively. The returned (roots, dirs) tuple will also
include directories that need to be implicitly considered as either, such as
parent directories.
- >>> _rootsanddirs(
+ >>> _rootsdirsandparents(
... [(b'glob', b'g/h/*', b''), (b'glob', b'g/h', b''),
... (b'glob', b'g*', b'')])
(['g/h', 'g/h', '.'], ['g', '.'])
- >>> _rootsanddirs(
+ >>> _rootsdirsandparents(
... [(b'rootfilesin', b'g/h', b''), (b'rootfilesin', b'', b'')])
([], ['g/h', '.', 'g', '.'])
- >>> _rootsanddirs(
+ >>> _rootsdirsandparents(
... [(b'relpath', b'r', b''), (b'path', b'p/p', b''),
... (b'path', b'', b'')])
(['r', 'p/p', '.'], ['p', '.'])
- >>> _rootsanddirs(
+ >>> _rootsdirsandparents(
... [(b'relglob', b'rg*', b''), (b're', b're/', b''),
... (b'relre', b'rr', b'')])
(['.', '.', '.'], ['.'])
'''
r, d = _patternrootsanddirs(kindpats)
+ p = []
# Append the parents as non-recursive/exact directories, since they must be
# scanned to get to either the roots or the other exact directories.
- d.extend(util.dirs(d))
- d.extend(util.dirs(r))
+ p.extend(util.dirs(d))
+ p.extend(util.dirs(r))
# util.dirs() does not include the root directory, so add it manually
- d.append('.')
+ p.append('.')
- return r, d
+ return r, d, p
def _explicitfiles(kindpats):
'''Returns the potential explicit filenames from the patterns.
To: spectral, #hg-reviewers
Cc: mercurial-devel
More information about the Mercurial-devel
mailing list