#!/usr/bin/env python
# utils/update-checkout - Utility to update your local checkouts -*- python -*-
#
# This source file is part of the Swift.org open source project
#
# Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
# Licensed under Apache License v2.0 with Runtime Library Exception
#
# See https://swift.org/LICENSE.txt for license information
# See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors

from __future__ import print_function

import argparse
import json
import os
import re
import sys


from functools import reduce

sys.path.append(os.path.dirname(__file__))

from SwiftBuildSupport import (
    SWIFT_SOURCE_ROOT,
)  # noqa (E402 module level import not at top of file)

SCRIPT_FILE = os.path.abspath(__file__)
SCRIPT_DIR = os.path.dirname(SCRIPT_FILE)

sys.path.append(os.path.join(SCRIPT_DIR, 'swift_build_support'))

from swift_build_support import shell  # noqa (E402)


def update_single_repository(repo_path, branch, reset_to_remote, should_clean,
                             cross_repo):
    if not os.path.isdir(repo_path):
        return

    print("--- Updating '" + repo_path + "' ---")
    with shell.pushd(repo_path, dry_run=False, echo=False):
        shell.call(["git", "fetch", "--recurse-submodules=yes"], echo=True)

        if should_clean:
            shell.call(['git', 'clean', '-fdx'],
                       echo=True)
            shell.call(['git', 'submodule', 'foreach', '--recursive', 'git',
                        'clean', '-fdx'], echo=True)
            shell.call(['git', 'submodule', 'foreach', '--recursive', 'git',
                        'reset', '--hard', 'HEAD'], echo=True)
            status = shell.call(['git', 'reset', '--hard', 'HEAD'],
                                echo=True)
            if status:
                print("Please, commit your changes.")
                print(status)
                exit(1)

        if branch:
            status = shell.capture(['git', 'status', '--porcelain', '-uno'],
                                   echo=False)
            if status:
                print("Please, commit your changes.")
                print(status)
                exit(1)
            shell.call(['git', 'checkout', branch], echo=True)

            # If we were asked to reset to the specified branch, do the hard
            # reset and return.
            if reset_to_remote and not cross_repo:
                shell.call(['git', 'reset', '--hard', "origin/%s" % branch],
                           echo=True)
                return

        # Prior to Git 2.6, this is the way to do a "git pull
        # --rebase" that respects rebase.autostash.  See
        # http://stackoverflow.com/a/30209750/125349
        if not cross_repo:
            shell.call(["git", "rebase", "FETCH_HEAD"], echo=True)
        shell.call(["git", "submodule", "update", "--recursive"],
                   echo=True)


def update_repository_to_tag(args, repo_name, repo_path, tag_name):
    with shell.pushd(repo_path, dry_run=False, echo=False):
        tag_exists = shell.capture(['git', 'ls-remote', '--tags',
                                    'origin', tag_name], echo=False)
        if not tag_exists:
            print("--- Skipping '" + repo_name + "' ---")
            return
        update_single_repository(repo_path,
                                 tag_name,
                                 args.reset_to_remote,
                                 args.clean,
                                 cross_repo=True)


def update_repository_to_scheme(
        args, config, repo_name, repo_path, scheme_name, cross_repos_pr):
    cross_repo = False
    repo_branch = scheme_name
    # This loop is only correct, since we know that each alias set has
    # unique contents. This is checked by verify config. Thus the first
    # branch scheme data that has scheme_name as one of its aliases is
    # the only possible correct answer.
    for v in config['branch-schemes'].values():
        if scheme_name not in v['aliases']:
            continue
        repo_branch = v['repos'][repo_name]
        remote_repo_id = config['repos'][repo_name]['remote']['id']
        if remote_repo_id in cross_repos_pr:
            cross_repo = True
            pr_id = cross_repos_pr[remote_repo_id]
            repo_branch = "ci_pr_{0}".format(pr_id)
            with shell.pushd(repo_path, dry_run=False, echo=False):
                shell.call(["git", "checkout", v['repos'][repo_name]],
                           echo=True)
                shell.capture(["git", "branch", "-D", repo_branch],
                              echo=True, allow_non_zero_exit=True)
                shell.call(["git", "fetch", "origin",
                            "pull/{0}/merge:{1}"
                            .format(pr_id, repo_branch)], echo=True)
        break
    update_single_repository(repo_path,
                             repo_branch,
                             args.reset_to_remote,
                             args.clean,
                             cross_repo)


