#!/usr/bin/env python
#
# ======- git-llvm - LLVM Git Help Integration ---------*- python -*--========#
#
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
# ==------------------------------------------------------------------------==#

"""
git-llvm integration
====================

This file provides integration for git.
"""

from __future__ import print_function
import argparse
import collections
import os
import re
import shutil
import subprocess
import sys
import time
assert sys.version_info >= (2, 7)

try:
    dict.iteritems
except AttributeError:
    # Python 3
    def iteritems(d):
        return iter(d.items())
else:
    # Python 2
    def iteritems(d):
        return d.iteritems()

try:
    # Python 3
    from shlex import quote
except ImportError:
    # Python 2
    from pipes import quote

# It's *almost* a straightforward mapping from the monorepo to svn...
LLVM_MONOREPO_SVN_MAPPING = {
    d: (d + '/trunk')
    for d in [
        'clang-tools-extra',
        'compiler-rt',
        'debuginfo-tests',
        'dragonegg',
        'klee',
        'libc',
        'libclc',
        'libcxx',
        'libcxxabi',
        'libunwind',
        'lld',
        'lldb',
        'llgo',
        'llvm',
        'openmp',
        'parallel-libs',
        'polly',
        'pstl',
    ]
}
LLVM_MONOREPO_SVN_MAPPING.update({'clang': 'cfe/trunk'})
LLVM_MONOREPO_SVN_MAPPING.update({'': 'monorepo-root/trunk'})

SPLIT_REPO_NAMES = {'llvm-' + d: d + '/trunk'
                    for d in ['www', 'zorg', 'test-suite', 'lnt']}

VERBOSE = False
QUIET = False
dev_null_fd = None


def eprint(*args, **kwargs):
    print(*args, file=sys.stderr, **kwargs)


def log(*args, **kwargs):
    if QUIET:
        return
    print(*args, **kwargs)


def log_verbose(*args, **kwargs):
    if not VERBOSE:
        return
    print(*args, **kwargs)


def die(msg):
    eprint(msg)
    sys.exit(1)


def ask_confirm(prompt):
    # Python 2/3 compatibility
    try:
        read_input = raw_input
    except NameError:
        read_input = input

    while True:
        query = read_input('%s (y/N): ' % (prompt))
        if query.lower() not in ['y','n', '']:
           print('Expect y or n!')
           continue
        return query.lower() == 'y'


def split_first_path_component(d):
    # Assuming we have a git path, it'll use slashes even on windows...I hope.
    if '/' in d:
        return d.split('/', 1)
    else:
        return (d, None)


def get_dev_null():
    """Lazily create a /dev/null fd for use in shell()"""
    global dev_null_fd
    if dev_null_fd is None:
        dev_null_fd = open(os.devnull, 'w')
    return dev_null_fd


def shell(cmd, strip=True, cwd=None, stdin=None, die_on_failure=True,
          ignore_errors=False, text=True):
    # Escape args when logging for easy repro.
    quoted_cmd = [quote(arg) for arg in cmd]
    log_verbose('Running in %s: %s' % (cwd, ' '.join(quoted_cmd)))

    err_pipe = subprocess.PIPE
    if ignore_errors:
        # Silence errors if requested.
        err_pipe = get_dev_null()

    start = time.time()
    p = subprocess.Popen(cmd, cwd=cwd, stdout=subprocess.PIPE, stderr=err_pipe,
                         stdin=subprocess.PIPE,
                         universal_newlines=text)
    stdout, stderr = p.communicate(input=stdin)
    elapsed = time.time() - start

    log_verbose('Command took %0.1fs' % elapsed)

    if p.returncode == 0 or ignore_errors:
        if stderr and not ignore_errors:
            eprint('`%s` printed to stderr:' % ' '.join(quoted_cmd))
            eprint(stderr.rstrip())
        if strip:
            if text:
                stdout = stdout.rstrip('\r\n')
            else:
                stdout = stdout.rstrip(b'\r\n')
        if VERBOSE:
            for l in stdout.splitlines():
                log_verbose("STDOUT: %s" % l)
        return stdout
    err_msg = '`%s` returned %s' % (' '.join(quoted_cmd), p.returncode)
    eprint(err_msg)
    if stderr:
        eprint(stderr.rstrip())
    if die_on_failure:
        sys.exit(2)
    raise RuntimeError(err_msg)


