mirror of
https://gerrit.googlesource.com/git-repo
synced 2026-05-30 06:29:52 +00:00
e8deeabf2a
This PR adds `completion.zsh` to allow for relatively intelligent completion of `repo` command-line arguments for all commands of the `repo` CLI. The `completion.zsh` can be added to your zsh completions by copying (and renaming) the completion script to a directory that you have added to your zsh completion path. ``` cp completion.zsh $ZSH_COMPLETION_DIRECTORY/_repo ``` You must name the file `_repo` for it to register as completion for `repo`. You can add a directory to your zsh completion by updating your `fpath` variable before calling `compinit` as follows: ``` fpath=( /path/to/zsh-completions/dir $fpath ) ``` Future work: Generate this file using the subcommand classes and python reflection. Change-Id: I6a4e785c1efcf9076bd693976ac03578836b691b Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/579561 Commit-Queue: Mike Frysinger <vapier@google.com> Reviewed-by: Gavin Mak <gavinmak@google.com> Tested-by: Kamal Sacranie <sacranie@google.com> Reviewed-by: Mike Frysinger <vapier@google.com>
450 lines
17 KiB
Bash
450 lines
17 KiB
Bash
#compdef _repo repo
|
|
|
|
# Copyright (C) 2026 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.
|
|
|
|
_repo() {
|
|
local context state line
|
|
typeset -A opt_args
|
|
|
|
local -a subcommands
|
|
subcommands=(
|
|
'abandon:Abandon a development branch'
|
|
'branches:View current topic branches'
|
|
'checkout:Checkout a branch'
|
|
'cherry-pick:Cherry-pick a change'
|
|
'diff:Show changes between commit and working tree'
|
|
'diffmanifests:Show differences between two manifests'
|
|
'download:Download and find a change'
|
|
'forall:Run a shell command in each project'
|
|
'gc:Garbage collect'
|
|
'grep:Print lines matching a pattern'
|
|
'help:Display help about a command'
|
|
'info:Get info about the manifest'
|
|
'init:Initialize a repo client'
|
|
'list:List projects and their names'
|
|
'manifest:Manifest management'
|
|
'overview:Display overview of topic branches'
|
|
'prune:Prune topic branches'
|
|
'rebase:Rebase local branches'
|
|
'selfupdate:Update repo'
|
|
'smartsync:Update working tree to latest known good revision'
|
|
'stage:Stage file(s) for commit'
|
|
'start:Start a new branch for development'
|
|
'status:Show the working tree status'
|
|
'sync:Update working tree'
|
|
'upload:Upload changes to the review server'
|
|
'version:Display version'
|
|
'wipe:Wipe uncommitted changes'
|
|
)
|
|
|
|
local -a global_opts
|
|
global_opts=(
|
|
'(-h --help)'{-h,--help}'[Show help message]'
|
|
'--help-all[Show help message for all commands]'
|
|
'(-p --paginate)'{-p,--paginate}'[Pipe all output into less]'
|
|
'--no-pager[Do not pipe output into a pager]'
|
|
'--color=[Control color output]:color:(always never auto)'
|
|
'--trace[Trace git command execution]'
|
|
'--trace-to-stderr[Trace git command execution to stderr]'
|
|
'--trace-python[Trace python execution]'
|
|
'--time[Time execute of command]'
|
|
'--version[Show version]'
|
|
'--show-toplevel[Show top level of workspace]'
|
|
'--event-log=[File to log events to]:file:_files'
|
|
'--git-trace2-event-log=[File to log git trace2 events to]:file:_files'
|
|
'--submanifest-path=[Path to submanifest]:path:_files'
|
|
)
|
|
|
|
_arguments -C \
|
|
${global_opts} \
|
|
'1: :->cmds' \
|
|
'*:: :->subcmds'
|
|
|
|
case ${state} in
|
|
cmds)
|
|
_describe -t commands 'repo command' subcommands
|
|
;;
|
|
subcmds)
|
|
local cmd=${words[1]}
|
|
curcontext="${curcontext%:*}-${cmd}:"
|
|
|
|
local -a common_opts
|
|
common_opts=(
|
|
'(-h --help)'{-h,--help}'[Show help message]'
|
|
'(-v --verbose)'{-v,--verbose}'[Show verbose messages]'
|
|
'(-q --quiet)'{-q,--quiet}'[Show only errors]'
|
|
'(-j --jobs)'{-j,--jobs=}'[Number of jobs to run in parallel]:jobs:'
|
|
'--outer-manifest[Use outer manifest]'
|
|
'--no-outer-manifest[Do not use outer manifest]'
|
|
'--this-manifest-only[Only use this manifest]'
|
|
'--no-this-manifest-only[Do not only use this manifest]'
|
|
'--all-manifests[Use all manifests]'
|
|
)
|
|
|
|
case ${cmd} in
|
|
abandon)
|
|
_arguments \
|
|
${common_opts} \
|
|
'--all[Abandon all branches]' \
|
|
'1: :->branch' \
|
|
'*: :->project'
|
|
;;
|
|
branches)
|
|
_arguments \
|
|
${common_opts} \
|
|
'*: :->project'
|
|
;;
|
|
checkout)
|
|
_arguments \
|
|
${common_opts} \
|
|
'1: :->branch' \
|
|
'*: :->project'
|
|
;;
|
|
cherry-pick)
|
|
_arguments \
|
|
${common_opts} \
|
|
'1: :_message "sha1"'
|
|
;;
|
|
diff)
|
|
_arguments \
|
|
${common_opts} \
|
|
'(-u --absolute)'{-u,--absolute}'[Show absolute paths]' \
|
|
'*: :->project'
|
|
;;
|
|
diffmanifests)
|
|
_arguments \
|
|
'--raw[Show raw diff]' \
|
|
'--no-color[Do not show color]' \
|
|
'--pretty-format=[Pretty format]:format:' \
|
|
'1: :_files -g "*.xml"' \
|
|
'2: :_files -g "*.xml"'
|
|
;;
|
|
download)
|
|
_arguments \
|
|
${common_opts} \
|
|
'(-b --branch)'{-b,--branch=}'[One or more branches to check]:branch:' \
|
|
'(-c --cherry-pick)'{-c,--cherry-pick}'[Cherry-pick the change]' \
|
|
'(-x --record-origin)'{-x,--record-origin}'[Record origin of cherry-pick]' \
|
|
'(-r --revert)'{-r,--revert}'[Revert the change]' \
|
|
'(-f --ff-only)'{-f,--ff-only}'[Force fast-forward]' \
|
|
'*: :_message "change[/patchset]"'
|
|
;;
|
|
forall)
|
|
_arguments \
|
|
${common_opts} \
|
|
'(-r --regex)'{-r,--regex}'[Execute command only on projects matching regex]' \
|
|
'(-i --inverse-regex)'{-i,--inverse-regex}'[Execute command only on projects not matching regex]' \
|
|
'(-g --groups)'{-g,--groups=}'[Execute command only on projects matching groups]:groups:' \
|
|
'(-c --command)'{-c,--command}'[Command to execute]' \
|
|
'(-e --abort-on-errors)'{-e,--abort-on-errors}'[Abort on errors]' \
|
|
'--ignore-missing[Ignore missing projects]' \
|
|
'--interactive[Run interactively]' \
|
|
'-p[Show project headers]' \
|
|
'*: :->project'
|
|
;;
|
|
gc)
|
|
_arguments \
|
|
${common_opts} \
|
|
'(-n --dry-run)'{-n,--dry-run}'[Dry run]' \
|
|
'(-y --yes)'{-y,--yes}'[Answer yes to all prompts]' \
|
|
'--repack[Repack objects]'
|
|
;;
|
|
grep)
|
|
_arguments \
|
|
${common_opts} \
|
|
'--cached[Search cached files]' \
|
|
'(-r --revision)'{-r,--revision=}'[Search in revision]:revision:' \
|
|
'-e[Pattern]' \
|
|
'(-i --ignore-case)'{-i,--ignore-case}'[Ignore case]' \
|
|
'(-a --text)'{-a,--text}'[Treat all files as text]' \
|
|
'-I[Do not match binary files]' \
|
|
'(-w --word-regexp)'{-w,--word-regexp}'[Match word boundaries]' \
|
|
'(-v --invert-match)'{-v,--invert-match}'[Invert match]' \
|
|
'(-G --basic-regexp)'{-G,--basic-regexp}'[Basic regexp]' \
|
|
'(-E --extended-regexp)'{-E,--extended-regexp}'[Extended regexp]' \
|
|
'(-F --fixed-strings)'{-F,--fixed-strings}'[Fixed strings]' \
|
|
'--all-match[All match]' \
|
|
'--and[And]' \
|
|
'--or[Or]' \
|
|
'--not[Not]' \
|
|
'-([Open paren]' \
|
|
'-)[Close paren]' \
|
|
'-n[Line number]' \
|
|
'-C[Context]:lines:' \
|
|
'-B[Before context]:lines:' \
|
|
'-A[After context]:lines:' \
|
|
'-l[Name only]' \
|
|
'--name-only[Name only]' \
|
|
'--files-with-matches[Files with matches]' \
|
|
'-L[Files without match]' \
|
|
'--files-without-match[Files without match]' \
|
|
'1: :->pattern' \
|
|
'*: :->project'
|
|
;;
|
|
help)
|
|
_arguments \
|
|
'(-a --all)'{-a,--all}'[Show all commands]' \
|
|
'--help-all[Show help message for all commands]' \
|
|
'1: :->help_cmds'
|
|
;;
|
|
info)
|
|
_arguments \
|
|
${common_opts} \
|
|
'(-d --diff)'{-d,--diff}'[Show diff]' \
|
|
'(-o --overview)'{-o,--overview}'[Show overview]' \
|
|
'(-c --current-branch)'{-c,--current-branch}'[Show current branch]' \
|
|
'--no-current-branch[Do not show current branch]' \
|
|
'(-l --local-only)'{-l,--local-only}'[Local only]' \
|
|
'*: :->project'
|
|
;;
|
|
init)
|
|
_arguments \
|
|
'(-u --manifest-url)'{-u,--manifest-url=}'[Manifest URL]:url:' \
|
|
'(-b --manifest-branch)'{-b,--manifest-branch=}'[Manifest branch]:branch:' \
|
|
'--manifest-upstream-branch=[Manifest upstream branch]:branch:' \
|
|
'(-m --manifest-name)'{-m,--manifest-name=}'[Manifest name]:file:_files -g "*.xml"' \
|
|
'(-g --groups)'{-g,--groups=}'[Restrict manifest projects to groups]:groups:' \
|
|
'(-p --platform)'{-p,--platform=}'[Restrict manifest projects to platform]:platform:' \
|
|
'--submodules[Sync submodules]' \
|
|
'--standalone-manifest[Standalone manifest]' \
|
|
'--manifest-depth=[Manifest depth]:depth:' \
|
|
'(-c --current-branch)'{-c,--current-branch}'[Sync current branch only]' \
|
|
'--no-current-branch[Do not sync current branch only]' \
|
|
'--tags[Sync tags]' \
|
|
'--no-tags[Do not sync tags]' \
|
|
'--mirror[Mirror]' \
|
|
'--archive[Archive]' \
|
|
'--worktree[Worktree]' \
|
|
'--reference=[Reference repository]:repository:_files -/' \
|
|
'--dissociate[Dissociate from reference]' \
|
|
'--depth=[Depth]:depth:' \
|
|
'--partial-clone[Partial clone]' \
|
|
'--no-partial-clone[Do not partial clone]' \
|
|
'--partial-clone-exclude=[Exclude from partial clone]:projects:' \
|
|
'--clone-filter=[Clone filter]:filter:' \
|
|
'--use-superproject[Use superproject]' \
|
|
'--no-use-superproject[Do not use superproject]' \
|
|
'--clone-bundle[Use clone bundle]' \
|
|
'--no-clone-bundle[Do not use clone bundle]' \
|
|
'--git-lfs[Use git lfs]' \
|
|
'--no-git-lfs[Do not use git lfs]' \
|
|
'--repo-url=[Repo URL]:url:' \
|
|
'--repo-rev=[Repo revision]:revision:' \
|
|
'--no-repo-verify[Do not verify repo]' \
|
|
'--config-name[Use config name]'
|
|
;;
|
|
list)
|
|
_arguments \
|
|
${common_opts} \
|
|
'(-r --regex)'{-r,--regex}'[Filter by regex]' \
|
|
'(-g --groups)'{-g,--groups=}'[Filter by groups]:groups:' \
|
|
'(-a --all)'{-a,--all}'[Show all projects]' \
|
|
'(-n --name-only)'{-n,--name-only}'[Show only names]' \
|
|
'(-p --path-only)'{-p,--path-only}'[Show only paths]' \
|
|
'(-f --fullpath)'{-f,--fullpath}'[Show full paths]' \
|
|
'--relative-to=[Show paths relative to]:path:_files -/' \
|
|
'*: :->project'
|
|
;;
|
|
manifest)
|
|
_arguments \
|
|
'(-r --revision-as-HEAD)'{-r,--revision-as-HEAD}'[Save revisions as current HEAD]' \
|
|
'(-m --manifest-name)'{-m,--manifest-name=}'[Manifest name]:file:_files -g "*.xml"' \
|
|
'--suppress-upstream-revision[Suppress upstream revision]' \
|
|
'--suppress-dest-branch[Suppress dest branch]' \
|
|
'--format=[Output format]:format:(xml json)' \
|
|
'--pretty[Pretty print]' \
|
|
'--no-local-manifests[Ignore local manifests]' \
|
|
'(-o --output-file)'{-o,--output-file=}'[Output file]:file:_files'
|
|
;;
|
|
overview)
|
|
_arguments \
|
|
${common_opts} \
|
|
'(-c --current-branch)'{-c,--current-branch}'[Show current branch]' \
|
|
'--no-current-branch[Do not show current branch]' \
|
|
'*: :->project'
|
|
;;
|
|
prune)
|
|
_arguments \
|
|
${common_opts} \
|
|
'*: :->project'
|
|
;;
|
|
rebase)
|
|
_arguments \
|
|
${common_opts} \
|
|
'--fail-fast[Fail fast]' \
|
|
'(-f --force-rebase)'{-f,--force-rebase}'[Force rebase]' \
|
|
'--no-ff[No fast forward]' \
|
|
'--autosquash[Autosquash]' \
|
|
'--whitespace=[Whitespace option]:option:' \
|
|
'--auto-stash[Auto stash]' \
|
|
'(-m --onto-manifest)'{-m,--onto-manifest}'[Rebase onto manifest]' \
|
|
'(-i --interactive)'{-i,--interactive}'[Interactive rebase]' \
|
|
'*: :->project'
|
|
;;
|
|
selfupdate)
|
|
_arguments \
|
|
'--no-repo-verify[Do not verify repo]'
|
|
;;
|
|
smartsync | sync)
|
|
_arguments \
|
|
${common_opts} \
|
|
'--jobs-network=[Number of network jobs]:jobs:' \
|
|
'--jobs-checkout=[Number of checkout jobs]:jobs:' \
|
|
'(-f --force-broken)'{-f,--force-broken}'[Continue sync even if a project fails]' \
|
|
'--fail-fast[Fail fast]' \
|
|
'--force-sync[Overwrite existing git directories]' \
|
|
'--force-checkout[Force checkout]' \
|
|
'--force-remove-dirty[Force remove dirty]' \
|
|
'--rebase[Rebase local branches]' \
|
|
'(-l --local-only)'{-l,--local-only}'[Only use local files]' \
|
|
'--no-manifest-update[Do not update manifest]' \
|
|
'--nmu[Do not update manifest]' \
|
|
'--interleaved[Interleave output]' \
|
|
'--no-interleaved[Do not interleave output]' \
|
|
'(-n --network-only)'{-n,--network-only}'[Only fetch]' \
|
|
'(-d --detach)'{-d,--detach}'[Detach HEAD]' \
|
|
'(-c --current-branch)'{-c,--current-branch}'[Fetch only current branch]' \
|
|
'--no-current-branch[Do not fetch only current branch]' \
|
|
'(-m --manifest-name)'{-m,--manifest-name=}'[Manifest name]:file:_files -g "*.xml"' \
|
|
'--clone-bundle[Use clone bundle]' \
|
|
'--no-clone-bundle[Do not use clone bundle]' \
|
|
'(-u --manifest-server-username)'{-u,--manifest-server-username=}'[Username for manifest server]:username:' \
|
|
'(-p --manifest-server-password)'{-p,--manifest-server-password=}'[Password for manifest server]:password:' \
|
|
'--fetch-submodules[Fetch submodules]' \
|
|
'--use-superproject[Use superproject]' \
|
|
'--no-use-superproject[Do not use superproject]' \
|
|
'--tags[Sync tags]' \
|
|
'--no-tags[Do not sync tags]' \
|
|
'--optimized-fetch[Optimized fetch]' \
|
|
'--retry-fetches=[Retry fetches]:count:' \
|
|
'--prune[Prune]' \
|
|
'--no-prune[Do not prune]' \
|
|
'--auto-gc[Run auto gc]' \
|
|
'--no-auto-gc[Do not run auto gc]' \
|
|
'(-s --smart-sync)'{-s,--smart-sync}'[Smart sync]' \
|
|
'(-t --smart-tag)'{-t,--smart-tag=}'[Smart tag]:tag:' \
|
|
'--no-repo-verify[Do not verify repo]' \
|
|
'--no-verify[Do not verify]' \
|
|
'--verify[Verify]' \
|
|
'--ignore-hooks[Ignore hooks]' \
|
|
'*: :->project'
|
|
;;
|
|
stage)
|
|
_arguments \
|
|
${common_opts} \
|
|
'(-i --interactive)'{-i,--interactive}'[Interactive staging]' \
|
|
'*: :->project'
|
|
;;
|
|
start)
|
|
_arguments \
|
|
${common_opts} \
|
|
'--all[Start branch in all projects]' \
|
|
'(-r --rev --revision)'{-r,--rev=,--revision=}'[Revision]:revision:' \
|
|
'--head[Head]' \
|
|
'--HEAD[Head]' \
|
|
'1: :->newbranch' \
|
|
'*: :->project'
|
|
;;
|
|
status)
|
|
_arguments \
|
|
${common_opts} \
|
|
'(-o --orphans)'{-o,--orphans}'[Show orphans]' \
|
|
'*: :->project'
|
|
;;
|
|
upload)
|
|
_arguments \
|
|
${common_opts} \
|
|
'(-t --topic-branch)'{-t,--topic-branch}'[Topic branch]' \
|
|
'--topic=[Topic]:topic:' \
|
|
'--hashtag=[Hashtag]:hashtag:' \
|
|
'--ht=[Hashtag]:hashtag:' \
|
|
'--hashtag-branch[Hashtag branch]' \
|
|
'--htb[Hashtag branch]' \
|
|
'(-l --label)'{-l,--label=}'[Label]:label:' \
|
|
'--pd=[Patchset description]:description:' \
|
|
'--patchset-description=[Patchset description]:description:' \
|
|
'--re=[Reviewers]:reviewers:' \
|
|
'--reviewers=[Reviewers]:reviewers:' \
|
|
'--cc=[CC]:cc:' \
|
|
'--br=[Branch]:branch:' \
|
|
'--branch=[Branch]:branch:' \
|
|
'(-c --current-branch)'{-c,--current-branch}'[Upload current branch]' \
|
|
'--no-current-branch[Do not upload current branch]' \
|
|
'--ne[No emails]' \
|
|
'--no-emails[No emails]' \
|
|
'(-p --private)'{-p,--private}'[Private]' \
|
|
'(-w --wip)'{-w,--wip}'[Work in progress]' \
|
|
'(-r --ready)'{-r,--ready}'[Ready]' \
|
|
'(-o --push-option)'{-o,--push-option=}'[Push option]:option:' \
|
|
'(-D --destination --dest)'{-D,--destination=,--dest=}'[Destination]:destination:' \
|
|
'(-n --dry-run)'{-n,--dry-run}'[Dry run]' \
|
|
'(-y --yes)'{-y,--yes}'[Answer yes to all prompts]' \
|
|
'--ignore-untracked-files[Ignore untracked files]' \
|
|
'--no-ignore-untracked-files[Do not ignore untracked files]' \
|
|
'--no-cert-checks[Do not check certificates]' \
|
|
'--no-verify[Do not verify]' \
|
|
'--verify[Verify]' \
|
|
'--ignore-hooks[Ignore hooks]' \
|
|
'*: :->project'
|
|
;;
|
|
version)
|
|
_arguments ${common_opts}
|
|
;;
|
|
wipe)
|
|
_arguments \
|
|
${common_opts} \
|
|
'(-f --force)'{-f,--force}'[Force wipe]' \
|
|
'--force-uncommitted[Force uncommitted]' \
|
|
'--force-shared[Force shared]' \
|
|
'*: :->project'
|
|
;;
|
|
esac
|
|
|
|
# Handle states for positional arguments.
|
|
case ${state} in
|
|
branch)
|
|
[[ ${PREFIX} != -* ]] && _repo_branches
|
|
;;
|
|
project)
|
|
[[ ${PREFIX} != -* ]] && _repo_projects
|
|
;;
|
|
pattern)
|
|
_message 'pattern'
|
|
;;
|
|
newbranch)
|
|
_message 'new branch name'
|
|
;;
|
|
help_cmds)
|
|
_describe -t commands 'repo command' subcommands
|
|
;;
|
|
esac
|
|
;;
|
|
esac
|
|
}
|
|
|
|
_repo_branches() {
|
|
local -a branches
|
|
branches=(${(f)"$(_call_program branches repo branches 2>/dev/null | sed -E 's/^.*[[:space:]]([^[:space:]]+)[[:space:]]+\|.*$/\1/' | awk '{print $1}')"})
|
|
_describe -t branches 'branch' branches
|
|
}
|
|
|
|
_repo_projects() {
|
|
local -a projects
|
|
projects=(${(f)"$(_call_program projects repo list -n 2>/dev/null)"})
|
|
_describe -t projects 'project' projects
|
|
}
|
|
|
|
_repo "$@"
|