def update_all_repositories(args, config, scheme_name, cross_repos_pr):
    for repo_name in config['repos'].keys():
        if repo_name in args.skip_repository_list:
            print("--- Skipping '" + repo_name + "' ---")
            continue
        repo_path = os.path.join(SWIFT_SOURCE_ROOT, repo_name)
        if args.tag:
            update_repository_to_tag(args, repo_name, repo_path, args.tag)
        elif scheme_name:
            update_repository_to_scheme(args,
                                        config,
                                        repo_name,
                                        repo_path,
                                        scheme_name,
                                        cross_repos_pr)
        else:
            update_single_repository(repo_path,
                                     branch=None,
                                     reset_to_remote=args.reset_to_remote,
                                     should_clean=args.clean,
                                     cross_repo=False)


def obtain_additional_swift_sources(
        config, with_ssh, scheme_name, skip_history, skip_repository_list):
    with shell.pushd(SWIFT_SOURCE_ROOT, dry_run=False,
                     echo=False):
        for repo_name, repo_info in config['repos'].items():
            if repo_name in skip_repository_list:
                print("--- Skipping '" + repo_name + "' ---")
                continue

            if os.path.isdir(os.path.join(repo_name, ".git")):
                continue

            print("--- Cloning '" + repo_name + "' ---")

            # If we have a url override, use that url instead of
            # interpolating.
            remote_repo_info = repo_info['remote']
            if 'url' in remote_repo_info:
                remote = remote_repo_info['url']
            else:
                remote_repo_id = remote_repo_info['id']
                if with_ssh is True or 'https-clone-pattern' not in config:
                    remote = config['ssh-clone-pattern'] % remote_repo_id
                else:
                    remote = config['https-clone-pattern'] % remote_repo_id

            if skip_history:
                shell.call(['git', 'clone', '--recursive', '--depth', '1',
                            remote, repo_name], echo=True)
            else:
                shell.call(['git', 'clone', '--recursive', remote,
                            repo_name], echo=True)
            if scheme_name:
                for v in config['branch-schemes'].values():
                    if scheme_name not in v['aliases']:
                        continue
                    repo_branch = v['repos'][repo_name]
                    break
                else:
                    repo_branch = scheme_name
                src_path = os.path.join(SWIFT_SOURCE_ROOT, repo_name,
                                        ".git")
                shell.call(['git', '--git-dir', src_path, '--work-tree',
                            os.path.join(SWIFT_SOURCE_ROOT, repo_name),
                            'checkout', repo_branch], echo=False)
    with shell.pushd(os.path.join(SWIFT_SOURCE_ROOT, repo_name),
                     dry_run=False, echo=False):
        shell.call(["git", "submodule", "update", "--recursive"],
                   echo=False)


def dump_repo_hashes(config):
    max_len = reduce(lambda acc, x: max(acc, len(x)),
                     config['repos'].keys(), 0)
    fmt = "{:<%r}{}" % (max_len+5)
    for repo_name, repo_info in sorted(config['repos'].items(),
                                       key=lambda x: x[0]):
        with shell.pushd(os.path.join(SWIFT_SOURCE_ROOT, repo_name),
                         dry_run=False,
                         echo=False):
            h = shell.capture(["git", "log", "--oneline", "-n", "1"],
                              echo=False).strip()
            print(fmt.format(repo_name, h))