def git(*cmd, **kwargs):
    return shell(['git'] + list(cmd), **kwargs)


def svn(cwd, *cmd, **kwargs):
    return shell(['svn'] + list(cmd), cwd=cwd, **kwargs)


def program_exists(cmd):
    if sys.platform == 'win32' and not cmd.endswith('.exe'):
        cmd += '.exe'
    for path in os.environ["PATH"].split(os.pathsep):
        if os.access(os.path.join(path, cmd), os.X_OK):
            return True
    return False


def get_default_rev_range():
    # Get the newest common ancestor between HEAD and our upstream branch.
    upstream_rev = git('merge-base', 'HEAD', '@{upstream}', ignore_errors=True)
    if not upstream_rev:
        eprint("Warning: git-llvm assumes that origin/master is the upstream "
               "branch but git does not.")
        eprint("To make this warning go away: git branch -u origin/master")
        eprint("To avoid this warning when creating branches: "
               "git checkout -b MyBranchName origin/master")
        upstream_rev = git('merge-base', 'HEAD', 'origin/master')

    return '%s..' % upstream_rev


def get_revs_to_push(rev_range):
    if not rev_range:
        rev_range = get_default_rev_range()
    # Use git show rather than some plumbing command to figure out which revs
    # are in rev_range because it handles single revs (HEAD^) and ranges
    # (foo..bar) like we want.
    return git('show', '--reverse', '--quiet',
               '--pretty=%h', rev_range).splitlines()


def clean_svn(svn_repo):
    svn(svn_repo, 'revert', '-R', '.')

    # Unfortunately it appears there's no svn equivalent for git clean, so we
    # have to do it ourselves.
    for line in svn(svn_repo, 'status', '--no-ignore').split('\n'):
        if not line.startswith('?'):
            continue
        filename = line[1:].strip()
        filepath = os.path.abspath(os.path.join(svn_repo, filename))
        abs_svn_repo = os.path.abspath(svn_repo)
        # Safety check that the directory we are about to delete is
        # actually within our svn staging dir.
        if not filepath.startswith(abs_svn_repo):
            die("Path to clean (%s) is not in svn staging dir (%s)"
                % (filepath, abs_svn_repo))

        if os.path.isdir(filepath):
            shutil.rmtree(filepath)
        else:
            os.remove(filepath)


def svn_init(svn_root):
    if not os.path.exists(svn_root):
        log('Creating svn staging directory: (%s)' % (svn_root))
        os.makedirs(svn_root)
        svn(svn_root, 'checkout', '--depth=empty',
            'https://llvm.org/svn/llvm-project/', '.')
        log("svn staging area ready in '%s'" % svn_root)
    if not os.path.isdir(svn_root):
        die("Can't initialize svn staging dir (%s)" % svn_root)


def fix_eol_style_native(rev, svn_sr_path, files):
    """Fix line endings before applying patches with Unix endings

    SVN on Windows will check out files with CRLF for files with the
    svn:eol-style property set to "native". This breaks `git apply`, which
    typically works with Unix-line ending patches. Work around the problem here
    by doing a dos2unix up front for files with svn:eol-style set to "native".
    SVN will not commit a mass line ending re-doing because it detects the line
    ending format for files with this property.
    """
    # Skip files that don't exist in SVN yet.
    files = [f for f in files if os.path.exists(os.path.join(svn_sr_path, f))]
    # Use ignore_errors because 'svn propget' prints errors if the file doesn't
    # have the named property. There doesn't seem to be a way to suppress that.
    eol_props = svn(svn_sr_path, 'propget', 'svn:eol-style', *files,
                    ignore_errors=True)
    crlf_files = []
    if len(files) == 1:
        # No need to split propget output on ' - ' when we have one file.
        if eol_props.strip() in ['native', 'CRLF']:
            crlf_files = files
    else:
        for eol_prop in eol_props.split('\n'):
            # Remove spare CR.
            eol_prop = eol_prop.strip('\r')
            if not eol_prop:
                continue
            prop_parts = eol_prop.rsplit(' - ', 1)
            if len(prop_parts) != 2:
                eprint("unable to parse svn propget line:")
                eprint(eol_prop)
                continue
            (f, eol_style) = prop_parts
            if eol_style == 'native':
                crlf_files.append(f)
    if crlf_files:
        # Reformat all files with native SVN line endings to Unix format. SVN
        # knows files with native line endings are text files. It will commit
        # just the diff, and not a mass line ending change.
        shell(['dos2unix'] + crlf_files, ignore_errors=True, cwd=svn_sr_path)


