Index: recipe_engine/fetch.py |
diff --git a/recipe_engine/fetch.py b/recipe_engine/fetch.py |
index 4554f4c8e5f0af0a1a20bc8a3a71f4cabf772e86..50f82eb0aa0e38629007eaa83d218567b9fd53ff 100644 |
--- a/recipe_engine/fetch.py |
+++ b/recipe_engine/fetch.py |
@@ -7,6 +7,7 @@ import httplib |
import json |
import logging |
import os |
+import re |
import shutil |
import sys |
import tarfile |
@@ -16,6 +17,7 @@ import tempfile |
from . import env |
from . import requests_ssl |
from . import util |
+from . import types |
from .requests_ssl import requests |
import subprocess42 |
@@ -60,10 +62,35 @@ class Backend(object): |
""" |
raise NotImplementedError() |
+ # This is a simple mapping of |
+ # repo -> git_revision -> commit_metadata() |
+ # It only holds cache entries for git commits (e.g. sha1 hashes) |
+ _GIT_METADATA_CACHE = {} |
+ |
+ # This matches git commit hashes. |
+ _COMMIT_RE = re.compile('^[a-fA-F0-9]{40}$') |
+ |
def commit_metadata(self, repo, revision, checkout_dir, allow_fetch): |
+ """Cached version of commit_metadata_slow. Implementations should only |
+ override commit_metadata_slow and this implementation will call it if |
+ there's no cached value for (repo, revision). |
+ """ |
+ if self._COMMIT_RE.match(revision): |
+ cache = self._GIT_METADATA_CACHE.setdefault(repo, {}) |
+ if revision not in cache: |
+ cache[revision] = types.freeze(self.commit_metadata_slow( |
+ repo, revision, checkout_dir, allow_fetch)) |
+ return cache[revision] |
+ return self.commit_metadata_slow(repo, revision, checkout_dir, allow_fetch) |
+ |
+ def commit_metadata_slow(self, repo, revision, checkout_dir, allow_fetch): |
"""Returns a dictionary of metadata about commit |revision|. |
The dictionary contains the following keys: author, message. |
+ |
+ This implementation will likely do slow operations (e.g. subprocess |
+ invocations, network access, etc.). Users of Backend will always want to use |
+ commit_metadata() instead. |
""" |
raise NotImplementedError() |
@@ -175,7 +202,7 @@ class GitBackend(Backend): |
args.extend(['--'] + paths) |
return filter(bool, git(*args).strip().split('\n')) |
- def commit_metadata(self, repo, revision, checkout_dir, allow_fetch): |
+ def commit_metadata_slow(self, repo, revision, checkout_dir, allow_fetch): |
git = self.Git(checkout_dir=checkout_dir) |
return { |
'author': git('show', '-s', '--pretty=%aE', revision).strip(), |
@@ -290,7 +317,7 @@ class GitilesBackend(Backend): |
return list(reversed(results)) |
- def commit_metadata(self, repo, revision, checkout_dir, allow_fetch): |
+ def commit_metadata_slow(self, repo, revision, checkout_dir, allow_fetch): |
if not allow_fetch: |
raise FetchNotAllowedError( |
('requested commit metadata for %s (%s)from gitiles but fetch not ' |