#!/usr/bin/env python3
# Copyright 2014 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""
Create new branch tracking origin HEAD by default.
"""

import argparse
import sys

import gclient_utils
import git_common
import subprocess2


def create_new_branch(
    branch_name, upstream_current=False, upstream=None, inject_current=False
):
    upstream = upstream or git_common.root()
    try:
        if inject_current:
            below = git_common.current_branch()
            if below is None:
                raise Exception("no current branch")
            above = git_common.upstream(below)
            if above is None:
                raise Exception("branch %s has no upstream" % (below))
            git_common.run("checkout", "--track", above, "-b", branch_name)
            git_common.run("branch", "--set-upstream-to", branch_name, below)
        elif upstream_current:
            git_common.run("checkout", "--track", "-b", branch_name)
        else:
            if upstream in git_common.tags():
                # TODO(iannucci): ensure that basis_ref is an ancestor of HEAD?
                git_common.run(
                    "checkout",
                    "--no-track",
                    "-b",
                    branch_name,
                    git_common.hash_one(upstream),
                )
                git_common.set_config("branch.%s.remote" % branch_name, ".")
                git_common.set_config("branch.%s.merge" % branch_name, upstream)
            else:
                # TODO(iannucci): Detect unclean workdir then stash+pop if we
                # need to teleport to a conflicting portion of history?
                git_common.run(
                    "checkout", "--track", upstream, "-b", branch_name
                )
        git_common.get_or_create_merge_base(branch_name)
    except subprocess2.CalledProcessError as cpe:
        sys.stdout.write(cpe.stdout.decode("utf-8", "replace"))
        sys.stderr.write(cpe.stderr.decode("utf-8", "replace"))
        return 1
    sys.stderr.write("Switched to branch %s.\n" % branch_name)
    return 0


def main(args):
    if gclient_utils.IsEnvCog():
        print(
            "new-branch command is not supported in non-git environment.",
            file=sys.stderr,
        )
        return 1
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
        description=__doc__,
    )
    parser.add_argument("branch_name")
    g = parser.add_mutually_exclusive_group()
    g.add_argument(
        "--upstream-current",
        "--upstream_current",
        action="store_true",
        help="set upstream branch to current branch.",
    )
    g.add_argument(
        "--upstream", metavar="REF", help="upstream branch (or tag) to track."
    )
    g.add_argument(
        "--inject-current",
        "--inject_current",
        action="store_true",
        help="new branch adopts current branch's upstream,"
        + " and new branch becomes current branch's upstream.",
    )
    g.add_argument(
        "--lkgr",
        action="store_const",
        const="origin/lkgr",
        dest="upstream",
        help="set basis ref for new branch to lkgr.",
    )

    opts = parser.parse_args(args)

    return create_new_branch(
        opts.branch_name,
        opts.upstream_current,
        opts.upstream,
        opts.inject_current,
    )


if __name__ == "__main__":  # pragma: no cover
    try:
        sys.exit(main(sys.argv[1:]))
    except KeyboardInterrupt:
        sys.stderr.write("interrupted\n")
        sys.exit(1)
