| #!/usr/bin/env python | |
| # Copyright 2017 The Fuchsia Authors. All rights reserved. | |
| # Use of this source code is governed by a BSD-style license that can be | |
| # found in the LICENSE file. | |
| ### view commits not yet rolled to a layer | |
| import argparse | |
| from argparse import RawTextHelpFormatter | |
| import base64 | |
| import json | |
| import requests | |
| import sys | |
| import xml.etree.ElementTree as xml | |
| LAYERS = [ | |
| 'vendor', # For checkouts building on top of Topaz. | |
| 'topaz', | |
| 'peridot', | |
| 'garnet', | |
| 'zircon', | |
| ] | |
| def get_lower_layer(layer): | |
| """Returns the layer immediately below the given layer.""" | |
| index = LAYERS.index(layer) | |
| if index == len(LAYERS) - 1: | |
| return None | |
| return LAYERS[index + 1] | |
| def get_lower_layer_commit(layer, at): | |
| """Returns the pinned revision of the layer below the given layer.""" | |
| lower_layer = get_lower_layer(layer) | |
| if not lower_layer: | |
| return (None, None) | |
| url = ('https://fuchsia.googlesource.com/%s/+/%s/manifest/%s?format=TEXT' | |
| % (layer, at, layer)) | |
| content = requests.get(url).content | |
| content = base64.b64decode(content) | |
| manifest = xml.fromstring(content) | |
| nodes = manifest.findall('./imports/import[@name="%s"]' % lower_layer) | |
| return (lower_layer, nodes[0].get('revision')) | |
| def get_commits(layer, revision): | |
| """Returns the commits in the given layer up to a given commit.""" | |
| url = 'https://fuchsia.googlesource.com/%s/+log/master?format=JSON' % layer | |
| def get_more(result, start=None): | |
| get_url = url | |
| if start: | |
| get_url = '%s&s=%s' % (url, start) | |
| content = requests.get(url).content | |
| # Remove the anti-XSSI header. | |
| content = content[5:] | |
| data = json.loads(content) | |
| for commit in data['log']: | |
| if commit['commit'] == revision: | |
| return | |
| result.append(commit) | |
| get_more(result, start=content['next']) | |
| result = [] | |
| get_more(result) | |
| return result | |
| def filter_commit(commit): | |
| """Returns True if a commit should be listed.""" | |
| author = commit['author']['name'] | |
| if author == 'skia-deps-roller@chromium.org': | |
| return False | |
| for layer in LAYERS: | |
| if author == '%s-roller' % layer: | |
| return False | |
| return True | |
| def print_commits(layer, commits): | |
| """Prints the given commits in a user=pleasing format.""" | |
| commits = [c for c in commits if filter_commit(c)] | |
| print('') | |
| print(' --------------') | |
| print(' | %s |' % '{:^10}'.format(layer)) | |
| print(' --------------') | |
| for commit in commits: | |
| print('%s | %s | %s' % (commit['commit'][:7], | |
| commit['author']['name'][:15].ljust(15), | |
| commit['message'].splitlines()[0])) | |
| if not commits: | |
| print('None') | |
| def main(): | |
| parser = argparse.ArgumentParser(formatter_class=RawTextHelpFormatter, | |
| description="""Displays the commits not yet rolled to a given layer. | |
| For vendor layers, specify the Topaz revision with --topaz-revision.""") | |
| parser.add_argument('--layer', | |
| help='Name of the layer to inspect', | |
| choices=LAYERS, | |
| default='topaz') | |
| parser.add_argument('--topaz-revision', | |
| help='(vendor only) revision of the Topaz layer') | |
| args = parser.parse_args() | |
| layer = args.layer | |
| revision = args.topaz_revision | |
| if layer != 'vendor' and revision: | |
| print('Warning: Topaz revision only used with vendor layers.') | |
| if layer == 'vendor' and not revision: | |
| print('Error: vendor layers require a Topaz revision.') | |
| return 1 | |
| if layer == 'vendor': | |
| commits = get_commits('topaz', revision) | |
| print_commits('topaz', commits) | |
| layer = 'topaz' | |
| else: | |
| revision = 'master' | |
| while True: | |
| (lower_layer, lower_revision) = get_lower_layer_commit(layer, revision) | |
| if not lower_layer: | |
| break | |
| commits = get_commits(lower_layer, lower_revision) | |
| print_commits(lower_layer, commits) | |
| layer = lower_layer | |
| revision = lower_revision | |
| return 0 | |
| if __name__ == "__main__": | |
| sys.exit(main()) |