[PATCH 9 of 9 sparse] sparse: move working directory refreshing into core

Gregory Szorc gregory.szorc at gmail.com
Thu Jul 6 17:54:25 EDT 2017


# HG changeset patch
# User Gregory Szorc <gregory.szorc at gmail.com>
# Date 1499377988 25200
#      Thu Jul 06 14:53:08 2017 -0700
# Node ID bb3e1889d6de938af6841d92f4065eb75c562111
# Parent  61066164673a2d4213bbfedc2081377b18f2d47c
sparse: move working directory refreshing into core

This is a pretty straightforward move of the code.

I converted the "force" argument to a keyword argument.

Like other recent changes, this code is tightly coupled with
working directory update code in merge.py. I suspect the code
will become more tightly coupled over time, possibly even moved
to merge.py. For now, let's get the code in core.

diff --git a/hgext/sparse.py b/hgext/sparse.py
--- a/hgext/sparse.py
+++ b/hgext/sparse.py
@@ -85,7 +85,6 @@ from mercurial import (
     extensions,
     hg,
     localrepo,
-    merge as mergemod,
     registrar,
     sparse,
     util,
@@ -156,7 +155,7 @@ def _setupcommit(ui):
         if set(profiles) & set(ctx.files()):
             origstatus = repo.status()
             origsparsematch = sparse.matcher(repo)
-            _refresh(repo.ui, repo, origstatus, origsparsematch, True)
+            sparse.refreshwdir(repo, origstatus, origsparsematch, force=True)
 
         sparse.prunetemporaryincludes(repo)
 
@@ -405,7 +404,8 @@ def debugsparse(ui, repo, *pats, **opts)
             wlock = repo.wlock()
             fcounts = map(
                 len,
-                _refresh(ui, repo, repo.status(), sparse.matcher(repo), force))
+                sparse.refreshwdir(repo, repo.status(), sparse.matcher(repo),
+                                   force=force))
             _verbose_output(ui, opts, 0, 0, 0, *fcounts)
         finally:
             wlock.release()
@@ -459,7 +459,9 @@ def _config(ui, repo, pats, opts, includ
             sparse.writeconfig(repo, newinclude, newexclude, newprofiles)
 
             fcounts = map(
-                len, _refresh(ui, repo, oldstatus, oldsparsematch, force))
+                len,
+                sparse.refreshwdir(repo, oldstatus, oldsparsematch,
+                                   force=force))
 
             profilecount = (len(newprofiles - oldprofiles) -
                             len(oldprofiles - newprofiles))
@@ -523,7 +525,9 @@ def _import(ui, repo, files, opts, force
 
             try:
                 fcounts = map(
-                    len, _refresh(ui, repo, oldstatus, oldsparsematch, force))
+                    len,
+                    sparse.refreshwdir(repo, oldstatus, oldsparsematch,
+                                       force=force))
             except Exception:
                 sparse.writeconfig(repo, oincludes, oexcludes, oprofiles)
                 raise
@@ -540,101 +544,7 @@ def _clear(ui, repo, files, force=False)
             oldstatus = repo.status()
             oldsparsematch = sparse.matcher(repo)
             sparse.writeconfig(repo, set(), set(), profiles)
-            _refresh(ui, repo, oldstatus, oldsparsematch, force)
-
-def _refresh(ui, repo, origstatus, origsparsematch, force):
-    """Refreshes which files are on disk by comparing the old status and
-    sparsematch with the new sparsematch.
-
-    Will raise an exception if a file with pending changes is being excluded
-    or included (unless force=True).
-    """
-    modified, added, removed, deleted, unknown, ignored, clean = origstatus
-
-    # Verify there are no pending changes
-    pending = set()
-    pending.update(modified)
-    pending.update(added)
-    pending.update(removed)
-    sparsematch = sparse.matcher(repo)
-    abort = False
-    for file in pending:
-        if not sparsematch(file):
-            ui.warn(_("pending changes to '%s'\n") % file)
-            abort = not force
-    if abort:
-        raise error.Abort(_("could not update sparseness due to " +
-            "pending changes"))
-
-    # Calculate actions
-    dirstate = repo.dirstate
-    ctx = repo['.']
-    added = []
-    lookup = []
-    dropped = []
-    mf = ctx.manifest()
-    files = set(mf)
-
-    actions = {}
-
-    for file in files:
-        old = origsparsematch(file)
-        new = sparsematch(file)
-        # Add files that are newly included, or that don't exist in
-        # the dirstate yet.
-        if (new and not old) or (old and new and not file in dirstate):
-            fl = mf.flags(file)
-            if repo.wvfs.exists(file):
-                actions[file] = ('e', (fl,), '')
-                lookup.append(file)
-            else:
-                actions[file] = ('g', (fl, False), '')
-                added.append(file)
-        # Drop files that are newly excluded, or that still exist in
-        # the dirstate.
-        elif (old and not new) or (not old and not new and file in dirstate):
-            dropped.append(file)
-            if file not in pending:
-                actions[file] = ('r', [], '')
-
-    # Verify there are no pending changes in newly included files
-    abort = False
-    for file in lookup:
-        ui.warn(_("pending changes to '%s'\n") % file)
-        abort = not force
-    if abort:
-        raise error.Abort(_("cannot change sparseness due to " +
-            "pending changes (delete the files or use --force " +
-            "to bring them back dirty)"))
-
-    # Check for files that were only in the dirstate.
-    for file, state in dirstate.iteritems():
-        if not file in files:
-            old = origsparsematch(file)
-            new = sparsematch(file)
-            if old and not new:
-                dropped.append(file)
-
-    # Apply changes to disk
-    typeactions = dict((m, []) for m in 'a f g am cd dc r dm dg m e k'.split())
-    for f, (m, args, msg) in actions.iteritems():
-        if m not in typeactions:
-            typeactions[m] = []
-        typeactions[m].append((f, args, msg))
-    mergemod.applyupdates(repo, typeactions, repo[None], repo['.'], False)
-
-    # Fix dirstate
-    for file in added:
-        dirstate.normal(file)
-
-    for file in dropped:
-        dirstate.drop(file)
-
-    for file in lookup:
-        # File exists on disk, and we're bringing it back in an unknown state.
-        dirstate.normallookup(file)
-
-    return added, dropped, lookup
+            sparse.refreshwdir(repo, oldstatus, oldsparsematch, force)
 
 def _verbose_output(ui, opts, profilecount, includecount, excludecount, added,
                     dropped, lookup):
