Ejemplo n.º 1
0
    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))
Ejemplo n.º 2
0
    def Run(self, user_allows_all_hooks, **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.

    Raises:
      HookError: If there was a problem finding the hook or the user declined
          to run a required hook (from _CheckForHookApproval).
    """
        # No-op if there is no hooks project or if hook is disabled.
        if ((not self._hooks_project) or
            (self._hook_type not in self._hooks_project.enabled_repo_hooks)):
            return

        # 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)

        # Make sure the user is OK with running the hook.
        if (not user_allows_all_hooks) and (not self._CheckForHookApproval()):
            return

        # Run the hook with the same version of python we're using.
        self._ExecuteHook(**kwargs)
Ejemplo n.º 3
0
    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 = 'repo.hooks.%s.%s' % (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 = 'WARNING: %s\n\n' % (changed_prompt, )
        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
Ejemplo n.º 4
0
Archivo: subcmd.py Proyecto: krep2/krep
    def run_hook(hook, hargs, cwd=None, dryrun=False, *args, **kws):
        if hook:
            if os.path.exists(hook):
                cli = list([hook])
                if hargs:
                    cli.extend(hargs)
                if args:
                    cli.extend(args)

                cmd = Command(cwd=cwd, dryrun=dryrun)
                cmd.new_args(*cli)
                ret = cmd.wait(**kws)
                if ret != 0:
                    raise HookError('Failed to run %s' % hook)

                return 0
            else:
                SubCommand.get_logger().debug("Error: %s not existed", hook)
Ejemplo n.º 5
0
    def _ExecuteHookViaReexec(self, interp, context, **kwargs):
        """Execute the hook script through |interp|.

    Note: Support for this feature should be dropped ~Jun 2021.

    Args:
      interp: The Python program to run.
      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.
    """
        # This logic needs to be kept in sync with _ExecuteHookViaImport below.
        script = """
import json, os, sys
path = '''%(path)s'''
kwargs = json.loads('''%(kwargs)s''')
context = json.loads('''%(context)s''')
sys.path.insert(0, os.path.dirname(path))
data = open(path).read()
exec(compile(data, path, 'exec'), context)
context['main'](**kwargs)
""" % {
            'path': self._script_fullpath,
            'kwargs': json.dumps(kwargs),
            'context': json.dumps(context),
        }

        # We pass the script via stdin to avoid OS argv limits.  It also makes
        # unhandled exception tracebacks less verbose/confusing for users.
        cmd = [interp, '-c', 'import sys; exec(sys.stdin.read())']
        proc = subprocess.Popen(cmd, stdin=subprocess.PIPE)
        proc.communicate(input=script.encode('utf-8'))
        if proc.returncode:
            raise HookError('Failed to run %s hook.' % (self._hook_type, ))
Ejemplo n.º 6
0
 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)