#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) 2012 Spotify AB

# Script to create a Gerrit review for a commit, specifying reviewers and
# optional CCs on the command line.

import argparse
import itertools
import subprocess
import sys


def main(argv):
    parser = argparse.ArgumentParser(description='Send a git commit for review in Gerrit.',
        prog='git review',
        epilog='NOTE: the commit you want reviewed should be the HEAD of the current branch')
    parser.add_argument('-r', '--reviewers', metavar='reviewer', type=str, nargs='+',
        help=('one or more usernames or group names to review this commit, '
              'must be valid Gerrit users or groups; comma- or space-separated.'))
    parser.add_argument('-b', '--branch', type=str, dest='branch', default=None,
        help='remote branch to push to for review. Default: current branch')
    parser.add_argument('-d', '--draft', action='store_true', default=False,
        help='push as draft. Default: false')
    parser.add_argument('-c', '--cc', type=str, metavar='ccEmail', default=[], nargs='+',
        help=('usernames or group names to CC on the review email, '
              'must be valid Gerrit users or groups; comma- or space-separated. '
              'Default: none'))

    # make sure git command exists
    try:
        subprocess.check_call(['git', '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    except OSError, e:
        print "Cannot find git executable!\n"
        parser.print_help()
        sys.exit(1)

    args = parser.parse_args(argv[1:])

    if not args.reviewers:
        print "Missing required -r/--reviewers argument!\n"
        parser.print_help()
        sys.exit(1)

    if not args.branch:
        current = _get_current_branch()
        args.branch = current if current else 'master'

    reviewers = _get_names(args.reviewers)
    reviewer_emails = [u + '@spotify.com' for u in reviewers]
    ccs = _get_names(args.cc)
    cc_emails = [u + '@spotify.com' for u in ccs]

    try:
        reviewer_flags = ' '.join('--reviewer=' + r for r in reviewer_emails)
        cc_flags = ' '.join('--cc=' + c for c in cc_emails)
        receive_pack = 'git receive-pack %s %s' % (reviewer_flags, cc_flags)
        git_push = ['git', 'push', 'origin', '--receive-pack=%s' % receive_pack,
                    'HEAD:refs/%s/%s' % (('drafts' if args.draft else 'for'), args.branch)]
        print ' '.join(git_push)
        subprocess.check_call(git_push)
    except subprocess.CalledProcessError as e:
        print 'git command failed', e
        raise e


def _get_names(user_group_names):
  """Construct a list of names from a list of user/group names.

  Input names may be comma delimited instead of separated into multiple strings.
  Output will be a list of separate strings, no commas.
  """
  return list(itertools.chain.from_iterable(s.split(',') for s in user_group_names))


def _get_current_branch():
    """Get current branch."""
    child = subprocess.Popen(['git', 'symbolic-ref', 'HEAD'],
        stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    if child.wait() != 0: return None

    out = child.stdout.readlines()
    PREFIX='refs/heads/'
    if len(out) > 0 and out[0].startswith(PREFIX):
        return out[0].strip()[len(PREFIX):]

    return None


if __name__ == "__main__":
    main(sys.argv)
