#!/usr/bin/env python3
# Copyright (C) 2020 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Helper tool for signing repo release tags correctly.

This is intended to be run only by the official Repo release managers, but it
could be run by people maintaining their own fork of the project.

NB: Check docs/release-process.md for production freeze information.
"""

import argparse
import os
import re
import subprocess
import sys

import util


# We currently sign with the old DSA key as it's been around the longest.
# We should transition to RSA by Jun 2020, and ECC by Jun 2021.
KEYID = util.KEYID_DSA

# Regular expression to validate tag names.
RE_VALID_TAG = r"^v([0-9]+[.])+[0-9]+$"


def sign(opts):
    """Tag the commit & sign it!"""
    # We use ! at the end of the key so that gpg uses this specific key.
    # Otherwise it uses the key as a lookup into the overall key and uses the
    # default signing key.  i.e. It will see that KEYID_RSA is a subkey of
    # another key, and use the primary key to sign instead of the subkey.
    cmd = [
        "git",
        "tag",
        "-s",
        opts.tag,
        "-u",
        f"{opts.key}!",
        "-m",
        f"repo {opts.tag}",
        opts.commit,
    ]

    key = "GNUPGHOME"
    print("+", f'export {key}="{opts.gpgdir}"')
    oldvalue = os.getenv(key)
    os.putenv(key, opts.gpgdir)
    util.run(opts, cmd)
    if oldvalue is None:
        os.unsetenv(key)
    else:
        os.putenv(key, oldvalue)


def check(opts):
    """Check the signature."""
    util.run(opts, ["git", "tag", "--verify", opts.tag])


def postmsg(opts):
    """Helpful info to show at the end for release manager."""
    cmd = ["git", "rev-parse", "remotes/origin/stable"]
    ret = util.run(opts, cmd, encoding="utf-8", stdout=subprocess.PIPE)
    current_release = ret.stdout.strip()

    cmd = [
        "git",
        "log",
        "--format=%h (%aN) %s",
        "--no-merges",
        f"remotes/origin/stable..{opts.tag}",
    ]
    ret = util.run(opts, cmd, encoding="utf-8", stdout=subprocess.PIPE)
    shortlog = ret.stdout.strip()

    print(
        f"""
Here's the short log since the last release.
{shortlog}

To push release to the public:
  git push origin {opts.commit}:stable {opts.tag} -n
NB: People will start upgrading to this version immediately.

To roll back a release:
  git push origin --force {current_release}:stable -n
"""
    )


def get_parser():
    """Get a CLI parser."""
    parser = argparse.ArgumentParser(
        description=__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    parser.add_argument(
        "-n",
        "--dry-run",
        dest="dryrun",
        action="store_true",
        help="show everything that would be done",
    )
    parser.add_argument(
        "--gpgdir",
        default=os.path.join(util.HOMEDIR, ".gnupg", "repo"),
        help="path to dedicated gpg dir with release keys "
        "(default: ~/.gnupg/repo/)",
    )
    parser.add_argument(
        "-f", "--force", action="store_true", help="force signing of any tag"
    )
    parser.add_argument(
        "--keyid", dest="key", help="alternative signing key to use"
    )
    parser.add_argument("tag", help='the tag to create (e.g. "v2.0")')
    parser.add_argument(
        "commit", default="HEAD", nargs="?", help="the commit to tag"
    )
    return parser


def main(argv):
    """The main func!"""
    parser = get_parser()
    opts = parser.parse_args(argv)

    if not os.path.exists(opts.gpgdir):
        parser.error(f"--gpgdir does not exist: {opts.gpgdir}")

    if not opts.force and not re.match(RE_VALID_TAG, opts.tag):
        parser.error(
            f'tag "{opts.tag}" does not match regex "{RE_VALID_TAG}"; '
            "use --force to sign anyways"
        )

    if opts.key:
        print(f"Using custom key to sign: {opts.key}")
    else:
        print("Using official Repo release key to sign")
        opts.key = KEYID
        util.import_release_key(opts)

    sign(opts)
    check(opts)
    postmsg(opts)

    return 0


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