blob: 8f3a5a9af8102b9dcdf097e257c849d77c998b00 [file] [log] [blame]
#!src/build/run_python
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Suggest owners using owners.py functionality."""
import argparse
import os
import subprocess
import sys
from src.build import owners
from src.build.util import git
def get_owners_db():
return owners.Database(os.getcwd(), open, os.path)
def _get_reviewer_set_for_commit(db, commit):
files = subprocess.check_output(['git', 'diff-tree', '--no-commit-id',
'--name-only', '-r', commit]).splitlines()
author = subprocess.check_output(['git', '--no-pager', 'show', '-s',
'--format=%ae', commit]).rstrip()
return db.reviewer_set_for(files, author)
def suggest_reviewer_set_for_in_flight_commits(verbose):
in_flight_commits = git.get_in_flight_commits()
if not in_flight_commits:
print 'All commits have already been landed on this branch'
return False
db = get_owners_db()
for commit in in_flight_commits:
reviewer_set = _get_reviewer_set_for_commit(db, commit)
print ('REVIEWERS FOR "%s":\n %s' %
(git.get_oneline_for_commit(commit),
format_reviewer_set_in_conjunctive_normal_form(reviewer_set)))
if verbose:
explain_reviewer_set(reviewer_set)
if verbose:
print ''
else:
print ('For more details run: '
'./src/build/suggest_reviewers.py push -v')
def explain_reviewer_set(rs):
for r in sorted(rs.reviewers.keys()):
print ' Reviewer: %s' % r,
if rs.reviewers[r].alternates:
print '(or %s)' % ', '.join(rs.reviewers[r].alternates)
else:
print ''
for comment in sorted(rs.reviewers[r].comments.keys()):
if comment:
print ' # %s' % comment
all_paths = sorted(rs.reviewers[r].comments[comment])
for path in all_paths[:5]:
print ' ' + path
if len(all_paths) == 6:
print ' ' + all_paths[5]
elif len(all_paths) > 6:
print ' (...and %d more...)' % (len(all_paths) - 5)
print ''
def format_reviewer_set_in_conjunctive_normal_form(rs):
def strip_domain(email):
return email.split('@')[0]
def format_disjunction(winner, alternates, needs_parens):
if alternates:
result = ' || '.join([strip_domain(winner)] + list([strip_domain(a)
for a in alternates]))
if needs_parens:
result = '(%s)' % result
return result
return strip_domain(winner)
needs_parens = rs.reviewers.keys() > 1
revs = rs.reviewers
return ' && '.join([format_disjunction(r, revs[r].alternates, needs_parens)
for r in sorted(rs.reviewers.keys())])
def main():
parser = argparse.ArgumentParser()
parser.add_argument('mode', choices=('push', 'commit', 'file'))
parser.add_argument('--verbose', '-v', action='store_true',
help='Verbose output')
parser.add_argument('args', nargs='*')
args = parser.parse_args(sys.argv[1:])
if args.mode == 'push':
return suggest_reviewer_set_for_in_flight_commits(args.verbose) is not False
elif args.mode == 'commit':
db = get_owners_db()
for commit in args.args:
commit = git.canonicalize_commit(commit)
print ('Suggested reviewers for "%s": ' %
git.get_oneline_for_commit(commit))
reviewers = _get_reviewer_set_for_commit(db, commit)
explain_reviewer_set(reviewers)
elif args.mode == 'file':
reviewers = get_owners_db().reviewer_set_for(args.args,
git.get_current_email())
explain_reviewer_set(reviewers)
return 0
if __name__ == '__main__':
sys.exit(main())