Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add zsh completion #947

Merged
merged 3 commits into from Jun 25, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
281 changes: 281 additions & 0 deletions swupd.zsh
@@ -0,0 +1,281 @@
#compdef swupd
# -----------------------------------------------------------------------
# Software Updater - autocompletion script
#
# Author: Lucius Hu - http://github.com/lebensterben
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 2 or later of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# -----------------------------------------------------------------------

local context curcontext="$curcontext" state state_descr line subcmd ops ret=1
local -A opt_args
local -A val_args
local installed # cache for installed bundles

(( $+functions[_swupd_bundle_add] )) ||
_swupd_bundle_add () {
local bundles
local MoM
if [ -r /var/tmp/swupd/Manifest.MoM ]; then
MoM=/var/tmp/swupd/Manifest.MoM
elif [ -r /var/lib/swupd/version ] && [ -r /var/lib/swupd/"$(cat /var/lib/swupd/version)"/Manifest.MoM ]; then
MoM=/var/lib/swupd/"$(cat /var/lib/swupd/version)"/Manifest.MoM
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is only accessible as root. I didn't test this, isn't this going to print errors when running as a regular user?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The [ -r foo ] test reruns true if the file is readable by current user, from which a list of bundles are added as candidates for completion.

The bottom line is, even if none of those are readble, it shall not report error while users will just not seeing any completion candidates here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right about that. But there's another problem.

It looks like [ -n $"MoM" ] is true when running as a regular user in the case /var/tmp/swupd doesn't exist. And I'm seeing the error: "sed: can't read : No such file or directory"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fixed the typo. It should be [ -n "$MoM" ]

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. Works for me now

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there is any change to swupd command, please let me know and I will update this zsh completion.

fi
if [ -n "$MoM" ]; then
bundles="$(sed '1,/^$/d; s/^.*\t/ /; /.*\.I\..*/d' "$MoM" | LC_ALL=C sort )"
bundles='('"$(sed 's/\n/ /g' <<< $bundles)"')'
fi
_alternative "$bundles" && ret=0
}

# FIXME: the number of available completion is not correct
(( $+functions[_swupd_bundle_rm] )) ||
_swupd_bundle_rm () {
local bundles i
if [ -z $installed ]; then
installed="$(unset CDPATH; test -d /usr/share/clear/bundles && \
find /usr/share/clear/bundles/ -maxdepth 1 -type f ! -name os-core -printf '%f ')"
fi
bundles=$installed
for i in $words; do
bundles=${bundles/$i}
done
_alternative \
"bundle:installed bundles: _values -s ' ' $bundles" && ret=0
}

(( $+functions[_swupd_hashdump] )) ||
_swupd_hashdump () {
local dumppath dumpfile
if [[ "$words" =~ '.* (-p +|--path +|--path=).*' ]]; then
dumppath="$(echo $words | sed -E 's/.* +(-p|--path)//' | sed -E 's/(\=| +)//' | sed -E 's/ +-.*//')"
fi
if [ -n "$dumppath" ]; then
dumpfile='('"$(ls -AFL "$dumppath" | grep -v '/$')"')'
_alternative "$dumpfile" && ret=0
else
_path_files && ret=0
fi
}

# TODO: combine this with _swupd_bundle_rm
(( $+functions[_swupd_diagnose] )) ||
_swupd_diagnose () {
local bundles i
if [ -z $installed ]; then
installed="$(unset CDPATH; test -d /usr/share/clear/bundles && \
find /usr/share/clear/bundles/ -maxdepth 1 -type f ! -name os-core -printf '%f ')"
fi
bundles=$installed
for i in $words; do
bundles=${bundles/$i}
done
_alternative \
"bundle:installed bundles: _values -s , $bundles" && ret=0
}

local -a global_opts; global_opts=(
+ '(help)'
'(-)'{-h,--help}'[Show help options]'
+ '(msg)'
'(help)--quiet[Quiet output. Print only important information and errors]'
'(help)--debug[Print extra information to help debugging problems]'
'(help -j --json-output)'{-j,--json-output}'[Print all output as a JSON stream]'
+ options
'(help status -p --path)'{-p,--path=}'[Use \[PATH...\] as the path to verify (eg\: a chroot or btrfs subvol)]:path:_path_files -/'
'(help status -u --url)'{-u,--url=}'[RFC-3986 encoded url for version string and content file downloads]:url:_urls'
'(help status -P --port)'{-P,--port=}'[Port number to connect to at the url for version string and content file downloads]:port:_ports'
'(help status -c --contenturl)'{-c,--contenturl=}'[RFC-3986 encoded url for content file downloads]:url:_urls'
'(help status -v --versionurl)'{-v,--versionurl=}'[RFC-3986 encoded url for version file downloads]:url:_urls'
'(help status -F --format)'{-F,--format=}'[\[staging,1,2,etc.\]\:the format suffix for version file downloads]:format:()'
'(help status -n --nosigcheck)'{-n,--nosigcheck}'[Do not attempt to enforce certificate or signature checking]'
'(help status -I --ignore-time)'{-I,--ignore-time}'[Ignore system/certificate time when validating signature]'
'(help status -S --statedir)'{-S,--statedir=}'[Specify alternate swupd state directory]:statedir:_path_files -/'
'(help status -C --certpath)'{-C,--certpath=}'[Specify alternate path to swupd certificates]:certpath:_path_files -/'
'(help status -t --time)'{-t,--time}'[Show verbose time output for swupd operations]'
'(help status -N --no-scripts)'{-N,--no-scripts}'[Do not run the post-update scripts and boot update tool]'
'(help status -b --no-boot-update)'{-b,--no-boot-update}'[Do not install boot files to the boot partition (containers)]'
'(help status -W --max-parallel-downloads)'{-W,--max-parallel-downloads=}'[Set the maximum number of parallel downloads]:downloadThreads:()'
'(help status -r --max-retries)'{-r,--max-retries=}'[Maximum number of retries for download failures]:maxRetries:()'
'(help status -d --retry-delay)'{-d,--retry-delay}'[Initial delay between download retries, this will be doubled for each retry]:retryDelay:()'
)

_arguments -C \
'(-)'{-h,--help}'[Show help options]' \
'(-)'{-v,--version}'[Output version information and exit]:version:->ops' \
':swupd subcommand:->subcmd' \
'*:: :->args' \
&& ret=0

if [[ -n "$state" ]]; then
case "$state" in
subcmd)
local -a subcmds; subcmds=(
"info:Show the version and the update URLs"
"autoupdate:Enable/disable automatic system updates"
"check-update:Check if a new OS version is available"
"update:Update to latest OS version"
"bundle-add:Install a new bundle"
"bundle-remove:Uninstall a bundle"
"bundle-list:List installed bundles"
"search:Searches for the best bundle to install a binary or library"
"search-file:Command to search files in Clear Linux bundles"
"diagnose:Verify content for OS version"
"repair:Repair local issues relative to server manifest (will not modify ignored files)"
"os-install:Install Clear Linux OS to a blank partition or directory"
"mirror:Configure mirror url for swupd content"
"clean:Clean cached files"
"hashdump:Dump the HMAC hash of a file"
)
_describe -t subcmds 'swupd subcommand' subcmds && ret=0
;;
args)
case $line[1] in
info)
_arguments $global_opts && ret=0
;;
autoupdate)
local -a autoupdates; autoupdates=(
'(-)--enable[enable autoupdates]'
'(-)--disable[disable autoupdates]'
'(-)'{-h,--help}'[Show help options]'
)
_arguments $autoupdates && ret=0
;;
check-update)
_arguments $global_opts && ret=0
;;
update)
local -a updates; updates=(
$global_opts
'(help status -d --download )'{-d,--download}'[Download all content, but do not actually install the update]'
'(help status -k --keepcache)'{-k,--keepcache}'[Do not delete the swupd state directory content after updating the system]'
'(help status -T --migrate)'{-T,--migrate}'[Migrate to augmented upstream/mix content]'
'(help status -a --allow-mix-collisions)'{-a,--allow-mix-collisions}'[Ignore and continue if custom user content conflicts with upstream provided content]'
+ '(version)'
'(help status)'{-V,--version=}'[Update to version V, also accepts "latest" (default)]:version:()'
+ '(status)'
'(help options)'{-s,--status}'[Show current OS version and latest version available on server. Equivalent to "swupd check-update"]'
)
_arguments $updates && ret=0
;;
bundle-add)
local -a addbundle; addbundle=(
$global_opts
'(help)--skip-diskspace-check[Do not check free disk space before adding bundle]'
'*:bundle-add:_swupd_bundle_add'
)
_arguments $addbundle && ret=0
;;
bundle-remove)
local -a rmbundle; rmbundle=(
$global_opts
'*:bundle-remove:_swupd_bundle_rm'
)
_arguments $rmbundle && ret=0
;;
bundle-list)
local -a lsbundle; lsbundle=(
$global_opts
+ '(list)'
'(help)'{-a,--all}'[List all available bundles for the current version of Clear Linux]'
'(help)'{-d,--deps=}'[List bundles included by BUNDLE]:deps:()'
'(help)'{-D,--has-dep=}'[List dependency tree of all bundles which have BUNDLE as a dependency]:has-dep:()'
)
_arguments $lsbundle && ret=0
;;
search)
local -a searches; searches=(
'(help -v -vv --verbose -q --quiet)'{-v,-vv,--verbose}'[verbose mode]'
'(help -a -all -q --quiet)'{-a,-all}'[show all]'
'(-)'{-q,--quiet}'[quiet mode]'
+ '(help)'
'(*)'{-h,--help}'[help for swupd-search]'
':target:()'
)
_arguments $searches && ret=0
;;
search-file)
local -a searchfiles; searchfiles=(
$global_opts
'(help -l --library)'{-l,--library=}'[Search paths where libraries are located for a match]:library:_path_files -/'
'(help -b --binary)'{-b,--binary=}'[Search paths where binaries are located for a match]:binary:_path_files -/'
'(help -T --top)'{-T,--top=}'[Only display the top NUM results for each bundle]:top:()'
'(help -m --csv)'{-m,--csv}'[Output all results in CSV format (machine-readable)]'
'(help -o --order)'{-o,--order=}'[Sort the output]:order:((alpha\:"Order alphabetically\(default\)"
size\:"Order by bundle size \(smaller to larger\)"))'
+ '(no-search)'
'(-)'{-i,--init}'[Download all manifests then return, no search done]'
':target:()'
)
_arguments $searchfiles && ret=0
;;
diagnose|repair)
local -a diagnoses; diagnoses=(
$global_opts
'(help -B --bundles)'{-B,--bundles=}'[Ensure BUNDLES are installed correctly. Example: --bundles=os-core,vi]:diagnose:_swupd_diagnose'
'(help -x --force)'{-x,--force}'[Attempt to proceed even if non-critical errors found]'
'(help -q --quick)'{-q,--quick}'[Don`t compare hashes, only fix missing files]'
'(help -V --version)'{-V,--version=}'[Verify against manifest version V]:version:()'
'(help -Y --picky)'{-Y,--picky}'[List files which should not exist]'
'(help -w --picky-whitelist)'{-w,--picky-whitelist=}'[Any path completely matching the POSIX extended regular expression is ignored by --picky. Matched directories get skipped. Example\: /var|/etc/machine-id. Default\: /usr/lib/modules|/usr/lib/kernel|/usr/local|/usr/src]:picky-whitelist:_path_files -/'
'(help -X --picky-tree)'{-X,--picky-tree=}'[Selects the sub-tree where --picky looks for extra files. Default\: /usr]:picky-tree:_path_files -/'
)
_arguments $diagnoses && ret=0
;;
os-install)
local -a osinstall; osinstall=(
$global_opts
'(help -B --bundles)'{-B,--bundles=}'[Ensure BUNDLES are installed correctly. Example: --bundles=os-core,vi]:diagnose:_swupd_diagnose'
'(help -x --force)'{-x,--force}'[Attempt to proceed even if non-critical errors found]'
'(help -V --version)'{-V,--version=}'[Verify against manifest version V]:version:()'
)
_arguments $osinstall && ret=0
;;
mirror)
local -a mirrors; mirrors=(
$global_opts
+ '(mirror)'
'(help)'{-s,--set}'[set mirror url]:mirro:_urls'
'(help)'{-u,--unset}'[unset mirror url]'
)
_arguments $mirrors && ret=0
;;
clean)
local -a cleans; cleans=(
$global_opts
'--all[remove all the content including recent metadata]'
'--dry-run[just print files that would be removed]'
)
_arguments $cleans && ret=0
;;
hashdump)
local -a hashdumps; hashdumps=(
'(-)'{-h,--help}'[Show help options]'
'(-h --help -n --no-xattrs)'{-n,--no-xattrs}'[Ignore extended attributes]'
'(-h --help -p --path)'{-p,--path=}'[Use \[PATH...\] for leading path to filename]:dumppath:_path_files -/'
'(-h --help)--quiet[Quiet output. Print only important information and errors]'
'(-h --help)--debug[Print extra information to help debugging problems]'
':hashdump:_swupd_hashdump'
)
_arguments $hashdumps && ret=0
;;
esac
;;
*)
ret=1
;;
esac
fi

return ret