#!/usr/bin/env python3
# Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.

# Script that automatically pulls and uploads all upstream direct and indirect
# branches into the current branch.
#
# Example:
#
#   $ git branch -vv
#   * feature_final    xxxxxxxxx [feature_prereq_c: ...] ...
#     feature_prereq_c xxxxxxxxx [feature_prereq_b: ...] ...
#     feature_prereq_b xxxxxxxxx [feature_prereq_a: ...] ...
#     feature_prereq_a xxxxxxxxx [main: ...] ...
#     main             xxxxxxxxx [origin/main] ...
#
# Executing `git_sync_cl_chain.py -m <message>` causes the following chain of
# commands to be executed:
#
#   $ git checkout feature_prereq_a; git pull; git cl upload -m <message>
#   $ git checkout feature_prereq_b; git pull; git cl upload -m <message>
#   $ git checkout feature_prereq_c; git pull; git cl upload -m <message>
#   $ git checkout feature_final;    git pull; git cl upload -m <message>

import optparse
import os
import sys

import defines
import utils

REPO_ROOT = defines.REPO_ROOT

class Repo(object):
  def __init__(self, name, is_current, upstream):
    self.name = name
    self.is_current = is_current
    self.upstream = upstream

def ParseOptions(argv):
  result = optparse.OptionParser()
  result.add_option('--bypass-hooks',
                    help='Bypass presubmit hooks',
                    action='store_true')
  result.add_option('--delete', '-d',
                    help='Delete closed branches',
                    choices=['y', 'n', 'ask'],
                    default='ask')
  result.add_option('--from_branch', '-f',
                    help='Uppermost upstream to sync from',
                    default='main')
  result.add_option('--leave_upstream', '--leave-upstream',
                    help='To not update the upstream of the first open branch',
                    action='store_true')
  result.add_option('--message', '-m',
                    help='Message for patchset', default='Sync')
  result.add_option('--rebase',
                    help='To use `git pull --rebase` instead of `git pull`',
                    action='store_true')
  result.add_option('--no_upload', '--no-upload',
                    help='Disable uploading to Gerrit', action='store_true')
  result.add_option('--skip_main', '--skip-main',
                    help='Disable syncing for main',
                    action='store_true')
  (options, args) = result.parse_args(argv)
  options.upload = not options.no_upload
  assert options.delete != 'y' or not options.leave_upstream, (
      'Inconsistent options: cannot leave the upstream of the first open ' +
      'branch (--leave_upstream) and delete the closed branches at the same ' +
      'time (--delete).')
  assert options.message, 'A message for the patchset is required.'
  assert len(args) == 0
  return options

def main(argv):
  options = ParseOptions(argv)
  with utils.ChangedWorkingDirectory(REPO_ROOT, quiet=True):
    branches = [
        parse(line)
        for line in utils.RunCmd(['git', 'branch', '-vv'], quiet=True)]

    current_branch = None
    for branch in branches:
      if branch.is_current:
        current_branch = branch
        break
    assert current_branch is not None

    if is_root_branch(current_branch, options):
      print('Nothing to sync')
      return

    stack = []
    while current_branch:
      stack.append(current_branch)
      if is_root_branch(current_branch, options):
        break
      current_branch = get_branch_with_name(current_branch.upstream, branches)

    closed_branches = []
    has_seen_local_branch = False # A branch that is not uploaded.
    has_seen_open_branch = False # A branch that is not closed.
    while len(stack) > 0:
      branch = stack.pop()

      utils.RunCmd(['git', 'checkout', branch.name], quiet=True)

      status = get_status_for_current_branch(branch)
      print('Syncing %s (status: %s)' % (branch.name, status))

      pull_for_current_branch(branch, options)

      if branch.name == 'main':
        continue

      if status == 'closed':
        assert not has_seen_local_branch, (
            'Unexpected closed branch %s after new branch' % branch.name)
        assert not has_seen_open_branch, (
            'Unexpected closed branch %s after open branch' % branch.name)
        closed_branches.append(branch.name)
        continue

      if not options.leave_upstream:
        if not has_seen_open_branch and len(closed_branches) > 0:
          print(
              'Setting upstream for first open branch %s to main'
                  % branch.name)
          set_upstream_for_current_branch_to_main()

      has_seen_open_branch = True
      has_seen_local_branch = has_seen_local_branch or (status == 'None')

      if options.upload and status != 'closed':
        if has_seen_local_branch:
          print(
              'Cannot upload branch %s since it comes after a local branch'
                  % branch.name)
        else:
          upload_cmd = ['git', 'cl', 'upload', '-m', options.message]
          if options.bypass_hooks:
            upload_cmd.append('--bypass-hooks')
          utils.RunCmd(upload_cmd, quiet=True)

    if get_delete_branches_option(closed_branches, options):
      delete_branches(closed_branches)

    utils.RunCmd(['git', 'cl', 'issue'])

def delete_branches(branches):
  assert len(branches) > 0
  cmd = ['git', 'branch', '-D']
  cmd.extend(branches)
  utils.RunCmd(cmd, quiet=True)

def get_branch_with_name(name, branches):
  for branch in branches:
    if branch.name == name:
      return branch
  return None

def get_delete_branches_option(closed_branches, options):
  if len(closed_branches) == 0:
    return False
  if options.leave_upstream:
    return False
  if options.delete == 'y':
    return True
  if options.delete == 'n':
    return False
  assert options.delete == 'ask'
  print('Delete closed branches: %s (Y/N)?' % ", ".join(closed_branches))
  answer = sys.stdin.read(1)
  return answer.lower() == 'y'

def get_status_for_current_branch(current_branch):
  if current_branch.name == 'main':
    return 'main'
  return utils.RunCmd(['git', 'cl', 'status', '--field', 'status'], quiet=True)[0].strip()

def is_root_branch(branch, options):
  return branch.name == options.from_branch or branch.upstream is None

def pull_for_current_branch(branch, options):
  if branch.name == 'main' and options.skip_main:
    return
  rebase_args = ['--rebase'] if options.rebase else []
  utils.RunCmd(['git', 'pull'] + rebase_args, quiet=True)


def set_upstream_for_current_branch_to_main():
  utils.RunCmd(['git', 'cl', 'upstream', 'main'], quiet=True)

# Parses a line from the output of `git branch -vv`.
#
# Example output ('*' denotes the current branch):
#
#   $ git branch -vv
#   * feature_final    xxxxxxxxx [feature_prereq_c: ...] ...
#     feature_prereq_c xxxxxxxxx [feature_prereq_b: ...] ...
#     feature_prereq_b xxxxxxxxx [feature_prereq_a: ...] ...
#     feature_prereq_a xxxxxxxxx [main: ...] ...
#     main             xxxxxxxxx [origin/main] ...
def parse(line):
  is_current = False
  if line.startswith('*'):
    is_current = True
    line = line[1:].lstrip()
  else:
    line = line.lstrip()

  name_end_index = line.index(' ')
  name = line[:name_end_index]
  line = line[name_end_index:].lstrip()

  if '[' in line:
    line = line[line.index('[')+1:]

    if ':' in line:
      upstream = line[:line.index(':')]
      return Repo(name, is_current, upstream)

    if ']' in line:
      upstream = line[:line.index(']')]
      return Repo(name, is_current, upstream)

  return Repo(name, is_current, None)

if __name__ == '__main__':
  sys.exit(main(sys.argv[1:]))
