Skip to content

Commit 1ff4756

Browse files
authored
Merge pull request #22300 from Homebrew/which-formula-install-status
Show install status in which-formula
2 parents fb60c87 + 28c3a66 commit 1ff4756

21 files changed

Lines changed: 531 additions & 252 deletions

AGENTS.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ When running Ruby directly (e.g. `ruby -e ...`, `gem`, profiling tools), never u
2727
### Development Flow
2828

2929
- Write new code (using Sorbet `sig` type signatures and `typed: strict` for new files).
30-
- Write new tests (avoid more than one `:integration_test` per file for speed). Try `typed: true` as a baseline but revert to `typed: false` if there are not easily fixable errors.
30+
- Write new tests (avoid more than one `:integration_test` per command for speed; add another only for essential core functionality in essential non-developer commands). Try `typed: true` as a baseline but revert to `typed: false` if there are not easily fixable errors.
3131
Write fast tests by preferring a single `expect` per unit test and combine expectations in a single test when it is an integration test or has non-trivial `before` for test setup.
3232
- When adding or tightening tests, verify them with a red/green cycle using the exact `--only=file:line` target for the example you changed.
3333
- Formula classes created in specs may be frozen; avoid stubbing class methods on them with RSpec mocks and prefer instance-level stubs or test setup that does not require class-method stubbing.
@@ -59,3 +59,4 @@ When running Ruby directly (e.g. `ruby -e ...`, `gem`, profiling tools), never u
5959
9. Inline new or existing methods as methods or local variables unless they are reused 2+ times or needed for unit tests.
6060
10. Avoid `T.must`; prefer explicit nil checks or APIs that return non-nil values.
6161
11. Keep `extend/os/*` prepends as thin as possible; put the `prepend` in the OS-specific `linux` or `macos` file rather than the shared `extend/os/*` loader with an inline `if`, and prefer putting substantive logic in shared code outside `extend/` when practical so it can be tested on all platforms instead of relying on `:needs_linux` or `:needs_macos` specs.
62+
12. When Bash logic mirrors Ruby logic, keep both implementations in sync and add two-way comments naming the matching Ruby and Bash locations; keep matching helper filenames aligned where practical.

Library/Homebrew/brew.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ esac
229229
##### Next, define all other helper functions.
230230
#####
231231

232-
source "${HOMEBREW_LIBRARY}/Homebrew/utils/helpers.sh"
232+
source "${HOMEBREW_LIBRARY}/Homebrew/utils.sh"
233233

