Merge branch 'Homebrew:master' into mohammad

This commit is contained in:
Mohammad Zain Abbas 2022-08-23 14:27:47 +02:00 committed by GitHub
commit 461ae71229
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
112 changed files with 7886 additions and 6224 deletions

View File

@ -21,6 +21,7 @@ Metrics/BlockLength:
# TODO: extract more of the bottling logic
- "dev-cmd/bottle.rb"
- "test/**/*"
- "cmd/install.rb"
Metrics/BlockNesting:
Max: 5
Metrics/ClassLength:

View File

@ -2,7 +2,11 @@
source "https://rubygems.org"
ruby ">= 2.6.0"
if ENV.fetch("HOMEBREW_DEVELOPER", "").empty? || ENV.fetch("HOMEBREW_USE_RUBY_FROM_PATH", "").empty?
ruby "~> 2.6.0"
else
ruby ">= 2.6.0"
end
# disallowed gems (should not be used)
# * nokogiri - use rexml instead for XML parsing

View File

@ -7,8 +7,8 @@ GEM
minitest (>= 5.1)
tzinfo (~> 2.0)
zeitwerk (~> 2.3)
addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
addressable (2.8.1)
public_suffix (>= 2.0.2, < 6.0)
ast (2.4.2)
bindata (2.4.10)
bootsnap (1.13.0)
@ -57,8 +57,8 @@ GEM
mime-types-data (~> 3.2015)
mime-types-data (3.2022.0105)
mini_portile2 (2.8.0)
minitest (5.16.2)
msgpack (1.5.4)
minitest (5.16.3)
msgpack (1.5.5)
mustache (1.1.1)
net-http-digest_auth (1.4.1)
net-http-persistent (4.0.1)
@ -82,7 +82,7 @@ GEM
pry (0.14.1)
coderay (~> 1.1)
method_source (~> 1.0)
public_suffix (4.0.7)
public_suffix (5.0.0)
racc (1.6.0)
rack (2.2.4)
rainbow (3.1.1)
@ -124,14 +124,14 @@ GEM
rspec (>= 3, < 4)
rspec_junit_formatter (0.5.1)
rspec-core (>= 2, < 4, != 2.12.0)
rubocop (1.34.1)
rubocop (1.35.1)
json (~> 2.3)
parallel (~> 1.10)
parser (>= 3.1.2.1)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.20.0, < 2.0)
rubocop-ast (>= 1.20.1, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 3.0)
rubocop-ast (1.21.0)
@ -170,7 +170,7 @@ GEM
sorbet (>= 0.5.9204)
sorbet-runtime (>= 0.5.9204)
thor (>= 0.19.2)
tapioca (0.7.2)
tapioca (0.7.3)
bundler (>= 1.17.3)
pry (>= 0.12.2)
rbi (~> 0.0.0, >= 0.0.14)

View File