diff --git a/mercurial/sparse.py b/mercurial/sparse.py
--- a/mercurial/sparse.py
+++ b/mercurial/sparse.py
@@ -453,3 +453,102 @@ def calculateupdates(repo, wctx, mctx, b
                 prunedactions[file] = ('r', [], '')
 
     return prunedactions, diverge, renamedelete
+
+def refreshwdir(repo, origstatus, origsparsematch, force=False):
+    """Refreshes working directory by taking sparse config into account.
+
+    The old status and sparse matcher is compared against the current sparse
+    matcher.
+
+    Will abort if a file with pending changes is being excluded or included
+    unless ``force`` is True.
+    """
+    modified, added, removed, deleted, unknown, ignored, clean = origstatus
+
+    # Verify there are no pending changes
+    pending = set()
+    pending.update(modified)
+    pending.update(added)
+    pending.update(removed)
+    sparsematch = matcher(repo)
+    abort = False
+
+    for f in pending:
+        if not sparsematch(f):
+            repo.ui.warn(_("pending changes to '%s'\n") % f)
+            abort = not force
+
+    if abort:
+        raise error.Abort(_('could not update sparseness due to pending '
+                            'changes'))
+
+    # Calculate actions
+    dirstate = repo.dirstate
+    ctx = repo['.']
+    added = []
+    lookup = []
+    dropped = []
+    mf = ctx.manifest()
+    files = set(mf)
+
+    actions = {}
+
+    for file in files:
+        old = origsparsematch(file)
+        new = sparsematch(file)
+        # Add files that are newly included, or that don't exist in
+        # the dirstate yet.
+        if (new and not old) or (old and new and not file in dirstate):
+            fl = mf.flags(file)
+            if repo.wvfs.exists(file):
+                actions[file] = ('e', (fl,), '')
+                lookup.append(file)
+            else:
+                actions[file] = ('g', (fl, False), '')
+                added.append(file)
+        # Drop files that are newly excluded, or that still exist in
+        # the dirstate.
+        elif (old and not new) or (not old and not new and file in dirstate):
+            dropped.append(file)
+            if file not in pending:
+                actions[file] = ('r', [], '')
+
+    # Verify there are no pending changes in newly included files
+    abort = False
+    for file in lookup:
+        repo.ui.warn(_("pending changes to '%s'\n") % file)
+        abort = not force
+    if abort:
+        raise error.Abort(_('cannot change sparseness due to pending '
+                            'changes (delete the files or use '
+                            '--force to bring them back dirty)'))
+
+    # Check for files that were only in the dirstate.
+    for file, state in dirstate.iteritems():
+        if not file in files:
+            old = origsparsematch(file)
+            new = sparsematch(file)
+            if old and not new:
+                dropped.append(file)
+
+    # Apply changes to disk
+    typeactions = dict((m, []) for m in 'a f g am cd dc r dm dg m e k'.split())
+    for f, (m, args, msg) in actions.iteritems():
+        if m not in typeactions:
+            typeactions[m] = []
+        typeactions[m].append((f, args, msg))
+
+    mergemod.applyupdates(repo, typeactions, repo[None], repo['.'], False)
+
+    # Fix dirstate
+    for file in added:
+        dirstate.normal(file)
+
+    for file in dropped:
+        dirstate.drop(file)
+
+    for file in lookup:
+        # File exists on disk, and we're bringing it back in an unknown state.
+        dirstate.normallookup(file)
+
+    return added, dropped, lookup
diff --git a/tests/test-sparse-import.t b/tests/test-sparse-import.t
--- a/tests/test-sparse-import.t
+++ b/tests/test-sparse-import.t
@@ -147,16 +147,11 @@ Same tests, with -Tjson enabled to outpu
 If importing results in no new rules being added, no refresh should take place!
 
   $ cat > $TESTTMP/trap_sparse_refresh.py <<EOF
-  > from mercurial import error, extensions
+  > from mercurial import error, sparse
   > def extsetup(ui):
-  >     def abort_refresh(ui, *args):
+  >     def abort_refresh(*args, **kwargs):
   >         raise error.Abort('sparse._refresh called!')
-  >     def sparseloaded(loaded):
-  >         if not loaded:
-  >             return
-  >         sparse = extensions.find('sparse')
-  >         sparse._refresh = abort_refresh
-  >     extensions.afterloaded('sparse', sparseloaded)
+  >     sparse.refreshwdir = abort_refresh
   > EOF
   $ cat >> $HGRCPATH <<EOF
   > [extensions]


More information about the Mercurial-devel mailing list