def split_subrepo(f, git_to_svn_mapping):
    # Given a path, splits it into (subproject, rest-of-path). If the path is
    # not in a subproject, returns ('', full-path).

    subproject, remainder = split_first_path_component(f)

    if subproject in git_to_svn_mapping:
        return subproject, remainder
    else:
        return '', f


def get_all_parent_dirs(name):
    parts = []
    head, tail = os.path.split(name)
    while head:
        parts.append(head)
        head, tail = os.path.split(head)
    return parts


def svn_push_one_rev(svn_repo, rev, git_to_svn_mapping, dry_run):
    def split_status(x):
        x = x.split('\t')
        return x[1], x[0]
    files_status = [split_status(x) for x in
                    git('diff-tree', '--no-commit-id', '--name-status',
                        '--no-renames', '-r', rev).split('\n')]
    if not files_status:
        raise RuntimeError('Empty diff for rev %s?' % rev)

    # Split files by subrepo
    subrepo_files = collections.defaultdict(list)
    for f, st in files_status:
        subrepo, remainder = split_subrepo(f, git_to_svn_mapping)
        subrepo_files[subrepo].append((remainder, st))

    status = svn(svn_repo, 'status', '--no-ignore')
    if status:
        die("Can't push git rev %s because status in svn staging dir (%s) is "
            "not empty:\n%s" % (rev, svn_repo, status))

    svn_dirs_to_update = set()
    for sr, files_status in iteritems(subrepo_files):
        svn_sr_path = git_to_svn_mapping[sr]
        for f, _ in files_status:
            svn_dirs_to_update.add(
                os.path.dirname(os.path.join(svn_sr_path, f)))

    # We also need to svn update any parent directories which are not yet
    # present
    parent_dirs = set()
    for dir in svn_dirs_to_update:
        parent_dirs.update(get_all_parent_dirs(dir))
    parent_dirs = set(dir for dir in parent_dirs
                      if not os.path.exists(os.path.join(svn_repo, dir)))
    svn_dirs_to_update.update(parent_dirs)

    # Sort by length to ensure that the parent directories are passed to svn
    # before child directories.
    sorted_dirs_to_update = sorted(svn_dirs_to_update, key=len)

    # SVN update only in the affected directories.
    svn(svn_repo, 'update', '--depth=files', *sorted_dirs_to_update)

    for sr, files_status in iteritems(subrepo_files):
        svn_sr_path = os.path.join(svn_repo, git_to_svn_mapping[sr])
        if os.name == 'nt':
            fix_eol_style_native(rev, svn_sr_path,
                                 [f for f, _ in files_status])

        # We use text=False (and pass '--binary') so that we can get an exact
        # diff that can be passed as-is to 'git apply' without any line ending,
        # encoding, or other mangling.
        diff = git('show', '--binary', rev, '--',
                   *(os.path.join(sr, f) for f, _ in files_status),
                   strip=False, text=False)
        # git is the only thing that can handle its own patches...
        if sr == '':
            prefix_strip = '-p1'
        else:
            prefix_strip = '-p2'
        try:
            shell(['git', 'apply', prefix_strip, '-'], cwd=svn_sr_path,
                  stdin=diff, die_on_failure=False, text=False)
        except RuntimeError as e:
            eprint("Patch doesn't apply: maybe you should try `git pull -r` "
                   "first?")
            sys.exit(2)

        # Handle removed files and directories. We need to be careful not to
        # remove directories just because they _look_ empty in the svn tree, as
        # we might be missing sibling directories in the working copy. So, only
        # remove parent directories if they're empty on both the git and svn
        # sides.
        maybe_dirs_to_remove = set()
        for f, st in files_status:
            if st == 'D':
                maybe_dirs_to_remove.update(get_all_parent_dirs(f))
                svn(svn_sr_path, 'remove', f)
            elif not (st == 'A' or st == 'M' or st == 'T'):
                # Add is handled below, and nothing needs to be done for Modify.
                # (FIXME: Type-change between symlink and file might need some
                # special handling, but let's ignore that for now.)
                die("Unexpected git status for %r: %r" % (f, st))

        maybe_dirs_to_remove = sorted(maybe_dirs_to_remove, key=len)
        for f in maybe_dirs_to_remove:
            if(not os.path.exists(os.path.join(svn_sr_path, f)) and
               git('ls-tree', '-d', rev, os.path.join(sr, f)) == ''):
                svn(svn_sr_path, 'remove', f)

    status_lines = svn(svn_repo, 'status', '--no-ignore').split('\n')

    for l in status_lines:
        f = l[1:].strip()
        if l.startswith('?') or l.startswith('I'):
            svn(svn_repo, 'add', '--no-ignore', f)

    # Now we're ready to commit.
    commit_msg = git('show', '--pretty=%B', '--quiet', rev)
    if not dry_run:
        commit_args = ['commit', '-m', commit_msg]
        if '--force-interactive' in svn(svn_repo, 'commit', '--help'):
            commit_args.append('--force-interactive')
        log(svn(svn_repo, *commit_args))
        log('Committed %s to svn.' % rev)
    else:
        log("Would have committed %s to svn, if this weren't a dry run." % rev)