@ -79,10 +79,11 @@ class Build
ENV.deps = formula_deps
ENV.run_time_deps = run_time_deps
ENV.setup_build_environment(
formula: formula,
cc: args.cc,
build_bottle: args.build_bottle?,
bottle_arch: args.bottle_arch,
formula: formula,
cc: args.cc,
build_bottle: args.build_bottle?,
bottle_arch: args.bottle_arch,
debug_symbols: args.debug_symbols?,
)
reqs.each do |req|
req.modify_build_environment(
@ -92,10 +93,11 @@ class Build
deps.each(&:modify_build_environment)
else
ENV.setup_build_environment(
formula: formula,
cc: args.cc,
build_bottle: args.build_bottle?,
bottle_arch: args.bottle_arch,
formula: formula,
cc: args.cc,
build_bottle: args.build_bottle?,
bottle_arch: args.bottle_arch,
debug_symbols: args.debug_symbols?,
)
reqs.each do |req|
req.modify_build_environment(
@ -127,9 +129,10 @@ class Build
formula.update_head_version
formula.brew(
fetch: false,
keep_tmp: args.keep_tmp?,
interactive: args.interactive?,
fetch: false,
keep_tmp: args.keep_tmp?,
debug_symbols: args.debug_symbols?,
interactive: args.interactive?,
) do
with_env(
# For head builds, HOMEBREW_FORMULA_PREFIX should include the commit,

View File

@ -55,22 +55,23 @@ class BuildEnvironment
].freeze
private_constant :KEYS
sig { params(env: T.untyped).returns(T::Array[String]) }
sig { params(env: T::Hash[String, T.nilable(T.any(String, Pathname))]).returns(T::Array[String]) }
def self.keys(env)
KEYS & env.keys
end
sig { params(env: T.untyped, f: IO).void }
sig { params(env: T::Hash[String, T.nilable(T.any(String, Pathname))], f: IO).void }
def self.dump(env, f = $stdout)
keys = self.keys(env)
keys -= %w[CC CXX OBJC OBJCXX] if env["CC"] == env["HOMEBREW_CC"]
keys.each do |key|
value = env.fetch(key)
s = +"#{key}: #{value}"
case key
when "CC", "CXX", "LD"
s << " => #{Pathname.new(value).realpath}" if File.symlink?(value)
s << " => #{Pathname.new(value).realpath}" if value.present? && File.symlink?(value)
end
s.freeze
f.puts s

View File

@ -20,28 +20,31 @@ module Cask
attr_reader :cask, :download
attr_predicate :appcast?, :new_cask?, :strict?, :online?, :token_conflicts?
attr_predicate :appcast?, :new_cask?, :strict?, :signing?, :online?, :token_conflicts?
def initialize(cask, appcast: nil, download: nil, quarantine: nil,
token_conflicts: nil, online: nil, strict: nil,
token_conflicts: nil, online: nil, strict: nil, signing: nil,
new_cask: nil)
# `new_cask` implies `online` and `strict`
# `new_cask` implies `online`, `token_conflicts`, `strict` and `signing`
online = new_cask if online.nil?
strict = new_cask if strict.nil?
signing = new_cask if signing.nil?
token_conflicts = new_cask if token_conflicts.nil?
# `online` implies `appcast` and `download`
appcast = online if appcast.nil?
download = online if download.nil?
# `new_cask` implies `token_conflicts`
token_conflicts = new_cask if token_conflicts.nil?
# `signing` implies `download`
download = signing if download.nil?
@cask = cask
@appcast = appcast
@download = Download.new(cask, quarantine: quarantine) if download
@online = online
@strict = strict
@signing = signing
@new_cask = new_cask
@token_conflicts = token_conflicts
end
@ -81,6 +84,7 @@ module Cask
check_github_repository_archived
check_github_prerelease_version
check_bitbucket_repository
check_signing
self
rescue => e
odebug e, e.backtrace
@ -550,6 +554,38 @@ module Cask
add_error "download not possible: #{e}"
end
def check_signing
return if !signing? || download.blank? || cask.url.blank?
odebug "Auditing signing"
odebug cask.artifacts
artifacts = cask.artifacts.select { |k| k.is_a?(Artifact::Pkg) || k.is_a?(Artifact::App) }
return if artifacts.empty?
downloaded_path = download.fetch
primary_container = UnpackStrategy.detect(downloaded_path, type: @cask.container&.type, merge_xattrs: true)
return if primary_container.nil?
Dir.mktmpdir do |tmpdir|
tmpdir = Pathname(tmpdir)
primary_container.extract_nestedly(to: tmpdir, basename: downloaded_path.basename, verbose: false)
artifacts.each do |artifact|
path = case artifact
when Artifact::Moved
tmpdir/artifact.source.basename
when Artifact::Pkg
artifact.path
end
next unless path.exist?
result = system_command("codesign", args: ["--verify", path], print_stderr: false)
add_warning result.merged_output unless result.success?
end
end
end
def check_livecheck_version
return unless appcast?

View File

@ -15,6 +15,7 @@ module Cask
audit_online: nil,
audit_new_cask: nil,
audit_strict: nil,
audit_signing: nil,
audit_token_conflicts: nil,
quarantine: nil,
any_named_args: nil,
@ -29,6 +30,7 @@ module Cask
audit_online: audit_online,
audit_new_cask: audit_new_cask,
audit_strict: audit_strict,
audit_signing: audit_signing,
audit_token_conflicts: audit_token_conflicts,
quarantine: quarantine,
any_named_args: any_named_args,
@ -46,6 +48,7 @@ module Cask
audit_appcast: nil,
audit_online: nil,
audit_strict: nil,
audit_signing: nil,
audit_token_conflicts: nil,
audit_new_cask: nil,
quarantine: nil,
@ -60,6 +63,7 @@ module Cask
@audit_online = audit_online
@audit_new_cask = audit_new_cask
@audit_strict = audit_strict
@audit_signing = audit_signing
@quarantine = quarantine
@audit_token_conflicts = audit_token_conflicts
@any_named_args = any_named_args
@ -133,6 +137,7 @@ module Cask
appcast: @audit_appcast,
online: @audit_online,
strict: @audit_strict,
signing: @audit_signing,
new_cask: @audit_new_cask,
token_conflicts: @audit_token_conflicts,
download: @audit_download,

View File

@ -19,6 +19,8 @@ module Cask
description: "Audit the appcast"
switch "--[no-]token-conflicts",
description: "Audit for token conflicts"
switch "--[no-]signing",
description: "Audit for signed apps, which is required on ARM"
switch "--[no-]strict",
description: "Run additional, stricter style checks"
switch "--[no-]online",
@ -50,6 +52,7 @@ module Cask
appcast: args.appcast?,
online: args.online?,
strict: args.strict?,
signing: args.signing?,
new_cask: args.new_cask?,
token_conflicts: args.token_conflicts?,
quarantine: args.quarantine?,
@ -71,6 +74,7 @@ module Cask
appcast: nil,
online: nil,
strict: nil,
signing: nil,
new_cask: nil,
token_conflicts: nil,
quarantine: nil,
@ -84,6 +88,7 @@ module Cask
audit_appcast: appcast,
audit_online: online,
audit_strict: strict,
audit_signing: signing,
audit_new_cask: new_cask,
audit_token_conflicts: token_conflicts,
quarantine: quarantine,

View File

@ -79,7 +79,7 @@ module Cask
end
def self.title_info(cask)
title = "#{cask.token}: #{cask.version}"
title = "#{oh1_title(cask.token)}: #{cask.version}"
title += " (auto_updates)" if cask.auto_updates
title
end

View File

@ -230,8 +230,13 @@ module Cask
end
# @api public
def sha256(arg = nil)
set_unique_stanza(:sha256, arg.nil?) do
def sha256(arg = nil, arm: nil, intel: nil)
should_return = arg.nil? && arm.nil? && intel.nil?
set_unique_stanza(:sha256, should_return) do
@on_system_blocks_exist = true if arm.present? || intel.present?
arg ||= on_arch_conditional(arm: arm, intel: intel)
case arg
when :no_check
arg
@ -245,7 +250,7 @@ module Cask
# @api public
def arch(arm: nil, intel: nil)
should_return = arm.blank? && intel.blank?
should_return = arm.nil? && intel.nil?
set_unique_stanza(:arch, should_return) do
@on_system_blocks_exist = true

View File

@ -150,20 +150,6 @@ module Cask
version { split(",", 2).second }
end
# @api public
sig { returns(T.self_type) }
def before_colon
odisabled "Cask::DSL::Version#before_colon", "Cask::DSL::Version#csv"
version { split(":", 2).first }
end
# @api public
sig { returns(T.self_type) }
def after_colon
odisabled "Cask::DSL::Version#after_colon", "Cask::DSL::Version#csv"
version { split(":", 2).second }
end
# @api public
sig { returns(T.self_type) }
def no_dividers

View File

@ -189,8 +189,8 @@ module Homebrew
def self.skip_clean_formula?(f)
return false if Homebrew::EnvConfig.no_cleanup_formulae.blank?
skip_clean_formulae = Homebrew::EnvConfig.no_cleanup_formulae.split(",")
skip_clean_formulae.include?(f.name) || (skip_clean_formulae & f.aliases).present?
@skip_clean_formulae ||= Homebrew::EnvConfig.no_cleanup_formulae.split(",")
@skip_clean_formulae.include?(f.name) || (@skip_clean_formulae & f.aliases).present?
end
def self.periodic_clean_due?
@ -428,7 +428,6 @@ module Homebrew
next if !use_system_ruby && portable_ruby_latest_version == path.basename.to_s
portable_rubies_to_remove << path
puts "Would remove: #{path} (#{path.abv})" if dry_run?
end
return if portable_rubies_to_remove.empty?
@ -440,20 +439,16 @@ module Homebrew
puts Utils.popen_read("git", "-C", HOMEBREW_REPOSITORY, "clean", "-ffqx", bundler_path).chomp
end
return if dry_run?
FileUtils.rm_rf portable_rubies_to_remove
portable_rubies_to_remove.each do |portable_ruby|
cleanup_path(portable_ruby) { portable_ruby.rmtree }
end
end
def cleanup_bootsnap
bootsnap = cache/"bootsnap"
return unless bootsnap.exist?
if dry_run?
puts "Would remove: #{bootsnap} (#{bootsnap.abv})"
else
FileUtils.rm_rf bootsnap
end
cleanup_path(bootsnap) { bootsnap.rmtree }
end
def cleanup_cache_db(rack = nil)
@ -540,8 +535,12 @@ module Homebrew
# the cache of installed formulae may no longer be valid.
Formula.clear_cache unless dry_run
# Remove formulae listed in HOMEBREW_NO_CLEANUP_FORMULAE.
formulae = Formula.installed.reject(&method(:skip_clean_formula?))
formulae = Formula.installed
# Remove formulae listed in HOMEBREW_NO_CLEANUP_FORMULAE and their dependencies.
if Homebrew::EnvConfig.no_cleanup_formulae.present?
formulae -= formulae.select(&method(:skip_clean_formula?))
.flat_map { |f| [f, *f.runtime_formula_dependencies] }
end
casks = Cask::Caskroom.casks
removable_formulae = Formula.unused_formulae_with_no_dependents(formulae, casks)

View File

@ -90,6 +90,9 @@ module Homebrew
sig { returns(T::Boolean) }
def keep_tmp?; end
sig { returns(T::Boolean) }
def debug_symbols?; end
sig { returns(T::Boolean) }
def overwrite?; end

View File

@ -51,7 +51,7 @@ module Homebrew
if shell.nil?
BuildEnvironment.dump ENV
else
BuildEnvironment.keys(ENV).each do |key|
BuildEnvironment.keys(ENV.to_h).each do |key|
puts Utils::Shell.export_value(key, ENV.fetch(key), shell)
end
end

View File

@ -274,7 +274,7 @@ module Homebrew
attrs << "pinned at #{f.pinned_version}" if f.pinned?
attrs << "keg-only" if f.keg_only?
puts "#{f.full_name}: #{specs * ", "}#{" [#{attrs * ", "}]" unless attrs.empty?}"
puts "#{oh1_title(f.full_name)}: #{specs * ", "}#{" [#{attrs * ", "}]" unless attrs.empty?}"
puts f.desc if f.desc
puts Formatter.url(f.homepage) if f.homepage

View File

@ -91,6 +91,10 @@ module Homebrew
[:switch, "--keep-tmp", {
description: "Retain the temporary files created during installation.",
}],
[:switch, "--debug-symbols", {
depends_on: "--build-from-source",
description: "Generate debug symbols on build. Source will be retained in a cache directory. ",
}],
[:switch, "--build-bottle", {
description: "Prepare the formula for eventual bottling during installation, skipping any " \
"post-install steps.",
@ -232,6 +236,7 @@ module Homebrew
git: args.git?,
interactive: args.interactive?,
keep_tmp: args.keep_tmp?,
debug_symbols: args.debug_symbols?,
force: args.force?,
overwrite: args.overwrite?,
debug: args.debug?,
@ -247,6 +252,7 @@ module Homebrew
build_from_source_formulae: args.build_from_source_formulae,
interactive: args.interactive?,
keep_tmp: args.keep_tmp?,
debug_symbols: args.debug_symbols?,
force: args.force?,
debug: args.debug?,
quiet: args.quiet?,

View File

@ -70,14 +70,6 @@ module Homebrew
def list
args = list_args.parse
# Unbrewed uses the PREFIX, which will exist
# Things below use the CELLAR, which doesn't until the first formula is installed.
unless HOMEBREW_CELLAR.exist?
raise NoSuchKegError, args.named.first if args.named.present? && !args.cask?
return
end
if args.full_name?
unless args.cask?
formula_names = args.no_named? ? Formula.installed : args.named.to_resolved_formulae
@ -112,12 +104,10 @@ module Homebrew
if !args.cask? && HOMEBREW_CELLAR.exist? && HOMEBREW_CELLAR.children.any?
ohai "Formulae" if $stdout.tty? && !args.formula?
safe_system "ls", *ls_args, HOMEBREW_CELLAR
puts if $stdout.tty? && !args.formula?
end
if !args.formula? && Cask::Caskroom.any_casks_installed?
if $stdout.tty? && !args.cask?
puts
ohai "Casks"
end
ohai "Casks" if $stdout.tty? && !args.cask?
safe_system "ls", *ls_args, Cask::Caskroom.path
end
else

View File

@ -57,6 +57,10 @@ module Homebrew
[:switch, "--keep-tmp", {
description: "Retain the temporary files created during installation.",
}],
[:switch, "--debug-symbols", {
depends_on: "--build-from-source",
description: "Generate debug symbols on build. Source will be retained in a cache directory. ",
}],
[:switch, "--display-times", {
env: :display_install_times,
description: "Print install times for each formula at the end of the run.",
@ -115,6 +119,7 @@ module Homebrew
build_from_source_formulae: args.build_from_source_formulae,
interactive: args.interactive?,
keep_tmp: args.keep_tmp?,
debug_symbols: args.debug_symbols?,
force: args.force?,
debug: args.debug?,
quiet: args.quiet?,
@ -132,6 +137,7 @@ module Homebrew
build_from_source_formulae: args.build_from_source_formulae,
interactive: args.interactive?,
keep_tmp: args.keep_tmp?,
debug_symbols: args.debug_symbols?,
force: args.force?,
debug: args.debug?,
quiet: args.quiet?,

View File

@ -68,6 +68,10 @@ module Homebrew
[:switch, "--keep-tmp", {
description: "Retain the temporary files created during installation.",
}],
[:switch, "--debug-symbols", {
depends_on: "--build-from-source",
description: "Generate debug symbols on build. Source will be retained in a cache directory. ",
}],
[:switch, "--display-times", {
env: :display_install_times,
description: "Print install times for each package at the end of the run.",
@ -187,6 +191,7 @@ module Homebrew
build_from_source_formulae: args.build_from_source_formulae,
interactive: args.interactive?,
keep_tmp: args.keep_tmp?,
debug_symbols: args.debug_symbols?,
force: args.force?,
debug: args.debug?,
quiet: args.quiet?,
@ -202,6 +207,7 @@ module Homebrew
build_from_source_formulae: args.build_from_source_formulae,
interactive: args.interactive?,
keep_tmp: args.keep_tmp?,
debug_symbols: args.debug_symbols?,
force: args.force?,
debug: args.debug?,
quiet: args.quiet?,

View File

@ -1,21 +1,2 @@
# typed: true
# frozen_string_literal: true
module Cask
class Cask
extend Enumerable
def self.each(&block)
odisabled "`Enumerable` methods on `Cask::Cask`",
"`Cask::Cask.all` (but avoid looping over all casks, it's slow and insecure)"
return to_enum unless block
Tap.flat_map(&:cask_files).each do |f|
yield CaskLoader::FromTapPathLoader.new(f).load(config: nil)
rescue CaskUnreadableError => e
opoo e.message
end
end
end
end

View File

@ -1,20 +1,2 @@
# typed: true
# frozen_string_literal: true
class Formula
extend Enumerable
def self.each(&_block)
odisabled "`Enumerable` methods on `Formula`",
"`Formula.all` (but avoid looping over all formulae, it's slow and insecure)"
files.each do |file|
yield Formulary.factory(file)
rescue FormulaUnavailableError, FormulaUnreadableError => e
# Don't let one broken formula break commands. But do complain.
onoe "Failed to import: #{file}"
$stderr.puts e
next
end
end
end

View File

@ -172,7 +172,7 @@ class CompilerSelector
def compiler_version(name)
case name.to_s
when "gcc", GNU_GCC_REGEXP
versions.non_apple_gcc_version(name.to_s)
versions.gcc_version(name.to_s)
else
versions.send("#{name}_build_version")
end

View File

@ -1,22 +1,55 @@
{
"licenseListVersion": "3.17",
"licenseListVersion": "3.18",
"exceptions": [
{
"reference": "./FLTK-exception.json",
"reference": "./Qt-GPL-exception-1.0.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./FLTK-exception.html",
"detailsUrl": "./Qt-GPL-exception-1.0.html",
"referenceNumber": 1,
"name": "FLTK exception",
"licenseExceptionId": "FLTK-exception",
"name": "Qt GPL exception 1.0",
"licenseExceptionId": "Qt-GPL-exception-1.0",
"seeAlso": [
"http://www.fltk.org/COPYING.php"
"http://code.qt.io/cgit/qt/qtbase.git/tree/LICENSE.GPL3-EXCEPT"
]
},
{
"reference": "./Fawkes-Runtime-exception.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./Fawkes-Runtime-exception.html",
"referenceNumber": 2,
"name": "Fawkes Runtime Exception",
"licenseExceptionId": "Fawkes-Runtime-exception",
"seeAlso": [
"http://www.fawkesrobotics.org/about/license/"
]
},
{
"reference": "./openvpn-openssl-exception.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./openvpn-openssl-exception.html",
"referenceNumber": 3,
"name": "OpenVPN OpenSSL Exception",
"licenseExceptionId": "openvpn-openssl-exception",
"seeAlso": [
"http://openvpn.net/index.php/license.html"
]
},
{
"reference": "./DigiRule-FOSS-exception.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./DigiRule-FOSS-exception.html",
"referenceNumber": 4,
"name": "DigiRule FOSS License Exception",
"licenseExceptionId": "DigiRule-FOSS-exception",
"seeAlso": [
"http://www.digirulesolutions.com/drupal/foss"
]
},
{
"reference": "./Bootloader-exception.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./Bootloader-exception.html",
"referenceNumber": 2,
"referenceNumber": 5,
"name": "Bootloader Distribution Exception",
"licenseExceptionId": "Bootloader-exception",
"seeAlso": [
@ -24,87 +57,21 @@
]
},
{
"reference": "./WxWindows-exception-3.1.json",
"reference": "./OpenJDK-assembly-exception-1.0.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./WxWindows-exception-3.1.html",
"referenceNumber": 3,
"name": "WxWindows Library Exception 3.1",
"licenseExceptionId": "WxWindows-exception-3.1",
"seeAlso": [
"http://www.opensource.org/licenses/WXwindows"
]
},
{
"reference": "./Linux-syscall-note.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./Linux-syscall-note.html",
"referenceNumber": 4,
"name": "Linux Syscall Note",
"licenseExceptionId": "Linux-syscall-note",
"seeAlso": [
"https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/COPYING"
]
},
{
"reference": "./Qt-LGPL-exception-1.1.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./Qt-LGPL-exception-1.1.html",
"referenceNumber": 5,
"name": "Qt LGPL exception 1.1",
"licenseExceptionId": "Qt-LGPL-exception-1.1",
"seeAlso": [
"http://code.qt.io/cgit/qt/qtbase.git/tree/LGPL_EXCEPTION.txt"
]
},
{
"reference": "./LLVM-exception.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./LLVM-exception.html",
"detailsUrl": "./OpenJDK-assembly-exception-1.0.html",
"referenceNumber": 6,
"name": "LLVM Exception",
"licenseExceptionId": "LLVM-exception",
"name": "OpenJDK Assembly exception 1.0",
"licenseExceptionId": "OpenJDK-assembly-exception-1.0",
"seeAlso": [
"http://llvm.org/foundation/relicensing/LICENSE.txt"
]
},
{
"reference": "./PS-or-PDF-font-exception-20170817.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./PS-or-PDF-font-exception-20170817.html",
"referenceNumber": 7,
"name": "PS/PDF font exception (2017-08-17)",
"licenseExceptionId": "PS-or-PDF-font-exception-20170817",
"seeAlso": [
"https://github.com/ArtifexSoftware/urw-base35-fonts/blob/65962e27febc3883a17e651cdb23e783668c996f/LICENSE"
]
},
{
"reference": "./GCC-exception-3.1.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./GCC-exception-3.1.html",
"referenceNumber": 8,
"name": "GCC Runtime Library exception 3.1",
"licenseExceptionId": "GCC-exception-3.1",
"seeAlso": [
"http://www.gnu.org/licenses/gcc-exception-3.1.html"
]
},
{
"reference": "./Autoconf-exception-3.0.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./Autoconf-exception-3.0.html",
"referenceNumber": 9,
"name": "Autoconf exception 3.0",
"licenseExceptionId": "Autoconf-exception-3.0",
"seeAlso": [
"http://www.gnu.org/licenses/autoconf-exception-3.0.html"
"http://openjdk.java.net/legal/assembly-exception.html"
]
},
{
"reference": "./LGPL-3.0-linking-exception.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./LGPL-3.0-linking-exception.html",
"referenceNumber": 10,
"referenceNumber": 7,
"name": "LGPL-3.0 Linking Exception",
"licenseExceptionId": "LGPL-3.0-linking-exception",
"seeAlso": [
@ -114,21 +81,21 @@
]
},
{
"reference": "./GCC-exception-2.0.json",
"reference": "./u-boot-exception-2.0.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./GCC-exception-2.0.html",
"referenceNumber": 11,
"name": "GCC Runtime Library exception 2.0",
"licenseExceptionId": "GCC-exception-2.0",
"detailsUrl": "./u-boot-exception-2.0.html",
"referenceNumber": 8,
"name": "U-Boot exception 2.0",
"licenseExceptionId": "u-boot-exception-2.0",
"seeAlso": [
"https://gcc.gnu.org/git/?p\u003dgcc.git;a\u003dblob;f\u003dgcc/libgcc1.c;h\u003d762f5143fc6eed57b6797c82710f3538aa52b40b;hb\u003dcb143a3ce4fb417c68f5fa2691a1b1b1053dfba9#l10"
"http://git.denx.de/?p\u003du-boot.git;a\u003dblob;f\u003dLicenses/Exceptions"
]
},
{
"reference": "./Bison-exception-2.2.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./Bison-exception-2.2.html",
"referenceNumber": 12,
"referenceNumber": 9,
"name": "Bison exception 2.2",
"licenseExceptionId": "Bison-exception-2.2",
"seeAlso": [
@ -136,37 +103,70 @@
]
},
{
"reference": "./openvpn-openssl-exception.json",
"reference": "./OCaml-LGPL-linking-exception.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./openvpn-openssl-exception.html",
"detailsUrl": "./OCaml-LGPL-linking-exception.html",
"referenceNumber": 10,
"name": "OCaml LGPL Linking Exception",
"licenseExceptionId": "OCaml-LGPL-linking-exception",
"seeAlso": [
"https://caml.inria.fr/ocaml/license.en.html"
]
},
{
"reference": "./Swift-exception.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./Swift-exception.html",
"referenceNumber": 11,
"name": "Swift Exception",
"licenseExceptionId": "Swift-exception",
"seeAlso": [
"https://swift.org/LICENSE.txt",
"https://github.com/apple/swift-package-manager/blob/7ab2275f447a5eb37497ed63a9340f8a6d1e488b/LICENSE.txt#L205"
]
},
{
"reference": "./CLISP-exception-2.0.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./CLISP-exception-2.0.html",
"referenceNumber": 12,
"name": "CLISP exception 2.0",
"licenseExceptionId": "CLISP-exception-2.0",
"seeAlso": [
"http://sourceforge.net/p/clisp/clisp/ci/default/tree/COPYRIGHT"
]
},
{
"reference": "./Qwt-exception-1.0.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./Qwt-exception-1.0.html",
"referenceNumber": 13,
"name": "OpenVPN OpenSSL Exception",
"licenseExceptionId": "openvpn-openssl-exception",
"name": "Qwt exception 1.0",
"licenseExceptionId": "Qwt-exception-1.0",
"seeAlso": [
"http://openvpn.net/index.php/license.html"
"http://qwt.sourceforge.net/qwtlicense.html"
]
},
{
"reference": "./Libtool-exception.json",
"reference": "./Universal-FOSS-exception-1.0.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./Libtool-exception.html",
"detailsUrl": "./Universal-FOSS-exception-1.0.html",
"referenceNumber": 14,
"name": "Libtool Exception",
"licenseExceptionId": "Libtool-exception",
"name": "Universal FOSS Exception, Version 1.0",
"licenseExceptionId": "Universal-FOSS-exception-1.0",
"seeAlso": [
"http://git.savannah.gnu.org/cgit/libtool.git/tree/m4/libtool.m4"
"https://oss.oracle.com/licenses/universal-foss-exception/"
]
},
{
"reference": "./Autoconf-exception-2.0.json",
"reference": "./LLVM-exception.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./Autoconf-exception-2.0.html",
"detailsUrl": "./LLVM-exception.html",
"referenceNumber": 15,
"name": "Autoconf exception 2.0",
"licenseExceptionId": "Autoconf-exception-2.0",
"name": "LLVM Exception",
"licenseExceptionId": "LLVM-exception",
"seeAlso": [
"http://ac-archive.sourceforge.net/doc/copyright.html",
"http://ftp.gnu.org/gnu/autoconf/autoconf-2.59.tar.gz"
"http://llvm.org/foundation/relicensing/LICENSE.txt"
]
},
{
@ -181,11 +181,267 @@
"https://github.com/mirror/wget/blob/master/src/http.c#L20"
]
},
{
"reference": "./GStreamer-exception-2008.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./GStreamer-exception-2008.html",
"referenceNumber": 17,
"name": "GStreamer Exception (2008)",
"licenseExceptionId": "GStreamer-exception-2008",
"seeAlso": [
"https://gstreamer.freedesktop.org/documentation/frequently-asked-questions/licensing.html?gi-language\u003dc#licensing-of-applications-using-gstreamer"
]
},
{
"reference": "./FLTK-exception.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./FLTK-exception.html",
"referenceNumber": 18,
"name": "FLTK exception",
"licenseExceptionId": "FLTK-exception",
"seeAlso": [
"http://www.fltk.org/COPYING.php"
]
},
{
"reference": "./GPL-3.0-linking-exception.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./GPL-3.0-linking-exception.html",
"referenceNumber": 19,
"name": "GPL-3.0 Linking Exception",
"licenseExceptionId": "GPL-3.0-linking-exception",
"seeAlso": [
"https://www.gnu.org/licenses/gpl-faq.en.html#GPLIncompatibleLibs"
]
},
{
"reference": "./Qt-LGPL-exception-1.1.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./Qt-LGPL-exception-1.1.html",
"referenceNumber": 20,
"name": "Qt LGPL exception 1.1",
"licenseExceptionId": "Qt-LGPL-exception-1.1",
"seeAlso": [
"http://code.qt.io/cgit/qt/qtbase.git/tree/LGPL_EXCEPTION.txt"
]
},
{
"reference": "./Classpath-exception-2.0.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./Classpath-exception-2.0.html",
"referenceNumber": 21,
"name": "Classpath exception 2.0",
"licenseExceptionId": "Classpath-exception-2.0",
"seeAlso": [
"http://www.gnu.org/software/classpath/license.html",
"https://fedoraproject.org/wiki/Licensing/GPL_Classpath_Exception"
]
},
{
"reference": "./Nokia-Qt-exception-1.1.json",
"isDeprecatedLicenseId": true,
"detailsUrl": "./Nokia-Qt-exception-1.1.html",
"referenceNumber": 22,
"name": "Nokia Qt LGPL exception 1.1",
"licenseExceptionId": "Nokia-Qt-exception-1.1",
"seeAlso": [
"https://www.keepassx.org/dev/projects/keepassx/repository/revisions/b8dfb9cc4d5133e0f09cd7533d15a4f1c19a40f2/entry/LICENSE.NOKIA-LGPL-EXCEPTION"
]
},
{
"reference": "./389-exception.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./389-exception.html",
"referenceNumber": 23,
"name": "389 Directory Server Exception",
"licenseExceptionId": "389-exception",
"seeAlso": [
"http://directory.fedoraproject.org/wiki/GPL_Exception_License_Text",
"https://web.archive.org/web/20080828121337/http://directory.fedoraproject.org/wiki/GPL_Exception_License_Text"
]
},
{
"reference": "./Font-exception-2.0.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./Font-exception-2.0.html",
"referenceNumber": 24,
"name": "Font exception 2.0",
"licenseExceptionId": "Font-exception-2.0",
"seeAlso": [
"http://www.gnu.org/licenses/gpl-faq.html#FontException"
]
},
{
"reference": "./GStreamer-exception-2005.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./GStreamer-exception-2005.html",
"referenceNumber": 25,
"name": "GStreamer Exception (2005)",
"licenseExceptionId": "GStreamer-exception-2005",
"seeAlso": [
"https://gstreamer.freedesktop.org/documentation/frequently-asked-questions/licensing.html?gi-language\u003dc#licensing-of-applications-using-gstreamer"
]
},
{
"reference": "./SHL-2.0.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./SHL-2.0.html",
"referenceNumber": 26,
"name": "Solderpad Hardware License v2.0",
"licenseExceptionId": "SHL-2.0",
"seeAlso": [
"https://solderpad.org/licenses/SHL-2.0/"
]
},
{
"reference": "./WxWindows-exception-3.1.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./WxWindows-exception-3.1.html",
"referenceNumber": 27,
"name": "WxWindows Library Exception 3.1",
"licenseExceptionId": "WxWindows-exception-3.1",
"seeAlso": [
"http://www.opensource.org/licenses/WXwindows"
]
},
{
"reference": "./Autoconf-exception-3.0.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./Autoconf-exception-3.0.html",
"referenceNumber": 28,
"name": "Autoconf exception 3.0",
"licenseExceptionId": "Autoconf-exception-3.0",
"seeAlso": [
"http://www.gnu.org/licenses/autoconf-exception-3.0.html"
]
},
{
"reference": "./PS-or-PDF-font-exception-20170817.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./PS-or-PDF-font-exception-20170817.html",
"referenceNumber": 29,
"name": "PS/PDF font exception (2017-08-17)",
"licenseExceptionId": "PS-or-PDF-font-exception-20170817",
"seeAlso": [
"https://github.com/ArtifexSoftware/urw-base35-fonts/blob/65962e27febc3883a17e651cdb23e783668c996f/LICENSE"
]
},
{
"reference": "./Autoconf-exception-2.0.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./Autoconf-exception-2.0.html",
"referenceNumber": 30,
"name": "Autoconf exception 2.0",
"licenseExceptionId": "Autoconf-exception-2.0",
"seeAlso": [
"http://ac-archive.sourceforge.net/doc/copyright.html",
"http://ftp.gnu.org/gnu/autoconf/autoconf-2.59.tar.gz"
]
},
{
"reference": "./SHL-2.1.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./SHL-2.1.html",
"referenceNumber": 31,
"name": "Solderpad Hardware License v2.1",
"licenseExceptionId": "SHL-2.1",
"seeAlso": [
"https://solderpad.org/licenses/SHL-2.1/"
]
},
{
"reference": "./LZMA-exception.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./LZMA-exception.html",
"referenceNumber": 32,
"name": "LZMA exception",
"licenseExceptionId": "LZMA-exception",
"seeAlso": [
"http://nsis.sourceforge.net/Docs/AppendixI.html#I.6"
]
},
{
"reference": "./GCC-exception-2.0.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./GCC-exception-2.0.html",
"referenceNumber": 33,
"name": "GCC Runtime Library exception 2.0",
"licenseExceptionId": "GCC-exception-2.0",
"seeAlso": [
"https://gcc.gnu.org/git/?p\u003dgcc.git;a\u003dblob;f\u003dgcc/libgcc1.c;h\u003d762f5143fc6eed57b6797c82710f3538aa52b40b;hb\u003dcb143a3ce4fb417c68f5fa2691a1b1b1053dfba9#l10"
]
},
{
"reference": "./eCos-exception-2.0.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./eCos-exception-2.0.html",
"referenceNumber": 34,
"name": "eCos exception 2.0",
"licenseExceptionId": "eCos-exception-2.0",
"seeAlso": [
"http://ecos.sourceware.org/license-overview.html"
]
},
{
"reference": "./gnu-javamail-exception.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./gnu-javamail-exception.html",
"referenceNumber": 35,
"name": "GNU JavaMail exception",
"licenseExceptionId": "gnu-javamail-exception",
"seeAlso": [
"http://www.gnu.org/software/classpathx/javamail/javamail.html"
]
},
{
"reference": "./OCCT-exception-1.0.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./OCCT-exception-1.0.html",
"referenceNumber": 36,
"name": "Open CASCADE Exception 1.0",
"licenseExceptionId": "OCCT-exception-1.0",
"seeAlso": [
"http://www.opencascade.com/content/licensing"
]
},
{
"reference": "./KiCad-libraries-exception.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./KiCad-libraries-exception.html",
"referenceNumber": 37,
"name": "KiCad Libraries Exception",
"licenseExceptionId": "KiCad-libraries-exception",
"seeAlso": [
"https://www.kicad.org/libraries/license/"
]
},
{
"reference": "./GCC-exception-3.1.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./GCC-exception-3.1.html",
"referenceNumber": 38,
"name": "GCC Runtime Library exception 3.1",
"licenseExceptionId": "GCC-exception-3.1",
"seeAlso": [
"http://www.gnu.org/licenses/gcc-exception-3.1.html"
]
},
{
"reference": "./freertos-exception-2.0.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./freertos-exception-2.0.html",
"referenceNumber": 39,
"name": "FreeRTOS Exception 2.0",
"licenseExceptionId": "freertos-exception-2.0",
"seeAlso": [
"https://web.archive.org/web/20060809182744/http://www.freertos.org/a00114.html"
]
},
{
"reference": "./GPL-CC-1.0.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./GPL-CC-1.0.html",
"referenceNumber": 17,
"referenceNumber": 40,
"name": "GPL Cooperation Commitment 1.0",
"licenseExceptionId": "GPL-CC-1.0",
"seeAlso": [
@ -193,143 +449,11 @@
"https://gplcc.github.io/gplcc/Project/README-PROJECT.html"
]
},
{
"reference": "./OCaml-LGPL-linking-exception.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./OCaml-LGPL-linking-exception.html",
"referenceNumber": 18,
"name": "OCaml LGPL Linking Exception",
"licenseExceptionId": "OCaml-LGPL-linking-exception",
"seeAlso": [
"https://caml.inria.fr/ocaml/license.en.html"
]
},
{
"reference": "./Universal-FOSS-exception-1.0.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./Universal-FOSS-exception-1.0.html",
"referenceNumber": 19,
"name": "Universal FOSS Exception, Version 1.0",
"licenseExceptionId": "Universal-FOSS-exception-1.0",
"seeAlso": [
"https://oss.oracle.com/licenses/universal-foss-exception/"
]
},
{
"reference": "./i2p-gpl-java-exception.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./i2p-gpl-java-exception.html",
"referenceNumber": 20,
"name": "i2p GPL+Java Exception",
"licenseExceptionId": "i2p-gpl-java-exception",
"seeAlso": [
"http://geti2p.net/en/get-involved/develop/licenses#java_exception"
]
},
{
"reference": "./CLISP-exception-2.0.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./CLISP-exception-2.0.html",
"referenceNumber": 21,
"name": "CLISP exception 2.0",
"licenseExceptionId": "CLISP-exception-2.0",
"seeAlso": [
"http://sourceforge.net/p/clisp/clisp/ci/default/tree/COPYRIGHT"
]
},
{
"reference": "./OCCT-exception-1.0.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./OCCT-exception-1.0.html",
"referenceNumber": 22,
"name": "Open CASCADE Exception 1.0",
"licenseExceptionId": "OCCT-exception-1.0",
"seeAlso": [
"http://www.opencascade.com/content/licensing"
]
},
{
"reference": "./Qwt-exception-1.0.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./Qwt-exception-1.0.html",
"referenceNumber": 23,
"name": "Qwt exception 1.0",
"licenseExceptionId": "Qwt-exception-1.0",
"seeAlso": [
"http://qwt.sourceforge.net/qwtlicense.html"
]
},
{
"reference": "./gnu-javamail-exception.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./gnu-javamail-exception.html",
"referenceNumber": 24,
"name": "GNU JavaMail exception",
"licenseExceptionId": "gnu-javamail-exception",
"seeAlso": [
"http://www.gnu.org/software/classpathx/javamail/javamail.html"
]
},
{
"reference": "./u-boot-exception-2.0.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./u-boot-exception-2.0.html",
"referenceNumber": 25,
"name": "U-Boot exception 2.0",
"licenseExceptionId": "u-boot-exception-2.0",
"seeAlso": [
"http://git.denx.de/?p\u003du-boot.git;a\u003dblob;f\u003dLicenses/Exceptions"
]
},
{
"reference": "./freertos-exception-2.0.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./freertos-exception-2.0.html",
"referenceNumber": 26,
"name": "FreeRTOS Exception 2.0",
"licenseExceptionId": "freertos-exception-2.0",
"seeAlso": [
"https://web.archive.org/web/20060809182744/http://www.freertos.org/a00114.html"
]
},
{
"reference": "./Qt-GPL-exception-1.0.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./Qt-GPL-exception-1.0.html",
"referenceNumber": 27,
"name": "Qt GPL exception 1.0",
"licenseExceptionId": "Qt-GPL-exception-1.0",
"seeAlso": [
"http://code.qt.io/cgit/qt/qtbase.git/tree/LICENSE.GPL3-EXCEPT"
]
},
{
"reference": "./OpenJDK-assembly-exception-1.0.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./OpenJDK-assembly-exception-1.0.html",
"referenceNumber": 28,
"name": "OpenJDK Assembly exception 1.0",
"licenseExceptionId": "OpenJDK-assembly-exception-1.0",
"seeAlso": [
"http://openjdk.java.net/legal/assembly-exception.html"
]
},
{
"reference": "./SHL-2.1.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./SHL-2.1.html",
"referenceNumber": 29,
"name": "Solderpad Hardware License v2.1",
"licenseExceptionId": "SHL-2.1",
"seeAlso": [
"https://solderpad.org/licenses/SHL-2.1/"
]
},
{
"reference": "./mif-exception.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./mif-exception.html",
"referenceNumber": 30,
"referenceNumber": 41,
"name": "Macros and Inline Functions Exception",
"licenseExceptionId": "mif-exception",
"seeAlso": [
@ -339,128 +463,38 @@
]
},
{
"reference": "./Fawkes-Runtime-exception.json",
"reference": "./Linux-syscall-note.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./Fawkes-Runtime-exception.html",
"referenceNumber": 31,
"name": "Fawkes Runtime Exception",
"licenseExceptionId": "Fawkes-Runtime-exception",
"detailsUrl": "./Linux-syscall-note.html",
"referenceNumber": 42,
"name": "Linux Syscall Note",
"licenseExceptionId": "Linux-syscall-note",
"seeAlso": [
"http://www.fawkesrobotics.org/about/license/"
"https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/COPYING"
]
},
{
"reference": "./Swift-exception.json",
"reference": "./i2p-gpl-java-exception.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./Swift-exception.html",
"referenceNumber": 32,
"name": "Swift Exception",
"licenseExceptionId": "Swift-exception",
"detailsUrl": "./i2p-gpl-java-exception.html",
"referenceNumber": 43,
"name": "i2p GPL+Java Exception",
"licenseExceptionId": "i2p-gpl-java-exception",
"seeAlso": [
"https://swift.org/LICENSE.txt",
"https://github.com/apple/swift-package-manager/blob/7ab2275f447a5eb37497ed63a9340f8a6d1e488b/LICENSE.txt#L205"
"http://geti2p.net/en/get-involved/develop/licenses#java_exception"
]
},
{
"reference": "./GPL-3.0-linking-exception.json",
"reference": "./Libtool-exception.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./GPL-3.0-linking-exception.html",
"referenceNumber": 33,
"name": "GPL-3.0 Linking Exception",
"licenseExceptionId": "GPL-3.0-linking-exception",
"detailsUrl": "./Libtool-exception.html",
"referenceNumber": 44,
"name": "Libtool Exception",
"licenseExceptionId": "Libtool-exception",
"seeAlso": [
"https://www.gnu.org/licenses/gpl-faq.en.html#GPLIncompatibleLibs"
]
},
{
"reference": "./SHL-2.0.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./SHL-2.0.html",
"referenceNumber": 34,
"name": "Solderpad Hardware License v2.0",
"licenseExceptionId": "SHL-2.0",
"seeAlso": [
"https://solderpad.org/licenses/SHL-2.0/"
]
},
{
"reference": "./Classpath-exception-2.0.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./Classpath-exception-2.0.html",
"referenceNumber": 35,
"name": "Classpath exception 2.0",
"licenseExceptionId": "Classpath-exception-2.0",
"seeAlso": [
"http://www.gnu.org/software/classpath/license.html",
"https://fedoraproject.org/wiki/Licensing/GPL_Classpath_Exception"
]
},
{
"reference": "./LZMA-exception.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./LZMA-exception.html",
"referenceNumber": 36,
"name": "LZMA exception",
"licenseExceptionId": "LZMA-exception",
"seeAlso": [
"http://nsis.sourceforge.net/Docs/AppendixI.html#I.6"
]
},
{
"reference": "./Font-exception-2.0.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./Font-exception-2.0.html",
"referenceNumber": 37,
"name": "Font exception 2.0",
"licenseExceptionId": "Font-exception-2.0",
"seeAlso": [
"http://www.gnu.org/licenses/gpl-faq.html#FontException"
]
},
{
"reference": "./Nokia-Qt-exception-1.1.json",
"isDeprecatedLicenseId": true,
"detailsUrl": "./Nokia-Qt-exception-1.1.html",
"referenceNumber": 38,
"name": "Nokia Qt LGPL exception 1.1",
"licenseExceptionId": "Nokia-Qt-exception-1.1",
"seeAlso": [
"https://www.keepassx.org/dev/projects/keepassx/repository/revisions/b8dfb9cc4d5133e0f09cd7533d15a4f1c19a40f2/entry/LICENSE.NOKIA-LGPL-EXCEPTION"
]
},
{
"reference": "./DigiRule-FOSS-exception.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./DigiRule-FOSS-exception.html",
"referenceNumber": 39,
"name": "DigiRule FOSS License Exception",
"licenseExceptionId": "DigiRule-FOSS-exception",
"seeAlso": [
"http://www.digirulesolutions.com/drupal/foss"
]
},
{
"reference": "./eCos-exception-2.0.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./eCos-exception-2.0.html",
"referenceNumber": 40,
"name": "eCos exception 2.0",
"licenseExceptionId": "eCos-exception-2.0",
"seeAlso": [
"http://ecos.sourceware.org/license-overview.html"
]
},
{
"reference": "./389-exception.json",
"isDeprecatedLicenseId": false,
"detailsUrl": "./389-exception.html",
"referenceNumber": 41,
"name": "389 Directory Server Exception",
"licenseExceptionId": "389-exception",
"seeAlso": [
"http://directory.fedoraproject.org/wiki/GPL_Exception_License_Text"
"http://git.savannah.gnu.org/cgit/libtool.git/tree/m4/libtool.m4"
]
}
],
"releaseDate": "2022-05-08"
"releaseDate": "2022-08-12"
}

File diff suppressed because it is too large Load Diff

View File

@ -30,12 +30,23 @@ class DependencyCollector
@requirements = Requirements.new
end
def initialize_copy(other)
super
@deps = @deps.dup
@requirements = @requirements.dup
end
def add(spec)
case dep = fetch(spec)
when Dependency
@deps << dep
when Requirement
@requirements << dep
when nil
# no-op when we have a nil value
nil
else
raise ArgumentError, "DependencyCollector#add passed something that isn't a Dependency or Requirement!"
end
dep
end
@ -63,7 +74,7 @@ class DependencyCollector
Dependency.new("git", tags)
end
def brewed_curl_dep_if_needed(tags)
def curl_dep_if_needed(tags)
Dependency.new("curl", tags)
end
@ -148,7 +159,7 @@ class DependencyCollector
strategy = spec.download_strategy
if strategy <= HomebrewCurlDownloadStrategy
@deps << brewed_curl_dep_if_needed(tags)
@deps << curl_dep_if_needed(tags)
parse_url_spec(spec.url, tags)
elsif strategy <= CurlDownloadStrategy
parse_url_spec(spec.url, tags)

View File

@ -138,11 +138,13 @@ module Homebrew
replacement_pairs << fetch_cask(tmp_contents, config: lang_config)
end
if tmp_contents.include?("Hardware::CPU.intel?")
other_intel = !Hardware::CPU.intel?
other_contents = tmp_contents.gsub("Hardware::CPU.intel?", other_intel.to_s)
other_cask = Cask::CaskLoader.load(other_contents)
# TODO: remove the `Hardware::CPU.intel?` substitution once no casks use the conditional
other_intel = !Hardware::CPU.intel?
Homebrew::SimulateSystem.arch = other_intel ? :intel : :arm
other_contents = tmp_contents.gsub("Hardware::CPU.intel?", other_intel.to_s)
other_cask = Cask::CaskLoader.load(other_contents)
if other_cask.url.to_s != tmp_cask.url.to_s
if other_cask.sha256 != :no_check && other_cask.language.blank?
replacement_pairs << fetch_cask(other_contents)
end
@ -152,6 +154,8 @@ module Homebrew
replacement_pairs << fetch_cask(other_contents, config: lang_config)
end
end
Homebrew::SimulateSystem.clear
end
end
@ -159,8 +163,8 @@ module Homebrew
hash_regex = (old_hash == :no_check) ? ":no_check" : "[\"']#{Regexp.escape(old_hash.to_s)}[\"']"
replacement_pairs << [
/sha256\s+#{hash_regex}/m,
"sha256 #{(new_hash == :no_check) ? ":no_check" : "\"#{new_hash}\""}",
/#{hash_regex}/m,
((new_hash == :no_check) ? ":no_check" : "\"#{new_hash}\"").to_s,
]
end

View File

@ -39,7 +39,6 @@ module Homebrew
hidden: true
switch "--write-only",
description: "Make the expected file modifications without taking any Git actions."
switch "--write", hidden: true
switch "--commit",
depends_on: "--write-only",
description: "When passed with `--write-only`, generate a new commit after writing changes " \
@ -87,7 +86,6 @@ module Homebrew
description: "Exclude these Python packages when finding resources."
conflicts "--dry-run", "--write-only"
conflicts "--dry-run", "--write"
conflicts "--no-audit", "--strict"
conflicts "--no-audit", "--online"
conflicts "--url", "--tag"
@ -100,8 +98,6 @@ module Homebrew
def bump_formula_pr
args = bump_formula_pr_args.parse
odisabled "`brew bump-formula-pr --write`", "`brew bump-formula-pr --write-only`" if args.write?
if args.revision.present? && args.tag.nil? && args.version.nil?
raise UsageError, "`--revision` must be passed with either `--tag` or `--version`!"
end

View File

@ -50,7 +50,7 @@ module Homebrew
if args.test?
result.display_test_output(strict: args.strict?)
Homebrew.failed = true if result.broken_library_linkage?(strict: args.strict?)
Homebrew.failed = true if result.broken_library_linkage?(test: true, strict: args.strict?)
elsif args.reverse?
result.display_reverse_output
else

View File

@ -30,7 +30,6 @@ module Homebrew
description: "Skip running `brew bottle` before uploading."
flag "--committer=",
description: "Specify a committer name and email in `git`'s standard author format."
flag "--github-org=", hidden: true
flag "--root-url=",
description: "Use the specified <URL> as the root of the bottle's URL instead of Homebrew's default."
flag "--root-url-using=",
@ -90,8 +89,6 @@ module Homebrew
def pr_upload
args = pr_upload_args.parse
odisabled "`brew pr-upload --github-org`", "`brew pr-upload` without `--github-org`" if args.github_org
json_files = Dir["*.bottle.json"]
odie "No bottle JSON files found in the current working directory" if json_files.blank?
bottles_hash = bottles_hash_from_json_files(json_files, args)

View File

@ -119,6 +119,7 @@ module Homebrew
if args.retry? && @test_failed.add?(f)
oh1 "Testing #{f.full_name} (again)"
f.clear_cache
ENV["RUST_BACKTRACE"] = "full"
true
else
Homebrew.failed = true

View File

@ -78,8 +78,8 @@ class DevelopmentTools
end
sig { params(cc: String).returns(Version) }
def non_apple_gcc_version(cc)
(@non_apple_gcc_version ||= {}).fetch(cc) do
def gcc_version(cc)
(@gcc_version ||= {}).fetch(cc) do
path = HOMEBREW_PREFIX/"opt/#{CompilerSelector.preferred_gcc}/bin"/cc
path = locate(cc) unless path.exist?
version = if path &&
@ -88,14 +88,14 @@ class DevelopmentTools
else
Version::NULL
end
@non_apple_gcc_version[cc] = version
@gcc_version[cc] = version
end
end
sig { void }
def clear_version_cache
@clang_version = @clang_build_version = nil
@non_apple_gcc_version = {}
@gcc_version = {}
end
sig { returns(T::Boolean) }

View File

@ -466,9 +466,19 @@ end
# Raised when an error occurs during a formula build.
class BuildError < RuntimeError
extend T::Sig
attr_reader :cmd, :args, :env
attr_accessor :formula, :options
sig {
params(
formula: T.nilable(Formula),
cmd: T.any(String, Pathname),
args: T::Array[T.any(String, Pathname, Integer)],
env: T::Hash[String, T.untyped],
).void
}
def initialize(formula, cmd, args, env)
@formula = formula
@cmd = cmd
@ -478,10 +488,12 @@ class BuildError < RuntimeError
super "Failed executing: #{cmd} #{pretty_args}".strip
end
sig { returns(T::Array[T.untyped]) }
def issues
@issues ||= fetch_issues
end
sig { returns(T::Array[T.untyped]) }
def fetch_issues
GitHub.issues_for_formula(formula.name, tap: formula.tap, state: "open")
rescue GitHub::API::RateLimitExceededError => e
@ -489,6 +501,7 @@ class BuildError < RuntimeError
[]
end
sig { params(verbose: T::Boolean).void }
def dump(verbose: false)
puts

View File

@ -33,19 +33,21 @@ module EnvActivation
sig {
params(
env: T.nilable(String),
cc: T.nilable(String),
build_bottle: T::Boolean,
bottle_arch: T.nilable(String),
_block: T.proc.returns(T.untyped),
env: T.nilable(String),
cc: T.nilable(String),
build_bottle: T::Boolean,
bottle_arch: T.nilable(String),
debug_symbols: T.nilable(T::Boolean),
_block: T.proc.returns(T.untyped),
).returns(T.untyped)
}
def with_build_environment(env: nil, cc: nil, build_bottle: false, bottle_arch: nil, &_block)
def with_build_environment(env: nil, cc: nil, build_bottle: false, bottle_arch: nil, debug_symbols: false, &_block)
old_env = to_hash.dup
tmp_env = to_hash.dup.extend(EnvActivation)
T.cast(tmp_env, EnvActivation).activate_extensions!(env: env)
T.cast(tmp_env, T.any(Superenv, Stdenv))
.setup_build_environment(cc: cc, build_bottle: build_bottle, bottle_arch: bottle_arch)
.setup_build_environment(cc: cc, build_bottle: build_bottle, bottle_arch: bottle_arch,
debug_symbols: debug_symbols)
replace(tmp_env)
begin

View File

@ -40,13 +40,16 @@ module SharedEnvExtension
build_bottle: T.nilable(T::Boolean),
bottle_arch: T.nilable(String),
testing_formula: T::Boolean,
debug_symbols: T.nilable(T::Boolean),
).void
}
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false)
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false,
debug_symbols: false)
@formula = formula
@cc = cc
@build_bottle = build_bottle
@bottle_arch = bottle_arch
@debug_symbols = debug_symbols
reset
end
private :setup_build_environment

View File

@ -21,9 +21,11 @@ module Stdenv
build_bottle: T.nilable(T::Boolean),
bottle_arch: T.nilable(String),
testing_formula: T::Boolean,
debug_symbols: T.nilable(T::Boolean),
).void
}
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false)
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false,
debug_symbols: false)
super
self["HOMEBREW_ENV"] = "std"

