Skip to content

Commit 3c76a93

Browse files
committed
upgrade: auto-tap formulae or casks before upgrading
When you `brew install org/tap/formula-name`, it automatically taps the repo if not present. Mirror this behaviour in `brew upgrade` so that specifying a tap-prefixed name works the same way. The use-case here is a formula adding a `depends_on my-org/my-tap/my-formula` line. This will work fine for people who `brew install` the formula fresh, but not for people who `brew upgrade` an existing formula.
1 parent ff29aa9 commit 3c76a93

File tree

2 files changed

+66
-1
lines changed

2 files changed

+66
-1
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# frozen_string_literal: true
2+
3+
require "upgrade"
4+
5+
RSpec.describe Homebrew::Upgrade do
6+
describe ".build_dependency_graph" do
7+
let(:formulae) { [instance_double(Formula)] }
8+
let(:graph) { instance_double(Utils::TopologicalHash) }
9+
let(:tap) { instance_double(Tap, user: "test", repository: "tap") }
10+
11+
it "returns the dependency graph when no tap errors occur" do
12+
allow(Utils::TopologicalHash).to receive(:graph_package_dependencies).with(formulae).and_return(graph)
13+
14+
expect(described_class.send(:build_dependency_graph, formulae)).to eq(graph)
15+
end
16+
17+
it "installs the tap and retries when a dependency's tap is not installed" do
18+
error = TapFormulaUnavailableError.new(tap, "formula")
19+
attempts = 0
20+
21+
allow(tap).to receive(:installed?).and_return(false, true)
22+
expect(tap).to receive(:ensure_installed!)
23+
allow(Utils::TopologicalHash).to receive(:graph_package_dependencies).with(formulae) do
24+
attempts += 1
25+
raise error if attempts == 1
26+
27+
graph
28+
end
29+
30+
expect(described_class.send(:build_dependency_graph, formulae)).to eq(graph)
31+
end
32+
33+
it "re-raises when the dependency's tap is already installed" do
34+
allow(tap).to receive(:installed?).and_return(true)
35+
error = TapFormulaUnavailableError.new(tap, "formula")
36+
37+
allow(Utils::TopologicalHash).to receive(:graph_package_dependencies).with(formulae).and_raise(error)
38+
39+
expect { described_class.send(:build_dependency_graph, formulae) }.to raise_error(TapFormulaUnavailableError)
40+
end
41+
42+
it "re-raises when the tap cannot be installed" do
43+
allow(tap).to receive(:installed?).and_return(false)
44+
error = TapFormulaUnavailableError.new(tap, "formula")
45+
46+
expect(tap).to receive(:ensure_installed!)
47+
allow(Utils::TopologicalHash).to receive(:graph_package_dependencies).with(formulae).and_raise(error)
48+
49+
expect { described_class.send(:build_dependency_graph, formulae) }.to raise_error(TapFormulaUnavailableError)
50+
end
51+
end
52+
end

Library/Homebrew/upgrade.rb

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def formula_installers(
6060
end
6161
end
6262

63-
dependency_graph = Utils::TopologicalHash.graph_package_dependencies(formulae_to_install)
63+
dependency_graph = build_dependency_graph(formulae_to_install)
6464
begin
6565
formulae_to_install = dependency_graph.tsort & formulae_to_install
6666
rescue TSort::Cyclic
@@ -112,6 +112,19 @@ def formula_installers(
112112
end
113113
end
114114

115+
sig { params(formulae: T::Array[Formula]).returns(Utils::TopologicalHash) }
116+
def build_dependency_graph(formulae)
117+
Utils::TopologicalHash.graph_package_dependencies(formulae)
118+
rescue TapFormulaUnavailableError => e
119+
raise if e.tap.installed?
120+
121+
e.tap.ensure_installed!
122+
retry if e.tap.installed? # It may have not installed if it's a core tap.
123+
124+
raise
125+
end
126+
private :build_dependency_graph
127+
115128
sig {
116129
params(formula_installers: T::Array[FormulaInstaller], dry_run: T::Boolean, verbose: T::Boolean,
117130
fetch: T::Boolean).void

0 commit comments

Comments
 (0)