Skip to content

Commit 8deef6a

Browse files
committed
WIP: setup-util: brew, flatpak
- brew-installed: rewrote for legibility, performance, and new capabilities - setup-util: cleanup deprecations, cleanup statuses, do brew and cask (by merging them), fix some return statuses, do flatpak, do go, drop rpm todos: - still have to handle `--all`/`--any`/`--none` in `brew-installed
1 parent 9c3825f commit 8deef6a

5 files changed

Lines changed: 976 additions & 520 deletions

File tree

TODOS.md

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,24 @@
99
# action
1010
case "$option_action" in
1111
# is-* ...<package>
12-
'is-installed-all') || return 1 ;;
13-
'is-installed-any') __is_installed_all_to_any "${packages[@]}" || return $? ;;
14-
'is-installed-none') __is_installed_all_to_none "${packages[@]}" || return $? ;;
12+
'is-installed-all')
13+
: || return $?
14+
;;
15+
'is-installed-any')
16+
__is_installed_all_to_any "${packages[@]}" || return $?
17+
;;
18+
'is-installed-none')
19+
__is_installed_all_to_none "${packages[@]}" || return $?
20+
;;
1521
# list-*
1622
'list-installed')
17-
;;
23+
;;
1824
'list-outdated')
19-
;;
25+
;;
2026
'list-updated')
21-
;;
27+
;;
2228
'list-available')
23-
;;
29+
;;
2430
# search-* ...<package> --search=...<search>
2531
'search-'*)
2632
local search_options=(--format=yaml --fields=name,version "${packages[@]}") search
@@ -29,13 +35,13 @@
2935
done
3036
;;&
3137
'search-installed' )
32-
;;
38+
;;
3339
'search-outdated')
34-
;;
40+
;;
3541
'search-updated')
36-
;;
42+
;;
3743
'search-available')
38-
;;
44+
;;
3945
# setup-* ...<package>
4046
'setup-'*)
4147
local repository_options=()
@@ -44,15 +50,15 @@
4450
fi
4551
;;&
4652
'setup-uninstall')
47-
;;
53+
;;
4854
'setup-install')
49-
;;
55+
;;
5056
'setup-upstall')
51-
;;
57+
;;
5258
'setup-upgrade')
53-
;;
59+
;;
5460
'setup-upgrade-all')
55-
;;
61+
;;
5662
*) return "$STATUS__INVALID_ACTION" ;;
5763
esac
5864
```

commands/brew-installed

Lines changed: 141 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
#!/usr/bin/env bash
22