View File

@ -55,9 +55,11 @@ module Superenv
build_bottle: T.nilable(T::Boolean),
bottle_arch: T.nilable(String),
testing_formula: T::Boolean,
debug_symbols: T.nilable(T::Boolean),
).void
}
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false)
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false,
debug_symbols: false)
super
send(compiler)
@ -87,6 +89,8 @@ module Superenv
self["HOMEBREW_DEPENDENCIES"] = determine_dependencies
self["HOMEBREW_FORMULA_PREFIX"] = @formula.prefix unless @formula.nil?
set_debug_symbols if debug_symbols
# The HOMEBREW_CCCFG ENV variable is used by the ENV/cc tool to control
# compiler flag stripping. It consists of a string of characters which act
# as flags. Some of these flags are mutually exclusive.
@ -100,6 +104,7 @@ module Superenv
# d - Don't strip -march=<target>. Use only in formulae that
# have runtime detection of CPU features.
# w - Pass -no_weak_imports to the linker
# D - Generate debugging information
#
# These flags will also be present:
# a - apply fix for apr-1-config path
@ -125,8 +130,13 @@ module Superenv
sig { returns(T::Array[Pathname]) }
def homebrew_extra_paths
[]
# Reverse sort by version so that we prefer the newest when there are multiple.
deps.select { |d| d.name.match? Version.formula_optionally_versioned_regex(:python) }
.sort_by(&:version)
.reverse
.map { |d| d.opt_libexec/"bin" }
end
alias generic_homebrew_extra_paths homebrew_extra_paths
sig { returns(T.nilable(PATH)) }
def determine_path
@ -331,6 +341,11 @@ module Superenv
append_to_cccfg "g" if compiler == :clang
end
sig { void }
def set_debug_symbols
append_to_cccfg "D"
end
# @private
sig { void }
def refurbish_args

View File

@ -4,8 +4,6 @@
class CompilerSelector
sig { returns(String) }
def self.preferred_gcc
# gcc-5 is the lowest gcc version we support on Linux.
# gcc-5 is the default gcc in Ubuntu 16.04 (used for our CI)
"gcc@5"
OS::LINUX_PREFERRED_GCC_FORMULA
end
end

View File

@ -139,6 +139,34 @@ module Homebrew
e.g. by using homebrew instead).
EOS
end
def check_gcc_dependent_linkage
gcc_dependents = Formula.installed.select do |formula|
next false unless formula.tap&.core_tap?
formula.recursive_dependencies.map(&:name).include? "gcc"
rescue TapFormulaUnavailableError
false
end
return if gcc_dependents.empty?
badly_linked = gcc_dependents.select do |dependent|
keg = Keg.new(dependent.prefix)
keg.binary_executable_or_library_files.any? do |binary|
paths = binary.rpath.split(":")
versioned_linkage = paths.any? { |path| path.match?(%r{lib/gcc/\d+$}) }
unversioned_linkage = paths.any? { |path| path.match?(%r{lib/gcc/current$}) }
versioned_linkage && !unversioned_linkage
end
end
return if badly_linked.empty?
inject_file_list badly_linked, <<~EOS
Formulae which link to GCC through a versioned path were found. These formulae
are prone to breaking when GCC is updated. You should `brew reinstall` these formulae:
EOS
end
end
end
end

View File

@ -2,11 +2,10 @@
# frozen_string_literal: true
module Stdenv
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false)
generic_setup_build_environment(
formula: formula, cc: cc, build_bottle: build_bottle,
bottle_arch: bottle_arch, testing_formula: testing_formula
)
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false,
debug_symbols: false)
generic_setup_build_environment(formula: formula, cc: cc, build_bottle: build_bottle, bottle_arch: bottle_arch,
testing_formula: testing_formula, debug_symbols: debug_symbols)
prepend_path "CPATH", HOMEBREW_PREFIX/"include"
prepend_path "LIBRARY_PATH", HOMEBREW_PREFIX/"lib"

View File

@ -15,11 +15,10 @@ module Superenv
end
# @private
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false)
generic_setup_build_environment(
formula: formula, cc: cc, build_bottle: build_bottle,
bottle_arch: bottle_arch, testing_formula: testing_formula
)
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false,
debug_symbols: false)
generic_setup_build_environment(formula: formula, cc: cc, build_bottle: build_bottle, bottle_arch: bottle_arch,
testing_formula: testing_formula, debug_symbols: debug_symbols)
self["HOMEBREW_OPTIMIZATION_LEVEL"] = "O2"
self["HOMEBREW_DYNAMIC_LINKER"] = determine_dynamic_linker_path
self["HOMEBREW_RPATH_PATHS"] = determine_rpath_paths(@formula)
@ -27,7 +26,7 @@ module Superenv
end
def homebrew_extra_paths
paths = []
paths = generic_homebrew_extra_paths
paths += %w[binutils make].map do |f|
bin = Formulary.factory(f).opt_bin
bin if bin.directory?

View File

@ -3,7 +3,7 @@
class Formula
undef shared_library
undef rpath
undef loader_path
undef deuniversalize_machos
sig { params(name: String, version: T.nilable(T.any(String, Integer))).returns(String) }
@ -17,8 +17,8 @@ class Formula
end
sig { returns(String) }
def rpath
"'$ORIGIN/../lib'"
def loader_path
"$ORIGIN"
end
sig { params(targets: T.nilable(T.any(Pathname, String))).void }

View File

