Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 29 additions & 2 deletions Library/Homebrew/diagnostic.rb
Original file line number Diff line number Diff line change
Expand Up @@ -712,26 +712,53 @@ def check_deprecated_disabled
deprecated_or_disabled += Formula.installed.select(&:disabled?)
return if deprecated_or_disabled.empty?

formula_lines = deprecated_or_disabled.sort_by(&:full_name).uniq.map do |f|
url = f.homepage.presence || f.head&.url.presence || formula_tap_url(f)
url ? "#{f.full_name} (#{Formatter.url(url)})" : f.full_name
Comment on lines +716 to +717
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
url = f.homepage.presence || f.head&.url.presence || formula_tap_url(f)
url ? "#{f.full_name} (#{Formatter.url(url)})" : f.full_name
if (homepage = f.homepage.presence)
"#{f.full_name} (#{Formatter.url(homepage)})"
else
f.full_name
end

end

<<~EOS
Some installed formulae are deprecated or disabled.
You should find replacements for the following formulae:
#{deprecated_or_disabled.sort_by(&:full_name).uniq * "\n "}
#{formula_lines.join("\n ")}
EOS
end

sig { params(formula: Formula).returns(T.nilable(String)) }
def formula_tap_url(formula)
tap = formula.tap
return if tap.blank? || tap.remote.blank?

path = formula.path.relative_path_from(tap.path)
"#{tap.remote}/blob/HEAD/#{path}"
end

Comment on lines +727 to +735
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
sig { params(formula: Formula).returns(T.nilable(String)) }
def formula_tap_url(formula)
tap = formula.tap
return if tap.blank? || tap.remote.blank?
path = formula.path.relative_path_from(tap.path)
"#{tap.remote}/blob/HEAD/#{path}"
end

sig { returns(T.nilable(String)) }
def check_cask_deprecated_disabled
deprecated_or_disabled = Cask::Caskroom.casks.select(&:deprecated?)
deprecated_or_disabled += Cask::Caskroom.casks.select(&:disabled?)
return if deprecated_or_disabled.empty?

cask_lines = deprecated_or_disabled.sort_by(&:token).uniq.map do |c|
url = c.homepage.presence || cask_tap_url(c)
url ? "#{c.token} (#{Formatter.url(url)})" : c.token
Comment on lines +743 to +744
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
url = c.homepage.presence || cask_tap_url(c)
url ? "#{c.token} (#{Formatter.url(url)})" : c.token
if (homepage = c.homepage.presence)
"#{c.token} (#{Formatter.url(homepage)})"
else
c.token
end

Copy link
Author

Choose a reason for hiding this comment

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

@MikeMcQuaid If all of them have homepages, why do we check for c.homepage.presence?

Copy link
Member

Choose a reason for hiding this comment

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

@seivan broken or non-homebrew core formulae may not.

Copy link
Author

Choose a reason for hiding this comment

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

You mean taps? I think we should keep the fallbacks in that case, a lot of people use taps. In fact I made one recently because of the gatekeeper issues. It's a diagnostic tool, it should diagnose things that are broken, no?

Copy link
Member

Choose a reason for hiding this comment

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

@seivan I don't think for this debugging tool we should handle the edge cases of "deprecated formulae in taps that fail audits and/or are otherwise broken". It's not worth the extra code.

end

<<~EOS
Some installed casks are deprecated or disabled.
You should find replacements for the following casks:
#{deprecated_or_disabled.sort_by(&:token).uniq * "\n "}
#{cask_lines.join("\n ")}
EOS
end

sig { params(cask: Cask::Cask).returns(T.nilable(String)) }
def cask_tap_url(cask)
tap = cask.tap
return if tap.blank? || tap.remote.blank?

"#{tap.remote}/blob/HEAD/#{tap.relative_cask_path(cask.token)}"
end
Comment on lines +754 to +760
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
sig { params(cask: Cask::Cask).returns(T.nilable(String)) }
def cask_tap_url(cask)
tap = cask.tap
return if tap.blank? || tap.remote.blank?
"#{tap.remote}/blob/HEAD/#{tap.relative_cask_path(cask.token)}"
end


sig { returns(T.nilable(String)) }
def check_git_status
return unless Utils::Git.available?
Expand Down
138 changes: 138 additions & 0 deletions Library/Homebrew/test/diagnostic_checks_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,142 @@

expect(checks.check_for_unnecessary_cask_tap).to match("unnecessary local Cask tap")
end

describe "#formula_tap_url" do
let(:tap) do
instance_double(Tap, remote: "https://github.com/Homebrew/homebrew-core",
path: Pathname.new("/tap/path"))
end

it "returns nil when tap is nil" do
formula = instance_double(Formula, tap: nil)
expect(checks.formula_tap_url(formula)).to be_nil
end

it "returns nil when tap remote is blank" do
tap_no_remote = instance_double(Tap, remote: nil)
formula = instance_double(Formula, tap: tap_no_remote)
expect(checks.formula_tap_url(formula)).to be_nil
end

