58bc76bb65
Checking if main.py exists is better than checking if it is a file, since it might be a symlink. Change-Id: I1a9e617470a05c2161479cd3f0a10712a2b9d2c2
654 lines
11 KiB
Bash
654 lines
11 KiB
Bash
# -*- mode: sh; -*-
|
|
|
|
declare -A CMD_HANDLERS
|
|
CMD_HANDLERS=(
|
|
["init"]=_repo_init
|
|
["help"]=_repo_help
|
|
["abandon"]=_repo_abandon
|
|
["branch"]=_repo_branch
|
|
["branches"]=_repo_branches
|
|
["checkout"]=_repo_checkout
|
|
["cherry-pick"]=_repo_cherry_pick
|
|
["diff"]=_repo_diff
|
|
["download"]=_repo_download
|
|
["forall"]=_repo_forall
|
|
["grep"]=_repo_grep
|
|
["list"]=_repo_list
|
|
["prune"]=_repo_prune
|
|
["rebase"]=_repo_rebase
|
|
["selfupdate"]=_repo_selfupdate
|
|
["smartsync"]=_repo_smartsync
|
|
["stage"]=_repo_stage
|
|
["start"]=_repo_start
|
|
["status"]=_repo_status
|
|
["sync"]=_repo_sync
|
|
["upload"]=_repo_upload
|
|
["version"]=_repo_version
|
|
)
|
|
|
|
# To be populated by command handlers.
|
|
declare -a OPTIONS
|
|
declare -A ARG_OPTIONS
|
|
|
|
declare cur
|
|
declare prev
|
|
|
|
_init_cur_prev() {
|
|
cur=$(_get_cword "=")
|
|
prev=$(_get_cword "=" 1)
|
|
|
|
_split_longopt
|
|
}
|
|
|
|
_find_repo() {
|
|
local dir=$(pwd)
|
|
local found=1
|
|
|
|
while [ "${dir}" != / ]
|
|
do
|
|
if [ -e "${dir}/.repo/repo/main.py" ]
|
|
then
|
|
found=0
|
|
break
|
|
fi
|
|
|
|
dir=$(cd "${dir}/.." && pwd)
|
|
done
|
|
|
|
if [ ${found} -eq 0 ]
|
|
then
|
|
echo "${dir}"
|
|
fi
|
|
}
|
|
|
|
_is_repo_dir() {
|
|
local repo_root=$(_find_repo)
|
|
|
|
[ -n "${repo_root}" ]
|
|
}
|
|
|
|
_gen_comps() {
|
|
local completions="$1"
|
|
local suffix="${2:- }"
|
|
|
|
local -i i
|
|
local -a tmp=( $(compgen -W "${completions}" -- ${cur}) )
|
|
|
|
for (( i=0; i < ${#tmp[*]}; i++ ))
|
|
do
|
|
tmp[$i]="${tmp[$i]}${suffix}"
|
|
done
|
|
|
|
COMPREPLY=(
|
|
"${COMPREPLY[@]}"
|
|
"${tmp[@]}"
|
|
)
|
|
}
|
|
|
|
_strip_colors () {
|
|
# taken from http://goo.gl/7KlLZ
|
|
sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g"
|
|
}
|
|
|
|
_no_completion() {
|
|
true
|
|
}
|
|
|
|
_command_completion() {
|
|
local cmds
|
|
|
|
if _is_repo_dir
|
|
then
|
|
cmds=("abandon" "branch" "branches" "checkout" "cherry-pick" "diff"
|
|
"download" "forall" "grep" "help" "init" "list" "prune" "rebase"
|
|
"selfupdate" "smartsync" "stage" "start" "status" "sync"
|
|
"upload" "version")
|
|
else
|
|
cmds=("help" "init")
|
|
fi
|
|
|
|
_gen_comps "${cmds[*]}"
|
|
}
|
|
|
|
_branch_completion() {
|
|
local raw_branches
|
|
|
|
# separate statement required to be able to access exit code
|
|
raw_branches=$(repo branches 2>/dev/null)
|
|
|
|
if [ $? -eq 0 ]
|
|
then
|
|
local branches=$(
|
|
echo "${raw_branches}" |
|
|
_strip_colors | awk 'BEGIN { FS="|" } { print $1 }' | cut -c 3-
|
|
)
|
|
|
|
_gen_comps "${branches}"
|
|
fi
|
|
}
|
|
|
|
_dir_completion() {
|
|
_filedir -d
|
|
}
|
|
|
|
_project_completion() {
|
|
local repo_root=$(_find_repo)
|
|
|
|
if [ -n "${repo_root}" -a -f "${repo_root}/.repo/project.list" ]
|
|
then
|
|
local projects=$(cat "${repo_root}/.repo/project.list")
|
|
_gen_comps "${projects}"
|
|
fi
|
|
}
|
|
|
|
_manifest_completion() {
|
|
local repo_root=$(_find_repo)
|
|
|
|
if [ -n "${repo_root}" ]
|
|
then
|
|
local manifests_dir="${repo_root}/.repo/manifests"
|
|
local git_dir="${manifests_dir}/.git"
|
|
local candidates
|
|
|
|
manifests=$(
|
|
git --git-dir "${git_dir}" ls-files "*.xml" 2>/dev/null)
|
|
|
|
if [ $? -eq 0 ]
|
|
then
|
|
_gen_comps "${manifests}"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
_path_cmd_completion() {
|
|
_gen_comps "$(compgen -c ${cur})"
|
|
}
|
|
|
|
_is_option() {
|
|
local opt="$1"
|
|
|
|
[[ "${opt}" == -* ]]
|
|
}
|
|
|
|
_is_long_option() {
|
|
local opt="$1"
|
|
|
|
[[ "${opt}" == --* ]]
|
|
}
|
|
|
|
_expects_arg() {
|
|
local opt="$1"
|
|
|
|
if [[ ${ARG_OPTIONS[$opt]} ]]
|
|
then
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
_handle_options() {
|
|
if _expects_arg "${prev}"
|
|
then
|
|
local handler=${ARG_OPTIONS[$prev]}
|
|
eval ${handler} "${cur}"
|
|
elif _is_option "${cur}"
|
|
then
|
|
_gen_comps "${OPTIONS[*]}"
|
|
|
|
local arg_short
|
|
local arg_long
|
|
|
|
for opt in "${!ARG_OPTIONS[@]}"
|
|
do
|
|
if _is_long_option "${opt}"
|
|
then
|
|
arg_long="${arg_long} ${opt}"
|
|
else
|
|
arg_short="${arg_short} ${opt}"
|
|
fi
|
|
done
|
|
|
|
_gen_comps "${arg_short}"
|
|
_gen_comps "${arg_long}" "="
|
|
else
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
_is_known_shortopt() {
|
|
local needle="$1"
|
|
|
|
for opt in ${OPTIONS[@]}
|
|
do
|
|
if [ "${opt}" = "${needle}" ]
|
|
then
|
|
return 0
|
|
fi
|
|
done
|
|
|
|
return 1
|
|
}
|
|
|
|
_is_known_longopt() {
|
|
local needle="$1"
|
|
|
|
[[ ${ARG_OPTIONS[$1]} ]]
|
|
}
|
|
|
|
_arg_index() {
|
|
local -i i=2 # skip repo and command
|
|
local -i ix=0
|
|
|
|
while [ ${i} -lt ${COMP_CWORD} ]
|
|
do
|
|
if _is_known_shortopt "${COMP_WORDS[i]}"
|
|
then
|
|
i+=1
|
|
elif _is_known_longopt "${COMP_WORDS[i]}"
|
|
then
|
|
i+=2
|
|
elif _is_option "${COMP_WORDS[i]}"
|
|
then
|
|
i+=1
|
|
else
|
|
i+=1
|
|
ix+=1
|
|
fi
|
|
done
|
|
|
|
eval $1="${ix}"
|
|
}
|
|
|
|
_when_ix() {
|
|
local ix="$1"
|
|
local completion="$2"
|
|
|
|
_arg_index arg_ix
|
|
|
|
if [ ${arg_ix} -eq ${ix} ]
|
|
then
|
|
${completion}
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
_when_first() {
|
|
_when_ix 0 "$1"
|
|
}
|
|
|
|
_when_even() {
|
|
local completion="$1"
|
|
|
|
_arg_index arg_ix
|
|
|
|
if [ $(( ${arg_ix} % 2 )) -eq 0 ]
|
|
then
|
|
${completion}
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
_cmp_opts() {
|
|
local opt="$1"
|
|
local word="$2"
|
|
|
|
if _is_option "${opt}" && ! _is_long_option "${opt}"
|
|
then
|
|
[ "${word}" == "${opt}" ]
|
|
else
|
|
[[ "${word}" == "${opt}"=* || "${word}" == "${opt}" ]]
|
|
fi
|
|
}
|
|
|
|
_before() {
|
|
local completion="$1"
|
|
local words
|
|
|
|
shift
|
|
|
|
_get_comp_words_by_ref -n = words
|
|
|
|
for word in "${words[@]}"
|
|
do
|
|
for needle in "$@"
|
|
do
|
|
if _cmp_opts "${needle}" "${word}"
|
|
then
|
|
return 1
|
|
fi
|
|
done
|
|
done
|
|
|
|
${completion}
|
|
return 0
|
|
}
|
|
|
|
_repo_init() {
|
|
OPTIONS=(
|
|
"-h" "--help"
|
|
"-q" "--quite"
|
|
"--mirror"
|
|
"--no-repo-verify"
|
|
)
|
|
|
|
ARG_OPTIONS=(
|
|
["-u"]=_no_completion
|
|
["--manifest-url"]=_no_completion
|
|
["-b"]=_no_completion
|
|
["--manifest-branch"]=_no_completion
|
|
["-m"]=_manifest_completion
|
|
["--manifest-name"]=_manifest_completion
|
|
["--reference"]=_dir_completion
|
|
["--repo-url"]=_no_completion
|
|
["--repo-branch"]=_no_completion
|
|
)
|
|
|
|
_handle_options
|
|
}
|
|
|
|
_repo_help() {
|
|
OPTIONS=(
|
|
"-a" "--all"
|
|
"-h" "--help"
|
|
)
|
|
|
|
ARG_OPTIONS=()
|
|
|
|
_handle_options || _when_first _command_completion
|
|
}
|
|
|
|
_repo_abandon() {
|
|
OPTIONS=(
|
|
"-h" "--help"
|
|
)
|
|
|
|
ARG_OPTIONS=()
|
|
|
|
_handle_options || _when_first _branch_completion || _project_completion
|
|
}
|
|
|
|
_repo_branch() {
|
|
OPTIONS=(
|
|
"-h" "--help"
|
|
)
|
|
|
|
ARG_OPTIONS=()
|
|
|
|
_handle_options
|
|
}
|
|
|
|
_repo_branches() {
|
|
OPTIONS=(
|
|
"-h" "--help"
|
|
)
|
|
|
|
ARG_OPTIONS=()
|
|
|
|
_handle_options
|
|
}
|
|
|
|
_repo_checkout() {
|
|
OPTIONS=(
|
|
"-h" "--help"
|
|
)
|
|
|
|
ARG_OPTIONS=()
|
|
|
|
_handle_options || _when_first _branch_completion || _project_completion
|
|
}
|
|
|
|
_repo_cherry_pick() {
|
|
OPTIONS=(
|
|
"-h" "--help"
|
|
)
|
|
|
|
ARG_OPTIONS=()
|
|
|
|
_handle_options
|
|
}
|
|
|
|
_repo_diff() {
|
|
OPTIONS=(
|
|
"-h" "--help"
|
|
)
|
|
|
|
ARG_OPTIONS=()
|
|
|
|
_handle_options || _project_completion
|
|
}
|
|
|
|
_repo_download() {
|
|
OPTIONS=(
|
|
"-h" "--help"
|
|
)
|
|
|
|
ARG_OPTIONS=()
|
|
|
|
_handle_options || _when_even _project_completion
|
|
}
|
|
|
|
_repo_forall() {
|
|
OPTIONS=(
|
|
"-h" "--help"
|
|
"-p"
|
|
"-v" "--verbose"
|
|
)
|
|
|
|
ARG_OPTIONS=(
|
|
["-c"]=_path_cmd_completion
|
|
["--command"]=_path_cmd_completion
|
|
)
|
|
|
|
_handle_options || _before _project_completion -c --command || _filedir
|
|
}
|
|
|
|
_repo_grep() {
|
|
OPTIONS=(
|
|
"-h" "--help"
|
|
"--cached"
|
|
"-r" "--revision"
|
|
"-i" "--ignore-case"
|
|
"-a" "--text"
|
|
"-I"
|
|
"-w" "--word-regexp"
|
|
"-v" "--invert-match"
|
|
"-G" "--basic-regexp"
|
|
"-E" "--extended-regexp"
|
|
"-F" "--fixed-strings"
|
|
"--all-match"
|
|
"--and" "--or" "--not"
|
|
"-(" "-)"
|
|
"-n"
|
|
"-l" "--name-only" "--files-with-matches"
|
|
"-L" "--files-without-match"
|
|
)
|
|
|
|
ARG_OPTIONS=(
|
|
["-e"]=_no_completion
|
|
["-C"]=_no_completion
|
|
["-B"]=_no_completion
|
|
["-A"]=_no_completion
|
|
)
|
|
|
|
_handle_options || _project_completion
|
|
}
|
|
|
|
_repo_list() {
|
|
OPTIONS=(
|
|
"-h" "--help"
|
|
)
|
|
|
|
ARG_OPTIONS=()
|
|
|
|
_handle_options || _project_completion
|
|
}
|
|
|
|
_repo_prune() {
|
|
OPTIONS=(
|
|
"-h" "--help"
|
|
)
|
|
|
|
ARG_OPTIONS=()
|
|
|
|
_handle_options || _project_completion
|
|
}
|
|
|
|
_repo_rebase() {
|
|
OPTIONS=(
|
|
"-h" "--help"
|
|
"-i" "--interactive"
|
|
"-f" "--force-rebase"
|
|
"--no-ff"
|
|
"-q" "--quiet"
|
|
"--autosquash"
|
|
)
|
|
|
|
ARG_OPTIONS=(
|
|
["--whitespace"]=_no_completion
|
|
)
|
|
|
|
_handle_options || _project_completion
|
|
}
|
|
|
|
_repo_selfupdate() {
|
|
OPTIONS=(
|
|
"-h" "--help"
|
|
"--no-repo-verify"
|
|
)
|
|
|
|
ARG_OPTIONS=()
|
|
|
|
_handle_options
|
|
}
|
|
|
|
_repo_smartsync() {
|
|
OPTIONS=(
|
|
"-h" "--help"
|
|
"-f" "--force-broken"
|
|
"-l" "--local-only"
|
|
"-n" "--network-only"
|
|
"-d" "--detach"
|
|
"-q" "--quiet"
|
|
"--no-repo-verify"
|
|
)
|
|
|
|
ARG_OPTIONS=(
|
|
["-j"]=_no_completion
|
|
["--jobs"]=_no_completion
|
|
|
|
)
|
|
|
|
_handle_options || _project_completion
|
|
}
|
|
|
|
_repo_stage() {
|
|
OPTIONS=(
|
|
"-h" "--help"
|
|
"-i" "--interactive"
|
|
)
|
|
|
|
ARG_OPTIONS=()
|
|
|
|
_handle_options || _project_completion
|
|
}
|
|
|
|
_repo_start() {
|
|
OPTIONS=(
|
|
"-h" "--help"
|
|
"--all"
|
|
)
|
|
|
|
ARG_OPTIONS=()
|
|
|
|
_handle_options || _when_first _branch_completion || _project_completion
|
|
}
|
|
|
|
_repo_status() {
|
|
OPTIONS=(
|
|
"-h" "--help"
|
|
)
|
|
|
|
ARG_OPTIONS=(
|
|
["-j"]=_no_completion
|
|
["--jobs"]=_no_completion
|
|
)
|
|
|
|
_handle_options || _project_completion
|
|
}
|
|
|
|
_repo_sync() {
|
|
OPTIONS=(
|
|
"-h" "--help"
|
|
"-f" "--force-broken"
|
|
"-l" "--local-only"
|
|
"-n" "--network-only"
|
|
"-d" "--detach"
|
|
"-q" "--quiet"
|
|
"-s" "--smart-sync"
|
|
"--no-repo-verify"
|
|
)
|
|
|
|
ARG_OPTIONS=(
|
|
["-j"]=_no_completion
|
|
["--jobs"]=_no_completion
|
|
)
|
|
|
|
_handle_options || _project_completion
|
|
}
|
|
|
|
_repo_upload() {
|
|
OPTIONS=(
|
|
"-h" "--help"
|
|
"-t"
|
|
"--no-verify"
|
|
"--verify"
|
|
)
|
|
|
|
ARG_OPTIONS=(
|
|
["--re"]=_no_completion
|
|
["--reviewers"]=_no_completion
|
|
["--cc"]=_no_completion
|
|
["--br"]=_branch_completion
|
|
)
|
|
|
|
_handle_options || _project_completion
|
|
}
|
|
|
|
_repo_version() {
|
|
OPTIONS=(
|
|
"-h" "--help"
|
|
)
|
|
|
|
ARG_OPTIONS=()
|
|
|
|
_handle_options
|
|
}
|
|
|
|
_repo() {
|
|
COMPREPLY=()
|
|
|
|
_init_cur_prev
|
|
|
|
if [ ${COMP_CWORD} -eq 1 ]
|
|
then
|
|
_command_completion
|
|
else
|
|
local cmd=${COMP_WORDS[1]}
|
|
local handler=${CMD_HANDLERS["${cmd}"]}
|
|
if [ -n ${handler} ]
|
|
then
|
|
eval ${handler}
|
|
fi
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
complete -o nospace -F _repo repo
|