def cmd_push(args):
    '''Push changes back to SVN: this is extracted from Justin Lebar's script
    available here: https://github.com/jlebar/llvm-repo-tools/

    Note: a current limitation is that git does not track file rename, so they
    will show up in SVN as delete+add.
    '''
    # Get the git root
    git_root = git('rev-parse', '--show-toplevel')
    if not os.path.isdir(git_root):
        die("Can't find git root dir")

    # Push from the root of the git repo
    os.chdir(git_root)

    # Get the remote URL, and check if it's one of the standalone repos.
    git_remote_url = git('ls-remote', '--get-url', 'origin')
    git_remote_url = git_remote_url.rstrip('.git').rstrip('/')
    git_remote_repo_name = git_remote_url.rsplit('/', 1)[-1]
    split_repo_path = SPLIT_REPO_NAMES.get(git_remote_repo_name)
    if split_repo_path:
        git_to_svn_mapping = {'': split_repo_path}
    else:
        # Default to the monorepo mapping
        git_to_svn_mapping = LLVM_MONOREPO_SVN_MAPPING

    # We need a staging area for SVN, let's hide it in the .git directory.
    dot_git_dir = git('rev-parse', '--git-common-dir')
    # Not all versions of git support --git-common-dir and just print the
    # unknown command back. If this happens, fall back to --git-dir
    if dot_git_dir == '--git-common-dir':
        dot_git_dir = git('rev-parse', '--git-dir')

    svn_root = os.path.join(dot_git_dir, 'llvm-upstream-svn')
    svn_init(svn_root)

    rev_range = args.rev_range
    dry_run = args.dry_run
    revs = get_revs_to_push(rev_range)

    if not args.force and not revs:
        die('Nothing to push: No revs in range %s.' % rev_range)

    log('%sPushing %d %s commit%s:\n%s' %
        ('[DryRun] ' if dry_run else '', len(revs),
         'split-repo (%s)' % split_repo_path
         if split_repo_path else 'monorepo',
         's' if len(revs) != 1 else '',
         '\n'.join('  ' + git('show', '--oneline', '--quiet', c)
                   for c in revs)))

    # Ask confirmation if multiple commits are about to be pushed
    if not args.force and len(revs) > 1:
        if not ask_confirm("Are you sure you want to create %d commits?" % len(revs)):
            die("Aborting")

    for r in revs:
        clean_svn(svn_root)
        svn_push_one_rev(svn_root, r, git_to_svn_mapping, dry_run)


