commit-bot@chromium.org | 0ed9002 | 2014-01-30 22:12:30 +0000 | [diff] [blame] | 1 | #!/usr/bin/python2 |
| 2 | |
| 3 | # Copyright 2014 Google Inc. |
| 4 | # |
| 5 | # Use of this source code is governed by a BSD-style license that can be |
| 6 | # found in the LICENSE file. |
| 7 | |
| 8 | """Add message to codereview issue. |
| 9 | |
| 10 | This script takes a codereview URL or a codereview issue number as its |
| 11 | argument and a (possibly multi-line) message on stdin. It then calls |
| 12 | `git cl upload` to append the message to the given codereview issue. |
| 13 | |
| 14 | Usage: |
| 15 | echo MESSAGE | %prog -c CHECKOUT_PATH CODEREVIEW_ISSUE |
| 16 | or: |
| 17 | cd /path/to/git/checkout |
| 18 | %prog CODEREVIEW_ISSUE <<EOF |
| 19 | MESSAGE |
| 20 | EOF |
| 21 | or: |
| 22 | %prog --help |
| 23 | """ |
| 24 | |
| 25 | import optparse |
| 26 | import os |
| 27 | import sys |
| 28 | |
| 29 | import git_utils |
| 30 | import misc_utils |
| 31 | |
| 32 | |
| 33 | DEFAULT_REVIEWERS = ','.join([ |
| 34 | 'rmistry@google.com', |
| 35 | 'reed@google.com', |
| 36 | 'bsalomon@google.com', |
| 37 | 'robertphillips@google.com', |
| 38 | ]) |
| 39 | |
| 40 | |
| 41 | DEFAULT_CC_LIST = ','.join([ |
| 42 | 'skia-team@google.com', |
| 43 | ]) |
| 44 | |
| 45 | |
| 46 | def add_codereview_message(codereview_url, message, checkout_path, |
| 47 | skip_cl_upload, verbose, reviewers, cclist): |
| 48 | """Add a message to a given codereview. |
| 49 | |
| 50 | Args: |
| 51 | codereview_url: (string) we will extract the issue number from |
| 52 | this url, or this could simply be the issue number. |
| 53 | message: (string) will be passed to `git cl upload -m $MESSAGE` |
| 54 | checkout_path: (string) location of the git |
| 55 | repository checkout to be used. |
| 56 | skip_cl_upload: (boolean) if true, don't actually |
| 57 | add the message and keep the temporary branch around. |
| 58 | verbose: (boolean) print out details useful for debugging. |
| 59 | reviewers: (string) comma-separated list of reviewers |
| 60 | cclist: (string) comma-separated list of addresses to be |
| 61 | carbon-copied |
| 62 | """ |
| 63 | # pylint: disable=I0011,R0913 |
| 64 | git = git_utils.git_executable() |
| 65 | issue = codereview_url.strip('/').split('/')[-1] |
| 66 | vsp = misc_utils.VerboseSubprocess(verbose) |
| 67 | if skip_cl_upload: |
| 68 | branch_name = 'issue_%s' % issue |
| 69 | else: |
| 70 | branch_name = None |
| 71 | upstream = 'origin/master' |
| 72 | |
| 73 | with misc_utils.ChangeDir(checkout_path, verbose): |
| 74 | vsp.check_call([git, 'fetch', '-q', 'origin']) |
| 75 | |
| 76 | with git_utils.ChangeGitBranch(branch_name, upstream, verbose): |
| 77 | vsp.check_call([git, 'cl', 'patch', issue]) |
| 78 | |
| 79 | git_upload = [ |
| 80 | git, 'cl', 'upload', '-t', 'bot report', '-m', message] |
| 81 | if cclist: |
| 82 | git_upload.append('--cc=' + cclist) |
| 83 | if reviewers: |
| 84 | git_upload.append('--reviewers=' + reviewers) |
| 85 | |
| 86 | if skip_cl_upload: |
| 87 | branch_name = git_utils.git_branch_name(verbose) |
| 88 | space = ' ' |
| 89 | print 'You should call:' |
| 90 | misc_utils.print_subprocess_args(space, ['cd', os.getcwd()]) |
| 91 | misc_utils.print_subprocess_args( |
| 92 | space, [git, 'checkout', branch_name]) |
| 93 | misc_utils.print_subprocess_args(space, git_upload) |
| 94 | else: |
| 95 | vsp.check_call(git_upload) |
| 96 | print vsp.check_output([git, 'cl', 'issue']) |
| 97 | |
| 98 | |
| 99 | def main(argv): |
| 100 | """main function; see module-level docstring and GetOptionParser help. |
| 101 | |
| 102 | Args: |
| 103 | argv: sys.argv[1:]-type argument list. |
| 104 | """ |
| 105 | option_parser = optparse.OptionParser(usage=__doc__) |
| 106 | option_parser.add_option( |
| 107 | '-c', '--checkout_path', |
| 108 | default=os.curdir, |
| 109 | help='Path to the Git repository checkout,' |
| 110 | ' defaults to current working directory.') |
| 111 | option_parser.add_option( |
| 112 | '', '--skip_cl_upload', action='store_true', default=False, |
| 113 | help='Skip the cl upload step; useful for testing.') |
| 114 | option_parser.add_option( |
| 115 | '', '--verbose', action='store_true', dest='verbose', default=False, |
| 116 | help='Do not suppress the output from `git cl`.',) |
| 117 | option_parser.add_option( |
| 118 | '', '--git_path', default='git', |
| 119 | help='Git executable, defaults to "git".',) |
| 120 | option_parser.add_option( |
| 121 | '', '--reviewers', default=DEFAULT_REVIEWERS, |
| 122 | help=('Comma-separated list of reviewers. Default is "%s".' |
| 123 | % DEFAULT_REVIEWERS)) |
| 124 | option_parser.add_option( |
| 125 | '', '--cc', default=DEFAULT_CC_LIST, |
| 126 | help=('Comma-separated list of addresses to be carbon-copied.' |
| 127 | ' Default is "%s".' % DEFAULT_CC_LIST)) |
| 128 | |
| 129 | options, arguments = option_parser.parse_args(argv) |
| 130 | |
| 131 | if not options.checkout_path: |
| 132 | option_parser.error('Must specify checkout_path.') |
| 133 | if not git_utils.git_executable(): |
| 134 | option_parser.error('Invalid git executable.') |
| 135 | if len(arguments) > 1: |
| 136 | option_parser.error('Extra arguments.') |
| 137 | if len(arguments) != 1: |
| 138 | option_parser.error('Missing Codereview URL.') |
| 139 | |
| 140 | message = sys.stdin.read() |
| 141 | add_codereview_message(arguments[0], message, options.checkout_path, |
| 142 | options.skip_cl_upload, options.verbose, |
| 143 | options.reviewers, options.cc) |
| 144 | |
| 145 | |
| 146 | if __name__ == '__main__': |
| 147 | main(sys.argv[1:]) |
| 148 | |