| #!/usr/bin/env python | 
 | # Copyright (C) 2014 The Android Open Source Project | 
 | # | 
 | # Licensed under the Apache License, Version 2.0 (the "License"); | 
 | # you may not use this file except in compliance with the License. | 
 | # You may obtain a copy of the License at | 
 | # | 
 | # http://www.apache.org/licenses/LICENSE-2.0 | 
 | # | 
 | # Unless required by applicable law or agreed to in writing, software | 
 | # distributed under the License is distributed on an "AS IS" BASIS, | 
 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | # See the License for the specific language governing permissions and | 
 | # limitations under the License. | 
 |  | 
 | from __future__ import print_function | 
 |  | 
 | import argparse | 
 | import collections | 
 | import os | 
 | import subprocess | 
 | import sys | 
 |  | 
 |  | 
 | def get_config(name): | 
 |  args = ['git', 'config', '--get', name] | 
 |  p = subprocess.Popen(args, stdout=subprocess.PIPE) | 
 |  out, _ = p.communicate() | 
 |  ret = p.poll() | 
 |  if ret not in (0, 1): | 
 |  raise subprocess.CalledProcessError(ret, ' '.join(args), output=out) | 
 |  return out.strip() | 
 |  | 
 |  | 
 | def deref(name): | 
 |  p = subprocess.Popen( | 
 |  ['git', 'rev-parse', '--symbolic-full-name', name], | 
 |  stdout=subprocess.PIPE, stderr=subprocess.PIPE) | 
 |  out, _ = p.communicate() | 
 |  return out.strip() | 
 |  | 
 |  | 
 | def main(argv): | 
 |  p = argparse.ArgumentParser(description='Push changes to Gerrit for review') | 
 |  p.add_argument('-r', '--remote', default='', metavar='REMOTE', | 
 |  help='remote name or URL to push to') | 
 |  p.add_argument('-b', '--branch', default='', metavar='BRANCH', | 
 |  help='remote branch name, refs/for/BRANCH') | 
 |  p.add_argument('args', nargs='*', metavar='REVIEWER_OR_HASHTAG', | 
 |  help='reviewer names or aliases, or #hashtags') | 
 |  p.add_argument('-t', '--topic', default='', metavar='TOPIC', | 
 |  help='topic for new changes') | 
 |  p.add_argument('--dry-run', action='store_true', | 
 |  help='dry run, print git command and exit') | 
 |  args = p.parse_args() | 
 |  | 
 |  if not args.remote or not args.branch: | 
 |  hp = 'refs/heads/' | 
 |  upstream = deref('HEAD') | 
 |  while upstream.startswith(hp): | 
 |  upstream = deref(upstream[len(hp):] + '@{u}') | 
 |  | 
 |  rp = 'refs/remotes/' | 
 |  if upstream.startswith(rp): | 
 |  def_remote, def_branch = upstream[len(rp):].split('/', 1) | 
 |  else: | 
 |  def_remote, def_branch = 'origin', 'master' | 
 |  args.remote = args.remote or def_remote | 
 |  args.branch = args.branch or def_branch | 
 |  | 
 |  | 
 |  opts = collections.defaultdict(list) | 
 |  is_hashtag = lambda x: x.startswith('#') | 
 |  opts['r'].extend( | 
 |  (get_config('reviewer.' + r) or r) | 
 |  for r in args.args if not is_hashtag(r)) | 
 |  opts['t'].extend(t[1:] for t in args.args if is_hashtag(t)) | 
 |  if args.topic: | 
 |  opts['topic'].append(args.topic) | 
 |  opts_str = ','.join('%s=%s' % (k, v) for k in opts for v in opts[k]) | 
 |  if opts_str: | 
 |  opts_str = '%' + opts_str | 
 |  | 
 |  git_args = ['git', 'push', args.remote, | 
 |  'HEAD:refs/for/%s%s' % (args.branch, opts_str)] | 
 |  if args.dry_run: | 
 |  print(' '.join(git_args)) | 
 |  return 0 | 
 |  os.execvp('git', git_args) | 
 |  | 
 |  | 
 | if __name__ == '__main__': | 
 |  sys.exit(main(sys.argv)) |