def lookup_llvm_svn_id(git_commit_hash):
    # Use --format=%b to get the raw commit message, without any extra
    # whitespace.
    commit_msg = git('log', '-1', '--format=%b', git_commit_hash,
                     ignore_errors=True)
    if len(commit_msg) == 0:
        die("Can't find git commit " + git_commit_hash)
    # If a commit has multiple "llvm-svn:" lines (e.g. if the commit is
    # reverting/quoting a previous commit), choose the last one, which should
    # be the authoritative one.
    svn_match_iter = re.finditer('^llvm-svn: (\d{5,7})$', commit_msg,
                                 re.MULTILINE)
    svn_match = None
    for m in svn_match_iter:
        svn_match = m.group(1)
    if svn_match:
        return int(svn_match)
    die("Can't find svn revision in git commit " + git_commit_hash)


def cmd_svn_lookup(args):
    '''Find the SVN revision id for a given git commit hash.

    This is identified by 'llvm-svn: NNNNNN' in the git commit message.'''
    # Get the git root
    git_root = git('rev-parse', '--show-toplevel')
    if not os.path.isdir(git_root):
        die("Can't find git root dir")

    # Run commands from the root
    os.chdir(git_root)

    log('r' + str(lookup_llvm_svn_id(args.git_commit_hash)))


def git_hash_by_svn_rev(svn_rev):
    '''Find the git hash for a given svn revision.

    This check is paranoid: 'llvm-svn: NNNNNN' could exist on its own line
    somewhere else in the commit message. Look in the full log message to see
    if it's actually on the last line.

    Since this check is expensive (we're searching every single commit), limit
    to the past 10k commits (about 5 months).
    '''
    possible_hashes = git(
        'log', '--format=%H', '--grep', '^llvm-svn: %d$' % svn_rev,
        'HEAD~10000...HEAD').split('\n')
    matching_hashes = [h for h in possible_hashes
                       if lookup_llvm_svn_id(h) == svn_rev]
    if len(matching_hashes) > 1:
        die("svn revision r%d has ambiguous commits: %s" % (
            svn_rev, ', '.join(matching_hashes)))
    elif len(matching_hashes) < 1:
        die("svn revision r%d matches no commits" % svn_rev)
    return matching_hashes[0]


def cmd_revert(args):
    '''Revert a commit by either SVN id (rNNNNNN) or git hash. This also
    populates the git commit message with both the SVN revision and git hash of
    the change being reverted.'''

    # Get the git root
    git_root = git('rev-parse', '--show-toplevel')
    if not os.path.isdir(git_root):
        die("Can't find git root dir")

    # Run commands from the root
    os.chdir(git_root)

    # Check for a client branch first.
    open_files = git('status', '-uno', '-s', '--porcelain')
    if len(open_files) > 0:
        die("Found open files. Please stash and then revert.\n" + open_files)

    # If the revision looks like rNNNNNN (or with a callsign, e.g. rLLDNNNNNN),
    # use that. Otherwise, look for it in the git commit.
    svn_match = re.match('^r[A-Z]*(\d{5,7})$', args.revision)
    if svn_match:
        # If the revision looks like rNNNNNN, use that as the svn revision, and
        # grep through git commits to find which one corresponds to that svn
        # revision.
        svn_rev = int(svn_match.group(1))
        git_hash = git_hash_by_svn_rev(svn_rev)
    else:
        # Otherwise, this looks like a git hash, so we just need to grab the
        # svn revision from the end of the commit message.  Get the actual git
        # hash in case the revision is something like "HEAD~1"
        git_hash = git('rev-parse', '--verify', args.revision + '^{commit}')
        svn_rev = lookup_llvm_svn_id(git_hash)

    msg = git('log', '-1', '--format=%s', git_hash)

    log_verbose('Ready to revert r%d (%s): "%s"' % (svn_rev, git_hash, msg))

    revert_args = ['revert', '--no-commit', git_hash]
    # TODO: Running --edit doesn't seem to work, with errors that stdin is not
    # a tty.
    commit_args = [
        'commit', '-m', 'Revert ' + msg,
        '-m', 'This reverts r%d (git commit %s)' % (svn_rev, git_hash)]
    if args.dry_run:
        log("Would have run the following commands, if this weren't a"
            "dry run:\n"
            '1) git %s\n2) git %s' % (
                ' '.join(quote(arg) for arg in revert_args),
                ' '.join(quote(arg) for arg in commit_args)))
        return

    git(*revert_args)
    commit_log = git(*commit_args)

    log('Created revert of r%d: %s' % (svn_rev, commit_log))
    log("Run 'git llvm push -n' to inspect your changes and "
        "run 'git llvm push' when ready")


