Remove unused cask url do code

This commit is contained in:
Rylan Polster 2025-08-23 15:02:23 -04:00
parent 78beba5440
commit 5d13ce9280
No known key found for this signature in database
8 changed files with 64 additions and 242 deletions

View File

@ -1245,15 +1245,17 @@ module Cask
url.sub(%r{^[^:/]+://(www\.)?}, "") url.sub(%r{^[^:/]+://(www\.)?}, "")
end end
sig { returns(String) } sig { returns(T.nilable(String)) }
def url_from_verified def url_from_verified
strip_url_scheme(T.must(cask.url).verified) return unless (verified_url = T.must(cask.url).verified)
strip_url_scheme(verified_url)
end end
sig { returns(T::Boolean) } sig { returns(T::Boolean) }
def verified_matches_url? def verified_matches_url?
url_domain, url_path = strip_url_scheme(cask.url.to_s).split("/", 2) url_domain, url_path = strip_url_scheme(cask.url.to_s).split("/", 2)
verified_domain, verified_path = url_from_verified.split("/", 2) verified_domain, verified_path = url_from_verified&.split("/", 2)
domains_match = (url_domain == verified_domain) || domains_match = (url_domain == verified_domain) ||
(verified_domain && url_domain&.end_with?(".#{verified_domain}")) (verified_domain && url_domain&.end_with?(".#{verified_domain}"))

View File

@ -314,17 +314,13 @@ module Cask
# ``` # ```
# #
# @api public # @api public
def url(*args, **options, &block) def url(*args, **options)
caller_location = T.must(caller_locations).fetch(0) caller_location = T.must(caller_locations).fetch(0)
set_unique_stanza(:url, args.empty? && options.empty? && !block) do set_unique_stanza(:url, args.empty? && options.empty?) do
if block
URL.new(*args, **options, caller_location:, dsl: self, &block)
else
URL.new(*args, **options, caller_location:) URL.new(*args, **options, caller_location:)
end end
end end
end
# Sets the cask's container type or nested container path. # Sets the cask's container type or nested container path.
# #

View File

@ -6,10 +6,8 @@ require "utils/curl"
module Cask module Cask
# Class corresponding to the `url` stanza. # Class corresponding to the `url` stanza.
class URL < SimpleDelegator class URL
# Methods for the `url` stanza. sig { returns(URI::Generic) }
class DSL
sig { returns(T.any(URI::Generic, String)) }
attr_reader :uri attr_reader :uri
sig { returns(T.nilable(T::Hash[T.any(Symbol, String), String])) } sig { returns(T.nilable(T::Hash[T.any(Symbol, String), String])) }
@ -62,13 +60,15 @@ module Cask
user_agent: T.nilable(T.any(Symbol, String)), user_agent: T.nilable(T.any(Symbol, String)),
data: T.nilable(T::Hash[String, String]), data: T.nilable(T::Hash[String, String]),
only_path: T.nilable(String), only_path: T.nilable(String),
caller_location: Thread::Backtrace::Location,
).void ).void
} }
def initialize( def initialize(
uri, verified: nil, using: nil, tag: nil, branch: nil, revisions: nil, revision: nil, trust_cert: nil, uri, verified: nil, using: nil, tag: nil, branch: nil, revisions: nil, revision: nil, trust_cert: nil,
cookies: nil, referer: nil, header: nil, user_agent: nil, data: nil, only_path: nil cookies: nil, referer: nil, header: nil, user_agent: nil, data: nil, only_path: nil,
caller_location: caller_locations.fetch(0)
) )
@uri = T.let(URI(uri), T.any(URI::Generic, String)) @uri = T.let(URI(uri), URI::Generic)
header = Array(header) unless header.nil? header = Array(header) unless header.nil?
@ -88,39 +88,6 @@ module Cask
specs[:only_path] = @only_path = T.let(only_path, T.nilable(String)) specs[:only_path] = @only_path = T.let(only_path, T.nilable(String))
@specs = T.let(specs.compact, T::Hash[Symbol, T.untyped]) @specs = T.let(specs.compact, T::Hash[Symbol, T.untyped])
end
end
sig {
params(
uri: T.nilable(T.any(URI::Generic, String)),
verified: T.nilable(String),
using: T.any(T::Class[AbstractDownloadStrategy], Symbol, NilClass),
tag: T.nilable(String),
branch: T.nilable(String),
revisions: T.nilable(T::Hash[T.any(Symbol, String), String]),
revision: T.nilable(String),
trust_cert: T.nilable(T::Boolean),
cookies: T.nilable(T::Hash[String, String]),
referer: T.nilable(T.any(URI::Generic, String)),
header: T.nilable(T.any(String, T::Array[String])),
user_agent: T.nilable(T.any(Symbol, String)),
data: T.nilable(T::Hash[String, String]),
only_path: T.nilable(String),
caller_location: Thread::Backtrace::Location,
dsl: T.nilable(::Cask::DSL),
).void
}
def initialize(
uri = nil, verified: nil, using: nil, tag: nil, branch: nil, revisions: nil, revision: nil, trust_cert: nil,
cookies: nil, referer: nil, header: nil, user_agent: nil, data: nil, only_path: nil,
caller_location: caller_locations.fetch(0), dsl: nil
)
super(
DSL.new(T.must(uri), verified:, using:, tag:, branch:, revisions:, revision:, trust_cert:, cookies:,
referer:, header:, user_agent:, data:, only_path:)
)
@caller_location = T.let(caller_location, Thread::Backtrace::Location) @caller_location = T.let(caller_location, Thread::Backtrace::Location)
end end

