upload: Allow user to configure unusual commit threshold

Add a per-remote option `uploadwarningthreshold` allowing the user to
override how many commits can be uploaded prior to a warning being
displayed.

Change-Id: Ia7e1b2c7de89a0bf9ca1c24cc83dc595b3667437
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/354375
Tested-by: David Greenaway <dgreenaway@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
This commit is contained in:
David Greenaway 2022-12-09 09:38:24 +11:00
parent 0324e43242
commit d98f393524
2 changed files with 79 additions and 44 deletions

View File

@ -222,23 +222,24 @@ The `[remote]` settings are automatically populated/updated from the manifest.
The `[branch]` settings are updated by `repo start` and `git branch`. The `[branch]` settings are updated by `repo start` and `git branch`.
| Setting | Subcommands | Use/Meaning | | Setting | Subcommands | Use/Meaning |
|-------------------------------|---------------|-------------| |---------------------------------------|---------------|-------------|
| review.\<url\>.autocopy | upload | Automatically add to `--cc=<value>` | | review.\<url\>.autocopy | upload | Automatically add to `--cc=<value>` |
| review.\<url\>.autoreviewer | upload | Automatically add to `--reviewers=<value>` | | review.\<url\>.autoreviewer | upload | Automatically add to `--reviewers=<value>` |
| review.\<url\>.autoupload | upload | Automatically answer "yes" or "no" to all prompts | | review.\<url\>.autoupload | upload | Automatically answer "yes" or "no" to all prompts |
| review.\<url\>.uploadhashtags | upload | Automatically add to `--hashtag=<value>` | | review.\<url\>.uploadhashtags | upload | Automatically add to `--hashtag=<value>` |
| review.\<url\>.uploadlabels | upload | Automatically add to `--label=<value>` | | review.\<url\>.uploadlabels | upload | Automatically add to `--label=<value>` |
| review.\<url\>.uploadnotify | upload | [Notify setting][upload-notify] to use | | review.\<url\>.uploadnotify | upload | [Notify setting][upload-notify] to use |
| review.\<url\>.uploadtopic | upload | Default [topic] to use | | review.\<url\>.uploadtopic | upload | Default [topic] to use |
| review.\<url\>.username | upload | Override username with `ssh://` review URIs | | review.\<url\>.uploadwarningthreshold | upload | Warn when attempting to upload more than this many CLs |
| remote.\<remote\>.fetch | sync | Set of refs to fetch | | review.\<url\>.username | upload | Override username with `ssh://` review URIs |
| remote.\<remote\>.projectname | \<network\> | The name of the project as it exists in Gerrit review | | remote.\<remote\>.fetch | sync | Set of refs to fetch |
| remote.\<remote\>.pushurl | upload | The base URI for pushing CLs | | remote.\<remote\>.projectname | \<network\> | The name of the project as it exists in Gerrit review |
| remote.\<remote\>.review | upload | The URI of the Gerrit review server | | remote.\<remote\>.pushurl | upload | The base URI for pushing CLs |
| remote.\<remote\>.url | sync & upload | The URI of the git project to fetch | | remote.\<remote\>.review | upload | The URI of the Gerrit review server |
| branch.\<branch\>.merge | sync & upload | The branch to merge & upload & track | | remote.\<remote\>.url | sync & upload | The URI of the git project to fetch |
| branch.\<branch\>.remote | sync & upload | The remote to track | | branch.\<branch\>.merge | sync & upload | The branch to merge & upload & track |
| branch.\<branch\>.remote | sync & upload | The remote to track |
## ~/ dotconfig layout ## ~/ dotconfig layout

View File