it "returns URL when tap has remote" do
formula = instance_double(Formula, tap: tap, path: Pathname.new("/tap/path/Formula/w/wget.rb"))
expect(checks.formula_tap_url(formula))
.to eq "https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/w/wget.rb"
end
end

describe "#cask_tap_url" do
let(:tap) do
instance_double(Tap, remote: "https://github.com/Homebrew/homebrew-cask")
end

before do
allow(tap).to receive(:relative_cask_path).with("firefox").and_return("Casks/f/firefox.rb")
end

it "returns nil when tap is nil" do
cask = instance_double(Cask::Cask, tap: nil)
expect(checks.cask_tap_url(cask)).to be_nil
end

it "returns nil when tap remote is blank" do
tap_no_remote = instance_double(Tap, remote: nil)
cask = instance_double(Cask::Cask, tap: tap_no_remote)
expect(checks.cask_tap_url(cask)).to be_nil
end

it "returns URL using remote and relative_cask_path" do
cask = instance_double(Cask::Cask, tap: tap, token: "firefox")
expect(checks.cask_tap_url(cask))
.to eq "https://github.com/Homebrew/homebrew-cask/blob/HEAD/Casks/f/firefox.rb"
end
end

describe "#check_deprecated_disabled" do
let(:tap) do
instance_double(Tap, remote: "https://github.com/Homebrew/homebrew-core",
path: Pathname.new("/tap/path"))
end
let(:head_spec) { instance_double(HeadSoftwareSpec, url: "https://github.com/example/repo.git") }

it "returns nil when no formulae are deprecated or disabled" do
allow(Formula).to receive(:installed).and_return([])
expect(checks.check_deprecated_disabled).to be_nil
end

it "includes deprecated formula with homepage URL" do
formula = instance_double(Formula, deprecated?: true, disabled?: false,
full_name: "deprecated-formula",
homepage: "https://example.com/deprecated",
head: nil, tap: tap,
path: Pathname.new("/tap/path/Formula/d/deprecated-formula.rb"))
allow(Formula).to receive(:installed).and_return([formula])

result = checks.check_deprecated_disabled
expect(result).to match("deprecated-formula")
expect(result).to match("https://example.com/deprecated")
end

it "falls back to head URL when homepage is nil" do
formula = instance_double(Formula, deprecated?: false, disabled?: true,
full_name: "disabled-head-formula",
homepage: nil, head: head_spec, tap: tap,
path: Pathname.new("/tap/path/Formula/d/disabled-head-formula.rb"))
allow(Formula).to receive(:installed).and_return([formula])

result = checks.check_deprecated_disabled
expect(result).to match("disabled-head-formula")
expect(result).to match("https://github.com/example/repo.git")
end

it "falls back to tap URL when homepage and head are nil" do
formula = instance_double(Formula, deprecated?: false, disabled?: true,
full_name: "disabled-formula",
homepage: nil, head: nil, tap: tap,
path: Pathname.new("/tap/path/Formula/d/disabled-formula.rb"))
allow(Formula).to receive(:installed).and_return([formula])

result = checks.check_deprecated_disabled
expect(result).to match("disabled-formula")
expect(result).to match("https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/d/disabled-formula.rb")
end
end

describe "#check_cask_deprecated_disabled" do
let(:tap) do
instance_double(Tap, remote: "https://github.com/Homebrew/homebrew-cask")
end

before do
allow(tap).to receive(:relative_cask_path).with("deprecated-cask").and_return("Casks/d/deprecated-cask.rb")
allow(tap).to receive(:relative_cask_path).with("disabled-cask").and_return("Casks/d/disabled-cask.rb")
end

it "returns nil when no casks are deprecated or disabled" do
allow(Cask::Caskroom).to receive(:casks).and_return([])
expect(checks.check_cask_deprecated_disabled).to be_nil
end

it "includes deprecated cask with homepage URL" do
cask = instance_double(Cask::Cask, deprecated?: true, disabled?: false,
token: "deprecated-cask",
homepage: "https://example.com/deprecated-cask", tap: tap)
allow(Cask::Caskroom).to receive(:casks).and_return([cask])

result = checks.check_cask_deprecated_disabled
expect(result).to match("deprecated-cask")
expect(result).to match("https://example.com/deprecated-cask")
end

it "falls back to cask tap URL when homepage is nil" do
cask = instance_double(Cask::Cask, deprecated?: false, disabled?: true,
token: "disabled-cask", homepage: nil, tap: tap)
allow(Cask::Caskroom).to receive(:casks).and_return([cask])

result = checks.check_cask_deprecated_disabled
expect(result).to match("disabled-cask")
expect(result).to match("https://github.com/Homebrew/homebrew-cask/blob/HEAD/Casks/d/disabled-cask.rb")
end
end
end
Loading