View File

@ -6,59 +6,12 @@
class Cask::URL class Cask::URL
include Kernel sig { params(args: T.untyped, block: T.untyped).returns(T.untyped) }
def path(*args, &block); end
sig { returns(T.untyped) } sig { params(args: T.untyped, block: T.untyped).returns(T.untyped) }
def branch; end def scheme(*args, &block); end
sig { returns(T.nilable(T::Hash[::String, ::String])) } sig { params(args: T.untyped, block: T.untyped).returns(String) }
def cookies; end def to_s(*args, &block); end
sig { returns(T.untyped) }
def data; end
sig { returns(T.nilable(T.any(::String, T::Array[::String]))) }
def header; end
sig { returns(T.untyped) }
def only_path; end
sig { returns(T.untyped) }
def path; end
sig { returns(T.nilable(T.any(::String, ::URI::Generic))) }
def referer; end
sig { returns(T.untyped) }
def revision; end
sig { returns(T.nilable(T::Hash[T.any(::String, ::Symbol), ::String])) }
def revisions; end
sig { returns(T.untyped) }
def scheme; end
sig { returns(T::Hash[::Symbol, T.untyped]) }
def specs; end
sig { returns(T.nilable(::String)) }
def tag; end
sig { returns(T.untyped) }
def to_s; end
sig { returns(T.nilable(T::Boolean)) }
def trust_cert; end
sig { returns(T.any(::String, ::URI::Generic)) }
def uri; end
sig { returns(T.nilable(T.any(::String, ::Symbol))) }
def user_agent; end
sig { returns(T.nilable(T.any(::Symbol, T::Class[::AbstractDownloadStrategy]))) }
def using; end
sig { returns(T.untyped) }
def verified; end
end end

View File

@ -1,17 +0,0 @@
# typed: true
# DO NOT EDIT MANUALLY
# This is an autogenerated file for dynamic methods in `Cask::URL::DSL`.
# Please instead update this file by running `bin/tapioca dsl Cask::URL::DSL`.
class Cask::URL::DSL
sig { params(args: T.untyped, block: T.untyped).returns(T.untyped) }
def path(*args, &block); end
sig { params(args: T.untyped, block: T.untyped).returns(T.untyped) }
def scheme(*args, &block); end
sig { params(args: T.untyped, block: T.untyped).returns(String) }
def to_s(*args, &block); end
end

View File

@ -1,40 +0,0 @@
# typed: strict
# frozen_string_literal: true
require_relative "../../../global"
require "cask/url"
module Tapioca
module Compilers
# A compiler for subclasses of Delegator.
# To add a new delegator: require it above and add it to the DELEGATIONS hash below.
class Delegators < Tapioca::Dsl::Compiler
# Mapping of delegator classes to the classes they delegate to (as defined in `__getobj__`).
DELEGATIONS = T.let({
Cask::URL => Cask::URL::DSL,
}.freeze, T::Hash[Module, Module])
ConstantType = type_member { { fixed: Module } }
sig { override.returns(T::Enumerable[Module]) }
def self.gather_constants = DELEGATIONS.keys
sig { override.void }
def decorate
root.create_path(constant) do |klass|
# Note that `Delegtor` does not subclass `Object`:
# https://github.com/ruby/ruby/blob/a6383fb/lib/delegate.rb#L41
# but we assume that we are delegating to a class that does.
klass.create_include("Kernel")
delegated = DELEGATIONS.fetch(constant)
delegated.instance_methods(false).each do |method|
signature = T::Utils.signature_for_method(delegated.instance_method(method))
# TODO: handle methods with parameters
return_type = signature&.return_type&.to_s || "T.untyped"
klass.create_method(method.to_s, return_type:)
end
end
end
end
end
end

View File