@ -10,7 +10,6 @@ class LinkageChecker
libanl.so.1
libatomic.so.1
libc.so.6
libcrypt.so.1
libdl.so.2
libm.so.6
libmvec.so.1
@ -27,18 +26,26 @@ class LinkageChecker
].freeze
def display_deprecated_warning(strict: false)
return unless @libcrypt_found
# Steps when moving this to `odisabled`:
# - Remove `libcrypt.so.1` from SYSTEM_LIBRARY_ALLOWLIST above.
# Steps when moving these to `odisabled`:
# - Remove the old library from SYSTEM_LIBRARY_ALLOWLIST above.
# - Remove the `disable` and `disable_for_developer` kwargs here.
# - Remove `broken_library_linkage?` override below and the generic alias in HOMEBREW_LIBRARY/linkage_checker.rb.
# - Remove `fail_on_libcrypt1?`.
# Steps when removing this entirely (assuming the above has already been done):
# - Adjust the `broken_library_linkage?` override below to not check for the library.
# - Remove the relevant `fail_on_lib*?`.
# If there's no more deprecations left:
# - Remove the `broken_library_linkage?` override and the generic alias in HOMEBREW_LIBRARY/linkage_checker.rb.
#
# Steps when removing handling for a library entirely (assuming the steps to `odisabled` has already been done):
# - Remove the relevant setting of `@lib*_found` in `check_dylibs` below.
# - Remove the `odisabled` line
# If there's no library deprecated/disabled handling left:
# - Remove the `display_` overrides here and the associated generic aliases in HOMEBREW_LIBRARY/linkage_checker.rb
# - Remove the setting of `@libcrypt_found` in `check_dylibs` below.
odeprecated "linkage to libcrypt.so.1", "libcrypt.so.2 in the libxcrypt formula",
disable: fail_on_libcrypt1?(strict: strict),
odisabled "linkage to libcrypt.so.1", "libcrypt.so.2 in the libxcrypt formula" if @libcrypt_found
return unless @libnsl_found
odeprecated "linkage to libnsl.so.1", "libnsl.so.3 in the libnsl formula",
disable: fail_on_libnsl1?(strict: strict),
disable_for_developers: false
end
@ -52,20 +59,21 @@ class LinkageChecker
display_deprecated_warning(strict: strict)
end
def broken_library_linkage?(strict: false)
generic_broken_library_linkage?(strict: strict) || (fail_on_libcrypt1?(strict: strict) && @libcrypt_found)
def broken_library_linkage?(test: false, strict: false)
generic_broken_library_linkage?(test: test, strict: strict) || (fail_on_libnsl1?(strict: strict) && @libnsl_found)
end
private
def fail_on_libcrypt1?(strict:)
strict || ENV["HOMEBREW_DISALLOW_LIBCRYPT1"].present?
def fail_on_libnsl1?(strict:)
strict || ENV["HOMEBREW_DISALLOW_LIBNSL1"].present?
end
def check_dylibs(rebuild_cache:)
generic_check_dylibs(rebuild_cache: rebuild_cache)
@libcrypt_found = true if @system_dylibs.any? { |s| File.basename(s) == "libcrypt.so.1" }
@libnsl_found = true if @system_dylibs.any? { |s| File.basename(s) == "libnsl.so.1" }
# glibc and gcc are implicit dependencies.
# No other linkage to system libraries is expected or desired.

View File

@ -4,11 +4,11 @@
module SharedEnvExtension
extend T::Sig
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false)
generic_shared_setup_build_environment(
formula: formula, cc: cc, build_bottle: build_bottle,
bottle_arch: bottle_arch, testing_formula: testing_formula
)
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false,
debug_symbols: false)
generic_shared_setup_build_environment(formula: formula, cc: cc, build_bottle: build_bottle,
bottle_arch: bottle_arch, testing_formula: testing_formula,
debug_symbols: debug_symbols)
# Normalise the system Perl version used, where multiple may be available
self["VERSIONER_PERL_VERSION"] = MacOS.preferred_perl_version

View File

@ -10,11 +10,10 @@ module Stdenv
["#{HOMEBREW_LIBRARY}/Homebrew/os/mac/pkgconfig/#{MacOS.version}"]
end
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false)
generic_setup_build_environment(
formula: formula, cc: cc, build_bottle: build_bottle,
bottle_arch: bottle_arch, testing_formula: testing_formula
)
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false,
debug_symbols: false)
generic_setup_build_environment(formula: formula, cc: cc, build_bottle: build_bottle, bottle_arch: bottle_arch,
testing_formula: testing_formula, debug_symbols: debug_symbols)
append "LDFLAGS", "-Wl,-headerpad_max_install_names"

View File

@ -85,7 +85,8 @@ module Superenv
end
# @private
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false)
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false,
debug_symbols: false)
sdk = formula ? MacOS.sdk_for_formula(formula) : MacOS.sdk
is_xcode_sdk = sdk&.source == :xcode
@ -100,10 +101,8 @@ module Superenv
MacOS::CLT::PKG_PATH
end
generic_setup_build_environment(
formula: formula, cc: cc, build_bottle: build_bottle,
bottle_arch: bottle_arch, testing_formula: testing_formula
)
generic_setup_build_environment(formula: formula, cc: cc, build_bottle: build_bottle, bottle_arch: bottle_arch,
testing_formula: testing_formula, debug_symbols: debug_symbols)
# Filter out symbols known not to be defined since GNU Autotools can't
# reliably figure this out with Xcode 8 and above.

View File

@ -62,4 +62,19 @@ class Keg
#{result.stderr}
EOS
end
def prepare_debug_symbols
binary_executable_or_library_files.each do |file|
odebug "Extracting symbols #{file}"
result = system_command("dsymutil", args: [file], print_stderr: false)
next if result.success?
# If it fails again, error out
ofail <<~EOS
Failed to extract symbols from #{file}:
#{result.stderr}
EOS
end
end
end

View File

@ -435,16 +435,26 @@ class Formula
end
# If this is a `@`-versioned formula.
sig { returns(T::Boolean) }
def versioned_formula?
name.include?("@")
end
# Returns any `@`-versioned formulae for any formula (including versioned formulae).
def versioned_formulae
Pathname.glob(path.to_s.gsub(/(@[\d.]+)?\.rb$/, "@*.rb")).map do |versioned_path|
# Returns any `@`-versioned formulae names for any formula (including versioned formulae).
sig { returns(T::Array[String]) }
def versioned_formulae_names
@versioned_formulae_names ||= Pathname.glob(path.to_s.gsub(/(@[\d.]+)?\.rb$/, "@*.rb")).map do |versioned_path|
next if versioned_path == path
Formula[versioned_path.basename(".rb").to_s]
versioned_path.basename(".rb").to_s
end.compact.sort
end
# Returns any `@`-versioned Formula objects for any Formula (including versioned formulae).
sig { returns(T::Array[Formula]) }
def versioned_formulae
@versioned_formulae ||= versioned_formulae_names.map do |name|
Formula[name]
rescue FormulaUnavailableError
nil
end.compact.sort_by(&:version).reverse
@ -1270,11 +1280,11 @@ class Formula
# Yields |self,staging| with current working directory set to the uncompressed tarball
# where staging is a {Mktemp} staging context.
# @private
def brew(fetch: true, keep_tmp: false, interactive: false)
def brew(fetch: true, keep_tmp: false, debug_symbols: false, interactive: false)
@prefix_returns_versioned_prefix = true
active_spec.fetch if fetch
stage(interactive: interactive) do |staging|
staging.retain! if keep_tmp
stage(interactive: interactive, debug_symbols: debug_symbols) do |staging|
staging.retain! if keep_tmp || debug_symbols
prepare_patches
fetch_patches if fetch
@ -1572,9 +1582,23 @@ class Formula
end
# Executable/Library RPATH according to platform conventions.
#
# Optionally specify a `source` or `target` depending on the location
# of the file containing the RPATH command and where its target is located.
#
# <pre>
# rpath #=> "@loader_path/../lib"
# rpath(target: frameworks) #=> "@loader_path/../Frameworks"
# rpath(source: libexec/"bin") #=> "@loader_path/../../lib"
# </pre>
sig { params(source: Pathname, target: Pathname).returns(String) }
def rpath(source: bin, target: lib)
"#{loader_path}/#{target.relative_path_from(source)}"
end
sig { returns(String) }
def rpath
"@loader_path/../lib"
def loader_path
"@loader_path"
end
# Creates a new `Time` object for use in the formula as the build time.
@ -1622,6 +1646,98 @@ class Formula
end
private :extract_macho_slice_from
# Generate shell completions for a formula for bash, zsh, and fish, using the formula's executable.
#
# @param commands [Pathname, String] the path to the executable and any passed subcommand(s)
# to use for generating the completion scripts.
# @param base_name [String] the base name of the generated completion script. Defaults to the formula name.
# @param shells [Array<Symbol>] the shells to generate completion scripts for. Defaults to `[:bash, :zsh, :fish]`.
# @param shell_parameter_format [String, Symbol] specify how `shells` should each be passed
# to the `executable`. Takes either a String representing a prefix, or one of [:flag, :arg, :none].
# Defaults to plainly passing the shell.
#
# @example Using default values for optional arguments
# generate_completions_from_executable(bin/"foo", "completions")
# translates to
#
# (bash_completion/"foo").write Utils.safe_popen_read({ "SHELL" => "bash" }, bin/"foo", "completions", "bash")
#
# (zsh_completion/"_foo").write Utils.safe_popen_read({ "SHELL" => "zsh" }, bin/"foo", "completions", "zsh")
#
# (fish_completion/"foo.fish").write Utils.safe_popen_read({ "SHELL" => "fish" }, bin/"foo", "completions", "fish")
#
# @example Selecting shells and using a different base_name
# generate_completions_from_executable(bin/"foo", "completions", shells: [:bash, :zsh], base_name: "bar")
# translates to
#
# (bash_completion/"bar").write Utils.safe_popen_read({ "SHELL" => "bash" }, bin/"foo", "completions", "bash")
#
# (zsh_completion/"_bar").write Utils.safe_popen_read({ "SHELL" => "zsh" }, bin/"foo", "completions", "zsh")
#
# @example Using predefined shell_parameter_format :flag
# generate_completions_from_executable(bin/"foo", "completions", shell_parameter_format: :flag, shells: [:bash])
# translates to
#
# (bash_completion/"foo").write Utils.safe_popen_read({ "SHELL" => "bash" }, bin/"foo", "completions", "--bash")
#
# @example Using predefined shell_parameter_format :arg
# generate_completions_from_executable(bin/"foo", "completions", shell_parameter_format: :arg, shells: [:bash])
# translates to
#
# (bash_completion/"foo").write Utils.safe_popen_read({ "SHELL" => "bash" }, bin/"foo",
# "completions", "--shell=bash")
#
# @example Using predefined shell_parameter_format :none
# generate_completions_from_executable(bin/"foo", "completions", shell_parameter_format: :none, shells: [:bash])
# translates to
#
# (bash_completion/"foo").write Utils.safe_popen_read({ "SHELL" => "bash" }, bin/"foo", "completions")
#
# @example Using custom shell_parameter_format
# generate_completions_from_executable(bin/"foo", "completions", shell_parameter_format: "--selected-shell=",
# shells: [:bash])
# translates to
#
# (bash_completion/"foo").write Utils.safe_popen_read({ "SHELL" => "bash" }, bin/"foo",
# "completions", "--selected-shell=bash")
sig {
params(commands: T.any(Pathname, String), base_name: String, shells: T::Array[Symbol],
shell_parameter_format: T.nilable(T.any(Symbol, String))).void
}
def generate_completions_from_executable(*commands,
base_name: name,
shells: [:bash, :zsh, :fish],
shell_parameter_format: nil)
completion_script_path_map = {
bash: bash_completion/base_name,
zsh: zsh_completion/"_#{base_name}",
fish: fish_completion/"#{base_name}.fish",
}
shells.each do |shell|
script_path = completion_script_path_map[shell]
shell_parameter = if shell_parameter_format.nil?
shell.to_s
elsif shell_parameter_format == :flag
"--#{shell}"
elsif shell_parameter_format == :arg
"--shell=#{shell}"
elsif shell_parameter_format == :none
""
else
"#{shell_parameter_format}#{shell}"
end
popen_read_args = %w[]
popen_read_args << commands
popen_read_args << shell_parameter
popen_read_args.flatten!
script_path.dirname.mkpath
script_path.write Utils.safe_popen_read({ "SHELL" => shell.to_s }, *popen_read_args)
end
end
# an array of all core {Formula} names
# @private
def self.core_names
@ -1911,7 +2027,7 @@ class Formula
# `any_installed_keg` and `runtime_dependencies` `select`s ensure
# that we don't end up with something `Formula#runtime_dependencies` can't
# read from a `Tab`.
Formula.cache[:runtime_installed_formula_dependents] = {}
Formula.cache[:runtime_installed_formula_dependents] ||= {}
Formula.cache[:runtime_installed_formula_dependents][full_name] ||= Formula.installed
.select(&:any_installed_keg)
.select(&:runtime_dependencies)
@ -2219,7 +2335,7 @@ class Formula
def inreplace(paths, before = nil, after = nil, audit_result = true) # rubocop:disable Style/OptionalBooleanParameter
super(paths, before, after, audit_result)
rescue Utils::Inreplace::Error
raise BuildError.new(self, "inreplace", paths, nil)
raise BuildError.new(self, "inreplace", paths, {})
end
protected
@ -2529,8 +2645,8 @@ class Formula
}
end
def stage(interactive: false)
active_spec.stage do |staging|
def stage(interactive: false, debug_symbols: false)
active_spec.stage(debug_symbols: debug_symbols) do |staging|
@source_modified_time = active_spec.source_modified_time
@buildpath = Pathname.pwd
env_home = buildpath/".brew_home"

View File

@ -263,7 +263,10 @@ module Homebrew
next
end
if dep_f.oldname && dep.name.split("/").last == dep_f.oldname
# FIXME: Remove `glib-utils` exemption when the following PRs are merged:
# https://github.com/Homebrew/homebrew-core/pull/108307
# https://github.com/Homebrew/homebrew-core/pull/108497
if dep_f.oldname && dep.name.split("/").last == dep_f.oldname && dep_f.oldname != "glib-utils"
problem "Dependency '#{dep.name}' was renamed; use new name '#{dep_f.name}'."
end
@ -332,6 +335,13 @@ module Homebrew
end
return unless @core_tap
bad_gcc_dep = linux_only_gcc_dep?(formula) && (@strict || begin
fv = FormulaVersions.new(formula)
fv.formula_at_revision("origin/HEAD") { |prev_f| !linux_only_gcc_dep?(prev_f) }
end)
problem "Formulae in homebrew/core should not have a Linux-only dependency on GCC." if bad_gcc_dep
return if formula.tap&.audit_exception :versioned_dependencies_conflicts_allowlist, formula.name
# The number of conflicts on Linux is absurd.
@ -344,6 +354,10 @@ module Homebrew
recursive_runtime_formulae.each do |f|
name = f.name
unversioned_name, = name.split("@")
# Allow use of the full versioned name (e.g. `python@3.99`) or an unversioned alias (`python`).
next if formula.tap&.audit_exception :versioned_formula_dependent_conflicts_allowlist, name
next if formula.tap&.audit_exception :versioned_formula_dependent_conflicts_allowlist, unversioned_name
version_hash[unversioned_name] ||= Set.new
version_hash[unversioned_name] << name
next if version_hash[unversioned_name].length < 2
@ -419,11 +433,12 @@ module Homebrew
def audit_glibc
return unless @core_tap
return if formula.name != "glibc"
return if [OS::CI_GLIBC_VERSION, "2.27", "2.31", "2.35"].include?(formula.version.to_s)
# Also allow LINUX_GLIBC_NEXT_CI_VERSION for when we're upgrading.
return if [OS::LINUX_GLIBC_CI_VERSION, OS::LINUX_GLIBC_NEXT_CI_VERSION].include?(formula.version.to_s)
problem "The glibc version must be #{OS::CI_GLIBC_VERSION}, as this is the version used by our CI on Linux. " \
"Glibc is for users who have a system Glibc with a lower version, " \
"which allows them to use our Linux bottles, which were compiled against system Glibc on CI."
problem "The glibc version must be #{OS::LINUX_GLIBC_CI_VERSION}, as needed by our CI on Linux. " \
"The glibc formula is for users who have a system glibc with a lower version, " \
"which allows them to use our Linux bottles, which were compiled against system glibc on CI."
end
ELASTICSEARCH_KIBANA_RELICENSED_VERSION = "7.11"
@ -848,5 +863,16 @@ module Homebrew
def head_only?(formula)
formula.head && formula.stable.nil?
end
def linux_only_gcc_dep?(formula)
# TODO: Make this check work when running on Linux and not simulating macOS too.
return false unless Homebrew::SimulateSystem.simulating_or_running_on_macos?
formula_hash = formula.to_hash_with_variations
deps = formula_hash["dependencies"]
linux_deps = formula_hash.dig("variations", :x86_64_linux, "dependencies")
deps.exclude?("gcc") && linux_deps&.include?("gcc")
end
end
end

View File

@ -39,6 +39,7 @@ class FormulaInstaller
attr_predicate :installed_as_dependency?, :installed_on_request?
attr_predicate :show_summary_heading?, :show_header?
attr_predicate :force_bottle?, :ignore_deps?, :only_deps?, :interactive?, :git?, :force?, :overwrite?, :keep_tmp?
attr_predicate :debug_symbols?
attr_predicate :verbose?, :debug?, :quiet?
def initialize(
@ -58,6 +59,7 @@ class FormulaInstaller
git: false,
interactive: false,
keep_tmp: false,
debug_symbols: false,
cc: nil,
options: Options.new,
force: false,
@ -71,6 +73,7 @@ class FormulaInstaller
@force = force
@overwrite = overwrite
@keep_tmp = keep_tmp
@debug_symbols = debug_symbols
@link_keg = !formula.keg_only? || link_keg
@show_header = show_header
@ignore_deps = ignore_deps
@ -688,6 +691,7 @@ class FormulaInstaller
include_test_formulae: @include_test_formulae,
build_from_source_formulae: @build_from_source_formulae,
keep_tmp: keep_tmp?,
debug_symbols: debug_symbols?,
force: force?,
debug: debug?,
quiet: quiet?,
@ -741,6 +745,7 @@ class FormulaInstaller
include_test_formulae: @include_test_formulae,
build_from_source_formulae: @build_from_source_formulae,
keep_tmp: keep_tmp?,
debug_symbols: debug_symbols?,
force: force?,
debug: debug?,
quiet: quiet?,
@ -802,6 +807,8 @@ class FormulaInstaller
post_install
end
keg.prepare_debug_symbols if debug_symbols?
# Updates the cache for a particular formula after doing an install
CacheStoreDatabase.use(:linkage) do |db|
break unless db.created?
@ -873,6 +880,11 @@ class FormulaInstaller
args << "--cc=#{@cc}" if @cc
args << "--keep-tmp" if keep_tmp?
if debug_symbols?
args << "--debug-symbols"
args << "--build-from-source"
end
if @env.present?
args << "--env=#{@env}"
elsif formula.env.std? || formula.deps.select(&:build?).any? { |d| d.name == "scons" }

View File

@ -333,9 +333,9 @@ class GitHubPackages
os_version ||= "macOS #{bottle_tag.to_macos_version}"
when "linux"
os_version&.delete_suffix!(" LTS")
os_version ||= OS::CI_OS_VERSION
os_version ||= OS::LINUX_CI_OS_VERSION
glibc_version = tab["built_on"]["glibc_version"].presence if tab["built_on"].present?
glibc_version ||= OS::CI_GLIBC_VERSION
glibc_version ||= OS::LINUX_GLIBC_CI_VERSION
cpu_variant = tab["oldest_cpu_family"] || Hardware::CPU::INTEL_64BIT_OLDEST_CPU.to_s
end

View File

@ -269,6 +269,7 @@ module Homebrew
git: false,
interactive: false,
keep_tmp: false,
debug_symbols: false,
force: false,
overwrite: false,
debug: false,
@ -293,6 +294,7 @@ module Homebrew
git: git,
interactive: interactive,
keep_tmp: keep_tmp,
debug_symbols: debug_symbols,
force: force,
overwrite: overwrite,
debug: debug,

View File

@ -483,6 +483,8 @@ class Keg
ObserverPathnameExtension.n
end
def prepare_debug_symbols; end
def remove_oldname_opt_record
return unless oldname_opt_record
return if oldname_opt_record.resolved_path != path

View File

@ -373,7 +373,7 @@ class Keg
@bottle_dependencies ||= begin
formulae = []
gcc = Formulary.factory(CompilerSelector.preferred_gcc)
formulae << gcc if DevelopmentTools.non_apple_gcc_version("gcc") < gcc.version.to_i
formulae << gcc if DevelopmentTools.gcc_version("gcc") < gcc.version.to_i
formulae
end
end

View File

@ -103,16 +103,22 @@ module Language
)
end
def detected_python_shebang(formula = self)
python_deps = formula.deps.map(&:name).grep(/^python(@.*)?$/)
def detected_python_shebang(formula = self, use_python_from_path: false)
python_path = if use_python_from_path
"/usr/bin/env python3"
else
python_deps = formula.deps.map(&:name).grep(/^python(@.*)?$/)
raise ShebangDetectionError.new("Python", "formula does not depend on Python") if python_deps.empty?
if python_deps.length > 1
raise ShebangDetectionError.new("Python", "formula has multiple Python dependencies")
raise ShebangDetectionError.new("Python", "formula does not depend on Python") if python_deps.empty?
if python_deps.length > 1
raise ShebangDetectionError.new("Python", "formula has multiple Python dependencies")
end
python_dep = python_deps.first
Formula[python_dep].opt_bin/python_dep.sub("@", "")
end
python_dep = python_deps.first
python_shebang_rewrite_info(Formula[python_dep].opt_bin/python_dep.sub("@", ""))
python_shebang_rewrite_info(python_path)
end
end

