Patchwork [7,of,8,sparse,V2] dirstate: move customizations to rebuild() from sparse extension

login
register
mail settings
Submitter Gregory Szorc
Date July 11, 2017, 4:57 a.m.
Message ID <f0ef4aff7559a680e216.1499749026@ubuntu-vm-main>
Download mbox | patch
Permalink /patch/22219/
State Accepted
Headers show

Comments

Gregory Szorc - July 11, 2017, 4:57 a.m.
# HG changeset patch
# User Gregory Szorc <gregory.szorc@gmail.com>
# Date 1499537680 25200
#      Sat Jul 08 11:14:40 2017 -0700
# Node ID f0ef4aff7559a680e216407e5822e3e281ef1a5f
# Parent  7b09c7c8f8457dd96f45334dad13a0ceaae92a18
dirstate: move customizations to rebuild() from sparse extension

This is a pretty straightforward port of the monkeypatch from
sparse directly into dirstate.

Unless the sparse feature is enabled via the sparse extension,
the sparse matcher will be an alwaysmatcher and the added
branch won't be taken.
via Mercurial-devel - July 11, 2017, 6:11 a.m.
On Mon, Jul 10, 2017 at 9:57 PM, Gregory Szorc <gregory.szorc@gmail.com> wrote:
> # HG changeset patch
> # User Gregory Szorc <gregory.szorc@gmail.com>
> # Date 1499537680 25200
> #      Sat Jul 08 11:14:40 2017 -0700
> # Node ID f0ef4aff7559a680e216407e5822e3e281ef1a5f
> # Parent  7b09c7c8f8457dd96f45334dad13a0ceaae92a18
> dirstate: move customizations to rebuild() from sparse extension
>
> This is a pretty straightforward port of the monkeypatch from
> sparse directly into dirstate.
>
> Unless the sparse feature is enabled via the sparse extension,
> the sparse matcher will be an alwaysmatcher and the added
> branch won't be taken.
>
> diff --git a/mercurial/dirstate.py b/mercurial/dirstate.py
> --- a/mercurial/dirstate.py
> +++ b/mercurial/dirstate.py
> @@ -774,6 +774,19 @@ class dirstate(object):
>          self._dirty = True
>
>      def rebuild(self, parent, allfiles, changedfiles=None):
> +        # Filter allfiles and changedfiles through a sparse matcher if it is
> +        # active.
> +        matcher = self._sparsematcher
> +        if not matcher.always():
> +            allfiles = allfiles.matches(matcher)

This seems to assume that allfiles is a manifest (where matches() is
defined). It looks like all in-tree callers do pass a manifest, but
this patch should at least have an (API) marker. Maybe we should
rename the argument to "mf" too.

Patch

diff --git a/hgext/sparse.py b/hgext/sparse.py
--- a/hgext/sparse.py
+++ b/hgext/sparse.py
@@ -223,23 +223,6 @@  def _setupdirstate(ui):
 
     replacefilecache(dirstate.dirstate, '_ignore', ignorewrapper)
 
-    # dirstate.rebuild should not add non-matching files
-    def _rebuild(orig, self, parent, allfiles, changedfiles=None):
-        matcher = self._sparsematcher
-        if not matcher.always():
-            allfiles = allfiles.matches(matcher)
-            if changedfiles:
-                changedfiles = [f for f in changedfiles if matcher(f)]
-
-            if changedfiles is not None:
-                # In _rebuild, these files will be deleted from the dirstate
-                # when they are not found to be in allfiles
-                dirstatefilestoremove = set(f for f in self if not matcher(f))
-                changedfiles = dirstatefilestoremove.union(changedfiles)
-
-        return orig(self, parent, allfiles, changedfiles)
-    extensions.wrapfunction(dirstate.dirstate, 'rebuild', _rebuild)
-
 @command('^debugsparse', [
     ('I', 'include', False, _('include files in the sparse checkout')),
     ('X', 'exclude', False, _('exclude files in the sparse checkout')),
diff --git a/mercurial/dirstate.py b/mercurial/dirstate.py
--- a/mercurial/dirstate.py
+++ b/mercurial/dirstate.py
@@ -774,6 +774,19 @@  class dirstate(object):
         self._dirty = True
 
     def rebuild(self, parent, allfiles, changedfiles=None):
+        # Filter allfiles and changedfiles through a sparse matcher if it is
+        # active.
+        matcher = self._sparsematcher
+        if not matcher.always():
+            allfiles = allfiles.matches(matcher)
+
+            if changedfiles:
+                changedfiles = [f for f in changedfiles if matcher(f)]
+
+            if changedfiles is not None:
+                toremove = set(f for f in self if not matcher(f))
+                changedfiles = toremove.union(changedfiles)
+
         if changedfiles is None:
             # Rebuild entire dirstate
             changedfiles = allfiles