@ -17,6 +17,7 @@ import functools
import optparse import optparse
import re import re
import sys import sys
from typing import List
from command import DEFAULT_LOCAL_JOBS, InteractiveCommand from command import DEFAULT_LOCAL_JOBS, InteractiveCommand
from editor import Editor from editor import Editor
@ -24,21 +25,54 @@ from error import UploadError
from git_command import GitCommand from git_command import GitCommand
from git_refs import R_HEADS from git_refs import R_HEADS
from hooks import RepoHook from hooks import RepoHook
from project import ReviewableBranch
UNUSUAL_COMMIT_THRESHOLD = 5 _DEFAULT_UNUSUAL_COMMIT_THRESHOLD = 5
def _ConfirmManyUploads(multiple_branches=False): def _VerifyPendingCommits(branches: List[ReviewableBranch]) -> bool:
if multiple_branches: """Perform basic safety checks on the given set of branches.
print('ATTENTION: One or more branches has an unusually high number '
'of commits.') Ensures that each branch does not have a "large" number of commits
else: and, if so, prompts the user to confirm they want to proceed with
print('ATTENTION: You are uploading an unusually high number of commits.') the upload.
print('YOU PROBABLY DO NOT MEAN TO DO THIS. (Did you rebase across '
'branches?)') Returns true if all branches pass the safety check or the user
answer = input("If you are sure you intend to do this, type 'yes': ").strip() confirmed. Returns false if the upload should be aborted.
return answer == "yes" """
# Determine if any branch has a suspicious number of commits.
many_commits = False
for branch in branches:
# Get the user's unusual threshold for the branch.
#
# Each branch may be configured to have a different threshold.
remote = branch.project.GetBranch(branch.name).remote
key = f'review.{remote.review}.uploadwarningthreshold'
threshold = branch.project.config.GetInt(key)
if threshold is None:
threshold = _DEFAULT_UNUSUAL_COMMIT_THRESHOLD
# If the branch has more commits than the threshold, show a warning.
if len(branch.commits) > threshold:
many_commits = True
break
# If any branch has many commits, prompt the user.
if many_commits:
if len(branches) > 1:
print('ATTENTION: One or more branches has an unusually high number '
'of commits.')
else:
print('ATTENTION: You are uploading an unusually high number of commits.')
print('YOU PROBABLY DO NOT MEAN TO DO THIS. (Did you rebase across '
'branches?)')
answer = input(
"If you are sure you intend to do this, type 'yes': ").strip()
return answer == 'yes'
return True
def _die(fmt, *args): def _die(fmt, *args):
@ -149,6 +183,13 @@ review.URL.uploadnotify:
Control e-mail notifications when uploading. Control e-mail notifications when uploading.
https://gerrit-review.googlesource.com/Documentation/user-upload.html#notify https://gerrit-review.googlesource.com/Documentation/user-upload.html#notify
review.URL.uploadwarningthreshold:
Repo will warn you if you are attempting to upload a large number
of commits in one or more branches. By default, the threshold
is five commits. This option allows you to override the warning
threshold to a different value.
# References # References
Gerrit Code Review: https://www.gerritcodereview.com/ Gerrit Code Review: https://www.gerritcodereview.com/
@ -261,16 +302,15 @@ Gerrit Code Review: https://www.gerritcodereview.com/
else: else:
answer = sys.stdin.readline().strip().lower() answer = sys.stdin.readline().strip().lower()
answer = answer in ('y', 'yes', '1', 'true', 't') answer = answer in ('y', 'yes', '1', 'true', 't')
if not answer:
_die("upload aborted by user")
if not opt.yes and answer: # Perform some basic safety checks prior to uploading.
if len(branch.commits) > UNUSUAL_COMMIT_THRESHOLD: if not opt.yes and not _VerifyPendingCommits([branch]):
answer = _ConfirmManyUploads()
if answer:
self._UploadAndReport(opt, [branch], people)
else:
_die("upload aborted by user") _die("upload aborted by user")
self._UploadAndReport(opt, [branch], people)
def _MultipleBranches(self, opt, pending, people): def _MultipleBranches(self, opt, pending, people):
projects = {} projects = {}
branches = {} branches = {}
@ -337,15 +377,9 @@ Gerrit Code Review: https://www.gerritcodereview.com/
if not todo: if not todo:
_die("nothing uncommented for upload") _die("nothing uncommented for upload")
if not opt.yes: # Perform some basic safety checks prior to uploading.
many_commits = False if not opt.yes and not _VerifyPendingCommits(todo):
for branch in todo: _die("upload aborted by user")
if len(branch.commits) > UNUSUAL_COMMIT_THRESHOLD:
many_commits = True
break
if many_commits:
if not _ConfirmManyUploads(multiple_branches=True):
_die("upload aborted by user")
self._UploadAndReport(opt, todo, people) self._UploadAndReport(opt, todo, people)