# HG changeset patch # User Durham Goode # Date 2017-05-03 17:30:57 # Node ID 6dea1701f170f38f931759267d2bbd3f49de92a5 # Parent 35a69efbf190a9538c6ac4053edd0812755fc3ce match: make subinclude construction lazy The matcher subinclude functionality allows us to have .hgignore files that include subdirectory hgignore files. Today it parses the entire repo at once, even if we only need to test a file in one subdirectory. This patch makes the subinclude tree creation lazy, which speeds up matcher creation significantly in large repos with very large trees of ignore patterns. diff --git a/mercurial/match.py b/mercurial/match.py --- a/mercurial/match.py +++ b/mercurial/match.py @@ -52,7 +52,7 @@ def _expandsets(kindpats, ctx, listsubre return fset, other def _expandsubinclude(kindpats, root): - '''Returns the list of subinclude matchers and the kindpats without the + '''Returns the list of subinclude matcher args and the kindpats without the subincludes in it.''' relmatchers = [] other = [] @@ -64,12 +64,12 @@ def _expandsubinclude(kindpats, root): path = pathutil.join(sourceroot, pat) newroot = pathutil.dirname(path) - relmatcher = match(newroot, '', [], ['include:%s' % path]) + matcherargs = (newroot, '', [], ['include:%s' % path]) prefix = pathutil.canonpath(root, root, newroot) if prefix: prefix += '/' - relmatchers.append((prefix, relmatcher)) + relmatchers.append((prefix, matcherargs)) else: other.append((kind, pat, source)) @@ -584,10 +584,17 @@ def _buildmatch(ctx, kindpats, globsuffi subincludes, kindpats = _expandsubinclude(kindpats, root) if subincludes: + submatchers = {} def matchsubinclude(f): - for prefix, mf in subincludes: - if f.startswith(prefix) and mf(f[len(prefix):]): - return True + for prefix, matcherargs in subincludes: + if f.startswith(prefix): + mf = submatchers.get(prefix) + if mf is None: + mf = match(*matcherargs) + submatchers[prefix] = mf + + if mf(f[len(prefix):]): + return True return False matchfuncs.append(matchsubinclude)