3+
# @todo rename to `brew-query` and add support for `--installed` vs `--available`, as well as --search=...<fuzzy-match>
4+
# @todo add tests
5+
36
function brew_installed_test() (
47
source "$DOROTHY/sources/bash.bash"
58
eval-tester --ignore-stderr --status=22 -- brew-installed --help
@@ -23,19 +26,50 @@ function brew_installed() (
2326
-- ...<item>
2427
If provided, only get details for these <item>s. Fail if one of them has not yet been installed.
2528
26-
--[no-]formula
27-
Output consider formulas. Formulas can be installed by request, or by dependency; use <requested> to filter.
28-
--[no-]cask
29-
Output consider casks. All casks are only installed by request.
30-
--[no-]tap
31-
Output consider taps. All taps are only installed by request.
32-
29+
--type=
30+
Output only formulas and casks.
31+
! The default behaviour.
32+
--formula | --type=formula
33+
Output only formulas. Formulas can be installed by request, or by dependency; use <requested> to filter.
34+
--cask | --type=cask
35+
Output only casks. All casks are only installed by request.
36+
--tap | --type=tap
37+
Output only taps. All taps are only installed by request.
38+
39+
--expects[=<integer>] | --[no-]expects
40+
If provided, expect this amount of results otherwise [91] will be returned.
41+
! Defaults to the amount of <item>s specified.
3342
--[no-]quiet | --[no-]verbose
34-
If <quiet>, do not output anything, just return the exit status.
35-
36-
--[no-]requested
37-
Only consider formulas that were manually installed, not formulas that were only dependencies.
38-
Only compatible with --formula.
43+
If <quiet>, do not output anything.
44+
45+
The following are only compatible with <cask> and <formula>:
46+
47+
--type=
48+
Output packages, regardless of outdated/updated status.
49+
! The default behaviour.
50+
--[no-]outdated | --status=outdated
51+
Only output outdated packages.
52+
! If enabled, will default <versions> to \`latest\`.
53+
--[no-]updated | --status=updated
54+
Only output updated packages.
55+
! If enabled, will default <versions> to \`latest\`.
56+
57+
--[no-]versions | --versions=latest | --versions=current
58+
Output versions alongside the package name.
59+
If \`latest\`, format will be:
60+
\`\`\`
61+
<name> <version> <latest-version>
62+
\`\`\`
63+
If \`current\`, format will be:
64+
\`\`\`
65+
<name> <version>
66+
\`\`\`
67+
! Note that <version> may not equal <latest-version> and it can still be considered updated, this is because the cask will auto-updates enabled. See <https://github.com/Homebrew/brew/issues/22853>.
68+
69+
The following are only compatible with <formula>:
70+
71+
--[no-]requested | --[no-]explicit
72+
Output only packages that were manually/explicitly installed, not packages that were only dependencies.
3973
4074
QUIRKS:
4175
If <item>s are provided, failure exit status will be returned if any are missing.
@@ -45,17 +79,31 @@ function brew_installed() (
4579
}
4680

4781
# process
48-
local item option_quiet='' option_requested='no' option_items=() option_type='' # empty, formula, cask, tap
82+
local item option_quiet='' option_expects='' option_type='' option_status='no' option_versions='' option_requested='no' option_items=()
4983
while [[ $# -ne 0 ]]; do
5084
item="$1"
5185
shift
5286
case "$item" in
5387
'--help' | '-h') help ;;
88+
# quiet
5489
'--no-verbose'* | '--verbose'*) __flag --source={item} --target={option_quiet} --non-affirmative --coerce ;;
5590
'--no-quiet'* | '--quiet'*) __flag --source={item} --target={option_quiet} --affirmative --coerce ;;
56-
'--type=formula' | '--type=formulas' | '--formula' | '--formulae') option_type=formula ;;
57-
'--type=cask' | '--type=casks' | '--cask' | '--casks') option_type=cask ;;
58-
'--type=tap' | '--type=taps' | '--tap' | '--taps') option_type=tap ;;
91+
# type filter
92+
'--type=cask' | '--type=formula' | '--type=tap' | '--type=') option_type="${item#*=}" ;;
93+
'--no-cask'* | '--cask'*) __flag --source={item} --target={option_type} --yes='cask' --no='' --affirmative --coerce ;;
94+
'--no-formula'* | '--formula'*) __flag --source={item} --target={option_type} --yes='formula' --no='' --affirmative --coerce ;;
95+
'--no-tap'* | '--tap'*) __flag --source={item} --target={option_type} --yes='tap' --no='' --affirmative --coerce ;;
96+
# status filter
97+
'--status=updated' | '--status=outdated' | '--status=') option_status="${item#*=}" ;;
98+
'--no-updated'* | '--updated'*) __flag --source={item} --target={option_status} --yes='updated' --affirmative --coerce ;;
99+
'--no-outdated'* | '--outdated'*) __flag --source={item} --target={option_status} --yes='outdated' --affirmative --coerce ;;
100+
# expects
101+
'--no-expects'* | '--expects'*) __flag --source={item} --target={option_expects} --affirmative --no-coerce ;;
102+
# versions
103+
'--versions=latest') option_versions='latest' ;;
104+
'--versions=current') option_versions='current' ;;
105+
'--no-versions'* | '--versions'*) __flag --source={item} --target={option_versions} --affirmative --coerce ;;
106+
# requested
59107
'--no-requested'* | '--requested'*) __flag --source={item} --target={option_requested} --affirmative --coerce ;;
60108
'--')
61109
option_items+=("$@")
@@ -72,64 +120,95 @@ function brew_installed() (
72120
return 46 # EPFNOSUPPORT 46 Protocol family not supported
73121
fi
74122

75-
# =====================================
76-
# Action
77-
78-
local deno_script_args=()
79-
if [[ $option_requested == 'yes' ]]; then
80-
if [[ $option_type != 'formula' ]]; then
81-
help --help='<requested> requires <formula>'
123+
# adjust
124+
if [[ -z $option_versions ]]; then
125+
if [[ $option_status != 'no' ]]; then
126+
option_versions='latest'
127+
else
128+
option_versions='no'
129+
fi
130+
elif [[ $option_versions == 'yes' ]]; then
131+
if [[ $option_status != 'no' ]]; then
132+
option_versions='latest'
133+
else
134+
option_versions='current'
82135
fi
83-
deno_script_args+=('--requested')
84136
fi
85137

86-
local brew_list_cmd=() brew_info_cmd=()
87-
if [[ $option_type == 'tap' ]]; then
88-
brew_info_cmd=(brew tap-info --json)
89-
deno_script_args+=(--type=tap)
90-
else
91-
brew_list_cmd=(brew list --versions)
92-
# --versions is necessary to limit to installed option_packages, as --full-name/-1 doesn't
93-
brew_info_cmd=(brew info --json=v2)
94-
if [[ -n $option_type ]]; then
95-
brew_list_cmd+=("--$option_type")
96-
brew_info_cmd+=("--$option_type")
97-
deno_script_args+=("--type=$option_type")
98-
fi
99-
# if no items, only get the installed ones
100-
if [[ ${#option_items[@]} -eq 0 ]]; then
101-
brew_info_cmd+=('--installed')
138+
# verify
139+
if [[ $option_requested == 'yes' && $option_type != 'formula' ]]; then
140+
help --help='<requested> requires <formula>'
141+
fi
142+
143+
# expects
144+
if [[ -z $option_expects ]]; then
145+
if [[ ${#option_items[@]} -ne 0 ]]; then
146+
option_expects=${#option_items[@]}
102147
fi
148+
elif [[ $option_expects == 'yes' ]]; then
149+
option_expects=${#option_items[@]}
150+
elif [[ $option_expects == 'no' ]]; then
151+
option_expects=''
152+
else
153+
__affirm_value_is_positive_integer "$option_expects" '<expects>' || return $?
103154
fi
104155

105-
function do_brew_simple {
106-
# handles only --cask and --formula, but not --requested
107-
if [[ $option_quiet == 'yes' ]]; then
108-
"${brew_list_cmd[@]}" "${option_items[@]}" &>/dev/null
109-
else
110-
"${brew_list_cmd[@]}" "${option_items[@]}" | cut -d' ' -f1 | echo-unique --stdin
156+
# =====================================
157+
# Action
158+
159+
# to debug, trim `2>/dev/null`
160+
161+
function __parse_and_validate_with_deno {
162+
local deno_script
163+
deno_script="$(type -P 'brew-installed.ts')" || return $?
164+
"$deno_script" --quiet="$option_quiet" --type="$option_type" --status="$option_status" --expects="$option_expects" --versions="$option_versions" --requested="$option_requested" 2>/dev/null || return $?
165+
}
166+
function __validate_ourselves {
167+
local REPLY=''
168+
__read_whole || return $?
169+
if [[ $option_quiet != 'yes' ]]; then
170+
printf '%s' "$REPLY" || return $?
171+
fi
172+
if [[ -n $option_expects ]]; then
173+
local results=()
174+
__split --source={REPLY} --target={results} --no-zero-length || return $?
175+
local -i received=${#results[@]}
176+
if [[ $option_expects -ne $received ]]; then
177+
return 91 # ENOMSG 91 No message of desired type
178+
fi
111179
fi
112180
}
113181

114-
function do_brew_advanced {
115-
# handles --requested, --cask, and --formula
182+
if [[ $option_type == 'tap' ]]; then
116183
__command_required -- 'deno' || return $?
117-
local deno_script
118-
deno_script="$(type -P 'brew-installed.ts')"
119-
if [[ $option_quiet == 'yes' ]]; then
120-
"${brew_info_cmd[@]}" "${option_items[@]}" | "$deno_script" "${deno_script_args[@]}" &>/dev/null
184+
brew tap-info --json 2>/dev/null | __parse_and_validate_with_deno || return $?
185+
else
186+
local brew_options=()
187+
# add type option
188+
case "$option_type" in
189+
'cask' | 'formula') brew_options+=("--$option_type") ;;
190+
esac
191+
# add requested option
192+
if [[ $option_status == 'no' && $option_versions != 'latest' && ! ($option_versions == 'current' && $option_requested == 'yes') ]]; then
193+
if [[ $option_versions == 'current' ]]; then
194+
brew_options+=(--versions)
195+
else
196+
if [[ $option_requested == 'yes' ]]; then
197+
# incompatible with --versions
198+
brew_options+=(--installed-on-request)
199+
fi
200+
brew_options+=(--full-name -1)
201+
fi
202+
# `brew list --cask "${option_items[@]}"` is a different format, but with `--full-names` and/or `-1` it is fine
203+
brew list "${brew_options[@]}" "${option_items[@]}" 2>/dev/null | __validate_ourselves || return $?
121204
else
122-
"${brew_info_cmd[@]}" "${option_items[@]}" | "$deno_script" "${deno_script_args[@]}"
205+
__command_required -- 'deno' || return $?
206+
# if no items, restrict to installed (rather than available casks); with items, --installed can't be used as otherwise it discards the items
207+
if [[ ${#option_items[@]} -eq 0 ]]; then
208+
brew_options+=(--installed)
209+
fi
210+
brew info --json=v2 "${brew_options[@]}" "${option_items[@]}" 2>/dev/null | __parse_and_validate_with_deno || return $?
123211
fi
124-
}
125-
126-
# get names of requested packages
127-
if [[ $option_requested == 'no' && ${#brew_list_cmd[@]} -ne 0 ]]; then
128-
do_brew_simple
129-
elif [[ ${#option_items[@]} -eq 0 ]]; then
130-
do_brew_advanced
131-
elif [[ "$(do_brew_advanced | echo-count-lines --no-inline --stdin)" -ne ${#option_items[@]} ]]; then
132-
return 1
133212
fi
134213
)
135214

0 commit comments

Comments
 (0)