def validate_config(config):
    # Make sure that our branch-names are unique.
    scheme_names = config['branch-schemes'].keys()
    if len(scheme_names) != len(set(scheme_names)):
        raise RuntimeError('Configuration file has duplicate schemes?!')

    # Then make sure the alias names used by our branches are unique.
    #
    # We do this by constructing a list consisting of len(names),
    # set(names). Then we reduce over that list summing the counts and taking
    # the union of the sets. We have uniqueness if the length of the union
    # equals the length of the sum of the counts.
    data = [(len(v['aliases']), set(v['aliases']))
            for v in config['branch-schemes'].values()]
    result = reduce(lambda acc, x: (acc[0] + x[0], acc[1] | x[1]), data,
                    (0, set([])))
    if result[0] == len(result[1]):
        return
    raise RuntimeError('Configuration file has schemes with duplicate '
                       'aliases?!')


def main():
    parser = argparse.ArgumentParser(
        formatter_class=argparse.RawDescriptionHelpFormatter,
        description="""
repositories.

By default, updates your checkouts of Swift, SourceKit, LLDB, and SwiftPM.""")
    parser.add_argument(
        "--clone",
        help="Obtain Sources for Swift and Related Projects",
        action="store_true")
    parser.add_argument(
        "--clone-with-ssh",
        help="Obtain Sources for Swift and Related Projects via SSH",
        action="store_true")
    parser.add_argument(
        "--skip-history",
        help="Skip histories when obtaining sources",
        action="store_true")
    parser.add_argument(
        "--skip-repository",
        metavar="DIRECTORY",
        default=[],
        help="Skip the specified repository",
        dest='skip_repository_list',
        action="append")
    parser.add_argument(
        "--scheme", "--branch",
        help='Use branches from the specified branch-scheme',
        metavar='BRANCH-SCHEME',
        dest='scheme')
    parser.add_argument(
        '--reset-to-remote',
        help='Reset each branch to the remote state.',
        action='store_true')
    parser.add_argument(
        '--clean',
        help='Clean unrelated files from each repository.',
        action='store_true')
    parser.add_argument(
        "--config",
        default=os.path.join(SCRIPT_DIR, "update-checkout-config.json"),
        help="Configuration file to use")
    parser.add_argument(
        "--github-comment",
        help="""Check out related pull requests referenced in the given
        free-form GitHub-style comment.""",
        metavar='GITHUB-COMMENT',
        dest='github_comment')
    parser.add_argument(
        '--dump-hashes',
        action='store_true',
        help='Dump the git hashes of all repositories being tracked')
    parser.add_argument(
        "--tag",
        help="""Check out each repository to the specified tag.""",
        metavar='TAG-NAME')
    args = parser.parse_args()

    clone = args.clone
    clone_with_ssh = args.clone_with_ssh
    skip_history = args.skip_history
    scheme = args.scheme
    github_comment = args.github_comment

    with open(args.config) as f:
        config = json.load(f)
    validate_config(config)

    if args.dump_hashes:
        dump_repo_hashes(config)
        return 0

    cross_repos_pr = {}
    if github_comment:
        regex_pr = r'(apple/[-a-zA-Z0-9_]+/pull/\d+|apple/[-a-zA-Z0-9_]+#\d+)'
        repos_with_pr = re.findall(regex_pr, github_comment)
        print("Found related pull requests:", str(repos_with_pr))
        repos_with_pr = [pr.replace('/pull/', '#') for pr in repos_with_pr]
        cross_repos_pr = dict(pr.split('#') for pr in repos_with_pr)

    if clone or clone_with_ssh:
        # If branch is None, default to using the default branch alias
        # specified by our configuration file.
        if scheme is None:
            scheme = config['default-branch-scheme']

        obtain_additional_swift_sources(
            config, clone_with_ssh, scheme, skip_history,
            args.skip_repository_list)

    update_all_repositories(args, config, scheme, cross_repos_pr)

    return 0

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