mirror of
https://github.com/Homebrew/brew.git
synced 2025-07-14 16:09:03 +08:00
Bump some utils/
files to Sorbet typed: strict
This commit is contained in:
parent
55475cb11a
commit
975a707b3c
@ -1,4 +1,4 @@
|
|||||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
# typed: strict
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "context"
|
require "context"
|
||||||
@ -60,7 +60,7 @@ module Utils
|
|||||||
puts Utils.popen_read(curl, *args, url)
|
puts Utils.popen_read(curl, *args, url)
|
||||||
else
|
else
|
||||||
pid = spawn curl, *args, url
|
pid = spawn curl, *args, url
|
||||||
Process.detach T.must(pid)
|
Process.detach(pid)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -161,52 +161,62 @@ module Utils
|
|||||||
report_influx(:test_bot_test, tags, fields)
|
report_influx(:test_bot_test, tags, fields)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
def influx_message_displayed?
|
def influx_message_displayed?
|
||||||
config_true?(:influxanalyticsmessage)
|
config_true?(:influxanalyticsmessage)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
def messages_displayed?
|
def messages_displayed?
|
||||||
config_true?(:analyticsmessage) &&
|
!!(config_true?(:analyticsmessage) &&
|
||||||
config_true?(:caskanalyticsmessage) &&
|
config_true?(:caskanalyticsmessage) &&
|
||||||
influx_message_displayed?
|
influx_message_displayed?)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
def disabled?
|
def disabled?
|
||||||
return true if Homebrew::EnvConfig.no_analytics?
|
return true if Homebrew::EnvConfig.no_analytics?
|
||||||
|
|
||||||
config_true?(:analyticsdisabled)
|
config_true?(:analyticsdisabled)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
def not_this_run?
|
def not_this_run?
|
||||||
ENV["HOMEBREW_NO_ANALYTICS_THIS_RUN"].present?
|
ENV["HOMEBREW_NO_ANALYTICS_THIS_RUN"].present?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
def no_message_output?
|
def no_message_output?
|
||||||
# Used by Homebrew/install
|
# Used by Homebrew/install
|
||||||
ENV["HOMEBREW_NO_ANALYTICS_MESSAGE_OUTPUT"].present?
|
ENV["HOMEBREW_NO_ANALYTICS_MESSAGE_OUTPUT"].present?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { void }
|
||||||
def messages_displayed!
|
def messages_displayed!
|
||||||
Homebrew::Settings.write :analyticsmessage, true
|
Homebrew::Settings.write :analyticsmessage, true
|
||||||
Homebrew::Settings.write :caskanalyticsmessage, true
|
Homebrew::Settings.write :caskanalyticsmessage, true
|
||||||
Homebrew::Settings.write :influxanalyticsmessage, true
|
Homebrew::Settings.write :influxanalyticsmessage, true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { void }
|
||||||
def enable!
|
def enable!
|
||||||
Homebrew::Settings.write :analyticsdisabled, false
|
Homebrew::Settings.write :analyticsdisabled, false
|
||||||
delete_uuid!
|
delete_uuid!
|
||||||
messages_displayed!
|
messages_displayed!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { void }
|
||||||
def disable!
|
def disable!
|
||||||
Homebrew::Settings.write :analyticsdisabled, true
|
Homebrew::Settings.write :analyticsdisabled, true
|
||||||
delete_uuid!
|
delete_uuid!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { void }
|
||||||
def delete_uuid!
|
def delete_uuid!
|
||||||
Homebrew::Settings.delete :analyticsuuid
|
Homebrew::Settings.delete :analyticsuuid
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(args: Homebrew::Cmd::Info::Args, filter: T.nilable(String)).void }
|
||||||
def output(args:, filter: nil)
|
def output(args:, filter: nil)
|
||||||
require "api"
|
require "api"
|
||||||
|
|
||||||
@ -244,6 +254,7 @@ module Utils
|
|||||||
table_output(category, days, results, os_version:, cask_install:)
|
table_output(category, days, results, os_version:, cask_install:)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(json: T::Hash[String, T.untyped], args: Homebrew::Cmd::Info::Args).void }
|
||||||
def output_analytics(json, args:)
|
def output_analytics(json, args:)
|
||||||
full_analytics = args.analytics? || verbose?
|
full_analytics = args.analytics? || verbose?
|
||||||
|
|
||||||
@ -273,6 +284,7 @@ module Utils
|
|||||||
# It relies on screen scraping some GitHub HTML that's not available as an API.
|
# It relies on screen scraping some GitHub HTML that's not available as an API.
|
||||||
# This seems very likely to break in the future.
|
# This seems very likely to break in the future.
|
||||||
# That said, it's the only way to get the data we want right now.
|
# That said, it's the only way to get the data we want right now.
|
||||||
|
sig { params(formula: Formula, args: Homebrew::Cmd::Info::Args).void }
|
||||||
def output_github_packages_downloads(formula, args:)
|
def output_github_packages_downloads(formula, args:)
|
||||||
return unless args.github_packages_downloads?
|
return unless args.github_packages_downloads?
|
||||||
return unless formula.core_formula?
|
return unless formula.core_formula?
|
||||||
@ -316,6 +328,7 @@ module Utils
|
|||||||
puts "#{number_readable(thirty_day_download_count)} (30 days)"
|
puts "#{number_readable(thirty_day_download_count)} (30 days)"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(formula: Formula, args: Homebrew::Cmd::Info::Args).void }
|
||||||
def formula_output(formula, args:)
|
def formula_output(formula, args:)
|
||||||
return if Homebrew::EnvConfig.no_analytics? || Homebrew::EnvConfig.no_github_api?
|
return if Homebrew::EnvConfig.no_analytics? || Homebrew::EnvConfig.no_github_api?
|
||||||
|
|
||||||
@ -331,6 +344,7 @@ module Utils
|
|||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(cask: Cask::Cask, args: Homebrew::Cmd::Info::Args).void }
|
||||||
def cask_output(cask, args:)
|
def cask_output(cask, args:)
|
||||||
return if Homebrew::EnvConfig.no_analytics? || Homebrew::EnvConfig.no_github_api?
|
return if Homebrew::EnvConfig.no_analytics? || Homebrew::EnvConfig.no_github_api?
|
||||||
|
|
||||||
@ -388,6 +402,12 @@ module Utils
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig {
|
||||||
|
params(
|
||||||
|
category: String, days: String, results: T::Hash[String, Integer], os_version: T::Boolean,
|
||||||
|
cask_install: T::Boolean
|
||||||
|
).void
|
||||||
|
}
|
||||||
def table_output(category, days, results, os_version: false, cask_install: false)
|
def table_output(category, days, results, os_version: false, cask_install: false)
|
||||||
oh1 "#{category} (#{days} days)"
|
oh1 "#{category} (#{days} days)"
|
||||||
total_count = results.values.inject("+")
|
total_count = results.values.inject("+")
|
||||||
@ -475,14 +495,17 @@ module Utils
|
|||||||
"#{formatted_total_count_footer} | #{formatted_total_percent_footer}%"
|
"#{formatted_total_count_footer} | #{formatted_total_percent_footer}%"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(key: Symbol).returns(T::Boolean) }
|
||||||
def config_true?(key)
|
def config_true?(key)
|
||||||
Homebrew::Settings.read(key) == "true"
|
Homebrew::Settings.read(key) == "true"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(count: Integer).returns(String) }
|
||||||
def format_count(count)
|
def format_count(count)
|
||||||
count.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse
|
count.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(percent: T.any(Integer, Float)).returns(String) }
|
||||||
def format_percent(percent)
|
def format_percent(percent)
|
||||||
format("%<percent>.2f", percent:)
|
format("%<percent>.2f", percent:)
|
||||||
end
|
end
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
# typed: strict
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "fcntl"
|
require "fcntl"
|
||||||
require "utils/socket"
|
require "utils/socket"
|
||||||
|
|
||||||
module Utils
|
module Utils
|
||||||
|
sig { params(child_error: T::Hash[String, T.untyped]).returns(Exception) }
|
||||||
def self.rewrite_child_error(child_error)
|
def self.rewrite_child_error(child_error)
|
||||||
inner_class = Object.const_get(child_error["json_class"])
|
inner_class = Object.const_get(child_error["json_class"])
|
||||||
error = if child_error["cmd"] && inner_class == ErrorDuringExecution
|
error = if child_error["cmd"] && inner_class == ErrorDuringExecution
|
||||||
@ -33,7 +34,11 @@ module Utils
|
|||||||
# When using this function, remember to call `exec` as soon as reasonably possible.
|
# When using this function, remember to call `exec` as soon as reasonably possible.
|
||||||
# This function does not protect against the pitfalls of what you can do pre-exec in a fork.
|
# This function does not protect against the pitfalls of what you can do pre-exec in a fork.
|
||||||
# See `man fork` for more information.
|
# See `man fork` for more information.
|
||||||
def self.safe_fork(directory: nil, yield_parent: false)
|
sig {
|
||||||
|
params(directory: T.nilable(String), yield_parent: T::Boolean,
|
||||||
|
_blk: T.proc.params(arg0: T.nilable(String)).void).void
|
||||||
|
}
|
||||||
|
def self.safe_fork(directory: nil, yield_parent: false, &_blk)
|
||||||
require "json/add/exception"
|
require "json/add/exception"
|
||||||
|
|
||||||
block = proc do |tmpdir|
|
block = proc do |tmpdir|
|
||||||
@ -80,8 +85,6 @@ module Utils
|
|||||||
exit!(true)
|
exit!(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
pid = T.must(pid)
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
yield(nil) if yield_parent
|
yield(nil) if yield_parent
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
# typed: strict
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "utils/inreplace"
|
require "utils/inreplace"
|
||||||
@ -14,20 +14,20 @@ module PyPI
|
|||||||
class Package
|
class Package
|
||||||
sig { params(package_string: String, is_url: T::Boolean, python_name: String).void }
|
sig { params(package_string: String, is_url: T::Boolean, python_name: String).void }
|
||||||
def initialize(package_string, is_url: false, python_name: "python")
|
def initialize(package_string, is_url: false, python_name: "python")
|
||||||
@pypi_info = nil
|
@pypi_info = T.let(nil, T.nilable(T::Array[String]))
|
||||||
@package_string = package_string
|
@package_string = package_string
|
||||||
@is_url = is_url
|
@is_url = is_url
|
||||||
@is_pypi_url = package_string.start_with? PYTHONHOSTED_URL_PREFIX
|
@is_pypi_url = T.let(package_string.start_with?(PYTHONHOSTED_URL_PREFIX), T::Boolean)
|
||||||
@python_name = python_name
|
@python_name = python_name
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { returns(String) }
|
sig { returns(T.nilable(String)) }
|
||||||
def name
|
def name
|
||||||
basic_metadata if @name.blank?
|
basic_metadata if @name.blank?
|
||||||
@name
|
@name
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { returns(T::Array[T.nilable(String)]) }
|
sig { returns(T.nilable(T::Array[String])) }
|
||||||
def extras
|
def extras
|
||||||
basic_metadata if @extras.blank?
|
basic_metadata if @extras.blank?
|
||||||
@extras
|
@extras
|
||||||
@ -43,7 +43,7 @@ module PyPI
|
|||||||
def version=(new_version)
|
def version=(new_version)
|
||||||
raise ArgumentError, "can't update version for non-PyPI packages" unless valid_pypi_package?
|
raise ArgumentError, "can't update version for non-PyPI packages" unless valid_pypi_package?
|
||||||
|
|
||||||
@version = new_version
|
@version = T.let(new_version, T.nilable(String))
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { returns(T::Boolean) }
|
sig { returns(T::Boolean) }
|
||||||
@ -97,8 +97,8 @@ module PyPI
|
|||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
if valid_pypi_package?
|
if valid_pypi_package?
|
||||||
out = name
|
out = T.must(name)
|
||||||
out += "[#{extras.join(",")}]" if extras.present?
|
out += "[#{extras&.join(",")}]" if extras.present?
|
||||||
out += "==#{version}" if version.present?
|
out += "==#{version}" if version.present?
|
||||||
out
|
out
|
||||||
else
|
else
|
||||||
@ -132,14 +132,15 @@ module PyPI
|
|||||||
private
|
private
|
||||||
|
|
||||||
# Returns [name, [extras], version] for this package.
|
# Returns [name, [extras], version] for this package.
|
||||||
|
sig { returns(T.nilable(T.any(String, T::Array[String]))) }
|
||||||
def basic_metadata
|
def basic_metadata
|
||||||
if @is_pypi_url
|
if @is_pypi_url
|
||||||
match = File.basename(@package_string).match(/^(.+)-([a-z\d.]+?)(?:.tar.gz|.zip)$/)
|
match = File.basename(@package_string).match(/^(.+)-([a-z\d.]+?)(?:.tar.gz|.zip)$/)
|
||||||
raise ArgumentError, "Package should be a valid PyPI URL" if match.blank?
|
raise ArgumentError, "Package should be a valid PyPI URL" if match.blank?
|
||||||
|
|
||||||
@name ||= PyPI.normalize_python_package match[1]
|
@name ||= T.let(PyPI.normalize_python_package(T.must(match[1])), T.nilable(String))
|
||||||
@extras ||= []
|
@extras ||= T.let([], T.nilable(T::Array[String]))
|
||||||
@version ||= match[2]
|
@version ||= T.let(match[2], T.nilable(String))
|
||||||
elsif @is_url
|
elsif @is_url
|
||||||
ensure_formula_installed!(@python_name)
|
ensure_formula_installed!(@python_name)
|
||||||
|
|
||||||
@ -162,9 +163,9 @@ module PyPI
|
|||||||
|
|
||||||
metadata = JSON.parse(pip_output)["install"].first["metadata"]
|
metadata = JSON.parse(pip_output)["install"].first["metadata"]
|
||||||
|
|
||||||
@name ||= PyPI.normalize_python_package metadata["name"]
|
@name ||= T.let(PyPI.normalize_python_package(metadata["name"]), T.nilable(String))
|
||||||
@extras ||= []
|
@extras ||= T.let([], T.nilable(T::Array[String]))
|
||||||
@version ||= metadata["version"]
|
@version ||= T.let(metadata["version"], T.nilable(String))
|
||||||
else
|
else
|
||||||
if @package_string.include? "=="
|
if @package_string.include? "=="
|
||||||
name, version = @package_string.split("==")
|
name, version = @package_string.split("==")
|
||||||
@ -180,7 +181,7 @@ module PyPI
|
|||||||
extras = []
|
extras = []
|
||||||
end
|
end
|
||||||
|
|
||||||
@name ||= PyPI.normalize_python_package name
|
@name ||= T.let(PyPI.normalize_python_package(T.must(name)), T.nilable(String))
|
||||||
@extras ||= extras
|
@extras ||= extras
|
||||||
@version ||= version
|
@version ||= version
|
||||||
end
|
end
|
||||||
@ -248,7 +249,7 @@ module PyPI
|
|||||||
missing_msg = "formulae required to update \"#{formula.name}\" resources: #{missing_dependencies.join(", ")}"
|
missing_msg = "formulae required to update \"#{formula.name}\" resources: #{missing_dependencies.join(", ")}"
|
||||||
odie "Missing #{missing_msg}" unless install_dependencies
|
odie "Missing #{missing_msg}" unless install_dependencies
|
||||||
ohai "Installing #{missing_msg}"
|
ohai "Installing #{missing_msg}"
|
||||||
missing_dependencies.each(&method(:ensure_formula_installed!))
|
missing_dependencies.each(&:ensure_formula_installed!)
|
||||||
end
|
end
|
||||||
|
|
||||||
python_deps = formula.deps
|
python_deps = formula.deps
|
||||||
@ -327,12 +328,12 @@ module PyPI
|
|||||||
# Resolve the dependency tree of all input packages
|
# Resolve the dependency tree of all input packages
|
||||||
show_info = !print_only && !silent
|
show_info = !print_only && !silent
|
||||||
ohai "Retrieving PyPI dependencies for \"#{input_packages.join(" ")}\"..." if show_info
|
ohai "Retrieving PyPI dependencies for \"#{input_packages.join(" ")}\"..." if show_info
|
||||||
found_packages = pip_report(input_packages, python_name:, print_stderr: verbose && show_info)
|
found_packages = pip_report(input_packages, python_name:, print_stderr: !!(verbose && show_info))
|
||||||
# Resolve the dependency tree of excluded packages to prune the above
|
# Resolve the dependency tree of excluded packages to prune the above
|
||||||
exclude_packages.delete_if { |package| found_packages.exclude? package }
|
exclude_packages.delete_if { |package| found_packages.exclude? package }
|
||||||
ohai "Retrieving PyPI dependencies for excluded \"#{exclude_packages.join(" ")}\"..." if show_info
|
ohai "Retrieving PyPI dependencies for excluded \"#{exclude_packages.join(" ")}\"..." if show_info
|
||||||
exclude_packages = pip_report(exclude_packages, python_name:, print_stderr: verbose && show_info)
|
exclude_packages = pip_report(exclude_packages, python_name:, print_stderr: !!(verbose && show_info))
|
||||||
exclude_packages += [Package.new(main_package.name)] unless main_package.nil?
|
exclude_packages += [Package.new(T.must(main_package.name))] unless main_package.nil?
|
||||||
|
|
||||||
new_resource_blocks = ""
|
new_resource_blocks = ""
|
||||||
found_packages.sort.each do |package|
|
found_packages.sort.each do |package|
|
||||||
@ -404,12 +405,18 @@ module PyPI
|
|||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(name: String).returns(String) }
|
||||||
def self.normalize_python_package(name)
|
def self.normalize_python_package(name)
|
||||||
# This normalization is defined in the PyPA packaging specifications;
|
# This normalization is defined in the PyPA packaging specifications;
|
||||||
# https://packaging.python.org/en/latest/specifications/name-normalization/#name-normalization
|
# https://packaging.python.org/en/latest/specifications/name-normalization/#name-normalization
|
||||||
name.gsub(/[-_.]+/, "-").downcase
|
name.gsub(/[-_.]+/, "-").downcase
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig {
|
||||||
|
params(
|
||||||
|
packages: T::Array[Package], python_name: String, print_stderr: T::Boolean,
|
||||||
|
).returns(T::Array[Package])
|
||||||
|
}
|
||||||
def self.pip_report(packages, python_name: "python", print_stderr: false)
|
def self.pip_report(packages, python_name: "python", print_stderr: false)
|
||||||
return [] if packages.blank?
|
return [] if packages.blank?
|
||||||
|
|
||||||
@ -430,6 +437,7 @@ module PyPI
|
|||||||
pip_report_to_packages(JSON.parse(pip_output)).uniq
|
pip_report_to_packages(JSON.parse(pip_output)).uniq
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(report: T::Hash[String, T.untyped]).returns(T::Array[Package]) }
|
||||||
def self.pip_report_to_packages(report)
|
def self.pip_report_to_packages(report)
|
||||||
return [] if report.blank?
|
return [] if report.blank?
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
# typed: strict
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Utils
|
module Utils
|
||||||
@ -98,17 +98,20 @@ module Utils
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
SHELL_PROFILE_MAP = {
|
SHELL_PROFILE_MAP = T.let(
|
||||||
bash: "~/.profile",
|
{
|
||||||
csh: "~/.cshrc",
|
bash: "~/.profile",
|
||||||
fish: "~/.config/fish/config.fish",
|
csh: "~/.cshrc",
|
||||||
ksh: "~/.kshrc",
|
fish: "~/.config/fish/config.fish",
|
||||||
mksh: "~/.kshrc",
|
ksh: "~/.kshrc",
|
||||||
rc: "~/.rcrc",
|
mksh: "~/.kshrc",
|
||||||
sh: "~/.profile",
|
rc: "~/.rcrc",
|
||||||
tcsh: "~/.tcshrc",
|
sh: "~/.profile",
|
||||||
zsh: "~/.zshrc",
|
tcsh: "~/.tcshrc",
|
||||||
}.freeze
|
zsh: "~/.zshrc",
|
||||||
|
}.freeze,
|
||||||
|
T::Hash[T.nilable(Symbol), String],
|
||||||
|
)
|
||||||
|
|
||||||
UNSAFE_SHELL_CHAR = %r{([^A-Za-z0-9_\-.,:/@~+\n])}
|
UNSAFE_SHELL_CHAR = %r{([^A-Za-z0-9_\-.,:/@~+\n])}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
# typed: strict
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "utils/curl"
|
require "utils/curl"
|
||||||
@ -8,7 +8,7 @@ require "utils/github"
|
|||||||
module SPDX
|
module SPDX
|
||||||
module_function
|
module_function
|
||||||
|
|
||||||
DATA_PATH = (HOMEBREW_DATA_PATH/"spdx").freeze
|
DATA_PATH = T.let((HOMEBREW_DATA_PATH/"spdx").freeze, Pathname)
|
||||||
API_URL = "https://api.github.com/repos/spdx/license-list-data/releases/latest"
|
API_URL = "https://api.github.com/repos/spdx/license-list-data/releases/latest"
|
||||||
LICENSEREF_PREFIX = "LicenseRef-Homebrew-"
|
LICENSEREF_PREFIX = "LicenseRef-Homebrew-"
|
||||||
ALLOWED_LICENSE_SYMBOLS = [
|
ALLOWED_LICENSE_SYMBOLS = [
|
||||||
@ -16,24 +16,43 @@ module SPDX
|
|||||||
:cannot_represent,
|
:cannot_represent,
|
||||||
].freeze
|
].freeze
|
||||||
|
|
||||||
|
sig { returns(T::Hash[String, T.untyped]) }
|
||||||
def license_data
|
def license_data
|
||||||
@license_data ||= JSON.parse (DATA_PATH/"spdx_licenses.json").read
|
@license_data ||= T.let(JSON.parse((DATA_PATH/"spdx_licenses.json").read), T.nilable(T::Hash[String, T.untyped]))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Hash[String, T.untyped]) }
|
||||||
def exception_data
|
def exception_data
|
||||||
@exception_data ||= JSON.parse (DATA_PATH/"spdx_exceptions.json").read
|
@exception_data ||= T.let(JSON.parse((DATA_PATH/"spdx_exceptions.json").read),
|
||||||
|
T.nilable(T::Hash[String, T.untyped]))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(String) }
|
||||||
def latest_tag
|
def latest_tag
|
||||||
@latest_tag ||= GitHub::API.open_rest(API_URL)["tag_name"]
|
@latest_tag ||= T.let(GitHub::API.open_rest(API_URL)["tag_name"], T.nilable(String))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(to: Pathname).void }
|
||||||
def download_latest_license_data!(to: DATA_PATH)
|
def download_latest_license_data!(to: DATA_PATH)
|
||||||
data_url = "https://raw.githubusercontent.com/spdx/license-list-data/#{latest_tag}/json/"
|
data_url = "https://raw.githubusercontent.com/spdx/license-list-data/#{latest_tag}/json/"
|
||||||
Utils::Curl.curl_download("#{data_url}licenses.json", to: to/"spdx_licenses.json")
|
Utils::Curl.curl_download("#{data_url}licenses.json", to: to/"spdx_licenses.json")
|
||||||
Utils::Curl.curl_download("#{data_url}exceptions.json", to: to/"spdx_exceptions.json")
|
Utils::Curl.curl_download("#{data_url}exceptions.json", to: to/"spdx_exceptions.json")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig {
|
||||||
|
params(
|
||||||
|
license_expression: T.any(
|
||||||
|
String,
|
||||||
|
Symbol,
|
||||||
|
T::Hash[T.any(Symbol, String), T.untyped],
|
||||||
|
T::Array[String],
|
||||||
|
),
|
||||||
|
).returns(
|
||||||
|
[
|
||||||
|
T::Array[T.any(String, Symbol)], T::Array[String]
|
||||||
|
],
|
||||||
|
)
|
||||||
|
}
|
||||||
def parse_license_expression(license_expression)
|
def parse_license_expression(license_expression)
|
||||||
licenses = T.let([], T::Array[T.any(String, Symbol)])
|
licenses = T.let([], T::Array[T.any(String, Symbol)])
|
||||||
exceptions = T.let([], T::Array[String])
|
exceptions = T.let([], T::Array[String])
|
||||||
@ -63,6 +82,7 @@ module SPDX
|
|||||||
[licenses, exceptions]
|
[licenses, exceptions]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(license: T.any(String, Symbol)).returns(T::Boolean) }
|
||||||
def valid_license?(license)
|
def valid_license?(license)
|
||||||
return ALLOWED_LICENSE_SYMBOLS.include? license if license.is_a? Symbol
|
return ALLOWED_LICENSE_SYMBOLS.include? license if license.is_a? Symbol
|
||||||
|
|
||||||
@ -70,22 +90,31 @@ module SPDX
|
|||||||
license_data["licenses"].any? { |spdx_license| spdx_license["licenseId"] == license }
|
license_data["licenses"].any? { |spdx_license| spdx_license["licenseId"] == license }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(license: T.any(String, Symbol)).returns(T::Boolean) }
|
||||||
def deprecated_license?(license)
|
def deprecated_license?(license)
|
||||||
return false if ALLOWED_LICENSE_SYMBOLS.include? license
|
return false if ALLOWED_LICENSE_SYMBOLS.include? license
|
||||||
return false unless valid_license?(license)
|
return false unless valid_license?(license)
|
||||||
|
|
||||||
license = license.delete_suffix "+"
|
license = license.to_s.delete_suffix "+"
|
||||||
license_data["licenses"].none? do |spdx_license|
|
license_data["licenses"].none? do |spdx_license|
|
||||||
spdx_license["licenseId"] == license && !spdx_license["isDeprecatedLicenseId"]
|
spdx_license["licenseId"] == license && !spdx_license["isDeprecatedLicenseId"]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(exception: String).returns(T::Boolean) }
|
||||||
def valid_license_exception?(exception)
|
def valid_license_exception?(exception)
|
||||||
exception_data["exceptions"].any? do |spdx_exception|
|
exception_data["exceptions"].any? do |spdx_exception|
|
||||||
spdx_exception["licenseExceptionId"] == exception && !spdx_exception["isDeprecatedLicenseId"]
|
spdx_exception["licenseExceptionId"] == exception && !spdx_exception["isDeprecatedLicenseId"]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig {
|
||||||
|
params(
|
||||||
|
license_expression: T.any(String, Symbol, T::Hash[T.nilable(T.any(Symbol, String)), T.untyped]),
|
||||||
|
bracket: T::Boolean,
|
||||||
|
hash_type: T.nilable(T.any(String, Symbol)),
|
||||||
|
).returns(T.nilable(String))
|
||||||
|
}
|
||||||
def license_expression_to_string(license_expression, bracket: false, hash_type: nil)
|
def license_expression_to_string(license_expression, bracket: false, hash_type: nil)
|
||||||
case license_expression
|
case license_expression
|
||||||
when String
|
when String
|
||||||
@ -125,6 +154,19 @@ module SPDX
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig {
|
||||||
|
params(
|
||||||
|
string: T.nilable(String),
|
||||||
|
).returns(
|
||||||
|
T.nilable(
|
||||||
|
T.any(
|
||||||
|
String,
|
||||||
|
Symbol,
|
||||||
|
T::Hash[T.any(String, Symbol), T.untyped],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
def string_to_license_expression(string)
|
def string_to_license_expression(string)
|
||||||
return if string.blank?
|
return if string.blank?
|
||||||
|
|
||||||
@ -162,13 +204,23 @@ module SPDX
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig {
|
||||||
|
params(
|
||||||
|
license: T.any(String, Symbol),
|
||||||
|
).returns(
|
||||||
|
T.any(
|
||||||
|
[T.any(String, Symbol)],
|
||||||
|
[String, T.nilable(String), T::Boolean],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
def license_version_info(license)
|
def license_version_info(license)
|
||||||
return [license] if ALLOWED_LICENSE_SYMBOLS.include? license
|
return [license] if ALLOWED_LICENSE_SYMBOLS.include? license
|
||||||
|
|
||||||
match = license.match(/-(?<version>[0-9.]+)(?:-.*?)??(?<or_later>\+|-only|-or-later)?$/)
|
match = license.match(/-(?<version>[0-9.]+)(?:-.*?)??(?<or_later>\+|-only|-or-later)?$/)
|
||||||
return [license] if match.blank?
|
return [license] if match.blank?
|
||||||
|
|
||||||
license_name = license.split(match[0]).first
|
license_name = license.to_s.split(match[0].to_s).first
|
||||||
or_later = match["or_later"].present? && %w[+ -or-later].include?(match["or_later"])
|
or_later = match["or_later"].present? && %w[+ -or-later].include?(match["or_later"])
|
||||||
|
|
||||||
# [name, version, later versions allowed?]
|
# [name, version, later versions allowed?]
|
||||||
@ -176,12 +228,18 @@ module SPDX
|
|||||||
[license_name, match["version"], or_later]
|
[license_name, match["version"], or_later]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig {
|
||||||
|
params(license_expression: T.any(String, Symbol, T::Hash[Symbol, T.untyped]),
|
||||||
|
forbidden_licenses: T::Hash[Symbol, T.untyped]).returns(T::Boolean)
|
||||||
|
}
|
||||||
def licenses_forbid_installation?(license_expression, forbidden_licenses)
|
def licenses_forbid_installation?(license_expression, forbidden_licenses)
|
||||||
case license_expression
|
case license_expression
|
||||||
when String, Symbol
|
when String, Symbol
|
||||||
forbidden_licenses_include? license_expression.to_s, forbidden_licenses
|
forbidden_licenses_include? license_expression.to_s, forbidden_licenses
|
||||||
when Hash
|
when Hash
|
||||||
key = license_expression.keys.first
|
key = license_expression.keys.first
|
||||||
|
return false if key.nil?
|
||||||
|
|
||||||
case key
|
case key
|
||||||
when :any_of
|
when :any_of
|
||||||
license_expression[key].all? { |license| licenses_forbid_installation? license, forbidden_licenses }
|
license_expression[key].all? { |license| licenses_forbid_installation? license, forbidden_licenses }
|
||||||
@ -193,6 +251,12 @@ module SPDX
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig {
|
||||||
|
params(
|
||||||
|
license: T.any(Symbol, String),
|
||||||
|
forbidden_licenses: T::Hash[T.any(Symbol, String), T.untyped],
|
||||||
|
).returns(T::Boolean)
|
||||||
|
}
|
||||||
def forbidden_licenses_include?(license, forbidden_licenses)
|
def forbidden_licenses_include?(license, forbidden_licenses)
|
||||||
return true if forbidden_licenses.key? license
|
return true if forbidden_licenses.key? license
|
||||||
|
|
||||||
|
@ -1,49 +1,58 @@
|
|||||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
# typed: strict
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
# Various helper functions for interacting with TTYs.
|
# Various helper functions for interacting with TTYs.
|
||||||
module Tty
|
module Tty
|
||||||
@stream = $stdout
|
@stream = T.let($stdout, T.nilable(T.any(IO, StringIO)))
|
||||||
|
|
||||||
COLOR_CODES = {
|
COLOR_CODES = T.let(
|
||||||
red: 31,
|
{
|
||||||
green: 32,
|
red: 31,
|
||||||
yellow: 33,
|
green: 32,
|
||||||
blue: 34,
|
yellow: 33,
|
||||||
magenta: 35,
|
blue: 34,
|
||||||
cyan: 36,
|
magenta: 35,
|
||||||
default: 39,
|
cyan: 36,
|
||||||
}.freeze
|
default: 39,
|
||||||
|
}.freeze,
|
||||||
|
T::Hash[Symbol, Integer],
|
||||||
|
)
|
||||||
|
|
||||||
STYLE_CODES = {
|
STYLE_CODES = T.let(
|
||||||
reset: 0,
|
{
|
||||||
bold: 1,
|
reset: 0,
|
||||||
italic: 3,
|
bold: 1,
|
||||||
underline: 4,
|
italic: 3,
|
||||||
strikethrough: 9,
|
underline: 4,
|
||||||
no_underline: 24,
|
strikethrough: 9,
|
||||||
}.freeze
|
no_underline: 24,
|
||||||
|
}.freeze,
|
||||||
|
T::Hash[Symbol, Integer],
|
||||||
|
)
|
||||||
|
|
||||||
SPECIAL_CODES = {
|
SPECIAL_CODES = T.let(
|
||||||
up: "1A",
|
{
|
||||||
down: "1B",
|
up: "1A",
|
||||||
right: "1C",
|
down: "1B",
|
||||||
left: "1D",
|
right: "1C",
|
||||||
erase_line: "K",
|
left: "1D",
|
||||||
erase_char: "P",
|
erase_line: "K",
|
||||||
}.freeze
|
erase_char: "P",
|
||||||
|
}.freeze,
|
||||||
|
T::Hash[Symbol, String],
|
||||||
|
)
|
||||||
|
|
||||||
CODES = COLOR_CODES.merge(STYLE_CODES).freeze
|
CODES = T.let(COLOR_CODES.merge(STYLE_CODES).freeze, T::Hash[Symbol, Integer])
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
sig { params(stream: T.any(IO, StringIO), _block: T.proc.params(arg0: T.any(IO, StringIO)).void).void }
|
sig { params(stream: T.any(IO, StringIO), _block: T.proc.params(arg0: T.any(IO, StringIO)).void).void }
|
||||||
def with(stream, &_block)
|
def with(stream, &_block)
|
||||||
previous_stream = @stream
|
previous_stream = @stream
|
||||||
@stream = stream
|
@stream = T.let(stream, T.nilable(T.any(IO, StringIO)))
|
||||||
|
|
||||||
yield stream
|
yield stream
|
||||||
ensure
|
ensure
|
||||||
@stream = previous_stream
|
@stream = T.let(previous_stream, T.nilable(T.any(IO, StringIO)))
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { params(string: String).returns(String) }
|
sig { params(string: String).returns(String) }
|
||||||
@ -88,17 +97,17 @@ module Tty
|
|||||||
height, width = `/bin/stty size 2>/dev/null`.presence&.split&.map(&:to_i)
|
height, width = `/bin/stty size 2>/dev/null`.presence&.split&.map(&:to_i)
|
||||||
return if height.nil? || width.nil?
|
return if height.nil? || width.nil?
|
||||||
|
|
||||||
@size = [height, width]
|
@size = T.let([height, width], T.nilable([Integer, Integer]))
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { returns(Integer) }
|
sig { returns(Integer) }
|
||||||
def height
|
def height
|
||||||
@height ||= size&.first || `/usr/bin/tput lines 2>/dev/null`.presence&.to_i || 40
|
@height ||= T.let(size&.first || `/usr/bin/tput lines 2>/dev/null`.presence&.to_i || 40, T.nilable(Integer))
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { returns(Integer) }
|
sig { returns(Integer) }
|
||||||
def width
|
def width
|
||||||
@width ||= size&.second || `/usr/bin/tput cols 2>/dev/null`.presence&.to_i || 80
|
@width ||= T.let(size&.second || `/usr/bin/tput cols 2>/dev/null`.presence&.to_i || 80, T.nilable(Integer))
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { params(string: String).returns(String) }
|
sig { params(string: String).returns(String) }
|
||||||
@ -115,12 +124,12 @@ module Tty
|
|||||||
|
|
||||||
sig { void }
|
sig { void }
|
||||||
def reset_escape_sequence!
|
def reset_escape_sequence!
|
||||||
@escape_sequence = nil
|
@escape_sequence = T.let(nil, T.nilable(T::Array[Integer]))
|
||||||
end
|
end
|
||||||
|
|
||||||
CODES.each do |name, code|
|
CODES.each do |name, code|
|
||||||
define_method(name) do
|
define_method(name) do
|
||||||
@escape_sequence ||= []
|
@escape_sequence ||= T.let([], T.nilable(T::Array[Integer]))
|
||||||
@escape_sequence << code
|
@escape_sequence << code
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
@ -128,7 +137,8 @@ module Tty
|
|||||||
|
|
||||||
SPECIAL_CODES.each do |name, code|
|
SPECIAL_CODES.each do |name, code|
|
||||||
define_method(name) do
|
define_method(name) do
|
||||||
if @stream.tty?
|
@stream = T.let($stdout, T.nilable(T.any(IO, StringIO)))
|
||||||
|
if @stream&.tty?
|
||||||
"\033[#{code}"
|
"\033[#{code}"
|
||||||
else
|
else
|
||||||
""
|
""
|
||||||
@ -152,7 +162,7 @@ module Tty
|
|||||||
return false if Homebrew::EnvConfig.no_color?
|
return false if Homebrew::EnvConfig.no_color?
|
||||||
return true if Homebrew::EnvConfig.color?
|
return true if Homebrew::EnvConfig.color?
|
||||||
|
|
||||||
@stream.tty?
|
!!@stream&.tty?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user