#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 "$@"