sparse: directly inline the `set_tracked` and `copy` wrapping
authorPierre-Yves David <pierre-yves.david@octobus.net>
Fri, 10 Jun 2022 23:19:04 +0200
changeset 49360 bd3519dc6741
parent 49359 76b4b36cd5d0
child 49361 c2092612c424
sparse: directly inline the `set_tracked` and `copy` wrapping core is already aware of sparse, so lets move the handful of line of code that deal with this for the sake of simplicity and explicitness.
hgext/sparse.py
mercurial/dirstate.py
--- a/hgext/sparse.py	Sat Jun 11 00:00:29 2022 +0200
+++ b/hgext/sparse.py	Fri Jun 10 23:19:04 2022 +0200
@@ -77,7 +77,6 @@
 from mercurial import (
     cmdutil,
     commands,
-    dirstate,
     error,
     extensions,
     logcmdutil,
@@ -104,7 +103,6 @@
     _setupclone(ui)
     _setuplog(ui)
     _setupadd(ui)
-    _setupdirstate(ui)
 
 
 def replacefilecache(cls, propname, replacement):
@@ -207,40 +205,6 @@
     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 <pattern>` or use '
-        + b'`hg add -s <file>` 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',
     [
--- a/mercurial/dirstate.py	Sat Jun 11 00:00:29 2022 +0200
+++ b/mercurial/dirstate.py	Fri Jun 10 23:19:04 2022 +0200
@@ -427,6 +427,7 @@
             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 @@
                 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 <pattern>` or use '
+                    b'`hg add -s <file>` 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: