#!/usr/bin/env python3

"""Clone a fork of a git repository
"""

import argparse
import getpass
import os
import re
import subprocess

REMOTE_REGEX = re.compile(
    r"\A(?:http(?:s)?://|git@)"
    r"(?P<host>[\w_\.-]+)(?::|/)"
    r"(?P<group>\S+)/"
    r"(?P<repo>[\w_\.-]+)\Z"
)


def _default_github_user():
    user = getpass.getuser()
    if user in {
        'duncan',
        'duncan.macleod',
        'duncan.macleod',
        'spxdmm',
        'c.spxdmm',
    }:
        return 'duncanmmacleod'
    return user


def shell(cmd, *args, **kwargs):
    if isinstance(cmd, str):
        cmd = cmd.split()
    print("$ {}".format(" ".join(cmd)))
    subprocess.check_call(cmd, *args, **kwargs)


def git_add_remote(url, remote="origin"):
    # link the original to the fork as 'upstream'
    shell("git remote add {} {}".format(remote, url))
    shell("git fetch --quiet {}".format(remote))


DEFAULT_USER = os.getenv("GITHUB_USER", _default_github_user())

parser = argparse.ArgumentParser(
    description=__doc__,
    formatter_class=argparse.ArgumentDefaultsHelpFormatter,
)
parser.add_argument(
    'upstream',
    metavar='org/repo',
    help='URI of repo on github.com, e.g. gwpy/gwpy',
)
parser.add_argument(
    '-t',
    '--target',
    help='target directory for clone',
    metavar='DIR',
    default=None,
)
parser.add_argument(
    '-u',
    '--user',
    help='username of fork owner',
    default=DEFAULT_USER,
    required=DEFAULT_USER is None,
)
parser.add_argument(
    '-s',
    '--git-server',
    default='git@github.com',
    help='URL of git server',
)
parser.add_argument(
    '--no-recursive',
    action='store_true',
    default=False,
    help='don\'t clone in a --recursive way',
)
parser.add_argument(
    '--verbose',
    action='store_true',
    default=False,
    help='don\'t use --quiet git commands',
)

args = parser.parse_args()

# parse repo name
if args.upstream.endswith(".git"):
    args.upstream = args.upstream[:-4]
if not "://" in args.upstream:
    host = "github.com"
    org, repo = args.upstream.rsplit("/", 1)
else:
    host, org, repo = REMOTE_REGEX.match(args.upstream).groups()

# define default target
if args.target is None:
    args.target = repo
args.target = os.path.normpath(args.target)

# strip out scheme
if host.startswith("git@"):
    host = host[4:]
elif host.startswith(("http://", "https://")):
    host = host.split("//", 1)[1]

# define upstream and fork URLs
upstream = "https://{host}/{user}/{repo}.git".format(
    host=host,
    user=org,
    repo=repo,
)
fork = "git@{host}:{user}/{repo}.git".format(
    host=host,
    user=args.user,
    repo=repo,
)

# clone the upstream repo first
cloneargs = [upstream, args.target, "--origin", "upstream"]
if not args.no_recursive:
    cloneargs.insert(0, '--recursive')
if not args.verbose:
    cloneargs.insert(0, '--quiet')
shell('git clone %s' % ' '.join(cloneargs))

# enter the clone
os.chdir(args.target)

# add the fork as a new remote
git_add_remote(fork, "origin")

print("Fork is ready in {0}{1}{2}{1}".format(
    os.curdir,
    os.path.sep,
    args.target,
))
