mercurial/sparse.py
changeset 43076 2372284d9457
parent 42472 87a34c767384
child 43077 687b865b95ad
--- a/mercurial/sparse.py	Sat Oct 05 10:29:34 2019 -0400
+++ b/mercurial/sparse.py	Sun Oct 06 09:45:02 2019 -0400
@@ -30,6 +30,7 @@
 # a per-repo option, possibly a repo requirement.
 enabled = False
 
+
 def parseconfig(ui, raw, action):
     """Parse sparse config file content.
 
@@ -55,8 +56,13 @@
         elif line == '[include]':
             if havesection and current != includes:
                 # TODO pass filename into this API so we can report it.
-                raise error.Abort(_('%(action)s config cannot have includes '
-                                    'after excludes') % {'action': action})
+                raise error.Abort(
+                    _(
+                        '%(action)s config cannot have includes '
+                        'after excludes'
+                    )
+                    % {'action': action}
+                )
             havesection = True
             current = includes
             continue
@@ -65,21 +71,29 @@
             current = excludes
         elif line:
             if current is None:
-                raise error.Abort(_('%(action)s config entry outside of '
-                                    'section: %(line)s')
-                                  % {'action': action, 'line': line},
-                                  hint=_('add an [include] or [exclude] line '
-                                         'to declare the entry type'))
+                raise error.Abort(
+                    _('%(action)s config entry outside of ' 'section: %(line)s')
+                    % {'action': action, 'line': line},
+                    hint=_(
+                        'add an [include] or [exclude] line '
+                        'to declare the entry type'
+                    ),
+                )
 
             if line.strip().startswith('/'):
-                ui.warn(_('warning: %(action)s profile cannot use'
-                          ' paths starting with /, ignoring %(line)s\n')
-                        % {'action': action, 'line': line})
+                ui.warn(
+                    _(
+                        'warning: %(action)s profile cannot use'
+                        ' paths starting with /, ignoring %(line)s\n'
+                    )
+                    % {'action': action, 'line': line}
+                )
                 continue
             current.add(line)
 
     return includes, excludes, profiles
 
+
 # Exists as separate function to facilitate monkeypatching.
 def readprofile(repo, profile, changeid):
     """Resolve the raw content of a sparse profile file."""
@@ -87,6 +101,7 @@
     # resolve and can be slow.
     return repo.filectx(profile, changeid=changeid).data()
 
+
 def patternsforrev(repo, rev):
     """Obtain sparse checkout patterns for the given rev.
 
@@ -102,8 +117,9 @@
         return set(), set(), set()
 
     if rev is None:
-        raise error.Abort(_('cannot parse sparse patterns from working '
-                            'directory'))
+        raise error.Abort(
+            _('cannot parse sparse patterns from working ' 'directory')
+        )
 
     includes, excludes, profiles = parseconfig(repo.ui, raw, 'sparse')
     ctx = repo[rev]
@@ -122,10 +138,10 @@
             except error.ManifestLookupError:
                 msg = (
                     "warning: sparse profile '%s' not found "
-                    "in rev %s - ignoring it\n" % (profile, ctx))
+                    "in rev %s - ignoring it\n" % (profile, ctx)
+                )
                 # experimental config: sparse.missingwarning
-                if repo.ui.configbool(
-                        'sparse', 'missingwarning'):
+                if repo.ui.configbool('sparse', 'missingwarning'):
                     repo.ui.warn(msg)
                 else:
                     repo.ui.debug(msg)
@@ -143,14 +159,18 @@
 
     return includes, excludes, profiles
 
+
 def activeconfig(repo):
     """Determine the active sparse config rules.
 
     Rules are constructed by reading the current sparse config and bringing in
     referenced profiles from parents of the working directory.
     """
-    revs = [repo.changelog.rev(node) for node in
-            repo.dirstate.parents() if node != nullid]
+    revs = [
+        repo.changelog.rev(node)
+        for node in repo.dirstate.parents()
+        if node != nullid
+    ]
 
     allincludes = set()
     allexcludes = set()
@@ -164,6 +184,7 @@
 
     return allincludes, allexcludes, allprofiles
 
+
 def configsignature(repo, includetemp=True):
     """Obtain the signature string for the current sparse configuration.
 
@@ -189,6 +210,7 @@
 
     return '%s %s' % (signature, tempsignature)
 
+
 def writeconfig(repo, includes, excludes, profiles):
     """Write the sparse config file given a sparse configuration."""
     with repo.vfs('sparse', 'wb') as fh:
@@ -209,6 +231,7 @@
 
     repo._sparsesignaturecache.clear()
 
+
 def readtemporaryincludes(repo):
     raw = repo.vfs.tryread('tempsparse')
     if not raw:
@@ -216,16 +239,19 @@
 
     return set(raw.split('\n'))
 
+
 def writetemporaryincludes(repo, includes):
     repo.vfs.write('tempsparse', '\n'.join(sorted(includes)))
     repo._sparsesignaturecache.clear()
 
+
 def addtemporaryincludes(repo, additional):
     includes = readtemporaryincludes(repo)
     for i in additional:
         includes.add(i)
     writetemporaryincludes(repo, includes)
 
+
 def prunetemporaryincludes(repo):
     if not enabled or not repo.vfs.exists('tempsparse'):
         return
@@ -248,8 +274,9 @@
 
     typeactions = mergemod.emptyactions()
     typeactions['r'] = actions
-    mergemod.applyupdates(repo, typeactions, repo[None], repo['.'], False,
-                          wantfiledata=False)
+    mergemod.applyupdates(
+        repo, typeactions, repo[None], repo['.'], False, wantfiledata=False
+    )
 
     # Fix dirstate
     for file in dropped:
@@ -257,10 +284,12 @@
 
     repo.vfs.unlink('tempsparse')
     repo._sparsesignaturecache.clear()
-    msg = _('cleaned up %d temporarily added file(s) from the '
-            'sparse checkout\n')
+    msg = _(
+        'cleaned up %d temporarily added file(s) from the ' 'sparse checkout\n'
+    )
     repo.ui.status(msg % len(tempincludes))
 
+
 def forceincludematcher(matcher, includes):
     """Returns a matcher that returns true for any of the forced includes
     before testing against the actual matcher."""
@@ -268,6 +297,7 @@
     includematcher = matchmod.includematcher('', kindpats)
     return matchmod.unionmatcher([includematcher, matcher])
 
+
 def matcher(repo, revs=None, includetemp=True):
     """Obtain a matcher for sparse working directories for the given revs.
 
@@ -281,8 +311,11 @@
         return matchmod.always()
 
     if not revs or revs == [None]:
-        revs = [repo.changelog.rev(node)
-                for node in repo.dirstate.parents() if node != nullid]
+        revs = [
+            repo.changelog.rev(node)
+            for node in repo.dirstate.parents()
+            if node != nullid
+        ]
 
     signature = configsignature(repo, includetemp=includetemp)
 
@@ -298,9 +331,14 @@
             includes, excludes, profiles = patternsforrev(repo, rev)
 
             if includes or excludes:
-                matcher = matchmod.match(repo.root, '', [],
-                                         include=includes, exclude=excludes,
-                                         default='relpath')
+                matcher = matchmod.match(
+                    repo.root,
+                    '',
+                    [],
+                    include=includes,
+                    exclude=excludes,
+                    default='relpath',
+                )
                 matchers.append(matcher)
         except IOError:
             pass
@@ -320,6 +358,7 @@
 
     return result
 
+
 def filterupdatesactions(repo, wctx, mctx, branchmerge, actions):
     """Filter updates to only lay out files that match the sparse rules."""
     if not enabled:
@@ -367,8 +406,13 @@
                 temporaryfiles.append(f1)
 
     if len(temporaryfiles) > 0:
-        repo.ui.status(_('temporarily included %d file(s) in the sparse '
-                         'checkout for merging\n') % len(temporaryfiles))
+        repo.ui.status(
+            _(
+                'temporarily included %d file(s) in the sparse '
+                'checkout for merging\n'
+            )
+            % len(temporaryfiles)
+        )
         addtemporaryincludes(repo, temporaryfiles)
 
         # Add the new files to the working copy so they can be merged, etc
@@ -382,8 +426,9 @@
 
         typeactions = mergemod.emptyactions()
         typeactions['g'] = actions
-        mergemod.applyupdates(repo, typeactions, repo[None], repo['.'],
-                              False, wantfiledata=False)
+        mergemod.applyupdates(
+            repo, typeactions, repo[None], repo['.'], False, wantfiledata=False
+        )
 
         dirstate = repo.dirstate
         for file, flags, msg in actions:
@@ -407,6 +452,7 @@
 
     return prunedactions
 
+
 def refreshwdir(repo, origstatus, origsparsematch, force=False):
     """Refreshes working directory by taking sparse config into account.
 
@@ -430,8 +476,9 @@
             abort = not force
 
     if abort:
-        raise error.Abort(_('could not update sparseness due to pending '
-                            'changes'))
+        raise error.Abort(
+            _('could not update sparseness due to pending ' 'changes')
+        )
 
     # Calculate actions
     dirstate = repo.dirstate
@@ -470,9 +517,13 @@
         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)'))
+        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():
@@ -487,8 +538,9 @@
     for f, (m, args, msg) in actions.iteritems():
         typeactions[m].append((f, args, msg))
 
-    mergemod.applyupdates(repo, typeactions, repo[None], repo['.'], False,
-                          wantfiledata=False)
+    mergemod.applyupdates(
+        repo, typeactions, repo[None], repo['.'], False, wantfiledata=False
+    )
 
     # Fix dirstate
     for file in added:
@@ -503,6 +555,7 @@
 
     return added, dropped, lookup
 
+
 def aftercommit(repo, node):
     """Perform actions after a working directory commit."""
     # This function is called unconditionally, even if sparse isn't
@@ -519,8 +572,10 @@
 
     prunetemporaryincludes(repo)
 
-def _updateconfigandrefreshwdir(repo, includes, excludes, profiles,
-                                force=False, removing=False):
+
+def _updateconfigandrefreshwdir(
+    repo, includes, excludes, profiles, force=False, removing=False
+):
     """Update the sparse config and working directory state."""
     raw = repo.vfs.tryread('sparse')
     oldincludes, oldexcludes, oldprofiles = parseconfig(repo.ui, raw, 'sparse')
@@ -555,6 +610,7 @@
         writeconfig(repo, oldincludes, oldexcludes, oldprofiles)
         raise
 
+
 def clearrules(repo, force=False):
     """Clears include/exclude rules from the sparse config.
 
@@ -570,6 +626,7 @@
 
         _updateconfigandrefreshwdir(repo, set(), set(), profiles, force=force)
 
+
 def importfromfiles(repo, opts, paths, force=False):
     """Import sparse config rules from files.
 
@@ -589,8 +646,9 @@
             with util.posixfile(util.expandpath(p), mode='rb') as fh:
                 raw = fh.read()
 
-            iincludes, iexcludes, iprofiles = parseconfig(repo.ui, raw,
-                                                          'sparse')
+            iincludes, iexcludes, iprofiles = parseconfig(
+                repo.ui, raw, 'sparse'
+            )
             oldsize = len(includes) + len(excludes) + len(profiles)
             includes.update(iincludes - aincludes)
             excludes.update(iexcludes - aexcludes)
@@ -606,15 +664,31 @@
             includecount = len(includes - aincludes)
             excludecount = len(excludes - aexcludes)
 
-            fcounts = map(len, _updateconfigandrefreshwdir(
-                repo, includes, excludes, profiles, force=force))
+            fcounts = map(
+                len,
+                _updateconfigandrefreshwdir(
+                    repo, includes, excludes, profiles, force=force
+                ),
+            )
+
+        printchanges(
+            repo.ui, opts, profilecount, includecount, excludecount, *fcounts
+        )
+
 
-        printchanges(repo.ui, opts, profilecount, includecount, excludecount,
-                     *fcounts)
-
-def updateconfig(repo, pats, opts, include=False, exclude=False, reset=False,
-                 delete=False, enableprofile=False, disableprofile=False,
-                 force=False, usereporootpaths=False):
+def updateconfig(
+    repo,
+    pats,
+    opts,
+    include=False,
+    exclude=False,
+    reset=False,
+    delete=False,
+    enableprofile=False,
+    disableprofile=False,
+    force=False,
+    usereporootpaths=False,
+):
     """Perform a sparse config update.
 
     Only one of the actions may be performed.
@@ -623,8 +697,9 @@
     """
     with repo.wlock():
         raw = repo.vfs.tryread('sparse')
-        oldinclude, oldexclude, oldprofiles = parseconfig(repo.ui, raw,
-                                                          'sparse')
+        oldinclude, oldexclude, oldprofiles = parseconfig(
+            repo.ui, raw, 'sparse'
+        )
 
         if reset:
             newinclude = set()
@@ -645,8 +720,9 @@
             for kindpat in pats:
                 kind, pat = matchmod._patsplit(kindpat, None)
                 if kind in matchmod.cwdrelativepatternkinds or kind is None:
-                    ap = ((kind + ':' if kind else '') +
-                          pathutil.canonpath(root, cwd, pat))
+                    ap = (kind + ':' if kind else '') + pathutil.canonpath(
+                        root, cwd, pat
+                    )
                     abspats.append(ap)
                 else:
                     abspats.append(kindpat)
@@ -664,39 +740,78 @@
             newinclude.difference_update(pats)
             newexclude.difference_update(pats)
 
-        profilecount = (len(newprofiles - oldprofiles) -
-                        len(oldprofiles - newprofiles))
-        includecount = (len(newinclude - oldinclude) -
-                        len(oldinclude - newinclude))
-        excludecount = (len(newexclude - oldexclude) -
-                        len(oldexclude - newexclude))
+        profilecount = len(newprofiles - oldprofiles) - len(
+            oldprofiles - newprofiles
+        )
+        includecount = len(newinclude - oldinclude) - len(
+            oldinclude - newinclude
+        )
+        excludecount = len(newexclude - oldexclude) - len(
+            oldexclude - newexclude
+        )
 
-        fcounts = map(len, _updateconfigandrefreshwdir(
-            repo, newinclude, newexclude, newprofiles, force=force,
-            removing=reset))
+        fcounts = map(
+            len,
+            _updateconfigandrefreshwdir(
+                repo,
+                newinclude,
+                newexclude,
+                newprofiles,
+                force=force,
+                removing=reset,
+            ),
+        )
 
-        printchanges(repo.ui, opts, profilecount, includecount,
-                     excludecount, *fcounts)
+        printchanges(
+            repo.ui, opts, profilecount, includecount, excludecount, *fcounts
+        )
+
 
-def printchanges(ui, opts, profilecount=0, includecount=0, excludecount=0,
-                 added=0, dropped=0, conflicting=0):
+def printchanges(
+    ui,
+    opts,
+    profilecount=0,
+    includecount=0,
+    excludecount=0,
+    added=0,
+    dropped=0,
+    conflicting=0,
+):
     """Print output summarizing sparse config changes."""
     with ui.formatter('sparse', opts) as fm:
         fm.startitem()
-        fm.condwrite(ui.verbose, 'profiles_added', _('Profiles changed: %d\n'),
-                     profilecount)
-        fm.condwrite(ui.verbose, 'include_rules_added',
-                     _('Include rules changed: %d\n'), includecount)
-        fm.condwrite(ui.verbose, 'exclude_rules_added',
-                     _('Exclude rules changed: %d\n'), excludecount)
+        fm.condwrite(
+            ui.verbose,
+            'profiles_added',
+            _('Profiles changed: %d\n'),
+            profilecount,
+        )
+        fm.condwrite(
+            ui.verbose,
+            'include_rules_added',
+            _('Include rules changed: %d\n'),
+            includecount,
+        )
+        fm.condwrite(
+            ui.verbose,
+            'exclude_rules_added',
+            _('Exclude rules changed: %d\n'),
+            excludecount,
+        )
 
         # In 'plain' verbose mode, mergemod.applyupdates already outputs what
         # files are added or removed outside of the templating formatter
         # framework. No point in repeating ourselves in that case.
         if not fm.isplain():
-            fm.condwrite(ui.verbose, 'files_added', _('Files added: %d\n'),
-                         added)
-            fm.condwrite(ui.verbose, 'files_dropped', _('Files dropped: %d\n'),
-                         dropped)
-            fm.condwrite(ui.verbose, 'files_conflicting',
-                         _('Files conflicting: %d\n'), conflicting)
+            fm.condwrite(
+                ui.verbose, 'files_added', _('Files added: %d\n'), added
+            )
+            fm.condwrite(
+                ui.verbose, 'files_dropped', _('Files dropped: %d\n'), dropped
+            )
+            fm.condwrite(
+                ui.verbose,
+                'files_conflicting',
+                _('Files conflicting: %d\n'),
+                conflicting,
+            )