#!/usr/bin/env python
# Copyright 2022 The IREE Authors
#
# Licensed 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

# Creates a new branch that bumps the llvm-project commit.
# Typical usage (from the iree/ repository):
#   /path/to/here/bump_llvm.py
#
# In the default configuration, it will create a new branch
#   "bump-llvm-YYYYMMDD"
# This will fail if the branch already exists, in which case, you can:
#   * Specify an explicit branch name with --branch-name=my-integrate
#   * Pass "--reuse-branch" if you are sure that you want to lose the current
#     branch state. This is largely meant for developing this script or YOLO
#     use.
#
# In order to not interfere with your personal preferences, a remote named
# 'UPSTREAM_AUTOMATION' is used (and setup if needed). Sorry if you use that
# name for your daily work.
#
# This then reverts any changes to the llvm-project submodule setup (i.e.
# resets it to llvm-project's repository and disables branch tracking) and
# resets the submodule to the curren HEAD commit, generating a nice commit
# message.
#
# The branch is then pushed to the main repository. GitHub will print the usual
# message to create a pull request, which you should do to kick off pre-merge
# checks. You should land changes to this branch until green (or get other
# people to do so).
#
# When satisfied, Squash and Merge, opting to delete the branch to keep things
# tidy.

import argparse
from datetime import date
import os
import sys

import iree_modules
import iree_utils


def main(args):
    if not args.disable_setup_remote:
        iree_utils.git_setup_remote(args.upstream_remote, args.upstream_repository)

    iree_utils.git_check_porcelain()
    print(f"Fetching remote repository: {args.upstream_remote}")
    iree_utils.git_fetch(repository=args.upstream_remote)

    # If re-using a branch, make sure we are not on that branch.
    if args.reuse_branch:
        iree_utils.git_checkout("main")

    # Create branch.
    branch_name = args.branch_name
    if not branch_name:
        branch_name = f"bump-llvm-{date.today().strftime('%Y%m%d')}"
    print(f"Creating branch {branch_name} (override with --branch-name=)")
    iree_utils.git_create_branch(
        branch_name,
        checkout=True,
        ref=f"{args.upstream_remote}/main",
        force=args.reuse_branch,
    )

    # Reset the llvm-project submodule to track upstream.
    # This will discard any cherrypicks that may have been committed locally,
    # but the assumption is that if doing a main llvm version bump, the
    # cherrypicks will be incorporated at the new commit. If not, well, ymmv
    # and you will find out.
    iree_utils.git_submodule_set_origin(
        "third_party/llvm-project",
        url="https://github.com/iree-org/iree-llvm-fork.git",
        branch="--default",
    )

    # Remove the branch pin file, reverting us to pure upstream.
    branch_pin_file = os.path.join(
        iree_utils.get_repo_root(),
        iree_modules.MODULE_INFOS["llvm-project"].branch_pin_file,
    )
    if os.path.exists(branch_pin_file):
        os.remove(branch_pin_file)

    # Update the LLVM submodule.
    llvm_commit = args.llvm_commit
    print(f"Updating LLVM submodule to {llvm_commit}")
    llvm_root = iree_utils.get_submodule_root("llvm-project")
    iree_utils.git_fetch(repository="origin", ref="refs/heads/main", repo_dir=llvm_root)
    if llvm_commit == "HEAD":
        llvm_commit = "origin/main"
    iree_utils.git_reset(llvm_commit, repo_dir=llvm_root)
    llvm_commit, llvm_summary = iree_utils.git_current_commit(repo_dir=llvm_root)
    print(f"LLVM submodule reset to:\n  {llvm_summary}\n")

    # Create a commit.
    print("Create commit...")
    iree_utils.git_create_commit(
        message=(
            f"Integrate llvm-project at {llvm_commit}\n\n"
            f"* Reset third_party/llvm-project: {llvm_summary}"
        ),
        add_all=True,
    )

    # Push.
    print("Pushing...")
    iree_utils.git_push_branch(args.upstream_remote, branch_name)


def parse_arguments(argv):
    parser = argparse.ArgumentParser(description="IREE LLVM-bump-inator")
    parser.add_argument(
        "--upstream-remote", help="Upstream remote", default="UPSTREAM_AUTOMATION"
    )
    parser.add_argument(
        "--upstream-repository",
        help="Upstream repository URL",
        default="git@github.com:openxla/iree.git",
    )
    parser.add_argument(
        "--disable-setup-remote",
        help="Disable remote setup",
        action="store_true",
        default=False,
    )
    parser.add_argument("--llvm-commit", help="LLVM commit sha", default="HEAD")
    parser.add_argument(
        "--branch-name", help="Integrate branch to create", default=None
    )
    parser.add_argument(
        "--reuse-branch",
        help="Allow re-use of an existing branch",
        action="store_true",
        default=False,
    )
    args = parser.parse_args(argv)
    return args


if __name__ == "__main__":
    main(parse_arguments(sys.argv[1:]))
