Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(733)

Unified Diff: recipe_engine/fetch.py

Issue 2833723003: [autoroller] All commits in updates(), only roll interesting ones. (Closed)
Patch Set: fix nits Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « recipe_engine/autoroll_impl/commit_list.py ('k') | recipe_engine/package.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: recipe_engine/fetch.py
diff --git a/recipe_engine/fetch.py b/recipe_engine/fetch.py
index 8f417bf34906bf9da46a318720484a0ff8546544..4e5313227ed106226ad95ca2107fc2bab7187706 100644
--- a/recipe_engine/fetch.py
+++ b/recipe_engine/fetch.py
@@ -31,6 +31,14 @@ from google.protobuf import json_format
LOGGER = logging.getLogger(__name__)
+def has_interesting_changes(spec, changed_files):
+ # TODO(iannucci): analyze bundle_extra_paths.txt too.
+ return (
+ 'infra/config/recipes.cfg' in changed_files or
+ any(f.startswith(spec.recipes_path) for f in changed_files)
+ )
+
+
class FetchError(Exception):
pass
@@ -48,9 +56,12 @@ class UnresolvedRefspec(Exception):
# commit_timestamp (int): the unix commit timestamp for this commit
# message_lines (tuple(str)): the message of this commit
# spec (package_pb2.Package): the parsed infra/config/recipes.cfg file or None.
+# roll_candidate (bool): if this commit contains changes which are known to
+# affect the behavior of the recipes (i.e. modifications within recipe_path
+# and/or modifications to recipes.cfg)
CommitMetadata = namedtuple(
'_CommitMetadata',
- 'revision author_email commit_timestamp message_lines spec')
+ 'revision author_email commit_timestamp message_lines spec roll_candidate')
class Backend(object):
@@ -114,11 +125,7 @@ class Backend(object):
The refspec will be resolved if it's not absolute.
- Returns {
- 'author': '<author name>',
- 'message': '<commit message>',
- 'spec': package_pb2.Package or None, # the parsed recipes.cfg file.
- }
+ Returns (CommitMetadata).
"""
revision = self.resolve_refspec(refspec)
cache = self._GIT_METADATA_CACHE.setdefault(self.repo_url, {})
@@ -140,18 +147,16 @@ class Backend(object):
return refspec
return self._resolve_refspec_impl(refspec)
- def updates(self, revision, other_revision, paths):
+ def updates(self, revision, other_revision):
"""Returns a list of revisions |revision| through |other_revision|
(inclusive).
- If |paths| is a non-empty list, the history is scoped just to these paths.
-
Returns list(CommitMetadata) - The commit metadata in the range
(revision,other_revision].
"""
self.assert_resolved(revision)
self.assert_resolved(other_revision)
- return self._updates_impl(revision, other_revision, paths)
+ return self._updates_impl(revision, other_revision)
### direct overrides. These are public methods which must be overridden.
@@ -185,12 +190,10 @@ class Backend(object):
### private overrides. Override these in the implementations, but don't call
### externally.
- def _updates_impl(self, revision, other_revision, paths):
+ def _updates_impl(self, revision, other_revision):
"""Returns a list of revisions |revision| through |other_revision|. This
includes |revision| and |other_revision|.
- If |paths| is a non-empty list, the history is scoped just to these paths.
-
Args:
revision (str) - the first git commit
other_revision (str) - the second git commit
@@ -327,15 +330,13 @@ class GitBackend(Backend):
except GitError:
self._git('reset', '-q', '--hard', revision)
- def _updates_impl(self, revision, other_revision, paths):
+ def _updates_impl(self, revision, other_revision):
args = [
'rev-list',
'--reverse',
'--topo-order',
'%s..%s' % (revision, other_revision),
]
- if paths:
- args.extend(['--'] + paths)
return [
self.commit_metadata(rev)
for rev in self._git(*args).strip().split('\n')
@@ -367,9 +368,14 @@ class GitBackend(Backend):
except GitError:
spec = None
+ # check diff to see if it touches anything interesting.
+ changed_files = set(self._git(
+ 'diff-tree', '-r', '--no-commit-id', '--name-only', '%s^!' % revision)
+ .splitlines())
+
return CommitMetadata(revision, meta[0],
int(meta[1]), tuple(meta[2:]),
- spec)
+ spec, has_interesting_changes(spec, changed_files))
class GitilesFetchError(FetchError):
"""An HTTP error that occurred during Gitiles fetching."""
@@ -393,16 +399,22 @@ class GitilesFetchError(FetchError):
# commit (str) - the git commit hash
# author_email (str) - the author email for this commit
# message_lines (tuple) - the lines of the commit message
+# changed_files (frozenset) - all paths touched by this commit
class _GitilesCommitJson(namedtuple(
'_GitilesCommitJson',
- 'commit author_email commit_timestamp message_lines')):
+ 'commit author_email commit_timestamp message_lines changed_files')):
@classmethod
def from_raw_json(cls, raw):
+ mod_files = set()
+ for entry in raw['tree_diff']:
+ mod_files.add(entry['old_path'])
+ mod_files.add(entry['new_path'])
return cls(
raw['commit'],
raw['author']['email'],
calendar.timegm(time.strptime(raw['committer']['time'])),
tuple(raw['message'].splitlines()),
+ frozenset(mod_files),
)
@@ -432,9 +444,14 @@ class GitilesBackend(Backend):
raise GitilesFetchError(resp.status_code, resp.text)
return resp
- def _fetch_gitiles_json(self, url_fmt, *args):
+ def _fetch_gitiles_committish_json(self, url_fmt, *args):
"""Fetches a remote URL path and expects a JSON object on success.
+ This appends two GET params to url_fmt:
+ format=JSON - Does what you expect
+ name-status=1 - Ensures that commit objects returned have a 'tree_diff'
+ member which shows the diff for that commit.
+
Args:
url_fmt (str) - the url path fragment as a python %format string, like
'%s/foo/bar?something=value'
@@ -443,7 +460,7 @@ class GitilesBackend(Backend):
Returns the decoded JSON object
"""
- resp = self._fetch_gitiles(url_fmt, *args)
+ resp = self._fetch_gitiles(url_fmt+'?name-status=1&format=JSON', *args)
if not resp.text.startswith(self._GERRIT_XSRF_HEADER):
raise GitilesFetchError(resp.status_code, 'Missing XSRF prefix')
return json.loads(resp.text[len(self._GERRIT_XSRF_HEADER):])
@@ -466,7 +483,7 @@ class GitilesBackend(Backend):
if refspec in c:
return c[refspec]
- raw = self._fetch_gitiles_json('+/%s?format=JSON', refspec)
+ raw = self._fetch_gitiles_committish_json('+/%s', refspec)
ret = _GitilesCommitJson.from_raw_json(raw)
if self.is_resolved_revision(refspec):
c[refspec] = ret
@@ -525,14 +542,13 @@ class GitilesBackend(Backend):
with tarfile.open(fileobj=StringIO(archive_response.content)) as tf:
tf.extractall(recipes_path)
- def _updates_impl(self, revision, other_revision, paths):
+ def _updates_impl(self, revision, other_revision):
self.assert_remote('_updates_impl')
# TODO(iannucci): implement paging
- # To include info about touched paths (tree_diff), pass name-status=1 below.
- log_json = self._fetch_gitiles_json(
- '+log/%s..%s?name-status=1&format=JSON', revision, other_revision)
+ log_json = self._fetch_gitiles_committish_json(
+ '+log/%s..%s', revision, other_revision)
c = self._COMMIT_JSON_CACHE.setdefault(self.repo_url, {})
@@ -540,18 +556,7 @@ class GitilesBackend(Backend):
for entry in log_json['log']:
commit = entry['commit']
c[commit] = _GitilesCommitJson.from_raw_json(entry)
-
- matched = False
- for path in paths:
- for diff_entry in entry['tree_diff']:
- if (diff_entry['old_path'].startswith(path) or
- diff_entry['new_path'].startswith(path)):
- matched = True
- break
- if matched:
- break
- if matched or not paths:
- results.append(commit)
+ results.append(commit)
results.reverse()
return map(self.commit_metadata, results)
@@ -576,4 +581,5 @@ class GitilesBackend(Backend):
rev_json.author_email,
rev_json.commit_timestamp,
rev_json.message_lines,
- spec)
+ spec,
+ has_interesting_changes(spec, rev_json.changed_files))
« no previous file with comments | « recipe_engine/autoroll_impl/commit_list.py ('k') | recipe_engine/package.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698