if __name__ == '__main__':
    if not program_exists('svn'):
        die('error: git-llvm needs svn command, but svn is not installed.')

    argv = sys.argv[1:]
    p = argparse.ArgumentParser(
        prog='git llvm', formatter_class=argparse.RawDescriptionHelpFormatter,
        description=__doc__)
    subcommands = p.add_subparsers(title='subcommands',
                                   description='valid subcommands',
                                   help='additional help')
    verbosity_group = p.add_mutually_exclusive_group()
    verbosity_group.add_argument('-q', '--quiet', action='store_true',
                                 help='print less information')
    verbosity_group.add_argument('-v', '--verbose', action='store_true',
                                 help='print more information')

    parser_push = subcommands.add_parser(
        'push', description=cmd_push.__doc__,
        help='push changes back to the LLVM SVN repository')
    parser_push.add_argument(
        '-n',
        '--dry-run',
        dest='dry_run',
        action='store_true',
        help='Do everything other than commit to svn.  Leaves junk in the svn '
        'repo, so probably will not work well if you try to commit more '
        'than one rev.')
    parser_push.add_argument(
        '-f',
        '--force',
        action='store_true',
        help='Do not ask for confirmation when pushing multiple commits.')
    parser_push.add_argument(
        'rev_range',
        metavar='GIT_REVS',
        type=str,
        nargs='?',
        help="revs to push (default: everything not in the branch's "
        'upstream, or not in origin/master if the branch lacks '
        'an explicit upstream)')
    parser_push.set_defaults(func=cmd_push)

    parser_revert = subcommands.add_parser(
        'revert', description=cmd_revert.__doc__,
        help='Revert a commit locally.')
    parser_revert.add_argument(
        'revision',
        help='Revision to revert. Can either be an SVN revision number '
        "(rNNNNNN) or a git commit hash (anything that doesn't look "
        'like an SVN revision number).')
    parser_revert.add_argument(
        '-n',
        '--dry-run',
        dest='dry_run',
        action='store_true',
        help='Do everything other than perform a revert. Prints the git '
        'revert command it would have run.')
    parser_revert.set_defaults(func=cmd_revert)

    parser_svn_lookup = subcommands.add_parser(
        'svn-lookup', description=cmd_svn_lookup.__doc__,
        help='Find the llvm-svn revision for a given commit.')
    parser_svn_lookup.add_argument(
        'git_commit_hash',
        help='git_commit_hash for which we will look up the svn revision id.')
    parser_svn_lookup.set_defaults(func=cmd_svn_lookup)

    args = p.parse_args(argv)
    VERBOSE = args.verbose
    QUIET = args.quiet

    # Python3 workaround, for when not arguments are provided.
    # See https://bugs.python.org/issue16308
    try:
        func = args.func
    except AttributeError:
        # No arguments or subcommands were given.
        parser.print_help()
        parser.exit()

    # Dispatch to the right subcommand
    args.func(args)