@ -185,7 +185,7 @@ Fill in the following stanzas for your cask:
| ------------------ | ----------- | | ------------------ | ----------- |
| `version` | application version | | `version` | application version |
| `sha256` | SHA-256 checksum of the file downloaded from `url`, calculated by the command `shasum -a 256 <file>`. Can be suppressed by using the special value `:no_check`. (see [`sha256` Stanza Details](Cask-Cookbook.md#stanza-sha256)) | | `sha256` | SHA-256 checksum of the file downloaded from `url`, calculated by the command `shasum -a 256 <file>`. Can be suppressed by using the special value `:no_check`. (see [`sha256` Stanza Details](Cask-Cookbook.md#stanza-sha256)) |
| `url` | URL to the `.dmg`/`.zip`/`.tgz`/`.tbz2` file that contains the application.<br />A [`verified` parameter](Cask-Cookbook.md#when-url-and-homepage-domains-differ-add-verified) must be added if the hostnames in the `url` and `homepage` stanzas differ. [Block syntax](Cask-Cookbook.md#using-a-block-to-defer-code-execution) is available for URLs that change on every visit. | | `url` | URL to the `.dmg`/`.zip`/`.tgz`/`.tbz2` file that contains the application.<br />A [`verified` parameter](Cask-Cookbook.md#when-url-and-homepage-domains-differ-add-verified) must be added if the hostnames in the `url` and `homepage` stanzas differ. |
| `name` | the full and proper name defined by the vendor, and any useful alternate names (see [`name` Stanza Details](Cask-Cookbook.md#stanza-name)) | | `name` | the full and proper name defined by the vendor, and any useful alternate names (see [`name` Stanza Details](Cask-Cookbook.md#stanza-name)) |
| `desc` | one-line description of the software (see [`desc` Stanza Details](Cask-Cookbook.md#stanza-desc)) | | `desc` | one-line description of the software (see [`desc` Stanza Details](Cask-Cookbook.md#stanza-desc)) |
| `homepage` | application homepage; used for the `brew home` command | | `homepage` | application homepage; used for the `brew home` command |

View File

@ -1070,46 +1070,7 @@ If these formats are not available, and the application is macOS-exclusive (othe
Some hosting providers actively block command-line HTTP clients. Such URLs cannot be used in casks. Some hosting providers actively block command-line HTTP clients. Such URLs cannot be used in casks.
Other providers may use URLs that change periodically, or even on each visit (example: FossHub). While some cases [could be circumvented](#using-a-block-to-defer-code-execution), they tend to occur when the vendor is actively trying to prevent automated downloads, so we prefer to not add those casks to the main repository. Other providers may use URLs that change periodically, or even on each visit (example: FossHub). These cases tend to occur when the vendor is actively trying to prevent automated downloads, so we prefer to not add those casks to the main repository.
#### Using a block to defer code execution
Some applications—notably nightlies—have versioned download URLs that are updated so often that they become impractical to keep current with the usual process. For those, we want to dynamically determine `url`.
**Note:** Casks with a dynamically-determined `url` are not allowed in Homebrew/homebrew-cask as they interfere with API generation.
##### The Problem
In theory, one can write arbitrary Ruby code right in the cask definition to fetch and construct a disposable URL.
However, this typically involves an HTTP round trip to a landing site, which may take a long time. Because of the way Homebrew Cask loads and parses casks, it is not acceptable that such expensive operations be performed directly in the body of a cask definition.
##### Writing the block
Similar to the `preflight`, `postflight`, `uninstall_preflight` and `uninstall_postflight` blocks, the `url` stanza offers an optional *block syntax*:
```ruby
url "https://handbrake.fr/nightly.php" do |page|
file_path = page[/href=["']?([^"' >]*Handbrake[._-][^"' >]+\.dmg)["' >]/i, 1]
file_path ? URI.join(page.url, file_path) : nil
end
```
You can also nest `url do` blocks inside `url do` blocks to follow a chain of URLs.
The block is only evaluated when needed, for example at download time or when auditing a cask. Inside a block, you may safely do things such as HTTP(S) requests that may take a long time to execute. You may also refer to the `@cask` instance variable, and invoke [any method available on `@cask`](https://rubydoc.brew.sh/Cask/Cask).
The block will be called immediately before downloading; its resulting value is assumed to be a `String` (or a pair of a `String` and `Hash` containing parameters) and subsequently used as a download URL.
You can use the `url` stanza with either a direct argument or a block but not with both.
Historical example of using block syntax: [vlc@nightly.rb](https://github.com/Homebrew/homebrew-cask/blob/0b2b76ad8c3fbf4e1ee2f5e758640c4963ad6aaf/Casks/v/vlc%40nightly.rb#L7-L12)
##### Mixing additional URL parameters with block syntax
In rare cases, you might need to set URL parameters like `cookies` or `referer` while also using block syntax.
This is possible by returning a two-element array as a block result. The first element of the array must be the download URL; the second element must be a `Hash` containing the parameters.
### Stanza: `version` ### Stanza: `version`