[PATCH 1 of 6] scmutil: teach the file prefetch hook to handle multiple commits

Matt Harbison mharbison72 at gmail.com
Sun Apr 15 06:44:05 UTC 2018


# HG changeset patch
# User Matt Harbison <matt_harbison at yahoo.com>
# Date 1523746245 14400
#      Sat Apr 14 18:50:45 2018 -0400
# Node ID de2975df3997148a832ef41425b069fc6f8ff3bc
# Parent  64771e553b1a4fa66ae83a613208ef0adba08a6c
scmutil: teach the file prefetch hook to handle multiple commits

The remainder of the commands that need prefetch deal with multiple revisions.
I initially coded this as a separate hook, but then it needed a list of files
to handle `diff` and `grep`, so it didn't seem worth keeping them separate.

diff --git a/hgext/lfs/wrapper.py b/hgext/lfs/wrapper.py
--- a/hgext/lfs/wrapper.py
+++ b/hgext/lfs/wrapper.py
@@ -244,17 +244,25 @@ def hgpostshare(orig, sourcerepo, destre
     if 'lfs' in destrepo.requirements:
         destrepo.vfs.append('hgrc', util.tonativeeol('\n[extensions]\nlfs=\n'))
 
-def _prefetchfiles(repo, ctx, files):
+def _prefetchfiles(repo, ctxs, files=None):
     """Ensure that required LFS blobs are present, fetching them as a group if
     needed."""
     pointers = []
+    oids = set()
     localstore = repo.svfs.lfslocalblobstore
 
-    for f in files:
-        p = pointerfromctx(ctx, f)
-        if p and not localstore.has(p.oid()):
-            p.filename = f
-            pointers.append(p)
+    filelist = files
+
+    for ctx in ctxs:
+        if files is None:
+            filelist = ctx.manifest().keys()
+
+        for f in filelist:
+            p = pointerfromctx(ctx, f)
+            if p and p.oid() not in oids and not localstore.has(p.oid()):
+                p.filename = f
+                pointers.append(p)
+                oids.add(p.oid())
 
     if pointers:
         # Recalculating the repo store here allows 'paths.default' that is set
diff --git a/mercurial/archival.py b/mercurial/archival.py
--- a/mercurial/archival.py
+++ b/mercurial/archival.py
@@ -320,7 +320,7 @@ def archive(repo, dest, node, kind, deco
     total = len(files)
     if total:
         files.sort()
-        scmutil.fileprefetchhooks(repo, ctx, files)
+        scmutil.fileprefetchhooks(repo, [ctx], files)
         repo.ui.progress(_('archiving'), 0, unit=_('files'), total=total)
         for i, f in enumerate(files):
             ff = ctx.flags(f)
diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -2258,14 +2258,14 @@ def cat(ui, repo, ctx, matcher, basefm, 
         mfnode = ctx.manifestnode()
         try:
             if mfnode and mfl[mfnode].find(file)[0]:
-                scmutil.fileprefetchhooks(repo, ctx, [file])
+                scmutil.fileprefetchhooks(repo, [ctx], [file])
                 write(file)
                 return 0
         except KeyError:
             pass
 
     files = [f for f in ctx.walk(matcher)]
-    scmutil.fileprefetchhooks(repo, ctx, files)
+    scmutil.fileprefetchhooks(repo, [ctx], files)
 
     for abs in files:
         write(abs)
@@ -2946,7 +2946,7 @@ def revert(ui, repo, ctx, parents, *pats
                                 *[actions[name][0] for name in needdata])
             oplist = [actions[name][0] for name in needdata]
             prefetch = scmutil.fileprefetchhooks
-            prefetch(repo, ctx, [f for sublist in oplist for f in sublist])
+            prefetch(repo, [ctx], [f for sublist in oplist for f in sublist])
             _performrevert(repo, parents, ctx, actions, interactive, tobackup)
 
         if targetsubs:
diff --git a/mercurial/merge.py b/mercurial/merge.py
--- a/mercurial/merge.py
+++ b/mercurial/merge.py
@@ -1474,7 +1474,7 @@ def _prefetchfiles(repo, ctx, actions):
     oplist = [actions[a] for a in (ACTION_GET, ACTION_DELETED_CHANGED,
                                    ACTION_LOCAL_DIR_RENAME_GET, ACTION_MERGE)]
     prefetch = scmutil.fileprefetchhooks
-    prefetch(repo, ctx, [f for sublist in oplist for f, args, msg in sublist])
+    prefetch(repo, [ctx], [f for sublist in oplist for f, args, msg in sublist])
 
 @attr.s(frozen=True)
 class updateresult(object):
diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -1354,9 +1354,11 @@ class simplekeyvaluefile(object):
     'unbundle',
 ]
 
-# a list of (repo, ctx, files) functions called by various commands to allow
-# extensions to ensure the corresponding files are available locally, before the
-# command uses them.
+# A list of (repo, ctxs, files=None) functions called by various commands to
+# allow extensions to ensure the corresponding files are available locally,
+# before the command uses them.  If files is None, all files in the commit
+# should be fetched.  If files are listed, it is a union of the set of files,
+# and a given file may not be present in a particular context.
 fileprefetchhooks = util.hooks()
 
 # A marker that tells the evolve extension to suppress its own reporting
diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py
--- a/mercurial/subrepo.py
+++ b/mercurial/subrepo.py
@@ -562,7 +562,7 @@ class hgsubrepo(abstractsubrepo):
             files = [f for f in files if match(f)]
         rev = self._state[1]
         ctx = self._repo[rev]
-        scmutil.fileprefetchhooks(self._repo, ctx, files)
+        scmutil.fileprefetchhooks(self._repo, [ctx], files)
         total = abstractsubrepo.archive(self, archiver, prefix, match)
         for subpath in ctx.substate:
             s = subrepo(ctx, subpath, True)


More information about the Mercurial-devel mailing list