234234
check-run-command-as-root() {
235235
[[ "${EUID}" == 0 || "${UID}" == 0 ]] || return

Library/Homebrew/cmd/exec.sh

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Documentation defined in Library/Homebrew/cmd/exec.rb
22

33
# shellcheck disable=SC2154
4-
source "${HOMEBREW_LIBRARY}/Homebrew/cmd/which-formula.sh"
4+
source "${HOMEBREW_LIBRARY}/Homebrew/utils/executables.sh"
55

66
exec-formula-name() {
77
local formula="$1"
@@ -151,35 +151,20 @@ homebrew-exec() {
151151
download_and_cache_executables_file >&2
152152

153153
local -a matching_formulae=()
154-
local cmds_text line selected_formula formula
154+
local selected_formula formula
155155
selected_formula=""
156156
# Some executables are provided by multiple formulae. Prefer an already
157157
# installed provider to avoid unnecessary installs; otherwise use the first
158158
# provider listed by the database.
159-
while read -r line
159+
while read -r formula
160160
do
161-
[[ "${line}" == *:* ]] || continue
162-
163-
# `executables.txt` lines are `formula(version):exe exe...`. Use Bash's
164-
# prefix/suffix removal instead of splitting with `IFS`, so executable
165-
# lists are kept as one string for whole-word matching below.
166-
formula="${line%%:*}"
167-
cmds_text="${line#*:}"
168-
[[ -z "${formula}" ]] && continue
169-
[[ -z "${cmds_text}" ]] && continue
170-
171-
# Padding both sides with spaces avoids matching `foo` inside `foobar`.
172-
if [[ " ${cmds_text} " == *" ${executable} "* ]]
173-
then
174-
formula="${formula%\(*}"
175-
matching_formulae+=("${formula}")
161+
matching_formulae+=("${formula}")
176162

177-
if [[ -z "${selected_formula}" ]] && exec-formula-installed "${formula}"
178-
then
179-
selected_formula="${formula}"
180-
fi
163+
if [[ -z "${selected_formula}" ]] && exec-formula-installed "${formula}"
164+
then
165+
selected_formula="${formula}"
181166
fi
182-
done <"${DATABASE_FILE}" 2>/dev/null
167+
done < <(formulae_containing_executable "${executable}")
183168

184169
[[ "${#matching_formulae[@]}" -gt 0 ]] || odie "No Homebrew formula found for \`${executable}\`."
185170

Library/Homebrew/cmd/setup-ruby.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# HOMEBREW_BREW_FILE is set by extend/ENV/super.rb
55
# shellcheck disable=SC2154
66
homebrew-setup-ruby() {
7-
source "${HOMEBREW_LIBRARY}/Homebrew/utils/helpers.sh"
7+
source "${HOMEBREW_LIBRARY}/Homebrew/utils.sh"
88
source "${HOMEBREW_LIBRARY}/Homebrew/utils/ruby.sh"
99
setup-ruby-path
1010

Library/Homebrew/cmd/update.sh

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
# HOMEBREW_FORCE_BREWED_CURL, HOMEBREW_FORCE_BREWED_GIT,
1212
# HOMEBREW_SYSTEM_CURL_TOO_OLD, HOMEBREW_USER_AGENT_CURL are set by brew.sh
1313
# shellcheck disable=SC2154
14+
source "${HOMEBREW_LIBRARY}/Homebrew/utils/executables.sh"
1415
source "${HOMEBREW_LIBRARY}/Homebrew/utils/lock.sh"
1516

1617
macos_version_name() {
@@ -419,20 +420,16 @@ fetch_api_file() {
419420
echo "Checking if we need to fetch ${filename}..."
420421
fi
421422

422-
JSON_URLS=()
423-
if [[ -n "${HOMEBREW_API_DOMAIN}" && "${HOMEBREW_API_DOMAIN}" != "${HOMEBREW_API_DEFAULT_DOMAIN}" ]]
424-
then
425-
JSON_URLS=("${HOMEBREW_API_DOMAIN}/${filename}")
426-
fi
427-
428-
JSON_URLS+=("${HOMEBREW_API_DEFAULT_DOMAIN}/${filename}")
429-
for json_url in "${JSON_URLS[@]}"
423+
local arg json_url
424+
while read -r json_url
430425
do
431426
time_cond=()
432-
if [[ -s "${cache_path}" ]]
433-
then
434-
time_cond=("--time-cond" "${cache_path}")
435-
fi
427+
while read -r arg
428+
do
429+
time_cond+=("${arg}")
430+
done < <(api_time_cond_args "${cache_path}")
431+
# Keep curl request handling in sync with `download_and_cache_executables_file`
432+
# in Library/Homebrew/utils/executables.sh.
436433
curl \
437434
"${CURL_DISABLE_CURLRC_ARGS[@]}" \
438435
--fail --compressed --silent \
@@ -443,7 +440,7 @@ fetch_api_file() {
443440
"${json_url}"
444441
curl_exit_code=$?
445442
[[ ${curl_exit_code} -eq 0 ]] && break
446-
done
443+
done < <(api_urls "${filename}")
447444

448445
if [[ -n ${is_formula_file} ]] && [[ -f "${api_cache}/formula_names.txt" ]]
449446
then
@@ -479,6 +476,7 @@ fetch_api_file() {
479476
}
480477

481478
homebrew-update() {
479+
local arg
482480
local option
483481
local DIR
484482
local UPSTREAM_BRANCH
@@ -652,16 +650,11 @@ EOS
652650
fi
653651

654652
# HOMEBREW_CURLRC is optionally defined in the user environment.
655-
# shellcheck disable=SC2153
656-
if [[ -z "${HOMEBREW_CURLRC}" ]]
657-
then
658-
CURL_DISABLE_CURLRC_ARGS=(-q)
659-
elif [[ "${HOMEBREW_CURLRC}" == /* ]]
660-
then
661-
CURL_DISABLE_CURLRC_ARGS=(-q --config "${HOMEBREW_CURLRC}")
662-
else
663-
CURL_DISABLE_CURLRC_ARGS=()
664-
fi
653+
CURL_DISABLE_CURLRC_ARGS=()
654+
while read -r arg
655+
do
656+
CURL_DISABLE_CURLRC_ARGS+=("${arg}")
657+
done < <(api_curlrc_args)
665658

666659
# only allow one instance of brew update
667660
lock update
@@ -1042,7 +1035,8 @@ EOS
10421035
# Update executables.txt if the user has ever run `brew which-formula` before.
10431036
if [[ -n "${HOMEBREW_FETCH_EXECUTABLES_TXT}" ]]
10441037
then
1045-
fetch_api_file "internal/executables.txt" "${update_failed_file}"
1038+
ohai "Downloading executables.txt"
1039+
fetch_api_file "${HOMEBREW_EXECUTABLES_TXT_ENDPOINT}" "${update_failed_file}"
10461040
fi
10471041

10481042
if [[ -f "${update_failed_file}" ]]
Lines changed: 10 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,7 @@
11
# Documentation defined in Library/Homebrew/cmd/which-formula.rb
22

3-
# HOMEBREW_CACHE is set by utils/ruby.sh
4-
# HOMEBREW_LIBRARY is set by bin/brew
5-
# HOMEBREW_API_DEFAULT_DOMAIN HOMEBREW_CURL_SPEED_LIMIT HOMEBREW_CURL_SPEED_TIME HOMEBREW_USER_AGENT_CURL are set by brew.sh
63
# shellcheck disable=SC2154
7-
ENDPOINT="internal/executables.txt"
8-
DATABASE_FILE="${HOMEBREW_CACHE}/api/${ENDPOINT}"
9-
10-
is_formula_installed() {
11-
local name="$1"
12-
if [[ -d "${HOMEBREW_CELLAR}/${name}" ]]
13-
then
14-
return 0
15-
else
16-
return 1
17-
fi
18-
}
19-
20-
is_file_fresh() {
21-
if [[ -n "${HOMEBREW_MACOS}" ]]
22-
then
23-
STAT_PRINTF=("/usr/bin/stat" "-f")
24-
else
25-
STAT_PRINTF=("/usr/bin/stat" "-c")
26-
fi
27-
28-
local file_mtime
29-
local current_time
30-
local auto_update_secs
31-
32-
file_mtime=$("${STAT_PRINTF[@]}" %m "${DATABASE_FILE}")
33-
current_time=$(date +%s)
34-
auto_update_secs=${HOMEBREW_API_AUTO_UPDATE_SECS:-450}
35-
36-
[[ $((current_time - auto_update_secs)) -lt ${file_mtime} ]]
37-
}
38-
39-
download_and_cache_executables_file() {
40-
source "${HOMEBREW_LIBRARY}/Homebrew/utils/helpers.sh"
41-
if [[ -s "${DATABASE_FILE}" ]] && ([[ -n "${HOMEBREW_SKIP_UPDATE}" ]] || is_file_fresh)
42-
then
43-
return
44-
else
45-
local url
46-
url="${HOMEBREW_API_DEFAULT_DOMAIN}/${ENDPOINT}"
47-
48-
if [[ -n "${CI}" ]]
49-
then
50-
max_time=""
51-
retries="3"
52-
else
53-
max_time=10
54-
retries=0
55-
fi
56-
mkdir -p "${DATABASE_FILE%/*}"
57-
${HOMEBREW_CURL} \
58-
--compressed \
59-
--speed-limit "${HOMEBREW_CURL_SPEED_LIMIT}" --speed-time "${HOMEBREW_CURL_SPEED_TIME}" \
60-
--location --remote-time --output "${DATABASE_FILE}" \
61-
${max_time:+--max-time "${max_time}"} \
62-
${retries:+--retry "${retries}" --retry-delay 0 --retry-max-time 60} \
63-
--user-agent "${HOMEBREW_USER_AGENT_CURL}" \
64-
"${url}"
65-
touch "${DATABASE_FILE}"
66-
67-
git config --file="${HOMEBREW_REPOSITORY}/.git/config" --bool homebrew.commandnotfound true 2>/dev/null
68-
fi
69-
}
4+
source "${HOMEBREW_LIBRARY}/Homebrew/utils/executables.sh"
705

716
homebrew-which-formula() {
727
local args=()
@@ -105,19 +40,11 @@ homebrew-which-formula() {
10540
download_and_cache_executables_file
10641

10742
local formulae=()
108-
local formula cmds_text
109-
110-
while IFS=':' read -r formula cmds_text
43+
local formula
44+
while read -r formula
11145
do
112-
[[ -z "${formula}" ]] && continue
113-
[[ -z "${cmds_text}" ]] && continue
114-
115-
if [[ " ${cmds_text} " == *" ${cmd} "* ]]
116-
then
117-
formula="${formula%\(*}"
118-
formulae+=("${formula}")
119-
fi
120-
done <"${DATABASE_FILE}" 2>/dev/null
46+
formulae+=("${formula}")
47+
done < <(formulae_containing_executable "${cmd}")
12148

12249
[[ ${#formulae[@]} -eq 0 ]] && return 1
12350

@@ -126,7 +53,7 @@ homebrew-which-formula() {
12653
local filtered_formulae=()
12754
for formula in "${formulae[@]}"
12855
do
129-
if ! is_formula_installed "${formula}"
56+
if [[ ! -d "${HOMEBREW_CELLAR}/${formula}" ]]
13057
then
13158
filtered_formulae+=("${formula}")
13259
fi
@@ -147,7 +74,10 @@ homebrew-which-formula() {
14774
echo "Try: brew install <selected formula>"
14875
fi
14976
else
150-
printf '%s\n' "${formulae[@]}"
77+
for formula in "${formulae[@]}"
78+
do
79+
print_formula_install_status "${formula}"
80+
done
15181
fi
15282
done
15383
}

Library/Homebrew/extend/kernel.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ def quiet_system(cmd, argv0 = nil, *args)
8686
# Find a command.
8787
#
8888
# @api public
89+
# Keep in sync with `which` in Library/Homebrew/utils.sh.
8990
sig { params(cmd: String, path: PATH::Elements).returns(T.nilable(Pathname)) }
9091
def which(cmd, path = ENV.fetch("PATH"))
9192
PATH.new(path).each do |p|

Library/Homebrew/list.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ homebrew-list() {
1717
then
1818
tty=1
1919
ls_args+=("-Cq")
20-
source "${HOMEBREW_LIBRARY}/Homebrew/utils/helpers.sh"
20+
source "${HOMEBREW_LIBRARY}/Homebrew/utils.sh"
2121
ls_env+=("COLUMNS=$(columns)")
2222
fi
2323

0 commit comments

Comments
 (0)