mirror of
https://github.com/Homebrew/brew.git
synced 2025-07-14 16:09:03 +08:00
Fix loading casks/formulae from relative paths.
This commit is contained in:
parent
977ac20b2b
commit
3da0f8c4a6
@ -207,9 +207,9 @@ module Cask
|
|||||||
def self.try_new(ref, warn: false)
|
def self.try_new(ref, warn: false)
|
||||||
ref = ref.to_s
|
ref = ref.to_s
|
||||||
|
|
||||||
return unless ref.match?(HOMEBREW_TAP_CASK_REGEX)
|
return unless (token_tap_type = CaskLoader.tap_cask_token_type(ref, warn: warn))
|
||||||
|
|
||||||
token, tap, = CaskLoader.tap_cask_token_type(ref, warn: warn)
|
token, tap, = token_tap_type
|
||||||
new("#{tap}/#{token}")
|
new("#{tap}/#{token}")
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -529,9 +529,12 @@ module Cask
|
|||||||
self.for(ref, warn: warn).load(config: config)
|
self.for(ref, warn: warn).load(config: config)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(tapped_token: String, warn: T::Boolean).returns(T.nilable([String, Tap, T.nilable(Symbol)])) }
|
||||||
def self.tap_cask_token_type(tapped_token, warn:)
|
def self.tap_cask_token_type(tapped_token, warn:)
|
||||||
user, repo, token = tapped_token.split("/", 3).map(&:downcase)
|
return unless (tap_with_token = Tap.with_cask_token(tapped_token))
|
||||||
tap = Tap.fetch(user, repo)
|
|
||||||
|
tap, token = tap_with_token
|
||||||
|
|
||||||
type = nil
|
type = nil
|
||||||
|
|
||||||
if (new_token = tap.cask_renames[token].presence)
|
if (new_token = tap.cask_renames[token].presence)
|
||||||
@ -550,7 +553,9 @@ module Cask
|
|||||||
opoo "Tap migration for #{tapped_token} points to itself, stopping recursion."
|
opoo "Tap migration for #{tapped_token} points to itself, stopping recursion."
|
||||||
else
|
else
|
||||||
old_token = tap.core_cask_tap? ? token : tapped_token
|
old_token = tap.core_cask_tap? ? token : tapped_token
|
||||||
token, tap, = tap_cask_token_type(new_tapped_token, warn: false)
|
return unless (token_tap_type = tap_cask_token_type(new_tapped_token, warn: false))
|
||||||
|
|
||||||
|
token, tap, = token_tap_type
|
||||||
new_token = new_tap.core_cask_tap? ? token : "#{tap}/#{token}"
|
new_token = new_tap.core_cask_tap? ? token : "#{tap}/#{token}"
|
||||||
type = :migration
|
type = :migration
|
||||||
end
|
end
|
||||||
|
@ -142,8 +142,8 @@ on_request: true)
|
|||||||
return unless @cask.conflicts_with
|
return unless @cask.conflicts_with
|
||||||
|
|
||||||
@cask.conflicts_with[:cask].each do |conflicting_cask|
|
@cask.conflicts_with[:cask].each do |conflicting_cask|
|
||||||
if (match = conflicting_cask.match(HOMEBREW_TAP_CASK_REGEX))
|
if (conflicting_cask_tap_with_token = Tap.with_cask_token(conflicting_cask))
|
||||||
conflicting_cask_tap = Tap.fetch(match[1], match[2])
|
conflicting_cask_tap, = conflicting_cask_tap_with_token
|
||||||
next unless conflicting_cask_tap.installed?
|
next unless conflicting_cask_tap.installed?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -175,11 +175,13 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
|
|
||||||
args.named.each do |name|
|
args.named.each do |name|
|
||||||
next if File.exist?(name)
|
if (tap_with_name = Tap.with_formula_name(name))
|
||||||
next unless name =~ HOMEBREW_TAP_FORMULA_REGEX
|
tap, = tap_with_name
|
||||||
|
elsif (tap_with_token = Tap.with_cask_token(name))
|
||||||
|
tap, = tap_with_token
|
||||||
|
end
|
||||||
|
|
||||||
tap = Tap.fetch(Regexp.last_match(1), Regexp.last_match(2))
|
tap&.ensure_installed!
|
||||||
tap.ensure_installed!
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if args.ignore_dependencies?
|
if args.ignore_dependencies?
|
||||||
|
@ -19,7 +19,9 @@ class Dependency
|
|||||||
@name = name
|
@name = name
|
||||||
@tags = tags
|
@tags = tags
|
||||||
|
|
||||||
@tap = Tap.fetch(Regexp.last_match(1), Regexp.last_match(2)) if name =~ HOMEBREW_TAP_FORMULA_REGEX
|
return unless (tap_with_name = Tap.with_formula_name(name))
|
||||||
|
|
||||||
|
@tap, = tap_with_name
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
|
@ -34,9 +34,8 @@ module Homebrew
|
|||||||
def self.extract
|
def self.extract
|
||||||
args = extract_args.parse
|
args = extract_args.parse
|
||||||
|
|
||||||
if (match = args.named.first.match(HOMEBREW_TAP_FORMULA_REGEX))
|
if (tap_with_name = args.named.first&.then { Tap.with_formula_name(_1) })
|
||||||
name = match[3].downcase
|
source_tap, name = tap_with_name
|
||||||
source_tap = Tap.fetch(match[1], match[2])
|
|
||||||
else
|
else
|
||||||
name = args.named.first.downcase
|
name = args.named.first.downcase
|
||||||
source_tap = CoreTap.instance
|
source_tap = CoreTap.instance
|
||||||
|
@ -721,15 +721,15 @@ module Formulary
|
|||||||
}
|
}
|
||||||
def self.try_new(ref, from: T.unsafe(nil), warn: false)
|
def self.try_new(ref, from: T.unsafe(nil), warn: false)
|
||||||
ref = ref.to_s
|
ref = ref.to_s
|
||||||
return unless (name = ref[HOMEBREW_TAP_FORMULA_REGEX, :name])
|
|
||||||
|
|
||||||
alias_name = name
|
return unless (name_tap_type = Formulary.tap_formula_name_type(ref, warn: warn))
|
||||||
|
|
||||||
name, tap, type = Formulary.tap_formula_name_type(ref, warn: warn)
|
name, tap, type = name_tap_type
|
||||||
path = Formulary.find_formula_in_tap(name, tap)
|
path = Formulary.find_formula_in_tap(name, tap)
|
||||||
|
|
||||||
options = if type == :alias
|
options = if type == :alias
|
||||||
{ alias_name: alias_name.downcase }
|
# TODO: Simplify this by making `tap_formula_name_type` return the alias name.
|
||||||
|
{ alias_name: T.must(ref[HOMEBREW_TAP_FORMULA_REGEX, :name]).downcase }
|
||||||
else
|
else
|
||||||
{}
|
{}
|
||||||
end
|
end
|
||||||
@ -893,7 +893,9 @@ module Formulary
|
|||||||
|
|
||||||
ref = "#{CoreTap.instance}/#{name}"
|
ref = "#{CoreTap.instance}/#{name}"
|
||||||
|
|
||||||
name, tap, type = Formulary.tap_formula_name_type(ref, warn: warn)
|
return unless (name_tap_type = Formulary.tap_formula_name_type(ref, warn: warn))
|
||||||
|
|
||||||
|
name, tap, type = name_tap_type
|
||||||
|
|
||||||
options = if type == :alias
|
options = if type == :alias
|
||||||
{ alias_name: alias_name.downcase }
|
{ alias_name: alias_name.downcase }
|
||||||
@ -1127,9 +1129,12 @@ module Formulary
|
|||||||
loader_for(ref).path
|
loader_for(ref).path
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(tapped_name: String, warn: T::Boolean).returns(T.nilable([String, Tap, T.nilable(Symbol)])) }
|
||||||
def self.tap_formula_name_type(tapped_name, warn:)
|
def self.tap_formula_name_type(tapped_name, warn:)
|
||||||
user, repo, name = tapped_name.split("/", 3).map(&:downcase)
|
return unless (tap_with_name = Tap.with_formula_name(tapped_name))
|
||||||
tap = Tap.fetch(user, repo)
|
|
||||||
|
tap, name = tap_with_name
|
||||||
|
|
||||||
type = nil
|
type = nil
|
||||||
|
|
||||||
# FIXME: Remove the need to do this here.
|
# FIXME: Remove the need to do this here.
|
||||||
@ -1138,7 +1143,7 @@ module Formulary
|
|||||||
if (possible_alias = tap.alias_table[alias_table_key].presence)
|
if (possible_alias = tap.alias_table[alias_table_key].presence)
|
||||||
# FIXME: Remove the need to split the name and instead make
|
# FIXME: Remove the need to split the name and instead make
|
||||||
# the alias table only contain short names.
|
# the alias table only contain short names.
|
||||||
name = possible_alias.split("/").last
|
name = T.must(possible_alias.split("/").last)
|
||||||
type = :alias
|
type = :alias
|
||||||
elsif (new_name = tap.formula_renames[name].presence)
|
elsif (new_name = tap.formula_renames[name].presence)
|
||||||
old_name = tap.core_tap? ? name : tapped_name
|
old_name = tap.core_tap? ? name : tapped_name
|
||||||
@ -1156,7 +1161,10 @@ module Formulary
|
|||||||
opoo "Tap migration for #{tapped_name} points to itself, stopping recursion."
|
opoo "Tap migration for #{tapped_name} points to itself, stopping recursion."
|
||||||
else
|
else
|
||||||
old_name = tap.core_tap? ? name : tapped_name
|
old_name = tap.core_tap? ? name : tapped_name
|
||||||
name, tap, = tap_formula_name_type(new_tapped_name, warn: false)
|
return unless (name_tap_type = tap_formula_name_type(new_tapped_name, warn: false))
|
||||||
|
|
||||||
|
name, tap, = name_tap_type
|
||||||
|
|
||||||
new_name = new_tap.core_tap? ? name : "#{tap}/#{name}"
|
new_name = new_tap.core_tap? ? name : "#{tap}/#{name}"
|
||||||
type = :migration
|
type = :migration
|
||||||
end
|
end
|
||||||
|
@ -65,6 +65,38 @@ class Tap
|
|||||||
fetch(match[:user], match[:repo])
|
fetch(match[:user], match[:repo])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# @private
|
||||||
|
sig { params(name: String).returns(T.nilable([T.attached_class, String])) }
|
||||||
|
def self.with_formula_name(name)
|
||||||
|
return unless (match = name.match(HOMEBREW_TAP_FORMULA_REGEX))
|
||||||
|
|
||||||
|
user = T.must(match[:user])
|
||||||
|
repo = T.must(match[:repo])
|
||||||
|
name = T.must(match[:name])
|
||||||
|
|
||||||
|
# Relative paths are not taps.
|
||||||
|
return if [user, repo].intersect?([".", ".."])
|
||||||
|
|
||||||
|
tap = fetch(user, repo)
|
||||||
|
[tap, name.downcase]
|
||||||
|
end
|
||||||
|
|
||||||
|
# @private
|
||||||
|
sig { params(token: String).returns(T.nilable([T.attached_class, String])) }
|
||||||
|
def self.with_cask_token(token)
|
||||||
|
return unless (match = token.match(HOMEBREW_TAP_CASK_REGEX))
|
||||||
|
|
||||||
|
user = T.must(match[:user])
|
||||||
|
repo = T.must(match[:repo])
|
||||||
|
token = T.must(match[:token])
|
||||||
|
|
||||||
|
# Relative paths are not taps.
|
||||||
|
return if [user, repo].intersect?([".", ".."])
|
||||||
|
|
||||||
|
tap = fetch(user, repo)
|
||||||
|
[tap, token.downcase]
|
||||||
|
end
|
||||||
|
|
||||||
sig { returns(CoreCaskTap) }
|
sig { returns(CoreCaskTap) }
|
||||||
def self.default_cask_tap
|
def self.default_cask_tap
|
||||||
odisabled "`Tap.default_cask_tap`", "`CoreCaskTap.instance`"
|
odisabled "`Tap.default_cask_tap`", "`CoreCaskTap.instance`"
|
||||||
|
@ -535,6 +535,22 @@ RSpec.describe Formulary do
|
|||||||
end
|
end
|
||||||
|
|
||||||
describe "::loader_for" do
|
describe "::loader_for" do
|
||||||
|
context "when given a relative path with two slashes" do
|
||||||
|
it "returns a `FromPathLoader`" do
|
||||||
|
mktmpdir.cd do
|
||||||
|
FileUtils.mkdir "Formula"
|
||||||
|
FileUtils.touch "Formula/gcc.rb"
|
||||||
|
expect(described_class.loader_for("./Formula/gcc.rb")).to be_a Formulary::FromPathLoader
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when given a tapped name" do
|
||||||
|
it "returns a `FromTapLoader`" do
|
||||||
|
expect(described_class.loader_for("homebrew/core/gcc")).to be_a Formulary::FromTapLoader
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context "when not using the API" do
|
context "when not using the API" do
|
||||||
before do
|
before do
|
||||||
ENV["HOMEBREW_NO_INSTALL_FROM_API"] = "1"
|
ENV["HOMEBREW_NO_INSTALL_FROM_API"] = "1"
|
||||||
|
@ -599,4 +599,24 @@ RSpec.describe Tap do
|
|||||||
expect(described_class.fetch("my", "tap-with-@-symbol").repo_var_suffix).to eq "_MY_HOMEBREW_TAP_WITH___SYMBOL"
|
expect(described_class.fetch("my", "tap-with-@-symbol").repo_var_suffix).to eq "_MY_HOMEBREW_TAP_WITH___SYMBOL"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "::with_formula_name" do
|
||||||
|
it "returns the tap and formula name when given a full name" do
|
||||||
|
expect(described_class.with_formula_name("homebrew/core/gcc")).to eq [CoreTap.instance, "gcc"]
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns nil when given a relative path" do
|
||||||
|
expect(described_class.with_formula_name("./Formula/gcc.rb")).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "::with_cask_token" do
|
||||||
|
it "returns the tap and cask token when given a full token" do
|
||||||
|
expect(described_class.with_cask_token("homebrew/cask/alfred")).to eq [CoreCaskTap.instance, "alfred"]
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns nil when given a relative path" do
|
||||||
|
expect(described_class.with_cask_token("./Casks/alfred.rb")).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user