hooks: pass yes flag when available

Pass the -y flag as a keyword argument "yes" to the hook main function.
This allows upload hooks (such as auto-fixers) to automatically
apply fixes when the -y flag is passed, rather than prompting the user.

Bug: 498893733
Change-Id: I12096029aa3af471ba9175314d749deb0ebd1007
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/605261
Commit-Queue: Rahul Yadav <yadavrah@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
Tested-by: Rahul Yadav <yadavrah@google.com>
This commit is contained in:
Rahul Yadav
2026-07-10 08:39:24 -07:00
committed by gerrit-scoped@luci-project-accounts.iam.gserviceaccount.com
parent 1729aaebae
commit eeba6f268d
3 changed files with 53 additions and 3 deletions
+10 -1
View File
@@ -83,6 +83,13 @@ then check it directly. Hooks should not normally modify the active git repo
the user. Although user interaction is discouraged in the common case, it can
be useful when deploying automatic fixes.
### Safe Prompts
If the repo command that triggered the hook supports a "yes" option (e.g.,
`repo upload --yes`), this option is propagated to the hook's `main` function
as `yes` parameter (defaulting to `False`). Hooks can use this to bypass
interactive confirmation prompts when they can automatically fix issues.
### Shebang Handling
*** note
@@ -119,7 +126,7 @@ This hook runs when people run `repo upload`.
The `pre-upload.py` file should be defined like:
```py
def main(project_list, worktree_list=None, **kwargs):
def main(project_list, worktree_list=None, yes=False, **kwargs):
"""Main function invoked directly by repo.
We must use the name "main" as that is what repo requires.
@@ -130,6 +137,8 @@ def main(project_list, worktree_list=None, **kwargs):
project_list, so that each entry in project_list matches with a
directory in worktree_list. If None, we will attempt to calculate
the directories automatically.
yes: Whether to answer yes to all safe prompts (see
[Safe Prompts](#safe-prompts)).
kwargs: Leave this here for forward-compatibility.
"""
```
+9 -2
View File
@@ -68,6 +68,7 @@ class RepoHook:
allow_all_hooks=False,
ignore_hooks=False,
abort_if_user_denies=False,
yes=False,
):
"""RepoHook constructor.
@@ -89,6 +90,7 @@ class RepoHook:
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.
"""
self._hook_type = hook_type
self._hooks_project = hooks_project
@@ -99,6 +101,7 @@ class RepoHook:
self._allow_all_hooks = allow_all_hooks
self._ignore_hooks = ignore_hooks
self._abort_if_user_denies = abort_if_user_denies
self._yes = yes
# Store the full path to the script for convenience.
self._script_fullpath = None
@@ -374,8 +377,11 @@ class RepoHook:
# def main(project_list, **kwargs):
#
# This allows us to later expand the API without breaking old hooks.
kwargs = kwargs.copy()
kwargs["hook_should_take_kwargs"] = True
kwargs = {
**kwargs,
"hook_should_take_kwargs": True,
"yes": self._yes,
}
# See what version of python the hook has been written against.
data = open(self._script_fullpath).read()
@@ -497,6 +503,7 @@ class RepoHook:
"origin"
).url,
"bug_url": manifest.contactinfo.bugurl,
"yes": getattr(opt, "yes", False),
}
)
return cls(*args, **kwargs)
+34
View File
@@ -105,3 +105,37 @@ def test_post_sync_argument_validation() -> None:
finally:
sys.stderr = old_stderr
@pytest.mark.parametrize("yes_val", (True, False))
def test_repo_upload_yes_arg(tmp_path, yes_val: bool) -> None:
"""Test that yes is passed in kwargs during hook execution."""
class FakeProject:
def __init__(self, worktree):
self.worktree = worktree
self.enabled_repo_hooks = ["pre-upload"]
self.config = None
hook_file = tmp_path / "pre-upload.py"
hook_content = """
def main(project_list, **kwargs):
project_list.append(kwargs.get("yes"))
"""
hook_file.write_text(hook_content)
hook = hooks.RepoHook(
hook_type="pre-upload",
hooks_project=FakeProject(str(tmp_path)),
repo_topdir=str(tmp_path),
manifest_url="https://gerrit",
allow_all_hooks=True,
yes=yes_val,
)
project_list = []
res = hook.Run(project_list=project_list, worktree_list=[])
assert res is True
assert project_list == [yes_val]