changeset 33555:6755b719048c

sparse: consolidate common code for writing sparse config In 3 functions we were writing the sparse config and updating the working directory. In two of them we had a transaction-like process for restoring the sparse config in case of wdir update fail. Because the pattern is common, we've already made mistakes, and the complexity will increase in the near future, let's consolidate the code into a reusable function. As part of this refactor, we end up reading the "sparse" file twice when updating it. This is a bit sub-optimal. But I don't think it is worth the code complexity to pass around the variables to avoid the redundancy. Differential Revision: https://phab.mercurial-scm.org/D109
author Gregory Szorc <gregory.szorc@gmail.com>
date Mon, 17 Jul 2017 11:21:23 -0700
parents 2943141f5e07
children 22371eabb3b1
files mercurial/sparse.py
diffstat 1 files changed, 33 insertions(+), 44 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/sparse.py	Sat Jul 15 15:51:57 2017 -0700
+++ b/mercurial/sparse.py	Mon Jul 17 11:21:23 2017 -0700
@@ -521,6 +521,31 @@
 
     prunetemporaryincludes(repo)
 
+def _updateconfigandrefreshwdir(repo, includes, excludes, profiles,
+                                force=False):
+    """Update the sparse config and working directory state."""
+    raw = repo.vfs.tryread('sparse')
+    oldincludes, oldexcludes, oldprofiles = parseconfig(repo.ui, raw)
+
+    oldstatus = repo.status()
+    oldmatch = matcher(repo)
+
+    # TODO remove this try..except once the matcher integrates better
+    # with dirstate. We currently have to write the updated config
+    # because that will invalidate the matcher cache and force a
+    # re-read. We ideally want to update the cached matcher on the
+    # repo instance then flush the new config to disk once wdir is
+    # updated. But this requires massive rework to matcher() and its
+    # consumers.
+
+    writeconfig(repo, includes, excludes, profiles)
+
+    try:
+        return refreshwdir(repo, oldstatus, oldmatch, force=force)
+    except Exception:
+        writeconfig(repo, oldincludes, oldexcludes, oldprofiles)
+        raise
+
 def clearrules(repo, force=False):
     """Clears include/exclude rules from the sparse config.
 
@@ -534,10 +559,7 @@
         if not includes and not excludes:
             return
 
-        oldstatus = repo.status()
-        oldmatch = matcher(repo)
-        writeconfig(repo, set(), set(), profiles)
-        refreshwdir(repo, oldstatus, oldmatch, force=force)
+        _updateconfigandrefreshwdir(repo, set(), set(), profiles, force=force)
 
 def importfromfiles(repo, opts, paths, force=False):
     """Import sparse config rules from files.
@@ -548,10 +570,7 @@
     with repo.wlock():
         # read current configuration
         raw = repo.vfs.tryread('sparse')
-        oincludes, oexcludes, oprofiles = parseconfig(repo.ui, raw)
-        includes, excludes, profiles = map(
-                set, (oincludes, oexcludes, oprofiles))
-
+        includes, excludes, profiles = parseconfig(repo.ui, raw)
         aincludes, aexcludes, aprofiles = activeconfig(repo)
 
         # Import rules on top; only take in rules that are not yet
@@ -577,25 +596,8 @@
             includecount = len(includes - aincludes)
             excludecount = len(excludes - aexcludes)
 
-            oldstatus = repo.status()
-            oldsparsematch = matcher(repo)
-
-            # TODO remove this try..except once the matcher integrates better
-            # with dirstate. We currently have to write the updated config
-            # because that will invalidate the matcher cache and force a
-            # re-read. We ideally want to update the cached matcher on the
-            # repo instance then flush the new config to disk once wdir is
-            # updated. But this requires massive rework to matcher() and its
-            # consumers.
-            writeconfig(repo, includes, excludes, profiles)
-
-            try:
-                fcounts = map(
-                    len,
-                    refreshwdir(repo, oldstatus, oldsparsematch, force=force))
-            except Exception:
-                writeconfig(repo, oincludes, oexcludes, oprofiles)
-                raise
+            fcounts = map(len, _updateconfigandrefreshwdir(
+                repo, includes, excludes, profiles, force=force))
 
         printchanges(repo.ui, opts, profilecount, includecount, excludecount,
                      *fcounts)
@@ -610,8 +612,6 @@
     The new config is written out and a working directory refresh is performed.
     """
     with repo.wlock():
-        oldmatcher = matcher(repo)
-
         raw = repo.vfs.tryread('sparse')
         oldinclude, oldexclude, oldprofiles = parseconfig(repo.ui, raw)
 
@@ -624,8 +624,6 @@
             newexclude = set(oldexclude)
             newprofiles = set(oldprofiles)
 
-        oldstatus = repo.status()
-
         if any(pat.startswith('/') for pat in pats):
             repo.ui.warn(_('warning: paths cannot start with /, ignoring: %s\n')
                          % ([pat for pat in pats if pat.startswith('/')]))
@@ -648,20 +646,11 @@
         excludecount = (len(newexclude - oldexclude) -
                         len(oldexclude - newexclude))
 
-        # TODO clean up this writeconfig() + try..except pattern once we can.
-        # See comment in importfromfiles() explaining it.
-        writeconfig(repo, newinclude, newexclude, newprofiles)
+        fcounts = map(len, _updateconfigandrefreshwdir(
+            repo, newinclude, newexclude, newprofiles, force=force))
 
-        try:
-            fcounts = map(
-                len,
-                refreshwdir(repo, oldstatus, oldmatcher, force=force))
-
-            printchanges(repo.ui, opts, profilecount, includecount,
-                         excludecount, *fcounts)
-        except Exception:
-            writeconfig(repo, oldinclude, oldexclude, oldprofiles)
-            raise
+        printchanges(repo.ui, opts, profilecount, includecount,
+                     excludecount, *fcounts)
 
 def printchanges(ui, opts, profilecount=0, includecount=0, excludecount=0,
                  added=0, dropped=0, conflicting=0):