View File

@ -80,11 +80,16 @@ class LinkageChecker
alias generic_display_test_output display_test_output
private :generic_display_test_output
sig { params(strict: T::Boolean).returns(T::Boolean) }
def broken_library_linkage?(strict: false)
issues = [@broken_deps, @unwanted_system_dylibs, @version_conflict_deps]
issues += [@undeclared_deps, @files_missing_rpaths] if strict
[issues, unexpected_broken_dylibs, unexpected_present_dylibs].flatten.any?(&:present?)
sig { params(test: T::Boolean, strict: T::Boolean).returns(T::Boolean) }
def broken_library_linkage?(test: false, strict: false)
raise ArgumentError, "Strict linkage checking requires test mode to be enabled." if strict && !test
issues = [@broken_deps, unexpected_broken_dylibs]
if test
issues += [@unwanted_system_dylibs, @version_conflict_deps, unexpected_present_dylibs]
issues += [@undeclared_deps, @files_missing_rpaths] if strict
end
issues.any?(&:present?)
end
alias generic_broken_library_linkage? broken_library_linkage?
private :generic_broken_library_linkage?

View File

@ -89,6 +89,12 @@ module Homebrew
uconv is part of the icu4c formula:
brew install icu4c
EOS
when "postgresql", "postgres" then <<~EOS
postgresql breaks existing databases on upgrade without human intervention.
See a more specific version to install with:
brew formulae | grep postgresql@
EOS
end
end
alias generic_disallowed_reason disallowed_reason

View File

@ -13,7 +13,8 @@ class Mktemp
def initialize(prefix, opts = {})
@prefix = prefix
@retain = opts[:retain]
@retain_in_cache = opts[:retain_in_cache]
@retain = opts[:retain] || @retain_in_cache
@quiet = false
end
@ -28,6 +29,11 @@ class Mktemp
@retain
end
# True if the source files should be retained.
def retain_in_cache?
@retain_in_cache
end
# Instructs this Mktemp to not emit messages when retention is triggered.
sig { void }
def quiet!
@ -40,7 +46,15 @@ class Mktemp
end
def run
@tmpdir = Pathname.new(Dir.mktmpdir("#{@prefix.tr "@", "AT"}-", HOMEBREW_TEMP))
prefix_name = @prefix.tr "@", "AT"
@tmpdir = if retain_in_cache?
tmp_dir = HOMEBREW_CACHE/"Sources/#{prefix_name}"
chmod_rm_rf(tmp_dir) # clear out previous staging directory
tmp_dir.mkpath
tmp_dir
else
Pathname.new(Dir.mktmpdir("#{prefix_name}-", HOMEBREW_TEMP))
end
# Make sure files inside the temporary directory have the same group as the
# brew instance.
@ -54,18 +68,21 @@ class Mktemp
Process.gid
end
begin
chown(nil, group_id, tmpdir)
chown(nil, group_id, @tmpdir)
rescue Errno::EPERM
opoo "Failed setting group \"#{Etc.getgrgid(group_id).name}\" on #{tmpdir}"
opoo "Failed setting group \"#{Etc.getgrgid(group_id).name}\" on #{@tmpdir}"
end
begin
Dir.chdir(tmpdir) { yield self }
ensure
ignore_interrupts { chmod_rm_rf(tmpdir) } unless retain?
ignore_interrupts { chmod_rm_rf(@tmpdir) } unless retain?
end
ensure
ohai "Temporary files retained at:", @tmpdir.to_s if retain? && !@tmpdir.nil? && !@quiet
if retain? && @tmpdir.present? && !@quiet
message = retain_in_cache? ? "Source files for debugging available at:" : "Temporary files retained at:"
ohai message, @tmpdir.to_s
end
end
private

View File

@ -45,8 +45,15 @@ module OS
::OS_VERSION = ENV.fetch("HOMEBREW_OS_VERSION").freeze
CI_GLIBC_VERSION = "2.23"
CI_OS_VERSION = "Ubuntu 16.04"
LINUX_CI_OS_VERSION = "Ubuntu 16.04"
LINUX_GLIBC_CI_VERSION = "2.23"
LINUX_GCC_CI_VERSION = "5.0"
LINUX_PREFERRED_GCC_FORMULA = "gcc@5"
# Ubuntu 22.04 (see Linux-CI.md)
LINUX_GLIBC_NEXT_CI_VERSION = "2.35"
# LINUX_GCC_CI_VERSION = "11.0"
# LINUX_PREFERRED_GCC_FORMULA = "gcc@11"
if OS.mac?
require "os/mac"

View File

@ -16,6 +16,7 @@ module Homebrew
build_from_source_formulae: [],
interactive: false,
keep_tmp: false,
debug_symbols: false,
force: false,
debug: false,
quiet: false,
@ -48,6 +49,7 @@ module Homebrew
git: git,
interactive: interactive,
keep_tmp: keep_tmp,
debug_symbols: debug_symbols,
force: force,
debug: debug,
quiet: quiet,

View File

@ -89,14 +89,14 @@ class Resource
# dir using {Mktemp} so that works with all subtypes.
#
# @api public
def stage(target = nil, &block)
def stage(target = nil, debug_symbols: false, &block)
raise ArgumentError, "target directory or block is required" if !target && block.blank?
prepare_patches
fetch_patches(skip_downloaded: true)
fetch unless downloaded?
unpack(target, &block)
unpack(target, debug_symbols: debug_symbols, &block)
end
def prepare_patches
@ -120,9 +120,9 @@ class Resource
# If block is given, yield to that block with `|stage|`, where stage
# is a {ResourceStageContext}.
# A target or a block must be given, but not both.
def unpack(target = nil)
def unpack(target = nil, debug_symbols: false)
current_working_directory = Pathname.pwd
mktemp(download_name) do |staging|
stage_resource(download_name, debug_symbols: debug_symbols) do |staging|
downloader.stage do
@source_modified_time = downloader.source_modified_time
apply_patches
@ -235,8 +235,8 @@ class Resource
protected
def mktemp(prefix, &block)
Mktemp.new(prefix).run(&block)
def stage_resource(prefix, debug_symbols: false, &block)
Mktemp.new(prefix, retain_in_cache: debug_symbols).run(&block)
end
private

View File

@ -21,11 +21,11 @@ module RuboCop
alias stanza_node method_node
def_delegator :stanza_node, :method_name, :stanza_name
def_delegator :stanza_node, :parent, :parent_node
def_delegator :stanza_node, :arch_variable?
def source_range
stanza_node.expression
stanza_node.location_expression
end
def source_range_with_comments
@ -38,6 +38,12 @@ module RuboCop
def_delegator :source_range_with_comments, :source,
:source_with_comments
def stanza_name
return :on_arch_conditional if arch_variable?
stanza_node.method_name
end
def stanza_group
Constants::STANZA_GROUP_HASH[stanza_name]
end

View File

@ -6,6 +6,7 @@ module RuboCop
# Constants available globally for use in all cask cops.
module Constants
STANZA_GROUPS = [
[:arch, :on_arch_conditional],
[:version, :sha256],
[:language],
[:url, :appcast, :name, :desc, :homepage],

View File

@ -15,8 +15,11 @@ module RuboCop
def_node_matcher :val_node, "{(pair _ $_) (hash (pair _ $_) ...)}"
def_node_matcher :cask_block?, "(block (send nil? :cask _) args ...)"
def_node_matcher :arch_variable?, "(lvasgn _ (send nil? :on_arch_conditional ...))"
def stanza?
return true if arch_variable?
(send_type? || block_type?) && STANZA_ORDER.include?(method_name)
end
@ -24,7 +27,7 @@ module RuboCop
loc.is_a?(Parser::Source::Map::Heredoc)
end
def expression
def location_expression
base_expression = loc.expression
descendants.select(&:heredoc?).reduce(base_expression) do |expr, node|
expr.join(node.loc.heredoc_end)

View File

@ -0,0 +1,52 @@
# typed: true
# frozen_string_literal: true
require "forwardable"
require "rubocops/shared/on_system_conditionals_helper"
module RuboCop
module Cop
module Cask
# This cop makes sure that OS conditionals are consistent.
#
# @example
# # bad
# cask 'foo' do
# if MacOS.version == :high_sierra
# sha256 "..."
# end
# end
#
# # good
# cask 'foo' do
# on_high_sierra do
# sha256 "..."
# end
# end
class OnSystemConditionals < Base
extend Forwardable
extend AutoCorrector
include OnSystemConditionalsHelper
include CaskHelp
FLIGHT_STANZA_NAMES = [:preflight, :postflight, :uninstall_preflight, :uninstall_postflight].freeze
def on_cask(cask_block)
@cask_block = cask_block
toplevel_stanzas.each do |stanza|
next unless FLIGHT_STANZA_NAMES.include? stanza.stanza_name
audit_on_system_blocks(stanza.stanza_node, stanza.stanza_name)
end
end
private
attr_reader :cask_block
def_delegators :cask_block, :toplevel_stanzas, :cask_body
end
end
end
end

View File

@ -0,0 +1,76 @@
# typed: false
# frozen_string_literal: true
require "forwardable"
module RuboCop
module Cop
module Cask
# This cop audits variables in casks.
#
# @example
# # bad
# cask do
# arch = Hardware::CPU.intel? ? "darwin" : "darwin-arm64"
# end
#
# # good
# cask 'foo' do
# arch arm: "darwin-arm64", intel: "darwin"
# end
class Variables < Base
extend Forwardable
extend AutoCorrector
include CaskHelp
def on_cask(cask_block)
@cask_block = cask_block
add_offenses
end
private
def_delegator :@cask_block, :cask_node
def add_offenses
variable_assignment(cask_node) do |node, var_name, arch_condition, true_node, false_node|
arm_node, intel_node = if arch_condition == :arm?
[true_node, false_node]
else
[false_node, true_node]
end
replacement_string = if var_name == :arch
"arch "
else
"#{var_name} = on_arch_conditional "
end
replacement_parameters = []
replacement_parameters << "arm: #{arm_node.source}" unless blank_node?(arm_node)
replacement_parameters << "intel: #{intel_node.source}" unless blank_node?(intel_node)
replacement_string += replacement_parameters.join(", ")
add_offense(node, message: "Use `#{replacement_string}` instead of `#{node.source}`") do |corrector|
corrector.replace(node, replacement_string)
end
end
end
def blank_node?(node)
case node.type
when :str
node.value.empty?
when :nil
true
else
false
end
end
def_node_search :variable_assignment, <<~PATTERN
$(lvasgn $_ (if (send (const (const nil? :Hardware) :CPU) ${:arm? :intel?}) $_ $_))
PATTERN
end
end
end
end

View File

@ -3,6 +3,7 @@
require "macos_versions"
require "rubocops/extend/formula"
require "rubocops/shared/on_system_conditionals_helper"
module RuboCop
module Cop
@ -377,104 +378,20 @@ module RuboCop
#
# @api private
class OnSystemConditionals < FormulaCop
include OnSystemConditionalsHelper
extend AutoCorrector
NO_ON_SYSTEM_METHOD_NAMES = [:install, :post_install].freeze
NO_ON_SYSTEM_BLOCK_NAMES = [:service, :test].freeze
ON_ARCH_OPTIONS = [:intel, :arm].freeze
ON_BASE_OS_OPTIONS = [:macos, :linux].freeze
ON_MACOS_VERSION_OPTIONS = MacOSVersions::SYMBOLS.keys.freeze
ALL_SYSTEM_OPTIONS = [*ON_ARCH_OPTIONS, *ON_BASE_OS_OPTIONS, *ON_MACOS_VERSION_OPTIONS, :system].freeze
MACOS_VERSION_CONDITIONALS = {
"==" => nil,
"<=" => :or_older,
">=" => :or_newer,
}.freeze
ON_SYSTEM_CONDITIONALS = [:<, :<=].freeze
def on_system_method_info(on_system_option)
info = {}
info[:method] = :"on_#{on_system_option}"
info[:if_module], info[:if_method] = if ON_ARCH_OPTIONS.include?(on_system_option)
["Hardware::CPU", :"#{on_system_option}?"]
elsif ON_BASE_OS_OPTIONS.include?(on_system_option)
["OS", (on_system_option == :macos) ? :mac? : :linux?]
else
["MacOS", :version]
end
info[:on_system_string] = "on_#{on_system_option}"
info[:if_string] = if on_system_option == :system
"if OS.linux? || MacOS.version"
else
"if #{info[:if_module]}.#{info[:if_method]}"
end
info
end
def audit_formula(_node, _class_node, _parent_class_node, body_node)
top_level_nodes_to_check = []
NO_ON_SYSTEM_METHOD_NAMES.each do |formula_method_name|
method_node = find_method_def(body_node, formula_method_name)
top_level_nodes_to_check << [formula_method_name, method_node] if method_node
audit_on_system_blocks(method_node, formula_method_name) if method_node
end
NO_ON_SYSTEM_BLOCK_NAMES.each do |formula_block_name|
block_node = find_block(body_node, formula_block_name)
top_level_nodes_to_check << [formula_block_name, block_node] if block_node
end
ALL_SYSTEM_OPTIONS.each do |on_system_option|
method_info = on_system_method_info(on_system_option)
top_level_nodes_to_check.each do |top_level_name, top_level_node|
top_level_node_string = if top_level_node.def_type?
"def #{top_level_name}"
else
"#{top_level_name} do"
end
find_every_method_call_by_name(top_level_node, method_info[:method]).each do |method|
if ON_MACOS_VERSION_OPTIONS.include?(on_system_option)
on_macos_version_method_call(method, on_method: method_info[:method]) do |on_method_parameters|
if on_method_parameters.empty?
method_info[:if_string] = "if MacOS.version == :#{on_system_option}"
else
method_info[:on_system_string] = "#{method_info[:method]} :#{on_method_parameters.first}"
if_condition_operator = MACOS_VERSION_CONDITIONALS.key(on_method_parameters.first)
method_info[:if_string] = "if MacOS.version #{if_condition_operator} :#{on_system_option}"
end
end
elsif method_info[:method] == :on_system
on_system_method_call(method) do |macos_symbol|
base_os, condition = macos_symbol.to_s.split(/_(?=or_)/).map(&:to_sym)
method_info[:on_system_string] = if condition.present?
"on_system :linux, macos: :#{base_os}_#{condition}"
else
"on_system :linux, macos: :#{base_os}"
end
if_condition_operator = MACOS_VERSION_CONDITIONALS.key(condition)
method_info[:if_string] = "if OS.linux? || MacOS.version #{if_condition_operator} :#{base_os}"
end
end
offending_node(method)
problem "Don't use `#{method_info[:on_system_string]}` in `#{top_level_node_string}`, " \
"use `#{method_info[:if_string]}` instead." do |corrector|
block_node = offending_node.parent
next if block_node.type != :block
# TODO: could fix corrector to handle this but punting for now.
next if block_node.single_line?
source_range = offending_node.source_range.join(offending_node.parent.loc.begin)
corrector.replace(source_range, method_info[:if_string])
end
end
end
audit_on_system_blocks(block_node, formula_block_name) if block_node
end
# Don't restrict OS.mac? or OS.linux? usage in taps; they don't care
@ -483,115 +400,19 @@ module RuboCop
# that case.
return if formula_tap != "homebrew-core"
ALL_SYSTEM_OPTIONS.each do |on_system_option|
method_info = on_system_method_info(on_system_option)
audit_arch_conditionals(body_node,
allowed_methods: NO_ON_SYSTEM_METHOD_NAMES,
allowed_blocks: NO_ON_SYSTEM_BLOCK_NAMES)
if_nodes_to_check = []
audit_base_os_conditionals(body_node,
allowed_methods: NO_ON_SYSTEM_METHOD_NAMES,
allowed_blocks: NO_ON_SYSTEM_BLOCK_NAMES)
if ON_ARCH_OPTIONS.include?(on_system_option)
if_arch_node_search(body_node, arch: method_info[:if_method]) do |if_node, else_node|
else_info = if else_node.present?
{
can_autocorrect: true,
on_system_method: (on_system_option == :intel) ? "on_arm" : "on_intel",
node: else_node,
}
end
if_nodes_to_check << [if_node, else_info]
end
elsif ON_BASE_OS_OPTIONS.include?(on_system_option)
if_base_os_node_search(body_node, base_os: method_info[:if_method]) do |if_node, else_node|
else_info = if else_node.present?
{
can_autocorrect: true,
on_system_method: (on_system_option == :macos) ? "on_linux" : "on_macos",
node: else_node,
}
end
if_nodes_to_check << [if_node, else_info]
end
else
if_macos_version_node_search(body_node, os_name: on_system_option) do |if_node, operator, else_node|
if operator == :<
method_info[:on_system_string] = "on_system"
elsif operator == :<=
method_info[:on_system_string] = "on_system :linux, macos: :#{on_system_option}_or_older"
elsif operator != :== && MACOS_VERSION_CONDITIONALS.key?(operator.to_s)
method_info[:on_system_string] = "#{method_info[:method]} " \
":#{MACOS_VERSION_CONDITIONALS[operator.to_s]}"
end
method_info[:if_string] = "if #{method_info[:if_module]}.#{method_info[:if_method]} #{operator} " \
":#{on_system_option}"
if else_node.present? || !MACOS_VERSION_CONDITIONALS.key?(operator.to_s)
else_info = { can_autocorrect: false }
end
if_nodes_to_check << [if_node, else_info]
end
end
if_nodes_to_check.each do |if_node, else_info|
# TODO: check to see if it's legal
valid = T.let(false, T::Boolean)
if_node.each_ancestor do |ancestor|
valid_method_names = case ancestor.type
when :def
NO_ON_SYSTEM_METHOD_NAMES
when :block
NO_ON_SYSTEM_BLOCK_NAMES
else
next
end
next unless valid_method_names.include?(ancestor.method_name)
valid = true
break
end
next if valid
offending_node(if_node)
problem "Don't use `#{method_info[:if_string]}`, " \
"use `#{method_info[:on_system_string]} do` instead." do |corrector|
# TODO: could fix corrector to handle this but punting for now.
next if if_node.unless?
if else_info.present?
next unless else_info[:can_autocorrect]
corrector.replace(if_node.source_range,
"#{method_info[:on_system_string]} do\n#{if_node.body.source}\nend\n" \
"#{else_info[:on_system_method]} do\n#{else_info[:node].source}\nend")
else
corrector.replace(if_node.source_range,
"#{method_info[:on_system_string]} do\n#{if_node.body.source}\nend")
end
end
end
end
audit_macos_version_conditionals(body_node,
allowed_methods: NO_ON_SYSTEM_METHOD_NAMES,
allowed_blocks: NO_ON_SYSTEM_BLOCK_NAMES,
recommend_on_system: true)
end
def_node_matcher :on_macos_version_method_call, <<~PATTERN
(send nil? %on_method (sym ${:or_newer :or_older})?)
PATTERN
def_node_matcher :on_system_method_call, <<~PATTERN
(send nil? :on_system (sym :linux) (hash (pair (sym :macos) (sym $_))))
PATTERN
def_node_search :if_arch_node_search, <<~PATTERN
$(if (send (const (const nil? :Hardware) :CPU) %arch) _ $_)
PATTERN
def_node_search :if_base_os_node_search, <<~PATTERN
$(if (send (const nil? :OS) %base_os) _ $_)
PATTERN
def_node_search :if_macos_version_node_search, <<~PATTERN
$(if (send (send (const nil? :MacOS) :version) ${:== :<= :< :>= :> :!=} (sym %os_name)) _ $_)
PATTERN
end
# This cop checks for other miscellaneous style violations.

View File

@ -16,6 +16,8 @@ require_relative "cask/mixin/on_url_stanza"
require_relative "cask/desc"
require_relative "cask/homepage_url_trailing_slash"
require_relative "cask/no_dsl_version"
require_relative "cask/on_system_conditionals"
require_relative "cask/stanza_order"
require_relative "cask/stanza_grouping"
require_relative "cask/url_legacy_comma_separators"
require_relative "cask/variables"

View File

@ -0,0 +1,196 @@
# typed: false
# frozen_string_literal: true
require "macos_versions"
require "rubocops/shared/helper_functions"
module RuboCop
module Cop
# This module performs common checks on `on_{system}` blocks in both formulae and casks.
#
# @api private
module OnSystemConditionalsHelper
extend NodePattern::Macros
include HelperFunctions
ARCH_OPTIONS = [:arm, :intel].freeze
BASE_OS_OPTIONS = [:macos, :linux].freeze
MACOS_VERSION_OPTIONS = MacOSVersions::SYMBOLS.keys.freeze
ON_SYSTEM_OPTIONS = [*ARCH_OPTIONS, *BASE_OS_OPTIONS, *MACOS_VERSION_OPTIONS, :system].freeze
MACOS_VERSION_CONDITIONALS = {
"==" => nil,
"<=" => :or_older,
">=" => :or_newer,
}.freeze
def audit_on_system_blocks(body_node, parent_name)
parent_string = if body_node.def_type?
"def #{parent_name}"
else
"#{parent_name} do"
end
ON_SYSTEM_OPTIONS.each do |on_system_option|
on_system_method = :"on_#{on_system_option}"
if_statement_string = if ARCH_OPTIONS.include?(on_system_option)
"if Hardware::CPU.#{on_system_option}?"
elsif BASE_OS_OPTIONS.include?(on_system_option)
"if OS.#{(on_system_option == :macos) ? "mac" : "linux"}?"
elsif on_system_option == :system
"if OS.linux? || MacOS.version"
else
"if MacOS.version"
end
find_every_method_call_by_name(body_node, on_system_method).each do |on_system_node|
if_conditional = ""
if MACOS_VERSION_OPTIONS.include? on_system_option
on_macos_version_method_call(on_system_node, on_method: on_system_method) do |on_method_parameters|
if on_method_parameters.empty?
if_conditional = " == :#{on_system_option}"
else
if_condition_operator = MACOS_VERSION_CONDITIONALS.key(on_method_parameters.first)
if_conditional = " #{if_condition_operator} :#{on_system_option}"
end
end
elsif on_system_option == :system
on_system_method_call(on_system_node) do |macos_symbol|
base_os, condition = macos_symbol.to_s.split(/_(?=or_)/).map(&:to_sym)
if_condition_operator = MACOS_VERSION_CONDITIONALS.key(condition)
if_conditional = " #{if_condition_operator} :#{base_os}"
end
end
offending_node(on_system_node)
problem "Don't use `#{on_system_node.source}` in `#{parent_string}`, " \
"use `#{if_statement_string}#{if_conditional}` instead." do |corrector|
block_node = offending_node.parent
next if block_node.type != :block
# TODO: could fix corrector to handle this but punting for now.
next if block_node.single_line?
source_range = offending_node.source_range.join(offending_node.parent.loc.begin)
corrector.replace(source_range, "#{if_statement_string}#{if_conditional}")
end
end
end
end
def audit_arch_conditionals(body_node, allowed_methods: [], allowed_blocks: [])
ARCH_OPTIONS.each do |arch_option|
else_method = (arch_option == :arm) ? :on_intel : :on_arm
if_arch_node_search(body_node, arch: :"#{arch_option}?") do |if_node, else_node|
next if if_node_is_allowed?(if_node, allowed_methods: allowed_methods, allowed_blocks: allowed_blocks)
if_statement_problem(if_node, "if Hardware::CPU.#{arch_option}?", "on_#{arch_option}",
else_method: else_method, else_node: else_node)
end
end
end
def audit_base_os_conditionals(body_node, allowed_methods: [], allowed_blocks: [])
BASE_OS_OPTIONS.each do |base_os_option|
os_method, else_method = if base_os_option == :macos
[:mac?, :on_linux]
else
[:linux?, :on_macos]
end
if_base_os_node_search(body_node, base_os: os_method) do |if_node, else_node|
next if if_node_is_allowed?(if_node, allowed_methods: allowed_methods, allowed_blocks: allowed_blocks)
if_statement_problem(if_node, "if OS.#{os_method}", "on_#{base_os_option}",
else_method: else_method, else_node: else_node)
end
end
end
def audit_macos_version_conditionals(body_node, allowed_methods: [], allowed_blocks: [],
recommend_on_system: true)
MACOS_VERSION_OPTIONS.each do |macos_version_option|
if_macos_version_node_search(body_node, os_version: macos_version_option) do |if_node, operator, else_node|
next if if_node_is_allowed?(if_node, allowed_methods: allowed_methods, allowed_blocks: allowed_blocks)
autocorrect = else_node.blank? && MACOS_VERSION_CONDITIONALS.key?(operator.to_s)
on_system_method_string = if recommend_on_system && operator == :<
"on_system"
elsif recommend_on_system && operator == :<=
"on_system :linux, macos: :#{macos_version_option}_or_older"
elsif operator != :== && MACOS_VERSION_CONDITIONALS.key?(operator.to_s)
"on_#{macos_version_option} :#{MACOS_VERSION_CONDITIONALS[operator.to_s]}"
else
"on_#{macos_version_option}"
end
if_statement_problem(if_node, "if MacOS.version #{operator} :#{macos_version_option}",
on_system_method_string, autocorrect: autocorrect)
end
end
end
private
def if_statement_problem(if_node, if_statement_string, on_system_method_string,
else_method: nil, else_node: nil, autocorrect: true)
offending_node(if_node)
problem "Don't use `#{if_statement_string}`, " \
"use `#{on_system_method_string} do` instead." do |corrector|
next unless autocorrect
# TODO: could fix corrector to handle this but punting for now.
next if if_node.unless?
if else_method.present? && else_node.present?
corrector.replace(if_node.source_range,
"#{on_system_method_string} do\n#{if_node.body.source}\nend\n" \
"#{else_method} do\n#{else_node.source}\nend")
else
corrector.replace(if_node.source_range, "#{on_system_method_string} do\n#{if_node.body.source}\nend")
end
end
end
def if_node_is_allowed?(if_node, allowed_methods: [], allowed_blocks: [])
# TODO: check to see if it's legal
valid = false
if_node.each_ancestor do |ancestor|
valid_method_names = case ancestor.type
when :def
allowed_methods
when :block
allowed_blocks
else
next
end
next unless valid_method_names.include?(ancestor.method_name)
valid = true
break
end
return true if valid
false
end
def_node_matcher :on_macos_version_method_call, <<~PATTERN
(send nil? %on_method (sym ${:or_newer :or_older})?)
PATTERN
def_node_matcher :on_system_method_call, <<~PATTERN
(send nil? :on_system (sym :linux) (hash (pair (sym :macos) (sym $_))))
PATTERN
def_node_search :if_arch_node_search, <<~PATTERN
$(if (send (const (const nil? :Hardware) :CPU) %arch) _ $_)
PATTERN
def_node_search :if_base_os_node_search, <<~PATTERN
$(if (send (const nil? :OS) %base_os) _ $_)
PATTERN
def_node_search :if_macos_version_node_search, <<~PATTERN
$(if (send (send (const nil? :MacOS) :version) ${:== :<= :< :>= :> :!=} (sym %os_version)) _ $_)
PATTERN
end
end
end

View File

@ -28,6 +28,11 @@ module Homebrew
@service_block = block
end
sig { returns(Formula) }
def f
@formula
end
sig { params(command: T.nilable(T.any(T::Array[String], String, Pathname))).returns(T.nilable(Array)) }
def run(command = nil)
case T.unsafe(command)

View File

@ -292,6 +292,7 @@ class Cmd
args.concat(optflags) unless runtime_cpu_detection?
args.concat(archflags)
args << "-std=#{@arg0}" if /c[89]9/.match?(@arg0)
args << "-g" if debug_symbols?
args
end
@ -410,6 +411,10 @@ class Cmd
config.include?("w")
end
def debug_symbols?
config.include?("D")
end
def canonical_path(path)
path = Pathname.new(path)
path = path.realpath if path.exist?

View File

@ -8,8 +8,8 @@ module Homebrew
class TapAuditor
extend T::Sig
attr_reader :name, :path, :formula_names, :cask_tokens, :tap_audit_exceptions, :tap_style_exceptions,
:tap_pypi_formula_mappings, :problems
attr_reader :name, :path, :formula_names, :formula_aliases, :cask_tokens,
:tap_audit_exceptions, :tap_style_exceptions, :tap_pypi_formula_mappings, :problems
sig { params(tap: Tap, strict: T.nilable(T::Boolean)).void }
def initialize(tap, strict:)
@ -21,6 +21,7 @@ module Homebrew
@tap_pypi_formula_mappings = tap.pypi_formula_mappings
@problems = []
@formula_aliases = tap.aliases
@formula_names = tap.formula_names.map do |formula_name|
formula_name.split("/").last
end
@ -68,7 +69,9 @@ module Homebrew
list = list.keys if list.is_a? Hash
invalid_formulae_casks = list.select do |formula_or_cask_name|
@formula_names.exclude?(formula_or_cask_name) && @cask_tokens.exclude?("#{@name}/#{formula_or_cask_name}")
formula_names.exclude?(formula_or_cask_name) &&
formula_aliases.exclude?(formula_or_cask_name) &&
cask_tokens.exclude?("#{@name}/#{formula_or_cask_name}")
end
return if invalid_formulae_casks.empty?

View File

@ -205,5 +205,12 @@ describe "ENV" do
expect(env["HOMEBREW_CCCFG"]).to include("g")
end
end
describe "#set_debug_symbols" do
it "sets the debug symbols flag" do
env.set_debug_symbols
expect(env["HOMEBREW_CCCFG"]).to include("D")
end
end
end
end

View File

@ -411,6 +411,53 @@ describe Cask::Audit, :cask do
end
end
describe "signing checks" do
let(:download_double) { instance_double(Cask::Download) }
let(:unpack_double) { instance_double(UnpackStrategy::Zip) }
before do
allow(audit).to receive(:download).and_return(download_double)
allow(audit).to receive(:signing?).and_return(true)
allow(audit).to receive(:check_https_availability)
end
context "when cask is not using a signed artifact" do
let(:cask) do
tmp_cask "signing-cask-test", <<~RUBY
cask 'signing-cask-test' do
version '1.0'
url "https://brew.sh/index.html"
binary 'Audit.app'
end
RUBY
end
it "does not fail" do
expect(download_double).not_to receive(:fetch)
expect(UnpackStrategy).not_to receive(:detect)
expect(run).not_to warn_with(/Audit\.app/)
end
end
context "when cask is using a signed artifact" do
let(:cask) do
tmp_cask "signing-cask-test", <<~RUBY
cask 'signing-cask-test' do
version '1.0'
url "https://brew.sh/"
pkg 'Audit.app'
end
RUBY
end
it "does not fail since no extract" do
allow(download_double).to receive(:fetch).and_return(Pathname.new("/tmp/test.zip"))
allow(UnpackStrategy).to receive(:detect).and_return(nil)
expect(run).not_to warn_with(/Audit\.app/)
end
end
end
describe "livecheck should be skipped" do
let(:online) { true }
let(:message) { /Version '[^']*' differs from '[^']*' retrieved by livecheck\./ }
@ -888,7 +935,7 @@ describe Cask::Audit, :cask do
end
describe "audit of downloads" do
let(:cask_token) { "with-binary" }
let(:cask_token) { "basic-cask" }
let(:cask) { Cask::CaskLoader.load(cask_token) }
let(:download_double) { instance_double(Cask::Download) }
let(:message) { "Download Failed" }
@ -896,10 +943,11 @@ describe Cask::Audit, :cask do
before do
allow(audit).to receive(:download).and_return(download_double)
allow(audit).to receive(:check_https_availability)
allow(UnpackStrategy).to receive(:detect).and_return(nil)
end
it "when download and verification succeed it does not fail" do
expect(download_double).to receive(:fetch)
expect(download_double).to receive(:fetch).and_return(Pathname.new("/tmp/test.zip"))
expect(run).to pass
end

View File

@ -214,7 +214,7 @@ describe Cask::Cask, :cask do
describe "#to_hash_with_variations" do
let!(:original_macos_version) { MacOS.full_version.to_s }
let(:expected_variations) {
let(:expected_versions_variations) {
<<~JSON
{
"arm64_big_sur": {
@ -243,6 +243,28 @@ describe Cask::Cask, :cask do
}
JSON
}
let(:expected_sha256_variations) {
<<~JSON
{
"monterey": {
"url": "file://#{TEST_FIXTURE_DIR}/cask/caffeine-intel.zip",
"sha256": "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b"
},
"big_sur": {
"url": "file://#{TEST_FIXTURE_DIR}/cask/caffeine-intel.zip",
"sha256": "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b"
},
"catalina": {
"url": "file://#{TEST_FIXTURE_DIR}/cask/caffeine-intel.zip",
"sha256": "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b"
},
"mojave": {
"url": "file://#{TEST_FIXTURE_DIR}/cask/caffeine-intel.zip",
"sha256": "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b"
}
}
JSON
}
before do
# Use a more limited symbols list to shorten the variations hash
@ -263,12 +285,20 @@ describe Cask::Cask, :cask do
MacOS.full_version = original_macos_version
end
it "returns the correct variations hash" do
it "returns the correct variations hash for a cask with multiple versions" do
c = Cask::CaskLoader.load("multiple-versions")
h = c.to_hash_with_variations
expect(h).to be_a(Hash)
expect(JSON.pretty_generate(h["variations"])).to eq expected_variations.strip
expect(JSON.pretty_generate(h["variations"])).to eq expected_versions_variations.strip
end
it "returns the correct variations hash for a cask different sha256s on each arch" do
c = Cask::CaskLoader.load("sha256-arch")
h = c.to_hash_with_variations
expect(h).to be_a(Hash)
expect(JSON.pretty_generate(h["variations"])).to eq expected_sha256_variations.strip
end
end
end

View File

@ -8,7 +8,7 @@ describe Cask::Cmd::Info, :cask do
expect {
described_class.run("local-transmission")
}.to output(<<~EOS).to_stdout
local-transmission: 2.61
==> local-transmission: 2.61
https://transmissionbt.com/
Not installed
From: https://github.com/Homebrew/homebrew-cask/blob/HEAD/Casks/local-transmission.rb
@ -25,7 +25,7 @@ describe Cask::Cmd::Info, :cask do
expect {
described_class.run("with-auto-updates")
}.to output(<<~EOS).to_stdout
with-auto-updates: 1.0 (auto_updates)
==> with-auto-updates: 1.0 (auto_updates)
https://brew.sh/autoupdates
Not installed
From: https://github.com/Homebrew/homebrew-cask/blob/HEAD/Casks/with-auto-updates.rb
@ -41,7 +41,7 @@ describe Cask::Cmd::Info, :cask do
describe "given multiple Casks" do
let(:expected_output) {
<<~EOS
local-caffeine: 1.2.3
==> local-caffeine: 1.2.3
https://brew.sh/
Not installed
From: https://github.com/Homebrew/homebrew-cask/blob/HEAD/Casks/local-caffeine.rb
@ -52,7 +52,7 @@ describe Cask::Cmd::Info, :cask do
==> Artifacts
Caffeine.app (App)
local-transmission: 2.61
==> local-transmission: 2.61
https://transmissionbt.com/
Not installed
From: https://github.com/Homebrew/homebrew-cask/blob/HEAD/Casks/local-transmission.rb
@ -76,7 +76,7 @@ describe Cask::Cmd::Info, :cask do
expect {
described_class.run("with-caveats")
}.to output(<<~EOS).to_stdout
with-caveats: 1.2.3
==> with-caveats: 1.2.3
https://brew.sh/
Not installed
From: https://github.com/Homebrew/homebrew-cask/blob/HEAD/Casks/with-caveats.rb
@ -103,7 +103,7 @@ describe Cask::Cmd::Info, :cask do
expect {
described_class.run("with-conditional-caveats")
}.to output(<<~EOS).to_stdout
with-conditional-caveats: 1.2.3
==> with-conditional-caveats: 1.2.3
https://brew.sh/
Not installed
From: https://github.com/Homebrew/homebrew-cask/blob/HEAD/Casks/with-conditional-caveats.rb
@ -120,7 +120,7 @@ describe Cask::Cmd::Info, :cask do
expect {
described_class.run("with-languages")
}.to output(<<~EOS).to_stdout
with-languages: 1.2.3
==> with-languages: 1.2.3
https://brew.sh/
Not installed
From: https://github.com/Homebrew/homebrew-cask/blob/HEAD/Casks/with-languages.rb
@ -139,7 +139,7 @@ describe Cask::Cmd::Info, :cask do
expect {
described_class.run("without-languages")
}.to output(<<~EOS).to_stdout
without-languages: 1.2.3
==> without-languages: 1.2.3
https://brew.sh/
Not installed
From: https://github.com/Homebrew/homebrew-cask/blob/HEAD/Casks/without-languages.rb

View File

@ -126,6 +126,34 @@ describe Cask::DSL, :cask do
expect(cask.sha256).to eq("imasha2")
end
context "with a different arm and intel checksum" do
let(:cask) do
Cask::Cask.new("checksum-cask") do
sha256 arm: "imasha2arm", intel: "imasha2intel"
end
end
context "when running on arm" do
before do
allow(Hardware::CPU).to receive(:type).and_return(:arm)
end
it "stores only the arm checksum" do
expect(cask.sha256).to eq("imasha2arm")
end
end
context "when running on intel" do
before do
allow(Hardware::CPU).to receive(:type).and_return(:intel)
end
it "stores only the intel checksum" do
expect(cask.sha256).to eq("imasha2intel")
end
end
end
end
describe "language stanza" do

View File

@ -72,4 +72,16 @@ describe "brew install" do
.and be_a_success
expect(HOMEBREW_CELLAR/"testball1/HEAD-d5eb689/foo/test").not_to be_a_file
end
it "installs formulae with debug symbols", :integration_test do
setup_test_formula "testball1"
expect { brew "install", "testball1", "--debug-symbols", "--build-from-source" }
.to output(%r{#{HOMEBREW_CELLAR}/testball1/0\.1}o).to_stdout
.and not_to_output.to_stderr
.and be_a_success
expect(HOMEBREW_CELLAR/"testball1/0.1/bin/test").to be_a_file
expect(HOMEBREW_CELLAR/"testball1/0.1/bin/test.dSYM/Contents/Resources/DWARF/test").to be_a_file if OS.mac?
expect(HOMEBREW_CACHE/"Sources/testball1").to be_a_directory
end
end

View File

@ -18,7 +18,7 @@ describe CompilerSelector do
end
before do
allow(versions).to receive(:non_apple_gcc_version) do |name|
allow(versions).to receive(:gcc_version) do |name|
case name
when "gcc-7" then Version.create("7.1")
when "gcc-6" then Version.create("6.1")

View File

@ -149,7 +149,7 @@ describe Formula do
end
end
it "returns true by default" do
it "returns array with versioned formulae" do
FileUtils.touch f.path
FileUtils.touch f2.path
allow(Formulary).to receive(:load_formula_from_path).with(f2.name, f2.path).and_return(f2)
@ -1996,4 +1996,28 @@ describe Formula do
}.to raise_error("ignore_missing_libraries is available on Linux only")
end
end
describe "#generate_completions_from_executable" do
let(:f) do
Class.new(Testball) do
def install
bin.mkpath
(bin/"foo").write <<-EOF
echo completion
EOF
FileUtils.chmod "+x", bin/"foo"
generate_completions_from_executable(bin/"foo", "test")
end
end.new
end
it "generates completion scripts" do
f.brew { f.install }
expect(f.bash_completion/"testball").to be_a_file
expect(f.zsh_completion/"_testball").to be_a_file
expect(f.fish_completion/"testball.fish").to be_a_file
end
end
end

View File

@ -21,7 +21,7 @@ describe Language::Python::Shebang do
before do
file.write <<~EOS
#!/usr/bin/env python3
#!/usr/bin/python2
a
b
c
@ -34,7 +34,7 @@ describe Language::Python::Shebang do
describe "#detected_python_shebang" do
it "can be used to replace Python shebangs" do
expect(Formulary).to receive(:factory).with(python_f.name).and_return(python_f)
Utils::Shebang.rewrite_shebang described_class.detected_python_shebang(f), file
Utils::Shebang.rewrite_shebang described_class.detected_python_shebang(f, use_python_from_path: false), file
expect(File.read(file)).to eq <<~EOS
#!#{HOMEBREW_PREFIX}/opt/python@3.11/bin/python3.11
@ -43,5 +43,16 @@ describe Language::Python::Shebang do
c
EOS
end
it "can be pointed to a `python3` in PATH" do
Utils::Shebang.rewrite_shebang described_class.detected_python_shebang(f, use_python_from_path: true), file
expect(File.read(file)).to eq <<~EOS
#!/usr/bin/env python3
a
b
c
EOS
end
end
end

View File

@ -103,7 +103,7 @@ describe Homebrew::MissingFormula do
let(:formula) { "local-caffeine" }
let(:show_info) { true }
it { is_expected.to match(/Found a cask named "local-caffeine" instead.\n\nlocal-caffeine: 1.2.3\n/) }
it { is_expected.to match(/Found a cask named "local-caffeine" instead.\n\n==> local-caffeine: 1.2.3\n/) }
end
context "with a formula name that is not a cask" do

View File

@ -0,0 +1,140 @@
# typed: false
# frozen_string_literal: true
require "rubocops/rubocop-cask"
require "test/rubocops/cask/shared_examples/cask_cop"
describe RuboCop::Cop::Cask::OnSystemConditionals do
include CaskCop
subject(:cop) { described_class.new }
context "when auditing `postflight` stanzas" do
context "when there are no on_system blocks" do
let(:source) do
<<-CASK.undent
postflight do
foobar
end
CASK
end
include_examples "does not report any offenses"
end
context "when there is an `on_intel` block" do
let(:source) do
<<-CASK.undent
cask 'foo' do
postflight do
on_intel do
foobar
end
end
end
CASK
end
let(:correct_source) do
<<-CASK.undent
cask 'foo' do
postflight do
if Hardware::CPU.intel?
foobar
end
end
end
CASK
end
let(:expected_offenses) do
[{
message: "Don't use `on_intel` in `postflight do`, use `if Hardware::CPU.intel?` instead.",
severity: :convention,
line: 3,
column: 4,
source: "on_intel",
}]
end
include_examples "reports offenses"
include_examples "autocorrects source"
end
context "when there is an `on_monterey` block" do
let(:source) do
<<-CASK.undent
cask 'foo' do
postflight do
on_monterey do
foobar
end
end
end
CASK
end
let(:correct_source) do
<<-CASK.undent
cask 'foo' do
postflight do
if MacOS.version == :monterey
foobar
end
end
end
CASK
end
let(:expected_offenses) do
[{
message: "Don't use `on_monterey` in `postflight do`, use `if MacOS.version == :monterey` instead.",
severity: :convention,
line: 3,
column: 4,
source: "on_monterey",
}]
end
include_examples "reports offenses"
include_examples "autocorrects source"
end
context "when there is an `on_monterey :or_older` block" do
let(:source) do
<<-CASK.undent
cask 'foo' do
postflight do
on_monterey :or_older do
foobar
end
end
end
CASK
end
let(:correct_source) do
<<-CASK.undent
cask 'foo' do
postflight do
if MacOS.version <= :monterey
foobar
end
end
end
CASK
end
let(:expected_offenses) do
[{
message: "Don't use `on_monterey :or_older` in `postflight do`, " \
"use `if MacOS.version <= :monterey` instead.",
severity: :convention,
line: 3,
column: 4,
source: "on_monterey :or_older",
}]
end
include_examples "reports offenses"
include_examples "autocorrects source"
end
end
end

View File

@ -41,6 +41,22 @@ describe RuboCop::Cop::Cask::StanzaGrouping do
include_examples "does not report any offenses"
end
context "when no stanzas or variable assignments are incorrectly grouped" do
let(:source) do
<<-CASK.undent
cask 'foo' do
arch arm: "arm64", intel: "x86_64"
folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin"
version :latest
sha256 :no_check
end
CASK
end
include_examples "does not report any offenses"
end
context "when one stanza is incorrectly grouped" do
let(:source) do
<<-CASK.undent
@ -74,6 +90,78 @@ describe RuboCop::Cop::Cask::StanzaGrouping do
include_examples "autocorrects source"
end
context "when the arch stanza is incorrectly grouped" do
let(:source) do
<<-CASK.undent
cask 'foo' do
arch arm: "arm64", intel: "x86_64"
version :latest
sha256 :no_check
end
CASK
end
let(:correct_source) do
<<-CASK.undent
cask 'foo' do
arch arm: "arm64", intel: "x86_64"
version :latest
sha256 :no_check
end
CASK
end
let(:expected_offenses) do
[{
message: missing_line_msg,
severity: :convention,
line: 3,
column: 0,
source: " version :latest",
}]
end
include_examples "reports offenses"
include_examples "autocorrects source"
end
context "when one variable assignment is incorrectly grouped" do
let(:source) do
<<-CASK.undent
cask 'foo' do
arch arm: "arm64", intel: "x86_64"
folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin"
version :latest
sha256 :no_check
end
CASK
end
let(:correct_source) do
<<-CASK.undent
cask 'foo' do
arch arm: "arm64", intel: "x86_64"
folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin"
version :latest
sha256 :no_check
end
CASK
end
let(:expected_offenses) do
[{
message: missing_line_msg,
severity: :convention,
line: 4,
column: 0,
source: " version :latest",
}]
end
include_examples "reports offenses"
include_examples "autocorrects source"
end
context "when many stanzas are incorrectly grouped" do
let(:source) do
<<-CASK.undent
@ -142,6 +230,94 @@ describe RuboCop::Cop::Cask::StanzaGrouping do
include_examples "autocorrects source"
end
context "when many stanzas and variable assignments are incorrectly grouped" do
let(:source) do
<<-CASK.undent
cask 'foo' do
arch arm: "arm64", intel: "x86_64"
folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin"
platform = on_arch_conditional arm: "darwin-arm64", intel: "darwin"
version :latest
sha256 :no_check
url 'https://foo.brew.sh/foo.zip'
name 'Foo'
homepage 'https://foo.brew.sh'
app 'Foo.app'
uninstall :quit => 'com.example.foo',
:kext => 'com.example.foo.kextextension'
end
CASK
end
let(:correct_source) do
<<-CASK.undent
cask 'foo' do
arch arm: "arm64", intel: "x86_64"
folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin"
platform = on_arch_conditional arm: "darwin-arm64", intel: "darwin"
version :latest
sha256 :no_check
url 'https://foo.brew.sh/foo.zip'
name 'Foo'
homepage 'https://foo.brew.sh'
app 'Foo.app'
uninstall :quit => 'com.example.foo',
:kext => 'com.example.foo.kextextension'
end
CASK
end
let(:expected_offenses) do
[{
message: extra_line_msg,
severity: :convention,
line: 4,
column: 0,
source: "\n",
}, {
message: missing_line_msg,
severity: :convention,
line: 6,
column: 0,
source: " version :latest",
}, {
message: missing_line_msg,
severity: :convention,
line: 8,
column: 0,
source: " url 'https://foo.brew.sh/foo.zip'",
}, {
message: extra_line_msg,
severity: :convention,
line: 9,
column: 0,
source: "\n",
}, {
message: extra_line_msg,
severity: :convention,
line: 11,
column: 0,
source: "\n",
}, {
message: missing_line_msg,
severity: :convention,
line: 15,
column: 0,
source: " uninstall :quit => 'com.example.foo',",
}]
end
include_examples "reports offenses"
include_examples "autocorrects source"
end
context "when caveats stanza is incorrectly grouped" do
let(:source) do
format(<<-CASK.undent, caveats: caveats.strip)
@ -284,6 +460,52 @@ describe RuboCop::Cop::Cask::StanzaGrouping do
include_examples "autocorrects source"
end
context "when a stanza has a comment and there is a variable assignment" do
let(:source) do
<<-CASK.undent
cask 'foo' do
arch arm: "arm64", intel: "x86_64"
folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin"
# comment with an empty line between
version :latest
sha256 :no_check
# comment directly above
postflight do
puts 'We have liftoff!'
end
url 'https://foo.brew.sh/foo.zip'
name 'Foo'
app 'Foo.app'
end
CASK
end
let(:correct_source) do
<<-CASK.undent
cask 'foo' do
arch arm: "arm64", intel: "x86_64"
folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin"
# comment with an empty line between
version :latest
sha256 :no_check
# comment directly above
postflight do
puts 'We have liftoff!'
end
url 'https://foo.brew.sh/foo.zip'
name 'Foo'
app 'Foo.app'
end
CASK
end
include_examples "autocorrects source"
end
# TODO: detect incorrectly grouped stanzas in nested expressions
context "when stanzas are nested in a conditional expression" do
let(:source) do

View File

@ -25,8 +25,11 @@ describe RuboCop::Cop::Cask::StanzaOrder do
let(:source) do
<<-CASK.undent
cask 'foo' do
arch arm: "arm", intel: "x86_64"
folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin"
version :latest
sha256 :no_check
foo = "bar"
end
CASK
end
@ -72,6 +75,136 @@ describe RuboCop::Cop::Cask::StanzaOrder do
include_examples "autocorrects source"
end
context "when the arch stanza is out of order" do
let(:source) do
<<-CASK.undent
cask 'foo' do
version :latest
sha256 :no_check
arch arm: "arm", intel: "x86_64"
end
CASK
end
let(:correct_source) do
<<-CASK.undent
cask 'foo' do
arch arm: "arm", intel: "x86_64"
version :latest
sha256 :no_check
end
CASK
end
let(:expected_offenses) do
[{
message: "`version` stanza out of order",
severity: :convention,
line: 2,
column: 2,
source: "version :latest",
}, {
message: "`sha256` stanza out of order",
severity: :convention,
line: 3,
column: 2,
source: "sha256 :no_check",
}, {
message: "`arch` stanza out of order",
severity: :convention,
line: 4,
column: 2,
source: 'arch arm: "arm", intel: "x86_64"',
}]
end
include_examples "reports offenses"
include_examples "autocorrects source"
end
context "when an arch variable assignment is out of order" do
let(:source) do
<<-CASK.undent
cask 'foo' do
arch arm: "arm", intel: "x86_64"
sha256 :no_check
version :latest
folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin"
end
CASK
end
let(:correct_source) do
<<-CASK.undent
cask 'foo' do
arch arm: "arm", intel: "x86_64"
folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin"
version :latest
sha256 :no_check
end
CASK
end
let(:expected_offenses) do
[{
message: "`sha256` stanza out of order",
severity: :convention,
line: 3,
column: 2,
source: "sha256 :no_check",
}, {
message: "`on_arch_conditional` stanza out of order",
severity: :convention,
line: 5,
column: 2,
source: 'folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin"',
}]
end
include_examples "reports offenses"
include_examples "autocorrects source"
end
context "when an arch variable assignment is above the arch stanza" do
let(:source) do
<<-CASK.undent
cask 'foo' do
folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin"
arch arm: "arm", intel: "x86_64"
version :latest
sha256 :no_check
end
CASK
end
let(:correct_source) do
<<-CASK.undent
cask 'foo' do
arch arm: "arm", intel: "x86_64"
folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin"
version :latest
sha256 :no_check
end
CASK
end
let(:expected_offenses) do
[{
message: "`on_arch_conditional` stanza out of order",
severity: :convention,
line: 2,
column: 2,
source: 'folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin"',
}, {
message: "`arch` stanza out of order",
severity: :convention,
line: 3,
column: 2,
source: 'arch arm: "arm", intel: "x86_64"',
}]
end
include_examples "reports offenses"
include_examples "autocorrects source"
end
context "when many stanzas are out of order" do
let(:source) do
<<-CASK.undent
@ -197,6 +330,41 @@ describe RuboCop::Cop::Cask::StanzaOrder do
include_examples "autocorrects source"
end
context "when a variable assignment is out of order with a comment" do
let(:source) do
<<-CASK.undent
cask 'foo' do
version :latest
sha256 :no_check
# comment with an empty line between
# comment directly above
postflight do
puts 'We have liftoff!'
end
folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin" # comment on same line
end
CASK
end
let(:correct_source) do
<<-CASK.undent
cask 'foo' do
folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin" # comment on same line
version :latest
sha256 :no_check
# comment with an empty line between
# comment directly above
postflight do
puts 'We have liftoff!'
end
end
CASK
end
include_examples "autocorrects source"
end
context "when the caveats stanza is out of order" do
let(:source) do
format(<<-CASK.undent, caveats: caveats.strip)

View File

@ -0,0 +1,282 @@
# typed: false
# frozen_string_literal: true
require "rubocops/rubocop-cask"
require "test/rubocops/cask/shared_examples/cask_cop"
describe RuboCop::Cop::Cask::Variables do
include CaskCop
subject(:cop) { described_class.new }
context "when there are no variables" do
let(:source) do
<<-CASK.undent
cask "foo" do
version :latest
end
CASK
end
include_examples "does not report any offenses"
end
context "when there is an arch stanza" do
let(:source) do
<<-CASK.undent
cask "foo" do
arch arm: "darwin-arm64", intel: "darwin"
end
CASK
end
include_examples "does not report any offenses"
end
context "when there is a non-arch variable that uses the arch conditional" do
let(:source) do
<<-CASK.undent
cask "foo" do
folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin"
end
CASK
end
include_examples "does not report any offenses"
end
context "when there is an arch variable" do
let(:source) do
<<-CASK.undent
cask 'foo' do
arch = Hardware::CPU.intel? ? "darwin" : "darwin-arm64"
end
CASK
end
let(:correct_source) do
<<-CASK.undent
cask 'foo' do
arch arm: "darwin-arm64", intel: "darwin"
end
CASK
end
let(:expected_offenses) do
[{
message: 'Use `arch arm: "darwin-arm64", intel: "darwin"` instead of ' \
'`arch = Hardware::CPU.intel? ? "darwin" : "darwin-arm64"`',
severity: :convention,
line: 2,
column: 2,
source: 'arch = Hardware::CPU.intel? ? "darwin" : "darwin-arm64"',
}]
end
include_examples "reports offenses"
include_examples "autocorrects source"
end
context "when there is an arch variable that doesn't use strings" do
let(:source) do
<<-CASK.undent
cask 'foo' do
arch = Hardware::CPU.intel? ? :darwin : :darwin_arm64
end
CASK
end
let(:correct_source) do
<<-CASK.undent
cask 'foo' do
arch arm: :darwin_arm64, intel: :darwin
end
CASK
end
let(:expected_offenses) do
[{
message: "Use `arch arm: :darwin_arm64, intel: :darwin` instead of " \
"`arch = Hardware::CPU.intel? ? :darwin : :darwin_arm64`",
severity: :convention,
line: 2,
column: 2,
source: "arch = Hardware::CPU.intel? ? :darwin : :darwin_arm64",
}]
end
include_examples "reports offenses"
include_examples "autocorrects source"
end
context "when there is an arch with an empty string" do
let(:source) do
<<-CASK.undent
cask 'foo' do
arch = Hardware::CPU.intel? ? "" : "arm64"
end
CASK
end
let(:correct_source) do
<<-CASK.undent
cask 'foo' do
arch arm: "arm64"
end
CASK
end
let(:expected_offenses) do
[{
message: 'Use `arch arm: "arm64"` instead of ' \
'`arch = Hardware::CPU.intel? ? "" : "arm64"`',
severity: :convention,
line: 2,
column: 2,
source: 'arch = Hardware::CPU.intel? ? "" : "arm64"',
}]
end
include_examples "reports offenses"
include_examples "autocorrects source"
end
context "when there is a non-arch variable" do
let(:source) do
<<-CASK.undent
cask 'foo' do
folder = Hardware::CPU.intel? ? "darwin" : "darwin-arm64"
end
CASK
end
let(:correct_source) do
<<-CASK.undent
cask 'foo' do
folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin"
end
CASK
end
let(:expected_offenses) do
[{
message: 'Use `folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin"` instead of ' \
'`folder = Hardware::CPU.intel? ? "darwin" : "darwin-arm64"`',
severity: :convention,
line: 2,
column: 2,
source: 'folder = Hardware::CPU.intel? ? "darwin" : "darwin-arm64"',
}]
end
include_examples "reports offenses"
include_examples "autocorrects source"
end
context "when there is a non-arch variable with an empty string" do
let(:source) do
<<-CASK.undent
cask 'foo' do
folder = Hardware::CPU.intel? ? "amd64" : ""
end
CASK
end
let(:correct_source) do
<<-CASK.undent
cask 'foo' do
folder = on_arch_conditional intel: "amd64"
end
CASK
end
let(:expected_offenses) do
[{
message: 'Use `folder = on_arch_conditional intel: "amd64"` instead of ' \
'`folder = Hardware::CPU.intel? ? "amd64" : ""`',
severity: :convention,
line: 2,
column: 2,
source: 'folder = Hardware::CPU.intel? ? "amd64" : ""',
}]
end
include_examples "reports offenses"
include_examples "autocorrects source"
end
context "when there is an arch and a non-arch variable" do
let(:source) do
<<-CASK.undent
cask 'foo' do
arch = Hardware::CPU.arm? ? "darwin-arm64" : "darwin"
folder = Hardware::CPU.arm? ? "darwin-arm64" : "darwin"
end
CASK
end
let(:correct_source) do
<<-CASK.undent
cask 'foo' do
arch arm: "darwin-arm64", intel: "darwin"
folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin"
end
CASK
end
let(:expected_offenses) do
[{
message: 'Use `arch arm: "darwin-arm64", intel: "darwin"` instead of ' \
'`arch = Hardware::CPU.arm? ? "darwin-arm64" : "darwin"`',
severity: :convention,
line: 2,
column: 2,
source: 'arch = Hardware::CPU.arm? ? "darwin-arm64" : "darwin"',
}, {
message: 'Use `folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin"` instead of ' \
'`folder = Hardware::CPU.arm? ? "darwin-arm64" : "darwin"`',
severity: :convention,
line: 3,
column: 2,
source: 'folder = Hardware::CPU.arm? ? "darwin-arm64" : "darwin"',
}]
end
include_examples "reports offenses"
include_examples "autocorrects source"
end
context "when there are two non-arch variables" do
let(:source) do
<<-CASK.undent
cask 'foo' do
folder = Hardware::CPU.arm? ? "darwin-arm64" : "darwin"
platform = Hardware::CPU.intel? ? "darwin": "darwin-arm64"
end
CASK
end
let(:correct_source) do
<<-CASK.undent
cask 'foo' do
folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin"
platform = on_arch_conditional arm: "darwin-arm64", intel: "darwin"
end
CASK
end
let(:expected_offenses) do
[{
message: 'Use `folder = on_arch_conditional arm: "darwin-arm64", intel: "darwin"` instead of ' \
'`folder = Hardware::CPU.arm? ? "darwin-arm64" : "darwin"`',
severity: :convention,
line: 2,
column: 2,
source: 'folder = Hardware::CPU.arm? ? "darwin-arm64" : "darwin"',
}, {
message: 'Use `platform = on_arch_conditional arm: "darwin-arm64", intel: "darwin"` instead of ' \
'`platform = Hardware::CPU.intel? ? "darwin": "darwin-arm64"`',
severity: :convention,
line: 3,
column: 2,
source: 'platform = Hardware::CPU.intel? ? "darwin": "darwin-arm64"',
}]
end
include_examples "reports offenses"
include_examples "autocorrects source"
end
end

View File

@ -0,0 +1,12 @@
cask "sha256-arch" do
arch arm: "arm", intel: "intel"
version "1.2.3"
sha256 arm: "67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94",
intel: "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b"
url "file://#{TEST_FIXTURE_DIR}/cask/caffeine-#{arch}.zip"
homepage "https://brew.sh/"
app "Caffeine.app"
end

View File

@ -24,6 +24,7 @@ module Homebrew
build_from_source_formulae: [],
interactive: false,
keep_tmp: false,
debug_symbols: false,
force: false,
debug: false,
quiet: false,
@ -61,6 +62,7 @@ module Homebrew
build_from_source_formulae: build_from_source_formulae,
interactive: interactive,
keep_tmp: keep_tmp,
debug_symbols: debug_symbols,
force: force,
debug: debug,
quiet: quiet,
@ -128,6 +130,7 @@ module Homebrew
build_from_source_formulae: [],
interactive: false,
keep_tmp: false,
debug_symbols: false,
force: false,
debug: false,
quiet: false,
@ -161,6 +164,7 @@ module Homebrew
build_from_source_formulae: build_from_source_formulae,
interactive: interactive,
keep_tmp: keep_tmp,
debug_symbols: debug_symbols,
force: force,
debug: debug,
quiet: quiet,
@ -254,6 +258,7 @@ module Homebrew
build_from_source_formulae: [],
interactive: false,
keep_tmp: false,
debug_symbols: false,
force: false,
debug: false,
quiet: false,
@ -339,6 +344,7 @@ module Homebrew
build_from_source_formulae: build_from_source_formulae,
interactive: interactive,
keep_tmp: keep_tmp,
debug_symbols: debug_symbols,
force: force,
debug: debug,
quiet: quiet,
@ -407,6 +413,7 @@ module Homebrew
build_from_source_formulae: build_from_source_formulae + [formula.full_name],
interactive: interactive,
keep_tmp: keep_tmp,
debug_symbols: debug_symbols,
force: force,
debug: debug,
quiet: quiet,

View File

@ -125,7 +125,7 @@ module Kernel
puts sput unless sput.empty?
end
def oh1(title, truncate: :auto)
def oh1_title(title, truncate: :auto)
verbose = if respond_to?(:verbose?)
verbose?
else
@ -133,7 +133,11 @@ module Kernel
end
title = Tty.truncate(title) if $stdout.tty? && !verbose && truncate == :auto
puts Formatter.headline(title, color: :green)
Formatter.headline(title, color: :green)
end
def oh1(title, truncate: :auto)
puts oh1_title(title, truncate: truncate)
end
# Print a message prefixed with "Warning" (do this rarely).

View File

@ -5,16 +5,16 @@ ruby_version = RbConfig::CONFIG["ruby_version"]
path = File.expand_path('..', __FILE__)
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/concurrent-ruby-1.1.10/lib/concurrent-ruby"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/i18n-1.12.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/minitest-5.16.2/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/minitest-5.16.3/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/tzinfo-2.0.5/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/zeitwerk-2.6.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/activesupport-6.1.6.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/public_suffix-4.0.7/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/addressable-2.8.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/public_suffix-5.0.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/addressable-2.8.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ast-2.4.2/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/bindata-2.4.10/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/x86_64-darwin-15/2.6.0-static/msgpack-1.5.4"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/msgpack-1.5.4/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/x86_64-darwin-15/2.6.0-static/msgpack-1.5.5"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/msgpack-1.5.5/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/x86_64-darwin-15/2.6.0-static/bootsnap-1.13.0"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/bootsnap-1.13.0/lib"
$:.unshift "#{path}/"
@ -86,7 +86,7 @@ $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec_junit_formatter
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-ast-1.21.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-progressbar-1.11.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unicode-display_width-2.2.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-1.34.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-1.35.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-performance-1.14.3/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-rails-2.15.2/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-rspec-2.12.1/lib"
@ -103,5 +103,5 @@ $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/thor-1.2.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/spoom-1.1.11/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/yard-0.9.28/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/yard-sorbet-0.6.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/tapioca-0.7.2/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/tapioca-0.7.3/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/warning-1.3.0/lib"

View File

@ -1,6 +1,5 @@
# frozen_string_literal: true
# encoding:utf-8
#--
# Copyright (C) Bob Aman
#
@ -657,12 +656,12 @@ module Addressable
def ordered_variable_defaults
@ordered_variable_defaults ||= begin
expansions, _ = parse_template_pattern(pattern)
expansions.map do |capture|
expansions.flat_map do |capture|
_, _, varlist = *capture.match(EXPRESSION)
varlist.split(',').map do |varspec|
varspec[VARSPEC, 1]
end
end.flatten
end
end
end
@ -1023,7 +1022,7 @@ module Addressable
end
# Ensure that the regular expression matches the whole URI.
regexp_string = "^#{regexp_string}$"
regexp_string = "\\A#{regexp_string}\\z"
return expansions, Regexp.new(regexp_string)
end

View File

@ -1,6 +1,5 @@
# frozen_string_literal: true
# encoding:utf-8
#--
# Copyright (C) Bob Aman
#
@ -38,20 +37,26 @@ module Addressable
##
# Container for the character classes specified in
# <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>.
#
# Note: Concatenated and interpolated `String`s are not affected by the
# `frozen_string_literal` directive and must be frozen explicitly.
#
# Interpolated `String`s *were* frozen this way before Ruby 3.0:
# https://bugs.ruby-lang.org/issues/17104
module CharacterClasses
ALPHA = "a-zA-Z"
DIGIT = "0-9"
GEN_DELIMS = "\\:\\/\\?\\#\\[\\]\\@"
SUB_DELIMS = "\\!\\$\\&\\'\\(\\)\\*\\+\\,\\;\\="
RESERVED = GEN_DELIMS + SUB_DELIMS
UNRESERVED = ALPHA + DIGIT + "\\-\\.\\_\\~"
PCHAR = UNRESERVED + SUB_DELIMS + "\\:\\@"
SCHEME = ALPHA + DIGIT + "\\-\\+\\."
HOST = UNRESERVED + SUB_DELIMS + "\\[\\:\\]"
AUTHORITY = PCHAR + "\\[\\:\\]"
PATH = PCHAR + "\\/"
QUERY = PCHAR + "\\/\\?"
FRAGMENT = PCHAR + "\\/\\?"
RESERVED = (GEN_DELIMS + SUB_DELIMS).freeze
UNRESERVED = (ALPHA + DIGIT + "\\-\\.\\_\\~").freeze
PCHAR = (UNRESERVED + SUB_DELIMS + "\\:\\@").freeze
SCHEME = (ALPHA + DIGIT + "\\-\\+\\.").freeze
HOST = (UNRESERVED + SUB_DELIMS + "\\[\\:\\]").freeze
AUTHORITY = (PCHAR + "\\[\\:\\]").freeze
PATH = (PCHAR + "\\/").freeze
QUERY = (PCHAR + "\\/\\?").freeze
FRAGMENT = (PCHAR + "\\/\\?").freeze
end
module NormalizeCharacterClasses
@ -469,19 +474,13 @@ module Addressable
"Expected Class (String or Addressable::URI), " +
"got #{return_type.inspect}"
end
uri = uri.dup
# Seriously, only use UTF-8. I'm really not kidding!
uri.force_encoding("utf-8")
unless leave_encoded.empty?
leave_encoded = leave_encoded.dup.force_encoding("utf-8")
end
result = uri.gsub(/%[0-9a-f]{2}/iu) do |sequence|
result = uri.gsub(/%[0-9a-f]{2}/i) do |sequence|
c = sequence[1..3].to_i(16).chr
c.force_encoding("utf-8")
c.force_encoding(sequence.encoding)
leave_encoded.include?(c) ? sequence : c
end
result.force_encoding("utf-8")
if return_type == String
return result
@ -561,10 +560,10 @@ module Addressable
leave_re = if leave_encoded.length > 0
character_class = "#{character_class}%" unless character_class.include?('%')
"|%(?!#{leave_encoded.chars.map do |char|
"|%(?!#{leave_encoded.chars.flat_map do |char|
seq = SEQUENCE_ENCODING_TABLE[char]
[seq.upcase, seq.downcase]
end.flatten.join('|')})"
end.join('|')})"
end
character_class = if leave_re
@ -900,7 +899,7 @@ module Addressable
end
end
# All normalized values should be UTF-8
@normalized_scheme.force_encoding(Encoding::UTF_8) if @normalized_scheme
force_utf8_encoding_if_needed(@normalized_scheme)
@normalized_scheme
end
@ -955,7 +954,7 @@ module Addressable
end
end
# All normalized values should be UTF-8
@normalized_user.force_encoding(Encoding::UTF_8) if @normalized_user
force_utf8_encoding_if_needed(@normalized_user)
@normalized_user
end
@ -1012,9 +1011,7 @@ module Addressable
end
end
# All normalized values should be UTF-8
if @normalized_password
@normalized_password.force_encoding(Encoding::UTF_8)
end
force_utf8_encoding_if_needed(@normalized_password)
@normalized_password
end
@ -1082,9 +1079,7 @@ module Addressable
end
end
# All normalized values should be UTF-8
if @normalized_userinfo
@normalized_userinfo.force_encoding(Encoding::UTF_8)
end
force_utf8_encoding_if_needed(@normalized_userinfo)
@normalized_userinfo
end
@ -1151,9 +1146,7 @@ module Addressable
end
end
# All normalized values should be UTF-8
if @normalized_host && !@normalized_host.empty?
@normalized_host.force_encoding(Encoding::UTF_8)
end
force_utf8_encoding_if_needed(@normalized_host)
@normalized_host
end
@ -1271,9 +1264,7 @@ module Addressable
authority
end
# All normalized values should be UTF-8
if @normalized_authority
@normalized_authority.force_encoding(Encoding::UTF_8)
end
force_utf8_encoding_if_needed(@normalized_authority)
@normalized_authority
end
@ -1507,7 +1498,7 @@ module Addressable
site_string
end
# All normalized values should be UTF-8
@normalized_site.force_encoding(Encoding::UTF_8) if @normalized_site
force_utf8_encoding_if_needed(@normalized_site)
@normalized_site
end
@ -1570,7 +1561,7 @@ module Addressable
result
end
# All normalized values should be UTF-8
@normalized_path.force_encoding(Encoding::UTF_8) if @normalized_path
force_utf8_encoding_if_needed(@normalized_path)
@normalized_path
end
@ -1646,7 +1637,7 @@ module Addressable
component == "" ? nil : component
end
# All normalized values should be UTF-8
@normalized_query.force_encoding(Encoding::UTF_8) if @normalized_query
force_utf8_encoding_if_needed(@normalized_query)
@normalized_query
end
@ -1842,9 +1833,7 @@ module Addressable
component == "" ? nil : component
end
# All normalized values should be UTF-8
if @normalized_fragment
@normalized_fragment.force_encoding(Encoding::UTF_8)
end
force_utf8_encoding_if_needed(@normalized_fragment)
@normalized_fragment
end
@ -2440,30 +2429,35 @@ module Addressable
def self.normalize_path(path)
# Section 5.2.4 of RFC 3986
return nil if path.nil?
return if path.nil?
normalized_path = path.dup
begin
mod = nil
loop do
mod ||= normalized_path.gsub!(RULE_2A, SLASH)
pair = normalized_path.match(RULE_2B_2C)
parent, current = pair[1], pair[2] if pair
if pair
parent = pair[1]
current = pair[2]
else
parent = nil
current = nil
end
regexp = "/#{Regexp.escape(parent.to_s)}/\\.\\./|"
regexp += "(/#{Regexp.escape(current.to_s)}/\\.\\.$)"
if pair && ((parent != SELF_REF && parent != PARENT) ||
(current != SELF_REF && current != PARENT))
mod ||= normalized_path.gsub!(
Regexp.new(
"/#{Regexp.escape(parent.to_s)}/\\.\\./|" +
"(/#{Regexp.escape(current.to_s)}/\\.\\.$)"
), SLASH
)
mod ||= normalized_path.gsub!(Regexp.new(regexp), SLASH)
end
mod ||= normalized_path.gsub!(RULE_2D, EMPTY_STR)
# Non-standard, removes prefixed dotted segments from path.
mod ||= normalized_path.gsub!(RULE_PREFIXED_PARENT, SLASH)
end until mod.nil?
break if mod.nil?
end
return normalized_path
normalized_path
end
##
@ -2552,5 +2546,15 @@ module Addressable
remove_instance_variable(:@uri_string) if defined?(@uri_string)
remove_instance_variable(:@hash) if defined?(@hash)
end
##
# Converts the string to be UTF-8 if it is not already UTF-8
#
# @api private
def force_utf8_encoding_if_needed(str)
if str && str.encoding != Encoding::UTF_8
str.force_encoding(Encoding::UTF_8)
end
end
end
end

View File

@ -1,6 +1,5 @@
# frozen_string_literal: true
# encoding:utf-8
#--
# Copyright (C) Bob Aman
#
@ -24,7 +23,7 @@ if !defined?(Addressable::VERSION)
module VERSION
MAJOR = 2
MINOR = 8
TINY = 0
TINY = 1
STRING = [MAJOR, MINOR, TINY].join('.')
end

View File

@ -1340,7 +1340,7 @@ tt.im
tv.im
// in : https://en.wikipedia.org/wiki/.in
// see also: https://registry.in/Policies
// see also: https://registry.in/policies
// Please note, that nic.in is not an official eTLD, but used by most
// government institutions.
in
@ -7130,7 +7130,7 @@ org.zw
// newGTLDs
// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2022-03-27T15:13:38Z
// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2022-07-03T15:13:53Z
// This list is auto-generated, don't edit it manually.
// aaa : 2015-02-26 American Automobile Association, Inc.
aaa
@ -7471,7 +7471,7 @@ bio
// black : 2014-01-16 Afilias Limited
black
// blackfriday : 2014-01-16 UNR Corp.
// blackfriday : 2014-01-16 Registry Services, LLC
blackfriday
// blockbuster : 2015-07-30 Dish DBS Corporation
@ -7687,7 +7687,7 @@ chanel
// channel : 2014-05-08 Charleston Road Registry Inc.
channel
// charity : 2018-04-11 Binky Moon, LLC
// charity : 2018-04-11 Public Interest Registry
charity
// chase : 2015-04-30 JPMorgan Chase Bank, National Association
@ -7834,7 +7834,7 @@ coupon
// coupons : 2015-03-26 Binky Moon, LLC
coupons
// courses : 2014-12-04 OPEN UNIVERSITIES AUSTRALIA PTY LTD
// courses : 2014-12-04 Registry Services, LLC
courses
// cpa : 2019-06-10 American Institute of Certified Public Accountants
@ -8020,7 +8020,7 @@ dvag
// dvr : 2016-05-26 DISH Technologies L.L.C.
dvr
// earth : 2014-12-04 Interlink Co., Ltd.
// earth : 2014-12-04 Interlink Systems Innovation Institute K.K.
earth
// eat : 2014-01-23 Charleston Road Registry Inc.
@ -8227,7 +8227,7 @@ forsale
// forum : 2015-04-02 Fegistry, LLC
forum
// foundation : 2013-12-05 Binky Moon, LLC
// foundation : 2013-12-05 Public Interest Registry
foundation
// fox : 2015-09-11 FOX Registry, LLC
@ -8308,7 +8308,7 @@ gdn
// gea : 2014-12-04 GEA Group Aktiengesellschaft
gea
// gent : 2014-01-23 COMBELL NV
// gent : 2014-01-23 Easyhost BV
gent
// genting : 2015-03-12 Resorts World Inc Pte. Ltd.
@ -8326,7 +8326,7 @@ gift
// gifts : 2014-07-03 Binky Moon, LLC
gifts
// gives : 2014-03-06 Dog Beach, LLC
// gives : 2014-03-06 Public Interest Registry
gives
// giving : 2014-11-13 Giving Limited
@ -8452,7 +8452,7 @@ health
// healthcare : 2014-06-12 Binky Moon, LLC
healthcare
// help : 2014-06-26 UNR Corp.
// help : 2014-06-26 Innovation service Limited
help
// helsinki : 2015-02-05 City of Helsinki
@ -8851,7 +8851,7 @@ lincoln
// linde : 2014-12-04 Linde Aktiengesellschaft
linde
// link : 2013-11-14 UNR Corp.
// link : 2013-11-14 Nova Registry Ltd
link
// lipsy : 2015-06-25 Lipsy Ltd
@ -8866,7 +8866,7 @@ living
// llc : 2017-12-14 Afilias Limited
llc
// llp : 2019-08-26 UNR Corp.
// llp : 2019-08-26 Intercap Registry Inc.
llp
// loan : 2014-11-20 dot Loan Limited
@ -9034,7 +9034,7 @@ mobile
// moda : 2013-11-07 Dog Beach, LLC
moda
// moe : 2013-11-13 Interlink Co., Ltd.
// moe : 2013-11-13 Interlink Systems Innovation Institute K.K.
moe
// moi : 2014-12-18 Amazon Registry Services, Inc.
@ -9307,7 +9307,7 @@ philips
// phone : 2016-06-02 Dish DBS Corporation
phone
// photo : 2013-11-14 UNR Corp.
// photo : 2013-11-14 Registry Services, LLC
photo
// photography : 2013-09-20 Binky Moon, LLC
@ -9550,7 +9550,7 @@ rsvp
// rugby : 2016-12-15 World Rugby Strategic Developments Limited
rugby
// ruhr : 2013-10-02 regiodot GmbH & Co. KG
// ruhr : 2013-10-02 dotSaarland GmbH
ruhr
// run : 2015-03-19 Binky Moon, LLC
@ -9841,7 +9841,7 @@ stream
// studio : 2015-02-11 Dog Beach, LLC
studio
// study : 2014-12-11 OPEN UNIVERSITIES AUSTRALIA PTY LTD
// study : 2014-12-11 Registry Services, LLC
study
// style : 2014-12-04 Binky Moon, LLC
@ -9901,7 +9901,7 @@ tatamotors
// tatar : 2014-04-24 Limited Liability Company "Coordination Center of Regional Domain of Tatarstan Republic"
tatar
// tattoo : 2013-08-30 UNR Corp.
// tattoo : 2013-08-30 Top Level Design, LLC
tattoo
// tax : 2014-03-20 Binky Moon, LLC
@ -12111,6 +12111,7 @@ kill.jp
kilo.jp
kuron.jp
littlestar.jp
lolipopmc.jp
lolitapunk.jp
lomo.jp
lovepop.jp
@ -12281,6 +12282,10 @@ blogspot.vn
// Submitted by Niels Martignene <hello@goupile.fr>
goupile.fr
// Government of the Netherlands: https://www.government.nl
// Submitted by <domeinnaam@minaz.nl>
gov.nl
// Group 53, LLC : https://www.group53.com
// Submitted by Tyler Todd <noc@nova53.net>
awsmppl.com
@ -12357,7 +12362,6 @@ ltd.ng
ngo.ng
edu.scot
sch.so
org.yt
// HostyHosting (hostyhosting.com)
hostyhosting.io
@ -12375,6 +12379,11 @@ moonscale.net
// Submitted by Hannu Aronsson <haa@iki.fi>
iki.fi
// iliad italia: https://www.iliad.it
// Submitted by Marios Makassikis <mmakassikis@freebox.fr>
ibxos.it
iliadboxos.it
// Impertrix Solutions : <https://impertrixcdn.com>
// Submitted by Zhixiang Zhao <csuite@impertrix.com>
impertrixcdn.com
@ -12455,9 +12464,11 @@ iopsys.se
// Submitted by Matthew Hardeman <mhardeman@ipifony.com>
ipifony.net
// IServ GmbH : https://iserv.eu
// Submitted by Kim-Alexander Brodowski <info@iserv.eu>
// IServ GmbH : https://iserv.de
// Submitted by Mario Hoberg <info@iserv.de>
iservschule.de
mein-iserv.de
schulplattform.de
schulserver.de
test-iserv.de
iserv.dev
@ -12779,6 +12790,10 @@ hra.health
miniserver.com
memset.net
// Messerli Informatik AG : https://www.messerli.ch/
// Submitted by Ruben Schmidmeister <psl-maintainers@messerli.ch>
messerli.app
// MetaCentrum, CESNET z.s.p.o. : https://www.metacentrum.cz/en/
// Submitted by Zdeněk Šustr <zdenek.sustr@cesnet.cz>
*.cloud.metacentrum.cz
@ -12798,12 +12813,13 @@ eu.meteorapp.com
co.pl
// Microsoft Corporation : http://microsoft.com
// Submitted by Mitch Webster <miwebst@microsoft.com>
// Submitted by Public Suffix List Admin <msftpsladmin@microsoft.com>
*.azurecontainer.io
azurewebsites.net
azure-mobile.net
cloudapp.net
azurestaticapps.net
1.azurestaticapps.net
centralus.azurestaticapps.net
eastasia.azurestaticapps.net
eastus2.azurestaticapps.net
@ -13388,6 +13404,12 @@ rocky.page
спб.рус
я.рус
// Salesforce.com, Inc. https://salesforce.com/
// Submitted by Michael Biven <mbiven@salesforce.com>
*.builder.code.com
*.dev-builder.code.com
*.stg-builder.code.com
// Sandstorm Development Group, Inc. : https://sandcats.io/
// Submitted by Asheesh Laroia <asheesh@sandstorm.io>
sandcats.io
@ -13811,6 +13833,15 @@ hk.org
ltd.hk
inc.hk
// UNIVERSAL DOMAIN REGISTRY : https://www.udr.org.yt/
// see also: whois -h whois.udr.org.yt help
// Submitted by Atanunu Igbunuroghene <publicsuffixlist@udr.org.yt>
name.pm
sch.tf
biz.wf
sch.wf
org.yt
// United Gameserver GmbH : https://united-gameserver.de
// Submitted by Stefan Schwarz <sysadm@united-gameserver.de>
virtualuser.de

View File

@ -169,7 +169,7 @@ module PublicSuffix
return DomainInvalid.new("Name is blank") if name.empty?
return DomainInvalid.new("Name starts with a dot") if name.start_with?(DOT)
return DomainInvalid.new("%s is not expected to contain a scheme" % name) if name.include?("://")
return DomainInvalid.new(format("%s is not expected to contain a scheme", name)) if name.include?("://")
name
end

Some files were not shown because too many files have changed in this diff Show More