# Copyright (C) 2008 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.

import optparse
import os
import re
import sys
import traceback
import urllib.parse

from error import HookError
from git_refs import HEAD


# The API we've documented to hook authors.  Keep in sync with repo-hooks.md.
_API_ARGS = {
    "pre-upload": {"project_list", "worktree_list"},
    "post-sync": {"repo_topdir", "sync_duration_seconds"},
}


class RepoHook:
    """A RepoHook contains information about a script to run as a hook.

    Hooks are used to run a python script before running an upload (for
    instance, to run presubmit checks).  Eventually, we may have hooks for other
    actions.

    This shouldn't be confused with files in the 'repo/hooks' directory.  Those
    files are copied into each '.git/hooks' folder for each project.  Repo-level
    hooks are associated instead with repo actions.

    Hooks are always python.  When a hook is run, we will load the hook into the
    interpreter and execute its main() function.

    Combinations of hook option flags:
    - no-verify=False, verify=False (DEFAULT):
      If stdout is a tty, can prompt about running hooks if needed.
      If user denies running hooks, the action is cancelled. If stdout is
      not a tty and we would need to prompt about hooks, action is
      cancelled.
    - no-verify=False, verify=True:
      Always run hooks with no prompt.
    - no-verify=True, verify=False:
      Never run hooks, but run action anyway (AKA bypass hooks).
    - no-verify=True, verify=True:
      Invalid
    """

    def __init__(
        self,
        hook_type,
        hooks_project,
        repo_topdir,
        manifest_url,
        bug_url=None,
        bypass_hooks=False,
        allow_all_hooks=False,
        ignore_hooks=False,
        abort_if_user_denies=False,
        yes=False,
        fix=False,
    ):
        """RepoHook constructor.

        Params:
            hook_type: A string representing the type of hook. This is also used
                to figure out the name of the file containing the hook. For
                example: 'pre-upload'.
            hooks_project: The project containing the repo hooks.
                If you have a manifest, this is manifest.repo_hooks_project.
                OK if this is None, which will make the hook a no-op.
            repo_topdir: The top directory of the repo client checkout.
                This is the one containing the .repo directory. Scripts will
                run with CWD as this directory.
                If you have a manifest, this is manifest.topdir.
            manifest_url: The URL to the manifest git repo.
            bug_url: The URL to report issues.
            bypass_hooks: If True, then 'Do not run the hook'.
            allow_all_hooks: If True, then 'Run the hook without prompting'.
            ignore_hooks: If True, then 'Do not abort action if hooks fail'.
            abort_if_user_denies: If True, we'll abort running the hook if the
                user doesn't allow us to run the hook.
            yes: If True, then 'Yes' is assumed for any prompts.
            fix: If True, then 'Fix' is assumed for any fixup prompts.
        """
        self._hook_type = hook_type
        self._hooks_project = hooks_project
        self._repo_topdir = repo_topdir
        self._manifest_url = manifest_url
        self._bug_url = bug_url
        self._bypass_hooks = bypass_hooks
        self._allow_all_hooks = allow_all_hooks
        self._ignore_hooks = ignore_hooks
        self._abort_if_user_denies = abort_if_user_denies
        self._yes = yes
        self._fix = fix

        # Store the full path to the script for convenience.
        self._script_fullpath = None
        if self._hooks_project and self._hooks_project.worktree:
            self._script_fullpath = os.path.join(
                self._hooks_project.worktree, self._hook_type + ".py"
            )

    def _GetHash(self):
        """Return a hash of the contents of the hooks directory.

        We'll just use git to do this.  This hash has the property that if
        anything changes in the directory we will return a different has.

        SECURITY CONSIDERATION:
            This hash only represents the contents of files in the hook
            directory, not any other files imported or called by hooks.  Changes
            to imported files can change the script behavior without affecting
            the hash.

        Returns:
            A string representing the hash.  This will always be ASCII so that
            it can be printed to the user easily.
        """
        assert self._hooks_project, "Must have hooks to calculate their hash."

        # We will use the work_git object rather than just calling
        # GetRevisionId(). That gives us a hash of the latest checked in version
        # of the files that the user will actually be executing.  Specifically,
        # GetRevisionId() doesn't appear to change even if a user checks out a
        # different version of the hooks repo (via git checkout) nor if a user
        # commits their own revs.
        #
        # NOTE: Local (non-committed) changes will not be factored into this
        # hash. I think this is OK, since we're really only worried about
        # warning the user about upstream changes.
        return self._hooks_project.work_git.rev_parse(HEAD)

    def _GetMustVerb(self):
        """Return 'must' if the hook is required; 'should' if not."""
        if self._abort_if_user_denies:
            return "must"
        else:
            return "should"

    def _CheckForHookApproval(self):
        """Check to see whether this hook has been approved.

        We'll accept approval of manifest URLs if they're using secure
        transports. This way the user can say they trust the manifest hoster.
        For insecure hosts, we fall back to checking the hash of the hooks repo.

        Note that we ask permission for each individual hook even though we use
        the hash of all hooks when detecting changes.  We'd like the user to be
        able to approve / deny each hook individually.  We only use the hash of
        all hooks because there is no other easy way to detect changes to local
        imports.

        Returns:
            True if this hook is approved to run; False otherwise.

        Raises:
            HookError: Raised if the user doesn't approve and
                abort_if_user_denies was passed to the consturctor.
        """
        if self._ManifestUrlHasSecureScheme():
            return self._CheckForHookApprovalManifest()
        else:
            return self._CheckForHookApprovalHash()

    def _CheckForHookApprovalHelper(
        self, subkey, new_val, main_prompt, changed_prompt
    ):
        """Check for approval for a particular attribute and hook.

        Args:
            subkey: The git config key under [repo.hooks.<hook_type>] to store
                the last approved string.
            new_val: The new value to compare against the last approved one.
            main_prompt: Message to display to the user to ask for approval.
            changed_prompt: Message explaining why we're re-asking for approval.

        Returns:
            True if this hook is approved to run; False otherwise.

        Raises:
            HookError: Raised if the user doesn't approve and
                abort_if_user_denies was passed to the consturctor.
        """
        hooks_config = self._hooks_project.config
        git_approval_key = f"repo.hooks.{self._hook_type}.{subkey}"

        # Get the last value that the user approved for this hook; may be None.
        old_val = hooks_config.GetString(git_approval_key)

        if old_val is not None:
            # User previously approved hook and asked not to be prompted again.
            if new_val == old_val:
                # Approval matched.  We're done.
                return True
            else:
                # Give the user a reason why we're prompting, since they last
                # told us to "never ask again".
                prompt = f"WARNING: {changed_prompt}\n\n"
        else:
            prompt = ""

        # Prompt the user if we're not on a tty; on a tty we'll assume "no".
        if sys.stdout.isatty():
            prompt += main_prompt + " (yes/always/NO)? "
            response = input(prompt).lower()
            print()

            # User is doing a one-time approval.
            if response in ("y", "yes"):
                return True
            elif response == "always":
                hooks_config.SetString(git_approval_key, new_val)
                return True

        # For anything else, we'll assume no approval.
        if self._abort_if_user_denies:
            raise HookError(
                "You must allow the %s hook or use --no-verify."
                % self._hook_type
            )

        return False

    def _ManifestUrlHasSecureScheme(self):
        """Check if the URI for the manifest is a secure transport."""
        secure_schemes = (
            "file",
            "https",
            "ssh",
            "persistent-https",
            "sso",
            "rpc",
        )
        parse_results = urllib.parse.urlparse(self._manifest_url)
        return parse_results.scheme in secure_schemes

    def _CheckForHookApprovalManifest(self):
        """Check whether the user has approved this manifest host.

        Returns:
            True if this hook is approved to run; False otherwise.
        """
        return self._CheckForHookApprovalHelper(
            "approvedmanifest",
            self._manifest_url,
            f"Run hook scripts from {self._manifest_url}",
            f"Manifest URL has changed since {self._hook_type} was allowed.",
        )

    def _CheckForHookApprovalHash(self):
        """Check whether the user has approved the hooks repo.

        Returns:
            True if this hook is approved to run; False otherwise.
        """
        prompt = (
            "Repo %s run the script:\n"
            "  %s\n"
            "\n"
            "Do you want to allow this script to run"
        )
        return self._CheckForHookApprovalHelper(
            "approvedhash",
            self._GetHash(),
            prompt % (self._GetMustVerb(), self._script_fullpath),
            f"Scripts have changed since {self._hook_type} was allowed.",
        )

    @staticmethod
    def _ExtractInterpFromShebang(data):
        """Extract the interpreter used in the shebang.

        Try to locate the interpreter the script is using (ignoring `env`).

        Args:
            data: The file content of the script.

        Returns:
            The basename of the main script interpreter, or None if a shebang is
            not used or could not be parsed out.
        """
        firstline = data.splitlines()[:1]
        if not firstline:
            return None

        # The format here can be tricky.
        shebang = firstline[0].strip()
        m = re.match(r"^#!\s*([^\s]+)(?:\s+([^\s]+))?", shebang)
        if not m:
            return None

        # If the using `env`, find the target program.
        interp = m.group(1)
        if os.path.basename(interp) == "env":
            interp = m.group(2)

        return interp

    def _ExecuteHookViaImport(self, data, context, **kwargs):
        """Execute the hook code in |data| directly.

        Args:
            data: The code of the hook to execute.
            context: Basic Python context to execute the hook inside.
            kwargs: Arbitrary arguments to pass to the hook script.

        Raises:
            HookError: When the hooks failed for any reason.
        """
        # Exec, storing global context in the context dict.  We catch exceptions
        # and convert to a HookError w/ just the failing traceback.
        try:
            exec(compile(data, self._script_fullpath, "exec"), context)
        except Exception:
            raise HookError(
                "%s\nFailed to import %s hook; see traceback above."
                % (traceback.format_exc(), self._hook_type)
            )

        # Running the script should have defined a main() function.
        if "main" not in context:
            raise HookError('Missing main() in: "%s"' % self._script_fullpath)

        # Call the main function in the hook.  If the hook should cause the
        # build to fail, it will raise an Exception.  We'll catch that convert
        # to a HookError w/ just the failing traceback.
        try:
            context["main"](**kwargs)
        except Exception:
            raise HookError(
                "%s\nFailed to run main() for %s hook; see traceback "
                "above." % (traceback.format_exc(), self._hook_type)
            )

    def _ExecuteHook(self, **kwargs):
        """Actually execute the given hook.

        This will run the hook's 'main' function in our python interpreter.

        Args:
            kwargs: Keyword arguments to pass to the hook.  These are often
                specific to the hook type.  For instance, pre-upload hooks will
                contain a project_list.
        """
        # Keep sys.path and CWD stashed away so that we can always restore them
        # upon function exit.
        orig_path = os.getcwd()
        orig_syspath = sys.path

        try:
            # Always run hooks with CWD as topdir.
            os.chdir(self._repo_topdir)

            # Put the hook dir as the first item of sys.path so hooks can do
            # relative imports.  We want to replace the repo dir as [0] so
            # hooks can't import repo files.
            sys.path = [os.path.dirname(self._script_fullpath)] + sys.path[1:]

            # Initial global context for the hook to run within.
            context = {"__file__": self._script_fullpath}

            # Add 'hook_should_take_kwargs' to the arguments to be passed to
            # main. We don't actually want hooks to define their main with this
            # argument--it's there to remind them that their hook should always
            # take **kwargs.
            # For instance, a pre-upload hook should be defined like:
            #   def main(project_list, **kwargs):
            #
            # This allows us to later expand the API without breaking old hooks.
            kwargs = {
                **kwargs,
                "hook_should_take_kwargs": True,
                "fix": self._fix,
                "yes": self._yes,
            }

            # See what version of python the hook has been written against.
            data = open(self._script_fullpath).read()
            interp = self._ExtractInterpFromShebang(data)
            if interp:
                prog = os.path.basename(interp)
                if prog.startswith("python2"):
                    raise HookError("Python 2 is not supported")

            # Run the hook by importing directly.
            self._ExecuteHookViaImport(data, context, **kwargs)
        finally:
            # Restore sys.path and CWD.
            sys.path = orig_syspath
            os.chdir(orig_path)

    def _CheckHook(self):
        # Bail with a nice error if we can't find the hook.
        if not os.path.isfile(self._script_fullpath):
            raise HookError(
                "Couldn't find repo hook: %s" % self._script_fullpath
            )

    def Run(self, **kwargs):
        """Run the hook.

        If the hook doesn't exist (because there is no hooks project or because
        this particular hook is not enabled), this is a no-op.

        Args:
            user_allows_all_hooks: If True, we will never prompt about running
                the hook--we'll just assume it's OK to run it.
            kwargs: Keyword arguments to pass to the hook.  These are often
                specific to the hook type.  For instance, pre-upload hooks will
                contain a project_list.

        Returns:
            True: On success or ignore hooks by user-request
            False: The hook failed. The caller should respond with aborting the
                action. Some examples in which False is returned:
                * Finding the hook failed while it was enabled, or
                * the user declined to run a required hook (from
                    _CheckForHookApproval)
                In all these cases the user did not pass the proper arguments to
                ignore the result through the option combinations as listed in
                AddHookOptionGroup().
        """
        # Make sure our own callers use the documented API.
        exp_kwargs = _API_ARGS.get(self._hook_type, set())
        got_kwargs = set(kwargs.keys())
        if exp_kwargs != got_kwargs:
            print(
                "repo internal error: "
                f"hook '{self._hook_type}' called incorrectly\n"
                f"  got:      {sorted(got_kwargs)}\n"
                f"  expected: {sorted(exp_kwargs)}\n"
                f"Please file a bug: {self._bug_url}",
                file=sys.stderr,
            )
            return False

        # Do not do anything in case bypass_hooks is set, or
        # no-op if there is no hooks project or if hook is disabled.
        if (
            self._bypass_hooks
            or not self._hooks_project
            or not self._script_fullpath
            or self._hook_type not in self._hooks_project.enabled_repo_hooks
        ):
            return True

        passed = True
        try:
            self._CheckHook()

            # Make sure the user is OK with running the hook.
            if self._allow_all_hooks or self._CheckForHookApproval():
                # Run the hook with the same version of python we're using.
                self._ExecuteHook(**kwargs)
        except SystemExit as e:
            passed = False
            print(
                "ERROR: %s hooks exited with exit code: %s"
                % (self._hook_type, str(e)),
                file=sys.stderr,
            )
        except HookError as e:
            passed = False
            print("ERROR: %s" % str(e), file=sys.stderr)

        if not passed and self._ignore_hooks:
            print(
                "\nWARNING: %s hooks failed, but continuing anyways."
                % self._hook_type,
                file=sys.stderr,
            )
            passed = True

        return passed

    @classmethod
    def FromSubcmd(cls, manifest, opt, *args, **kwargs):
        """Method to construct the repo hook class

        Args:
            manifest: The current active manifest for this command from which we
                extract a couple of fields.
            opt: Contains the commandline options for the action of this hook.
                It should contain the options added by AddHookOptionGroup() in
                which we are interested in RepoHook execution.
        """
        for key in ("bypass_hooks", "allow_all_hooks", "ignore_hooks"):
            kwargs.setdefault(key, getattr(opt, key))
        kwargs.update(
            {
                "hooks_project": manifest.repo_hooks_project,
                "repo_topdir": manifest.topdir,
                "manifest_url": manifest.manifestProject.GetRemote(
                    "origin"
                ).url,
                "bug_url": manifest.contactinfo.bugurl,
                "yes": getattr(opt, "yes", False),
                "fix": getattr(opt, "fix", False),
            }
        )
        return cls(*args, **kwargs)

    @staticmethod
    def AddOptionGroup(
        parser: optparse.OptionParser,
        name: str,
        allow_fix: bool = False,
    ) -> None:
        """Help options relating to the various hooks."""

        # Note that verify and no-verify are NOT opposites of each other, which
        # is why they store to different locations. We are using them to match
        # 'git commit' syntax.
        group = parser.add_option_group(name + " hooks")
        group.add_option(
            "--no-verify",
            dest="bypass_hooks",
            action="store_true",
            help="Do not run the %s hook." % name,
        )
        group.add_option(
            "--verify",
            dest="allow_all_hooks",
            action="store_true",
            help="Run the %s hook without prompting." % name,
        )
        group.add_option(
            "--ignore-hooks",
            action="store_true",
            help="Do not abort if %s hooks fail." % name,
        )
        if allow_fix:
            group.add_option(
                "--fix",
                action="store_true",
                default=False,
                help="Automatically apply %s fixes without prompting." % name,
            )
