summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorPaul Hobbs <phobbs@google.com>2015-06-24 14:07:49 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-07-15 03:39:12 +0000
commit8976523cb7cb5c4b3c5ef751c4a22d8baaa1d659 (patch)
treeff97ab27d05ac564933e00fcf9eb023f66508e21 /scripts
parent8fa54f088d3cbd10c93d51e4a99b01968f0d7cf5 (diff)
downloadchromite-8976523cb7cb5c4b3c5ef751c4a22d8baaa1d659.tar.gz
gerrit: Added "gerrit deps" (finds transitive deps)
The command does breadth-first search on the dependency graph defined by Gerrit dependencies and CQ-DEPENDS dependencies. This enables, for example, marking all CLs reachable from a CL as ready: gerrit ready `gerrit --raw deps <cl-number>` 1 TEST=Manual testing with various CLs. BUG=chromium:412972 Change-Id: I3682313bf48636707c343b4bf9cee74fd3af2229 Reviewed-on: https://chromium-review.googlesource.com/281770 Reviewed-by: David James <davidjames@chromium.org> Tested-by: Paul Hobbs <phobbs@google.com> Commit-Queue: Paul Hobbs <phobbs@google.com>
Diffstat (limited to 'scripts')
-rw-r--r--scripts/gerrit.py72
1 files changed, 65 insertions, 7 deletions
diff --git a/scripts/gerrit.py b/scripts/gerrit.py
index dbd1b1394..ae97e4902 100644
--- a/scripts/gerrit.py
+++ b/scripts/gerrit.py
@@ -80,7 +80,7 @@ def GetGerrit(opts, cl=None):
A tuple of a gerrit object and a sanitized CL #.
"""
gob = opts.gob
- if not cl is None:
+ if cl is not None:
if cl.startswith('*'):
gob = constants.INTERNAL_GOB_INSTANCE
cl = cl[1:]
@@ -166,10 +166,8 @@ def _MyUserInfo():
return emails, reviewers, owners
-def FilteredQuery(opts, query):
- """Query gerrit and filter/clean up the results"""
- ret = []
-
+def _Query(opts, query, raw=True):
+ """Queries Gerrit with a query string built from the commandline options"""
if opts.branch is not None:
query += ' branch:%s' % opts.branch
if opts.project is not None:
@@ -178,7 +176,14 @@ def FilteredQuery(opts, query):
query += ' topic: %s' % opts.topic
helper, _ = GetGerrit(opts)
- for cl in helper.Query(query, raw=True, bypass_cache=False):
+ return helper.Query(query, raw=raw, bypass_cache=False)
+
+
+def FilteredQuery(opts, query):
+ """Query gerrit and filter/clean up the results"""
+ ret = []
+
+ for cl in _Query(opts, query, raw=True):
# Gerrit likes to return a stats record too.
if not 'project' in cl:
continue
@@ -193,7 +198,7 @@ def FilteredQuery(opts, query):
ret.append(cl)
- if opts.sort in ('number',):
+ if opts.sort == 'number':
key = lambda x: int(x[opts.sort])
else:
key = lambda x: x[opts.sort]
@@ -245,6 +250,59 @@ def UserActMine(opts):
UserActSearch(opts, '( %s ) status:new' % (' OR '.join(owners),))
+def _BreadthFirstSearch(to_visit, children, visited_key=lambda x: x):
+ """Runs breadth first search starting from the nodes in |to_visit|
+
+ Args:
+ to_visit: the starting nodes
+ children: a function which takes a node and returns the nodes adjacent to it
+ visited_key: a function for deduplicating node visits. Defaults to the
+ identity function (lambda x: x)
+
+ Returns:
+ A list of nodes which are reachable from any node in |to_visit| by calling
+ |children| any number of times.
+ """
+ to_visit = list(to_visit)
+ seen = set(map(visited_key, to_visit))
+ for node in to_visit:
+ for child in children(node):
+ key = visited_key(child)
+ if key not in seen:
+ seen.add(key)
+ to_visit.append(child)
+ return to_visit
+
+
+def UserActDeps(opts, query):
+ """List CLs matching a query, and all transitive dependencies of those CLs"""
+ cls = _Query(opts, query, raw=False)
+
+ @cros_build_lib.Memoize
+ def _QueryChange(cl):
+ return _Query(opts, cl, raw=False)
+
+ def _Children(cl):
+ """Returns the Gerrit and CQ-Depends dependencies of a patch"""
+ cq_deps = cl.PaladinDependencies(None)
+ direct_deps = cl.GerritDependencies() + cq_deps
+ # We need to query the change to guarantee that we have a .gerrit_number
+ for dep in direct_deps:
+ # TODO(phobbs) this should maybe catch network errors.
+ change = _QueryChange(dep.ToGerritQueryText())[-1]
+ if change.status == 'NEW':
+ yield change
+
+ transitives = _BreadthFirstSearch(
+ cls, _Children,
+ visited_key=lambda cl: cl.gerrit_number)
+
+ transitives_raw = [cl.patch_dict for cl in transitives]
+ lims = limits(transitives_raw)
+ for cl in transitives_raw:
+ PrintCl(opts, cl, lims)
+
+
def UserActInspect(opts, *args):
"""Inspect CL number <n> [n ...]"""
for arg in args: