Enable strict typing in Cask::Audit
This commit is contained in:
parent
00c528bc54
commit
157992be17
@ -1,4 +1,4 @@
|
|||||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
# typed: strict
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "cask/denylist"
|
require "cask/denylist"
|
||||||
@ -19,6 +19,14 @@ module Cask
|
|||||||
include SystemCommand::Mixin
|
include SystemCommand::Mixin
|
||||||
include ::Utils::Curl
|
include ::Utils::Curl
|
||||||
|
|
||||||
|
Error = T.type_alias do
|
||||||
|
{
|
||||||
|
message: T.nilable(String),
|
||||||
|
location: T.nilable(Homebrew::SourceLocation),
|
||||||
|
corrected: T::Boolean,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
sig { returns(Cask) }
|
sig { returns(Cask) }
|
||||||
attr_reader :cask
|
attr_reader :cask
|
||||||
|
|
||||||
@ -47,6 +55,7 @@ module Cask
|
|||||||
download ||= online || signing
|
download ||= online || signing
|
||||||
|
|
||||||
@cask = cask
|
@cask = cask
|
||||||
|
@download = T.let(nil, T.nilable(Download))
|
||||||
@download = Download.new(cask, quarantine:) if download
|
@download = Download.new(cask, quarantine:) if download
|
||||||
@online = online
|
@online = online
|
||||||
@strict = strict
|
@strict = strict
|
||||||
@ -88,8 +97,9 @@ module Cask
|
|||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Array[Error]) }
|
||||||
def errors
|
def errors
|
||||||
@errors ||= []
|
@errors ||= T.let([], T.nilable(T::Array[Error]))
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { returns(T::Boolean) }
|
sig { returns(T::Boolean) }
|
||||||
@ -113,9 +123,10 @@ module Cask
|
|||||||
# Only raise non-critical audits if the user specified `--strict`.
|
# Only raise non-critical audits if the user specified `--strict`.
|
||||||
return if strict_only && !@strict
|
return if strict_only && !@strict
|
||||||
|
|
||||||
errors << ({ message:, location:, corrected: false })
|
errors << { message:, location:, corrected: false }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T.nilable(String)) }
|
||||||
def result
|
def result
|
||||||
Formatter.error("failed") if errors?
|
Formatter.error("failed") if errors?
|
||||||
end
|
end
|
||||||
@ -346,6 +357,7 @@ module Cask
|
|||||||
location: url.location
|
location: url.location
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { void }
|
||||||
def audit_download_url_is_osdn
|
def audit_download_url_is_osdn
|
||||||
return if (url = cask.url).nil?
|
return if (url = cask.url).nil?
|
||||||
return if block_url_offline?
|
return if block_url_offline?
|
||||||
@ -541,8 +553,15 @@ module Cask
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { void }
|
sig {
|
||||||
def extract_artifacts
|
params(
|
||||||
|
_block: T.nilable(T.proc.params(
|
||||||
|
arg0: T::Array[T.any(Artifact::Pkg, Artifact::Relocated)],
|
||||||
|
arg1: Pathname,
|
||||||
|
).void),
|
||||||
|
).void
|
||||||
|
}
|
||||||
|
def extract_artifacts(&_block)
|
||||||
return unless online?
|
return unless online?
|
||||||
return if (download = self.download).nil?
|
return if (download = self.download).nil?
|
||||||
|
|
||||||
@ -557,7 +576,7 @@ module Cask
|
|||||||
|
|
||||||
return if artifacts.empty?
|
return if artifacts.empty?
|
||||||
|
|
||||||
@tmpdir ||= Pathname(Dir.mktmpdir("cask-audit", HOMEBREW_TEMP))
|
@tmpdir ||= T.let(Pathname(Dir.mktmpdir("cask-audit", HOMEBREW_TEMP)), T.nilable(Pathname))
|
||||||
|
|
||||||
# Clean up tmp dir when @tmpdir object is destroyed
|
# Clean up tmp dir when @tmpdir object is destroyed
|
||||||
ObjectSpace.define_finalizer(
|
ObjectSpace.define_finalizer(
|
||||||
@ -606,7 +625,8 @@ module Cask
|
|||||||
.extract_nestedly(to: @tmpdir, verbose: false)
|
.extract_nestedly(to: @tmpdir, verbose: false)
|
||||||
end
|
end
|
||||||
|
|
||||||
@artifacts_extracted = true # Set the flag to indicate that extraction has occurred.
|
# Set the flag to indicate that extraction has occurred.
|
||||||
|
@artifacts_extracted = T.let(true, T.nilable(TrueClass))
|
||||||
|
|
||||||
# Yield the artifacts and temp directory to the block if provided.
|
# Yield the artifacts and temp directory to the block if provided.
|
||||||
yield artifacts, @tmpdir if block_given?
|
yield artifacts, @tmpdir if block_given?
|
||||||
@ -626,8 +646,8 @@ module Cask
|
|||||||
extract_artifacts do |artifacts, tmpdir|
|
extract_artifacts do |artifacts, tmpdir|
|
||||||
is_container = artifacts.any? { |a| a.is_a?(Artifact::App) || a.is_a?(Artifact::Pkg) }
|
is_container = artifacts.any? { |a| a.is_a?(Artifact::App) || a.is_a?(Artifact::Pkg) }
|
||||||
|
|
||||||
artifacts.filter { |a| a.is_a?(Artifact::App) || a.is_a?(Artifact::Binary) }
|
artifacts.each do |artifact|
|
||||||
.each do |artifact|
|
next if !artifact.is_a?(Artifact::App) && !artifact.is_a?(Artifact::Binary)
|
||||||
next if artifact.is_a?(Artifact::Binary) && is_container
|
next if artifact.is_a?(Artifact::Binary) && is_container
|
||||||
|
|
||||||
path = tmpdir/artifact.source.relative_path_from(cask.staged_path)
|
path = tmpdir/artifact.source.relative_path_from(cask.staged_path)
|
||||||
@ -644,10 +664,10 @@ module Cask
|
|||||||
|
|
||||||
system_command("lipo", args: ["-archs", main_binary], print_stderr: false)
|
system_command("lipo", args: ["-archs", main_binary], print_stderr: false)
|
||||||
when Artifact::Binary
|
when Artifact::Binary
|
||||||
binary_path = path.to_s.gsub(cask.appdir, tmpdir)
|
binary_path = path.to_s.gsub(cask.appdir, tmpdir.to_s)
|
||||||
system_command("lipo", args: ["-archs", binary_path], print_stderr: true)
|
system_command("lipo", args: ["-archs", binary_path], print_stderr: true)
|
||||||
else
|
else
|
||||||
add_error "Unknown artifact type: #{artifact.class}", location: url.location
|
T.absurd(artifact)
|
||||||
end
|
end
|
||||||
|
|
||||||
# binary stanza can contain shell scripts, so we just continue if lipo fails.
|
# binary stanza can contain shell scripts, so we just continue if lipo fails.
|
||||||
@ -795,7 +815,7 @@ module Cask
|
|||||||
return unless online?
|
return unless online?
|
||||||
|
|
||||||
min_os = T.let(nil, T.untyped)
|
min_os = T.let(nil, T.untyped)
|
||||||
@staged_path ||= cask.staged_path
|
@staged_path ||= T.let(cask.staged_path, T.nilable(Pathname))
|
||||||
|
|
||||||
extract_artifacts do |artifacts, tmpdir|
|
extract_artifacts do |artifacts, tmpdir|
|
||||||
artifacts.each do |artifact|
|
artifacts.each do |artifact|
|
||||||
@ -1104,15 +1124,15 @@ module Cask
|
|||||||
|
|
||||||
sig { returns(T::Boolean) }
|
sig { returns(T::Boolean) }
|
||||||
def bad_osdn_url?
|
def bad_osdn_url?
|
||||||
domain.match?(%r{^(?:\w+\.)*osdn\.jp(?=/|$)})
|
T.must(domain).match?(%r{^(?:\w+\.)*osdn\.jp(?=/|$)})
|
||||||
end
|
end
|
||||||
|
|
||||||
# sig { returns(String) }
|
sig { returns(T.nilable(String)) }
|
||||||
def homepage
|
def homepage
|
||||||
URI(cask.homepage.to_s).host
|
URI(cask.homepage.to_s).host
|
||||||
end
|
end
|
||||||
|
|
||||||
# sig { returns(String) }
|
sig { returns(T.nilable(String)) }
|
||||||
def domain
|
def domain
|
||||||
URI(cask.url.to_s).host
|
URI(cask.url.to_s).host
|
||||||
end
|
end
|
||||||
@ -1127,24 +1147,25 @@ module Cask
|
|||||||
host_uri.host
|
host_uri.host
|
||||||
end
|
end
|
||||||
|
|
||||||
return false if homepage.blank?
|
home = homepage
|
||||||
|
return false if home.blank?
|
||||||
|
|
||||||
home = homepage.downcase
|
home.downcase!
|
||||||
if (split_host = T.must(host).split(".")).length >= 3
|
if (split_host = T.must(host).split(".")).length >= 3
|
||||||
host = T.must(split_host[-2..]).join(".")
|
host = T.must(split_host[-2..]).join(".")
|
||||||
end
|
end
|
||||||
if (split_home = homepage.split(".")).length >= 3
|
if (split_home = home.split(".")).length >= 3
|
||||||
home = split_home[-2..].join(".")
|
home = T.must(split_home[-2..]).join(".")
|
||||||
end
|
end
|
||||||
host == home
|
host == home
|
||||||
end
|
end
|
||||||
|
|
||||||
# sig { params(url: String).returns(String) }
|
sig { params(url: String).returns(String) }
|
||||||
def strip_url_scheme(url)
|
def strip_url_scheme(url)
|
||||||
url.sub(%r{^[^:/]+://(www\.)?}, "")
|
url.sub(%r{^[^:/]+://(www\.)?}, "")
|
||||||
end
|
end
|
||||||
|
|
||||||
# sig { returns(String) }
|
sig { returns(String) }
|
||||||
def url_from_verified
|
def url_from_verified
|
||||||
strip_url_scheme(T.must(cask.url).verified)
|
strip_url_scheme(T.must(cask.url).verified)
|
||||||
end
|
end
|
||||||
@ -1154,8 +1175,10 @@ module Cask
|
|||||||
url_domain, url_path = strip_url_scheme(cask.url.to_s).split("/", 2)
|
url_domain, url_path = strip_url_scheme(cask.url.to_s).split("/", 2)
|
||||||
verified_domain, verified_path = url_from_verified.split("/", 2)
|
verified_domain, verified_path = url_from_verified.split("/", 2)
|
||||||
|
|
||||||
(url_domain == verified_domain || (verified_domain && url_domain&.end_with?(".#{verified_domain}"))) &&
|
domains_match = (url_domain == verified_domain) ||
|
||||||
(!verified_path || url_path&.start_with?(verified_path))
|
(verified_domain && url_domain&.end_with?(".#{verified_domain}"))
|
||||||
|
paths_match = !verified_path || url_path&.start_with?(verified_path)
|
||||||
|
(domains_match && paths_match) || false
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { returns(T::Boolean) }
|
sig { returns(T::Boolean) }
|
||||||
@ -1177,10 +1200,10 @@ module Cask
|
|||||||
|
|
||||||
sig { returns(Tap) }
|
sig { returns(Tap) }
|
||||||
def core_tap
|
def core_tap
|
||||||
@core_tap ||= CoreTap.instance
|
@core_tap ||= T.let(CoreTap.instance, T.nilable(Tap))
|
||||||
end
|
end
|
||||||
|
|
||||||
# sig { returns(T::Array[String]) }
|
sig { returns(T::Array[String]) }
|
||||||
def core_formula_names
|
def core_formula_names
|
||||||
core_tap.formula_names
|
core_tap.formula_names
|
||||||
end
|
end
|
||||||
|
@ -445,7 +445,7 @@ module Homebrew
|
|||||||
.gsub(/`(.*?)`/m, "#{Tty.bold}\\1#{Tty.reset}")
|
.gsub(/`(.*?)`/m, "#{Tty.bold}\\1#{Tty.reset}")
|
||||||
.gsub(%r{<([^\s]+?://[^\s]+?)>}) { |url| Formatter.url(url) }
|
.gsub(%r{<([^\s]+?://[^\s]+?)>}) { |url| Formatter.url(url) }
|
||||||
.gsub(/\*(.*?)\*|<(.*?)>/m) do |underlined|
|
.gsub(/\*(.*?)\*|<(.*?)>/m) do |underlined|
|
||||||
underlined[1...-1].gsub(/^(\s*)(.*?)$/, "\\1#{Tty.underline}\\2#{Tty.reset}")
|
T.must(underlined[1...-1]).gsub(/^(\s*)(.*?)$/, "\\1#{Tty.underline}\\2#{Tty.reset}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
# typed: strict
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "utils/tty"
|
require "utils/tty"
|
||||||
@ -10,6 +10,7 @@ module Formatter
|
|||||||
COMMAND_DESC_WIDTH = 80
|
COMMAND_DESC_WIDTH = 80
|
||||||
OPTION_DESC_WIDTH = 45
|
OPTION_DESC_WIDTH = 45
|
||||||
|
|
||||||
|
sig { params(string: String, color: T.nilable(Symbol)).returns(String) }
|
||||||
def self.arrow(string, color: nil)
|
def self.arrow(string, color: nil)
|
||||||
prefix("==>", string, color)
|
prefix("==>", string, color)
|
||||||
end
|
end
|
||||||
@ -17,18 +18,22 @@ module Formatter
|
|||||||
# Format a string as headline.
|
# Format a string as headline.
|
||||||
#
|
#
|
||||||
# @api internal
|
# @api internal
|
||||||
|
sig { params(string: String, color: T.nilable(Symbol)).returns(String) }
|
||||||
def self.headline(string, color: nil)
|
def self.headline(string, color: nil)
|
||||||
arrow("#{Tty.bold}#{string}#{Tty.reset}", color:)
|
arrow("#{Tty.bold}#{string}#{Tty.reset}", color:)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(string: Object).returns(String) }
|
||||||
def self.identifier(string)
|
def self.identifier(string)
|
||||||
"#{Tty.green}#{string}#{Tty.default}"
|
"#{Tty.green}#{string}#{Tty.default}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(string: String).returns(String) }
|
||||||
def self.bold(string)
|
def self.bold(string)
|
||||||
"#{Tty.bold}#{string}#{Tty.reset}"
|
"#{Tty.bold}#{string}#{Tty.reset}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(string: String).returns(String) }
|
||||||
def self.option(string)
|
def self.option(string)
|
||||||
bold(string)
|
bold(string)
|
||||||
end
|
end
|
||||||
@ -36,6 +41,7 @@ module Formatter
|
|||||||
# Format a string as success, with an optional label.
|
# Format a string as success, with an optional label.
|
||||||
#
|
#
|
||||||
# @api internal
|
# @api internal
|
||||||
|
sig { params(string: String, label: T.nilable(String)).returns(String) }
|
||||||
def self.success(string, label: nil)
|
def self.success(string, label: nil)
|
||||||
label(label, string, :green)
|
label(label, string, :green)
|
||||||
end
|
end
|
||||||
@ -43,6 +49,7 @@ module Formatter
|
|||||||
# Format a string as warning, with an optional label.
|
# Format a string as warning, with an optional label.
|
||||||
#
|
#
|
||||||
# @api internal
|
# @api internal
|
||||||
|
sig { params(string: T.any(String, Exception), label: T.nilable(String)).returns(String) }
|
||||||
def self.warning(string, label: nil)
|
def self.warning(string, label: nil)
|
||||||
label(label, string, :yellow)
|
label(label, string, :yellow)
|
||||||
end
|
end
|
||||||
@ -50,6 +57,7 @@ module Formatter
|
|||||||
# Format a string as error, with an optional label.
|
# Format a string as error, with an optional label.
|
||||||
#
|
#
|
||||||
# @api internal
|
# @api internal
|
||||||
|
sig { params(string: T.any(String, Exception), label: T.nilable(String)).returns(String) }
|
||||||
def self.error(string, label: nil)
|
def self.error(string, label: nil)
|
||||||
label(label, string, :red)
|
label(label, string, :red)
|
||||||
end
|
end
|
||||||
@ -80,6 +88,7 @@ module Formatter
|
|||||||
# so we always wrap one word before an option.
|
# so we always wrap one word before an option.
|
||||||
# @see https://github.com/Homebrew/brew/pull/12672
|
# @see https://github.com/Homebrew/brew/pull/12672
|
||||||
# @see https://macromates.com/blog/2006/wrapping-text-with-regular-expressions/
|
# @see https://macromates.com/blog/2006/wrapping-text-with-regular-expressions/
|
||||||
|
sig { params(string: String, width: Integer).returns(String) }
|
||||||
def self.format_help_text(string, width: 172)
|
def self.format_help_text(string, width: 172)
|
||||||
desc = OPTION_DESC_WIDTH
|
desc = OPTION_DESC_WIDTH
|
||||||
indent = width - desc
|
indent = width - desc
|
||||||
@ -90,21 +99,26 @@ module Formatter
|
|||||||
.gsub(/(.{1,#{width}})( +|$)(?!-)\n?/, "\\1\n")
|
.gsub(/(.{1,#{width}})( +|$)(?!-)\n?/, "\\1\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(string: T.any(NilClass, String, URI::Generic)).returns(String) }
|
||||||
def self.url(string)
|
def self.url(string)
|
||||||
"#{Tty.underline}#{string}#{Tty.no_underline}"
|
"#{Tty.underline}#{string}#{Tty.no_underline}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(label: T.nilable(String), string: T.any(String, Exception), color: Symbol).returns(String) }
|
||||||
def self.label(label, string, color)
|
def self.label(label, string, color)
|
||||||
label = "#{label}:" unless label.nil?
|
label = "#{label}:" unless label.nil?
|
||||||
prefix(label, string, color)
|
prefix(label, string, color)
|
||||||
end
|
end
|
||||||
private_class_method :label
|
private_class_method :label
|
||||||
|
|
||||||
|
sig {
|
||||||
|
params(prefix: T.nilable(String), string: T.any(String, Exception), color: T.nilable(Symbol)).returns(String)
|
||||||
|
}
|
||||||
def self.prefix(prefix, string, color)
|
def self.prefix(prefix, string, color)
|
||||||
if prefix.nil? && color.nil?
|
if prefix.nil? && color.nil?
|
||||||
string
|
string.to_s
|
||||||
elsif prefix.nil?
|
elsif prefix.nil?
|
||||||
"#{Tty.send(color)}#{string}#{Tty.reset}"
|
"#{Tty.send(T.must(color))}#{string}#{Tty.reset}"
|
||||||
elsif color.nil?
|
elsif color.nil?
|
||||||
"#{prefix} #{string}"
|
"#{prefix} #{string}"
|
||||||
else
|
else
|
||||||
@ -116,7 +130,8 @@ module Formatter
|
|||||||
# Layout objects in columns that fit the current terminal width.
|
# Layout objects in columns that fit the current terminal width.
|
||||||
#
|
#
|
||||||
# @api internal
|
# @api internal
|
||||||
def self.columns(*objects, gap_size: 2)
|
sig { params(objects: T::Array[String], gap_size: Integer).returns(String) }
|
||||||
|
def self.columns(objects, gap_size: 2)
|
||||||
objects = objects.flatten.map(&:to_s)
|
objects = objects.flatten.map(&:to_s)
|
||||||
|
|
||||||
fallback = proc do
|
fallback = proc do
|
||||||
@ -145,7 +160,7 @@ module Formatter
|
|||||||
item_indices_for_row = T.cast(row_index.step(objects.size - 1, rows).to_a, T::Array[Integer])
|
item_indices_for_row = T.cast(row_index.step(objects.size - 1, rows).to_a, T::Array[Integer])
|
||||||
|
|
||||||
first_n = T.must(item_indices_for_row[0...-1]).map do |index|
|
first_n = T.must(item_indices_for_row[0...-1]).map do |index|
|
||||||
objects[index] + "".rjust(col_width - object_lengths.fetch(index))
|
objects.fetch(index) + "".rjust(col_width - object_lengths.fetch(index))
|
||||||
end
|
end
|
||||||
|
|
||||||
# don't add trailing whitespace to last column
|
# don't add trailing whitespace to last column
|
||||||
|
Loading…
x
Reference in New Issue
Block a user