Fix cask source file path loading issues

There are two big changes here. Both have to do with how we want
to load casks in different scenarios. One also is related to formulae.

1. Prevent loading casks & formulae outside of taps for specific commands.

There are certain commands like `bump`, `bump-*-pr`, `livecheck` and `audit`
where it really makes no sense to try and run things if the specified formulae
or cask is not in a tap. A new `#to_formulae_and_casks_with_taps` method was
added to the `CLI::NamedArgs` class to allow us to easily grab and validate
formulae and casks from named arguments.

2. Always load the source file path when loading casks with the path loader.

There was an edge case where all JSON cask files were being loaded without
setting the source file path because most of the work was handed off to the
API loader where that normally would make more sense. Now we set that when
calling the API loader which solves the problem. This improves the user
experience of people using the `--cache` and `fetch` commands in certain
edge cases. Hopefully it makes the user experience a bit more consistent.

A regression test was added for this point.
This commit is contained in:
apainintheneck 2024-05-06 23:34:23 -07:00
parent 55167f2965
commit ffc503f1d0
6 changed files with 34 additions and 19 deletions

View File

@ -125,7 +125,9 @@ module Cask
@content = path.read(encoding: "UTF-8")
@config = config
return FromAPILoader.new(token, from_json: JSON.parse(@content)).load(config:) if path.extname == ".json"
if path.extname == ".json"
return FromAPILoader.new(token, from_json: JSON.parse(@content), path:).load(config:)
end
begin
instance_eval(content, path).tap do |cask|
@ -278,10 +280,11 @@ module Cask
new("#{tap}/#{token}")
end
sig { params(token: String, from_json: Hash).void }
def initialize(token, from_json: T.unsafe(nil))
sig { params(token: String, from_json: Hash, path: T.nilable(Pathname)).void }
def initialize(token, from_json: T.unsafe(nil), path: nil)
@token = token.sub(%r{^homebrew/(?:homebrew-)?cask/}i, "")
@path = CaskLoader.default_path(@token)
@sourcefile_path = path
@path = path || CaskLoader.default_path(@token)
@from_json = from_json
end
@ -290,6 +293,7 @@ module Cask
cask_options = {
loaded_from_api: true,
sourcefile_path: @sourcefile_path,
source: JSON.pretty_generate(json_cask),
config:,
loader: self,

View File

@ -103,6 +103,20 @@ module Homebrew
.map(&:freeze).freeze
end
# Returns formulae and casks after validating that a tap is present for each of them.
def to_formulae_and_casks_with_taps
to_formulae_and_casks.each do |formula_or_cask|
case formula_or_cask
when Formula
odie "Formula #{formula_or_cask.name} is not in a tap!" unless formula_or_cask.tap
when Cask::Cask
odie "Cask #{formula_or_cask.token} is not in a tap!" unless formula_or_cask.tap
else
raise ArgumentError, "Expected a formula or a cask: #{formula_or_cask}"
end
end
end
def to_formulae_and_casks_and_unavailable(only: parent&.only_formula_or_cask, method: nil)
@to_formulae_casks_unknowns ||= {}
@to_formulae_casks_unknowns[method] = downcased_unique_named.map do |name|

View File

@ -158,7 +158,7 @@ module Homebrew
"brew audit [name ...]"
end
args.named.to_formulae_and_casks
args.named.to_formulae_and_casks_with_taps
.partition { |formula_or_cask| formula_or_cask.is_a?(Formula) }
end
end

View File

@ -78,13 +78,7 @@ module Homebrew
casks = args.formula? ? [] : Cask::Caskroom.casks
formulae + casks
elsif args.named.present?
if args.formula?
args.named.to_formulae
elsif args.cask?
args.named.to_casks
else
args.named.to_formulae_and_casks
end
args.named.to_formulae_and_casks_with_taps
end
formulae_and_casks = formulae_and_casks&.sort_by do |formula_or_cask|

View File

@ -73,13 +73,7 @@ module Homebrew
casks = args.formula? ? [] : Cask::Cask.all(eval_all: args.eval_all?)
formulae + casks
elsif args.named.present?
if args.formula?
args.named.to_formulae
elsif args.cask?
args.named.to_casks
else
args.named.to_formulae_and_casks
end
args.named.to_formulae_and_casks_with_taps
elsif File.exist?(watchlist_path)
begin
names = Pathname.new(watchlist_path).read.lines

View File

@ -42,5 +42,14 @@ RSpec.describe Cask::CaskLoader::FromPathLoader do
/invalid 'depends_on macos' value: unknown or unsupported macOS version:/)
end
end
context "with a JSON cask file" do
let(:sourcefile_path) { TEST_FIXTURE_DIR/"cask/everything.json" }
it "loads a cask with a source file path" do
cask = described_class.new(sourcefile_path).load(config: nil)
expect(cask.sourcefile_path).to eq sourcefile_path
end
end
end
end