diff --git a/hgext/largefiles/lfutil.py b/hgext/largefiles/lfutil.py --- a/hgext/largefiles/lfutil.py +++ b/hgext/largefiles/lfutil.py @@ -26,6 +26,7 @@ from mercurial import ( node, pycompat, scmutil, + sparse, util, vfs as vfsmod, ) @@ -147,7 +148,8 @@ def openlfdirstate(ui, repo, create=True lfstoredir = longname opener = vfsmod.vfs(vfs.join(lfstoredir)) lfdirstate = largefilesdirstate(opener, ui, repo.root, - repo.dirstate._validate) + repo.dirstate._validate, + lambda: sparse.matcher(repo)) # If the largefiles dirstate does not exist, populate and create # it. This ensures that we create it on the first meaningful diff --git a/hgext/sparse.py b/hgext/sparse.py --- a/hgext/sparse.py +++ b/hgext/sparse.py @@ -82,7 +82,6 @@ from mercurial import ( error, extensions, hg, - localrepo, match as matchmod, registrar, sparse, @@ -106,13 +105,6 @@ def extsetup(ui): _setupadd(ui) _setupdirstate(ui) -def reposetup(ui, repo): - if not util.safehasattr(repo, 'dirstate'): - return - - if 'dirstate' in repo._filecache: - repo.dirstate.repo = repo - def replacefilecache(cls, propname, replacement): """Replace a filecache property with a new class. This allows changing the cache invalidation condition.""" @@ -200,13 +192,6 @@ def _setupdirstate(ui): and to prevent modifications to files outside the checkout. """ - def _dirstate(orig, repo): - dirstate = orig(repo) - dirstate.repo = repo - return dirstate - extensions.wrapfunction( - localrepo.localrepository.dirstate, 'func', _dirstate) - # The atrocity below is needed to wrap dirstate._ignore. It is a cached # property, which means normal function wrapping doesn't work. class ignorewrapper(object): @@ -217,10 +202,9 @@ def _setupdirstate(ui): self.sparsematch = None def __get__(self, obj, type=None): - repo = obj.repo origignore = self.orig.__get__(obj) - sparsematch = sparse.matcher(repo) + sparsematch = obj._sparsematcher if sparsematch.always(): return origignore @@ -241,7 +225,7 @@ def _setupdirstate(ui): # dirstate.rebuild should not add non-matching files def _rebuild(orig, self, parent, allfiles, changedfiles=None): - matcher = sparse.matcher(self.repo) + matcher = self._sparsematcher if not matcher.always(): allfiles = allfiles.matches(matcher) if changedfiles: @@ -262,8 +246,7 @@ def _setupdirstate(ui): '`hg add -s ` to include file directory while adding') for func in editfuncs: def _wrapper(orig, self, *args): - repo = self.repo - sparsematch = sparse.matcher(repo) + sparsematch = self._sparsematcher if not sparsematch.always(): for f in args: if (f is not None and not sparsematch(f) and diff --git a/mercurial/dirstate.py b/mercurial/dirstate.py --- a/mercurial/dirstate.py +++ b/mercurial/dirstate.py @@ -70,7 +70,7 @@ def nonnormalentries(dmap): class dirstate(object): - def __init__(self, opener, ui, root, validate): + def __init__(self, opener, ui, root, validate, sparsematchfn): '''Create a new dirstate object. opener is an open()-like callable that can be used to open the @@ -80,6 +80,7 @@ class dirstate(object): self._opener = opener self._validate = validate self._root = root + self._sparsematchfn = sparsematchfn # ntpath.join(root, '') of Python 2.7.9 does not add sep if root is # UNC path pointing to root share (issue4557) self._rootdir = pathutil.normasprefix(root) @@ -197,6 +198,19 @@ class dirstate(object): f[normcase(name)] = name return f + @property + def _sparsematcher(self): + """The matcher for the sparse checkout. + + The working directory may not include every file from a manifest. The + matcher obtained by this property will match a path if it is to be + included in the working directory. + """ + # TODO there is potential to cache this property. For now, the matcher + # is resolved on every access. (But the called function does use a + # cache to keep the lookup fast.) + return self._sparsematchfn() + @repocache('branch') def _branch(self): try: diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -53,6 +53,7 @@ from . import ( revset, revsetlang, scmutil, + sparse, store, subrepo, tags as tagsmod, @@ -570,8 +571,10 @@ class localrepository(object): @repofilecache('dirstate') def dirstate(self): + sparsematchfn = lambda: sparse.matcher(self) + return dirstate.dirstate(self.vfs, self.ui, self.root, - self._dirstatevalidate) + self._dirstatevalidate, sparsematchfn) def _dirstatevalidate(self, node): try: