diff --git a/hgext/sparse.py b/hgext/sparse.py --- a/hgext/sparse.py +++ b/hgext/sparse.py @@ -77,7 +77,6 @@ from mercurial.pycompat import setattr from mercurial import ( cmdutil, commands, - dirstate, error, extensions, logcmdutil, @@ -104,7 +103,6 @@ def extsetup(ui): _setupclone(ui) _setuplog(ui) _setupadd(ui) - _setupdirstate(ui) def replacefilecache(cls, propname, replacement): @@ -207,40 +205,6 @@ def _setupadd(ui): extensions.wrapcommand(commands.table, b'add', _add) -def _setupdirstate(ui): - """Modify the dirstate to prevent stat'ing excluded files, - and to prevent modifications to files outside the checkout. - """ - - # Prevent adding files that are outside the sparse checkout - editfuncs = [ - b'set_tracked', - b'copy', - ] - hint = _( - b'include file with `hg debugsparse --include ` or use ' - + b'`hg add -s ` to include file directory while adding' - ) - for func in editfuncs: - - def _wrapper(orig, self, *args, **kwargs): - sparsematch = self._sparsematcher - if sparsematch is not None and not sparsematch.always(): - for f in args: - if f is not None and not sparsematch(f) and f not in self: - raise error.Abort( - _( - b"cannot add '%s' - it is outside " - b"the sparse checkout" - ) - % f, - hint=hint, - ) - return orig(self, *args, **kwargs) - - extensions.wrapfunction(dirstate.dirstate, func, _wrapper) - - @command( b'debugsparse', [ diff --git a/mercurial/dirstate.py b/mercurial/dirstate.py --- a/mercurial/dirstate.py +++ b/mercurial/dirstate.py @@ -427,6 +427,7 @@ class dirstate: return self._dirty = True if source is not None: + self._check_sparse(source) self._map.copymap[dest] = source else: self._map.copymap.pop(dest, None) @@ -588,6 +589,19 @@ class dirstate: msg = _(b'file %r in dirstate clashes with %r') msg %= (pycompat.bytestr(d), pycompat.bytestr(filename)) raise error.Abort(msg) + self._check_sparse(filename) + + def _check_sparse(self, filename): + """Check that a filename is inside the sparse profile""" + sparsematch = self._sparsematcher + if sparsematch is not None and not sparsematch.always(): + if not sparsematch(filename): + msg = _(b"cannot add '%s' - it is outside the sparse checkout") + hint = _( + b'include file with `hg debugsparse --include ` or use ' + b'`hg add -s ` to include file directory while adding' + ) + raise error.Abort(msg % filename, hint=hint) def _discoverpath(self, path, normed, ignoremissing, exists, storemap): if exists is None: