mercurial/dirstate.py
changeset 49363 bd3519dc6741
parent 49360 5b7a10ddb42f
child 49364 c2092612c424
--- 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: