From c4ec7442f1138f2c525f98febb0db6def0fbe142 Mon Sep 17 00:00:00 2001 From: Jun-ichi Takimoto Date: Mon, 10 Jul 2023 22:13:52 +0900 Subject: 51897: update _softwareupdate based on 51895 (Shohei YOSHIDA) --- Completion/Darwin/Command/_softwareupdate | 151 ++++++++++++++++++------------ 1 file changed, 93 insertions(+), 58 deletions(-) (limited to 'Completion') diff --git a/Completion/Darwin/Command/_softwareupdate b/Completion/Darwin/Command/_softwareupdate index 6054fd768..9ac9b9cd2 100644 --- a/Completion/Darwin/Command/_softwareupdate +++ b/Completion/Darwin/Command/_softwareupdate @@ -1,75 +1,110 @@ #compdef softwareupdate -_softwareupdate_ignored_update_name() { - if [[ -z "$_softwareupdate_ignored_updates" ]]; then - local res="$(_call_program pkgs softwareupdate --ignored)" - _softwareupdate_ignored_updates=("${(Qs/, /)${${res#Current ignored updates: \(}%\)}}") - fi - if (( ${#_softwareupdate_ignored_updates} > 0 )); then - _wanted pkgs expl "ignored package" compadd -a _softwareupdate_ignored_updates && return 0 - fi - return 1 +# rebuild cache for available updates everyday (ad hoc) +_softwareupdate_caching_policy() { + local -a newer=( "$1"(Nmd-1) ) + return $#newer } -_softwareupdate_update_name() { - local name line - if [[ -z "$_softwareupdate_updates" ]]; then +# completes available updates (with description) + +_softwareupdate_update_names () { + local name line update_policy ret=1 + local cache_id=softwareupdate-updates + zstyle -s ":completion:${curcontext}:" cache-policy update_policy + if [[ -z "$update_policy" ]]; then + zstyle ":completion:${curcontext}:" cache-policy \ + _softwareupdate_caching_policy + fi + if { [[ ! -v _softwareupdate_updates ]] || _cache_invalid $cache_id } && + ! _retrieve_cache $cache_id; then + # Output format of 'softwareupdate --list' seems to be not stable, + # but at least on macOS 12 and 13 it contains the following two lines + # for each update: + #* Label: update name (may contain spaces) + # Title: description of the update (single TAB before Title:) + # softwareupdate(1) manpage says the '*' before the Label: is replaced + # by '-' for non-recommended updates (but I've never seen it). _softwareupdate_updates=() - for line in ${(f)"$(_call_program pkgs softwareupdate --list)"}; do - if [[ $line == ' '* ]]; then - name="${line# ? }" - elif [[ -n "$name" ]]; then - _softwareupdate_updates+=("$name:${line# }") - name="" + for line in ${(f)"$(_call_program updates softwareupdate --list)"}; do + if [[ $line = [-\*]\ Label:\ (#b)(*) ]]; then + # add '*' or '-' in front of the name; this will be removed later + name=$line[1]$match[1] + elif [[ -n $name && $line = $'\t'Title:\ (#b)(*) ]]; then + _softwareupdate_updates+=( $name:$match[1] ) + name= fi done + _store_cache $cache_id _softwareupdate_updates fi - if (( ${#_softwareupdate_updates} > 0 )); then - _describe -t pkgs "update name" _softwareupdate_updates && return 0 - fi - return 1 + # recommended and non-recommended updates + local rec=( ${${_softwareupdate_updates:#-*}#\*} ) + local non=( ${${(M)_softwareupdate_updates:#-*}#-} ) + _describe -t updates "update" rec && ret=0 + _describe -t non-recommended-updates "non-recommended update" non && ret=0 + return ret +} + +# completes versions of available macOS full installer (with description) + +_softwareupdate_installer_versions () { + local versions=() + for line in ${(f)"$(_call_program installer-versions + softwareupdate --list-full-installers 2>/dev/null)"}; do + if [[ $line = \*\ Title:\ *\ Version:\ (#b)([0-9.]##)* ]]; then + versions+=( ${match[1]}:${line#*Title: } ) + fi + done + _describe -t insteller-versions "version" versions } +# main completion script + _softwareupdate() { - local context state line expl - typeset -A opt_args + local -a specs - _arguments -R \ - '(-h --help -l --list)-q[quiet mode]' \ - {-l,--list}'[list all available updates]:*:' \ - {-d,--download}'[download to directory set in InternetConfig]:*:' \ - {-i,--install}'[install (requires root)]:*: :->install' \ - '--ignored[show or manage ignored updates list (per-user)]:*:: :->ignored' \ - '--schedule[scheduler preferences (per-user)]:automatic checking:(on off)' \ - {-h,--help}'[print command usage]:*:' && return 0 + if (( ${words[(I)(-i|--install)]} == 0 )); then + specs=( + '--no-scan[do not scan when listing or installing updates]' + '--product-types[limit a scan to a particular product type only]:list of product types' + '--products[a comma separated list of product keys to operate on]:list of product keys' + '--force[force an operation to complete]' + '--agree-to-license[agree to the software license agreement without user interaction]' + '--verbose[enable verbose output]' + '(* -)'{-h,--help}'[print command usage]:*:' - case "$state" in - install) - _arguments \ - '(* -a --all)'{-a,--all}'[all available active updates]' \ - '(* -r --req)'{-r,--req}'[all required active updates]' \ - '*:update name:_softwareupdate_update_name' && return 0 - ;; - ignored) - local -a ignored_subcmd - ignored_subcmd=(add remove) + + '(operation)' - if (( CURRENT == 1 )); then - _describe -t commands "subcommand" ignored_subcmd && return 0 - fi - case $words[1] in - add) - _softwareupdate_update_name && return 0 - ;; - remove) - _arguments \ - '(* -a --all)'{-a,--all}'[all available active updates]' \ - '*:update name:_softwareupdate_ignored_update_name' && return 0 - ;; - esac - ;; - esac - return 1 + {-l,--list}'[list all available updates]' + {-d,--download}'[download but not install specified updates]:*: : _softwareupdate_update_names' + {-i,--install}'[download and install specified updates]' + '(* -)--list-full-installers[list the available macOS installers]' + '(* -)--fetch-full-installer[install the latest recommended macOS installer]: :(--full-installer-version): : _softwareupdate_installer_versions' + '--install-rosetta[install Rosetta 2 (Apple Silicon only)]' + '(* -)--schedule[returns the per-machine automatic check preference]' + '--background[trigger a background scan and update operation]' + '(* -)--dump-state[log the internal state of the SU daemon to /var/log/install.log]' + '--evaluate-products[evaluate a list of product keys specified by the --products option]' + '--history[show the install history]' + ) + else # if -i/--install is already on the command line + specs=( + !{-i,--install} + '(-R --restart)'{-R,--restart}'[automatically restart if required to complete installation]' + '--stdinpass[password to authenticate as an owner (Apple Silicon only)]' + '--user[local username to authenticate as an owner (Apple Silicon only)]' + '*: : _softwareupdate_update_names' + + + '(select-updates)' + + '(*)'{-a,--all}'[all updates that are applicable to your system]' + '(*)'{-r,--recommended}'[all updates recommended for your system]' + '(*)--os-only[only macOS updates]' + '(*)--safari-only[only Safari updates]' + ) + fi + + _arguments -s : $specs } _softwareupdate "$@" -- cgit 1.4.1