Merge branch 'master' into license

This commit is contained in:
Lionell 2020-06-30 22:25:17 +08:00
commit fb4db63e3b
35 changed files with 582 additions and 82 deletions

View File

@ -17,7 +17,7 @@ GEM
term-ansicolor (~> 1.3)
thor (>= 0.19.4, < 2.0)
tins (~> 1.6)
diff-lcs (1.4.2)
diff-lcs (1.4.3)
docile (1.3.2)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
@ -26,7 +26,7 @@ GEM
domain_name (~> 0.5)
i18n (1.8.3)
concurrent-ruby (~> 1.0)
json (2.3.0)
json (2.3.1)
mechanize (2.7.6)
domain_name (~> 0.5, >= 0.5.1)
http-cookie (~> 1.0)
@ -118,7 +118,7 @@ GEM
unf_ext (0.0.7.7)
unicode-display_width (1.7.0)
webrobots (0.1.2)
zeitwerk (2.3.0)
zeitwerk (2.3.1)
PLATFORMS
ruby

View File

@ -3,6 +3,7 @@
require "formula"
require "options"
require "cli/parser"
require "commands"
module Homebrew
module_function
@ -20,8 +21,10 @@ module Homebrew
description: "Show options for formulae that are currently installed."
switch "--all",
description: "Show options for all available formulae."
flag "--command=",
description: "Show options for the specified <command>."
switch :debug
conflicts "--installed", "--all"
conflicts "--installed", "--all", "--command"
end
end
@ -32,6 +35,22 @@ module Homebrew
puts_options Formula.to_a.sort
elsif args.installed?
puts_options Formula.installed.sort
elsif !args.command.nil?
path = Commands.path(args.command)
odie "Unknown command: #{args.command}" unless path
cmd_options = if cmd_parser = CLI::Parser.from_cmd_path(path)
cmd_parser.processed_options.map do |short, long, _, desc|
[long || short, desc]
end
else
cmd_comment_options(path)
end
if args.compact?
puts cmd_options.sort.map(&:first) * " "
else
cmd_options.sort.each { |option, desc| puts "#{option}\n\t#{desc}" }
puts
end
elsif args.no_named?
raise FormulaUnspecifiedError
else
@ -39,6 +58,20 @@ module Homebrew
end
end
def cmd_comment_options(cmd_path)
options = []
comment_lines = cmd_path.read.lines.grep(/^#:/)
return options if comment_lines.empty?
# skip the comment's initial usage summary lines
comment_lines.slice(2..-1).each do |line|
if / (?<option>-[-\w]+) +(?<desc>.*)$/ =~ line
options << [option, desc]
end
end
options
end
def puts_options(formulae)
formulae.each do |f|
next if f.options.empty?

View File

@ -579,6 +579,7 @@ module Homebrew
THROTTLED_DENYLIST = {
"aws-sdk-cpp" => "10",
"awscli@1" => "10",
"balena-cli" => "10",
"quicktype" => "10",
"vim" => "50",
}.freeze

View File

@ -147,7 +147,6 @@ module Homebrew
raise FormulaUnspecifiedError unless formula
tap_full_name, origin_branch, previous_branch = use_correct_linux_tap(formula)
check_for_duplicate_pull_requests(formula, tap_full_name)
requested_spec, formula_spec = if args.devel?
devel_message = " (devel)"
@ -315,6 +314,8 @@ module Homebrew
new_formula_version = formula_version(formula, requested_spec, new_contents)
check_for_duplicate_pull_requests(formula, tap_full_name, new_formula_version.to_s)
if !new_mirrors && !formula_spec.mirrors.empty?
if args.force?
opoo "#{formula}: Removing all mirrors because a --mirror= argument was not specified."
@ -468,23 +469,26 @@ module Homebrew
end
end
def fetch_pull_requests(formula, tap_full_name)
GitHub.issues_for_formula(formula.name, tap_full_name: tap_full_name).select do |pr|
def fetch_pull_requests(query, tap_full_name, state: nil)
GitHub.issues_for_formula(query, tap_full_name: tap_full_name, state: state).select do |pr|
pr["html_url"].include?("/pull/") &&
/(^|\s)#{Regexp.quote(formula.name)}(:|\s|$)/i =~ pr["title"]
/(^|\s)#{Regexp.quote(query)}(:|\s|$)/i =~ pr["title"]
end
rescue GitHub::RateLimitExceededError => e
opoo e.message
[]
end
def check_for_duplicate_pull_requests(formula, tap_full_name)
pull_requests = fetch_pull_requests(formula, tap_full_name)
return unless pull_requests
return if pull_requests.empty?
def check_for_duplicate_pull_requests(formula, tap_full_name, version)
# check for open requests
pull_requests = fetch_pull_requests(formula.name, tap_full_name, state: "open")
# if we haven't already found open requests, try for an exact match across all requests
pull_requests = fetch_pull_requests("#{formula.name} #{version}", tap_full_name) if pull_requests.blank?
return if pull_requests.blank?
duplicates_message = <<~EOS
These open pull requests may be duplicates:
These pull requests may be duplicates:
#{pull_requests.map { |pr| "#{pr["title"]} #{pr["html_url"]}" }.join("\n")}
EOS
error_message = "Duplicate PRs should not be opened. Use --force to override this error."

View File

@ -360,7 +360,7 @@ class BuildError < RuntimeError
end
def fetch_issues
GitHub.issues_for_formula(formula.name, tap: formula.tap)
GitHub.issues_for_formula(formula.name, tap: formula.tap, state: "open")
rescue GitHub::RateLimitExceededError => e
opoo e.message
[]

View File

@ -226,11 +226,10 @@ module RuboCop
next if succeeding_component.empty?
offensive_nodes = check_precedence(preceding_component, succeeding_component)
break if offensive_nodes
return [present_components, offensive_nodes] if offensive_nodes
end
end
[present_components, offensive_nodes]
nil
end
# Method to format message for reporting component precedence violations

View File

@ -115,6 +115,8 @@ class SoftwareSpec
raise DuplicateResourceError, name if resource_defined?(name)
res = klass.new(name, &block)
return unless res.url
resources[name] = res
dependency_collector.add(res)
else

View File

@ -652,6 +652,7 @@ false:
- ./test/rubocops/components_redundancy_spec.rb
- ./test/rubocops/conflicts_spec.rb
- ./test/rubocops/dependency_order_spec.rb
- ./test/rubocops/deprecate_spec.rb
- ./test/rubocops/formula_desc_spec.rb
- ./test/rubocops/homepage_spec.rb
- ./test/rubocops/lines_spec.rb
@ -884,6 +885,7 @@ true:
- ./rubocops/cask/ast/stanza.rb
- ./rubocops/cask/constants/stanza.rb
- ./rubocops/cask/extend/string.rb
- ./rubocops/deprecate.rb
- ./tap_constants.rb
- ./test/support/helper/fixtures.rb
- ./test/support/lib/config.rb

View File

@ -1,5 +1,5 @@
# This file is autogenerated. Do not edit it by hand. Regenerate it with:
# tapioca sync
# tapioca sync --exclude json
# typed: true
@ -344,6 +344,28 @@ class RuboCop::AST::IfNode < ::RuboCop::AST::Node
def unless?; end
end
class RuboCop::AST::IndexNode < ::RuboCop::AST::Node
include(::RuboCop::AST::ParameterizedNode)
include(::RuboCop::AST::MethodIdentifierPredicates)
include(::RuboCop::AST::MethodDispatchNode)
def arguments; end
def assignment_method?; end
def attribute_accessor?; end
def method_name; end
end
class RuboCop::AST::IndexasgnNode < ::RuboCop::AST::Node
include(::RuboCop::AST::ParameterizedNode)
include(::RuboCop::AST::MethodIdentifierPredicates)
include(::RuboCop::AST::MethodDispatchNode)
def arguments; end
def assignment_method?; end
def attribute_accessor?; end
def method_name; end
end
class RuboCop::AST::IntNode < ::RuboCop::AST::Node
include(::RuboCop::AST::NumericNode)
end
@ -359,6 +381,19 @@ end
RuboCop::AST::KeywordSplatNode::DOUBLE_SPLAT = T.let(T.unsafe(nil), String)
class RuboCop::AST::LambdaNode < ::RuboCop::AST::Node
include(::RuboCop::AST::ParameterizedNode)
include(::RuboCop::AST::MethodIdentifierPredicates)
include(::RuboCop::AST::MethodDispatchNode)
def arguments; end
def assignment_method?; end
def attribute_accessor?; end
def lambda?; end
def lambda_literal?; end
def method_name; end
end
module RuboCop::AST::MethodDispatchNode
include(::RuboCop::AST::MethodIdentifierPredicates)
extend(::RuboCop::AST::NodePattern::Macros)
@ -409,9 +444,16 @@ module RuboCop::AST::MethodIdentifierPredicates
def camel_case_method?; end
def comparison_method?; end
def const_receiver?; end
def enumerable_method?; end
def enumerator_method?; end
def method?(name); end
def negation_method?; end
def nonmutating_array_method?; end
def nonmutating_binary_operator_method?; end
def nonmutating_hash_method?; end
def nonmutating_operator_method?; end
def nonmutating_string_method?; end
def nonmutating_unary_operator_method?; end
def operator_method?; end
def predicate_method?; end
def prefix_bang?; end
@ -419,9 +461,23 @@ module RuboCop::AST::MethodIdentifierPredicates
def self_receiver?; end
end
RuboCop::AST::MethodIdentifierPredicates::ENUMERATOR_METHODS = T.let(T.unsafe(nil), Array)
RuboCop::AST::MethodIdentifierPredicates::ENUMERABLE_METHODS = T.let(T.unsafe(nil), Set)
RuboCop::AST::MethodIdentifierPredicates::OPERATOR_METHODS = T.let(T.unsafe(nil), Array)
RuboCop::AST::MethodIdentifierPredicates::ENUMERATOR_METHODS = T.let(T.unsafe(nil), Set)
RuboCop::AST::MethodIdentifierPredicates::NONMUTATING_ARRAY_METHODS = T.let(T.unsafe(nil), Set)
RuboCop::AST::MethodIdentifierPredicates::NONMUTATING_BINARY_OPERATOR_METHODS = T.let(T.unsafe(nil), Set)
RuboCop::AST::MethodIdentifierPredicates::NONMUTATING_HASH_METHODS = T.let(T.unsafe(nil), Set)
RuboCop::AST::MethodIdentifierPredicates::NONMUTATING_OPERATOR_METHODS = T.let(T.unsafe(nil), Set)
RuboCop::AST::MethodIdentifierPredicates::NONMUTATING_STRING_METHODS = T.let(T.unsafe(nil), Set)
RuboCop::AST::MethodIdentifierPredicates::NONMUTATING_UNARY_OPERATOR_METHODS = T.let(T.unsafe(nil), Set)
RuboCop::AST::MethodIdentifierPredicates::OPERATOR_METHODS = T.let(T.unsafe(nil), Set)
module RuboCop::AST::ModifierNode
def modifier_form?; end
@ -450,6 +506,7 @@ class RuboCop::AST::Node < ::Parser::AST::Node
def arg_type?; end
def args_type?; end
def argument?; end
def argument_type?; end
def array_pattern_type?; end
def array_pattern_with_tail_type?; end
def array_type?; end
@ -506,9 +563,11 @@ class RuboCop::AST::Node < ::Parser::AST::Node
def erange_type?; end
def false_type?; end
def falsey_literal?; end
def find_pattern_type?; end
def first_line; end
def float_type?; end
def for_type?; end
def forward_arg_type?; end
def forward_args_type?; end
def forwarded_args_type?; end
def guard_clause?; end
@ -542,6 +601,7 @@ class RuboCop::AST::Node < ::Parser::AST::Node
def last_line; end
def line_count; end
def literal?; end
def loop_keyword?; end
def lvar_type?; end
def lvasgn_type?; end
def masgn_type?; end
@ -582,6 +642,7 @@ class RuboCop::AST::Node < ::Parser::AST::Node
def parent_module_name; end
def parenthesized_call?; end
def pin_type?; end
def post_condition_loop?; end
def postexe_type?; end
def preexe_type?; end
def proc?(node = _); end
@ -654,6 +715,8 @@ class RuboCop::AST::Node < ::Parser::AST::Node
def while_until_value_used?; end
end
RuboCop::AST::Node::ARGUMENT_TYPES = T.let(T.unsafe(nil), Array)
RuboCop::AST::Node::ASSIGNMENTS = T.let(T.unsafe(nil), Array)
RuboCop::AST::Node::BASIC_CONDITIONALS = T.let(T.unsafe(nil), Array)
@ -676,10 +739,14 @@ RuboCop::AST::Node::KEYWORDS = T.let(T.unsafe(nil), Array)
RuboCop::AST::Node::LITERALS = T.let(T.unsafe(nil), Array)
RuboCop::AST::Node::LOOP_TYPES = T.let(T.unsafe(nil), Array)
RuboCop::AST::Node::MUTABLE_LITERALS = T.let(T.unsafe(nil), Array)
RuboCop::AST::Node::OPERATOR_KEYWORDS = T.let(T.unsafe(nil), Array)
RuboCop::AST::Node::POST_CONDITION_LOOP_TYPES = T.let(T.unsafe(nil), Array)
RuboCop::AST::Node::REFERENCES = T.let(T.unsafe(nil), Array)
RuboCop::AST::Node::SHORTHAND_ASSIGNMENTS = T.let(T.unsafe(nil), Array)
@ -697,7 +764,7 @@ class RuboCop::AST::NodePattern
def eql?(other); end
def marshal_dump; end
def marshal_load(pattern); end
def match(*args); end
def match(*args, **rest); end
def pattern; end
def to_s; end
@ -708,12 +775,8 @@ class RuboCop::AST::NodePattern::Invalid < ::StandardError
end
module RuboCop::AST::NodePattern::Macros
def def_node_matcher(method_name, pattern_str); end
def def_node_search(method_name, pattern_str); end
def node_search(method_name, compiler, on_match, prelude, called_from); end
def node_search_all(method_name, compiler, called_from); end
def node_search_body(method_name, trailing_params, prelude, match_code, on_match); end
def node_search_first(method_name, compiler, called_from); end
def def_node_matcher(method_name, pattern_str, **keyword_defaults); end
def def_node_search(method_name, pattern_str, **keyword_defaults); end
end
module RuboCop::AST::NumericNode
@ -825,8 +888,22 @@ end
class RuboCop::AST::RegexpNode < ::RuboCop::AST::Node
def content; end
def delimiter?(char); end
def delimiters; end
def extended?; end
def ignore_case?; end
def interpolation?; end
def multiline_mode?; end
def no_encoding?; end
def percent_r_literal?; end
def regopt; end
def single_interpolation?; end
def slash_literal?; end
def to_regexp; end
private
def regopt_include?(option); end
end
RuboCop::AST::RegexpNode::OPTIONS = T.let(T.unsafe(nil), Hash)
@ -920,6 +997,7 @@ class RuboCop::AST::Token
end
module RuboCop::AST::Traversal
def on___ENCODING__(node); end
def on_alias(node); end
def on_and(node); end
def on_and_asgn(node); end
@ -958,6 +1036,7 @@ module RuboCop::AST::Traversal
def on_false(node); end
def on_float(node); end
def on_for(node); end
def on_forward_arg(node); end
def on_forward_args(node); end
def on_forwarded_args(node); end
def on_gvar(node); end
@ -969,6 +1048,8 @@ module RuboCop::AST::Traversal
def on_iflipflop(node); end
def on_in_match(node); end
def on_in_pattern(node); end
def on_index(node); end
def on_indexasgn(node); end
def on_int(node); end
def on_irange(node); end
def on_ivar(node); end
@ -1005,6 +1086,7 @@ module RuboCop::AST::Traversal
def on_pin(node); end
def on_postexe(node); end
def on_preexe(node); end
def on_procarg0(node); end
def on_rational(node); end
def on_redo(node); end
def on_regexp(node); end
@ -1095,6 +1177,8 @@ RuboCop::AST::NodePattern::Compiler::CAPTURED_REST = T.let(T.unsafe(nil), String
RuboCop::AST::NodePattern::Compiler::CLOSING = T.let(T.unsafe(nil), Regexp)
RuboCop::AST::NodePattern::Compiler::CONST = T.let(T.unsafe(nil), Regexp)
RuboCop::AST::NodePattern::Compiler::CUR_ELEMENT = T.let(T.unsafe(nil), String)
RuboCop::AST::NodePattern::Compiler::CUR_NODE = T.let(T.unsafe(nil), String)
@ -1105,6 +1189,10 @@ RuboCop::AST::NodePattern::Compiler::FUNCALL = T.let(T.unsafe(nil), Regexp)
RuboCop::AST::NodePattern::Compiler::IDENTIFIER = T.let(T.unsafe(nil), Regexp)
RuboCop::AST::NodePattern::Compiler::KEYWORD = T.let(T.unsafe(nil), Regexp)
RuboCop::AST::NodePattern::Compiler::KEYWORD_NAME = T.let(T.unsafe(nil), Regexp)
RuboCop::AST::NodePattern::Compiler::LITERAL = T.let(T.unsafe(nil), Regexp)
RuboCop::AST::NodePattern::Compiler::META = T.let(T.unsafe(nil), Regexp)
@ -1117,6 +1205,8 @@ RuboCop::AST::NodePattern::Compiler::NUMBER = T.let(T.unsafe(nil), Regexp)
RuboCop::AST::NodePattern::Compiler::PARAM = T.let(T.unsafe(nil), Regexp)
RuboCop::AST::NodePattern::Compiler::PARAM_CONST = T.let(T.unsafe(nil), Regexp)
RuboCop::AST::NodePattern::Compiler::PARAM_NUMBER = T.let(T.unsafe(nil), Regexp)
RuboCop::AST::NodePattern::Compiler::PREDICATE = T.let(T.unsafe(nil), Regexp)

View File

@ -1,5 +1,5 @@
# This file is autogenerated. Do not edit it by hand. Regenerate it with:
# tapioca sync
# tapioca sync --exclude json
# typed: true

View File

@ -19429,10 +19429,6 @@ class RuboCop::AST::Node
def cask_block?(node=T.unsafe(nil)); end
def find_pattern_type?(); end
def forward_arg_type?(); end
def key_node(node=T.unsafe(nil)); end
def method_node(node=T.unsafe(nil)); end
@ -19604,6 +19600,10 @@ class RuboCop::Cop::FormulaAudit::Miscellaneous
def languageNodeModule?(node0); end
end
class RuboCop::Cop::FormulaAudit::Patches
def patch_data?(node0); end
end
class RuboCop::Cop::FormulaAudit::Test
def test_calls(node0); end
end

View File

@ -71,9 +71,82 @@ describe Cask::Cmd::Upgrade, :cask do
expect(local_transmission_path).to be_a_directory
expect(local_transmission.versions).to include("2.60")
end
it 'updates "auto_updates" and "latest" Casks when their tokens are provided in the command line' do
local_caffeine = Cask::CaskLoader.load("local-caffeine")
local_caffeine_path = Cask::Config.global.appdir.join("Caffeine.app")
auto_updates = Cask::CaskLoader.load("auto-updates")
auto_updates_path = Cask::Config.global.appdir.join("MyFancyApp.app")
expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory
expect(local_caffeine.versions).to include("1.2.2")
expect(auto_updates).to be_installed
expect(auto_updates_path).to be_a_directory
expect(auto_updates.versions).to include("2.57")
described_class.run("local-caffeine", "auto-updates")
expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory
expect(local_caffeine.versions).to include("1.2.3")
expect(auto_updates).to be_installed
expect(auto_updates_path).to be_a_directory
expect(auto_updates.versions).to include("2.61")
end
end
describe "with --greedy it checks additional Casks" do
it 'includes the Casks with "auto_updates true" or "version latest"' do
local_caffeine = Cask::CaskLoader.load("local-caffeine")
local_caffeine_path = Cask::Config.global.appdir.join("Caffeine.app")
auto_updates = Cask::CaskLoader.load("auto-updates")
auto_updates_path = Cask::Config.global.appdir.join("MyFancyApp.app")
local_transmission = Cask::CaskLoader.load("local-transmission")
local_transmission_path = Cask::Config.global.appdir.join("Transmission.app")
version_latest = Cask::CaskLoader.load("version-latest")
version_latest_path_1 = Cask::Config.global.appdir.join("Caffeine Mini.app")
version_latest_path_2 = Cask::Config.global.appdir.join("Caffeine Pro.app")
expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory
expect(local_caffeine.versions).to include("1.2.2")
expect(auto_updates).to be_installed
expect(auto_updates_path).to be_a_directory
expect(auto_updates.versions).to include("2.57")
expect(local_transmission).to be_installed
expect(local_transmission_path).to be_a_directory
expect(local_transmission.versions).to include("2.60")
expect(version_latest).to be_installed
expect(version_latest_path_1).to be_a_directory
expect(version_latest_path_2).to be_a_directory
expect(version_latest.versions).to include("latest")
described_class.run("--greedy")
expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory
expect(local_caffeine.versions).to include("1.2.3")
expect(auto_updates).to be_installed
expect(auto_updates_path).to be_a_directory
expect(auto_updates.versions).to include("2.61")
expect(local_transmission).to be_installed
expect(local_transmission_path).to be_a_directory
expect(local_transmission.versions).to include("2.61")
expect(version_latest).to be_installed
expect(version_latest_path_1).to be_a_directory
expect(version_latest_path_2).to be_a_directory
expect(version_latest.versions).to include("latest")
end
it 'does not include the Casks with "auto_updates true" when the version did not change' do
cask = Cask::CaskLoader.load("auto-updates")
cask_path = cask.config.appdir.join("MyFancyApp.app")
@ -97,6 +170,179 @@ describe Cask::Cmd::Upgrade, :cask do
end
end
context "dry run upgrade" do
let(:installed) {
[
"outdated/local-caffeine",
"outdated/local-transmission",
"outdated/auto-updates",
"outdated/version-latest",
]
}
before do
installed.each { |cask| Cask::Cmd::Install.run(cask) }
allow_any_instance_of(described_class).to receive(:verbose?).and_return(true)
end
describe 'without --greedy it ignores the Casks with "version latest" or "auto_updates true"' do
it "would update all the installed Casks when no token is provided" do
local_caffeine = Cask::CaskLoader.load("local-caffeine")
local_caffeine_path = Cask::Config.global.appdir.join("Caffeine.app")
local_transmission = Cask::CaskLoader.load("local-transmission")
local_transmission_path = Cask::Config.global.appdir.join("Transmission.app")
expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory
expect(local_caffeine.versions).to include("1.2.2")
expect(local_transmission).to be_installed
expect(local_transmission_path).to be_a_directory
expect(local_transmission.versions).to include("2.60")
described_class.run("--dry-run")
expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory
expect(local_caffeine.versions).to include("1.2.2")
expect(local_caffeine.versions).not_to include("1.2.3")
expect(local_transmission).to be_installed
expect(local_transmission_path).to be_a_directory
expect(local_transmission.versions).to include("2.60")
expect(local_transmission.versions).not_to include("2.61")
end
it "would update only the Casks specified in the command line" do
local_caffeine = Cask::CaskLoader.load("local-caffeine")
local_caffeine_path = Cask::Config.global.appdir.join("Caffeine.app")
local_transmission = Cask::CaskLoader.load("local-transmission")
local_transmission_path = Cask::Config.global.appdir.join("Transmission.app")
expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory
expect(local_caffeine.versions).to include("1.2.2")
expect(local_transmission).to be_installed
expect(local_transmission_path).to be_a_directory
expect(local_transmission.versions).to include("2.60")
described_class.run("--dry-run", "local-caffeine")
expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory
expect(local_caffeine.versions).to include("1.2.2")
expect(local_caffeine.versions).not_to include("1.2.3")
expect(local_transmission).to be_installed
expect(local_transmission_path).to be_a_directory
expect(local_transmission.versions).to include("2.60")
expect(local_transmission.versions).not_to include("2.61")
end
it 'would update "auto_updates" and "latest" Casks when their tokens are provided in the command line' do
local_caffeine = Cask::CaskLoader.load("local-caffeine")
local_caffeine_path = Cask::Config.global.appdir.join("Caffeine.app")
auto_updates = Cask::CaskLoader.load("auto-updates")
auto_updates_path = Cask::Config.global.appdir.join("MyFancyApp.app")
expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory
expect(local_caffeine.versions).to include("1.2.2")
expect(auto_updates).to be_installed
expect(auto_updates_path).to be_a_directory
expect(auto_updates.versions).to include("2.57")
described_class.run("--dry-run", "local-caffeine", "auto-updates")
expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory
expect(local_caffeine.versions).to include("1.2.2")
expect(local_caffeine.versions).not_to include("1.2.3")
expect(auto_updates).to be_installed
expect(auto_updates_path).to be_a_directory
expect(auto_updates.versions).to include("2.57")
expect(auto_updates.versions).not_to include("2.61")
end
end
describe "with --greedy it checks additional Casks" do
it 'would include the Casks with "auto_updates true" or "version latest"' do
local_caffeine = Cask::CaskLoader.load("local-caffeine")
local_caffeine_path = Cask::Config.global.appdir.join("Caffeine.app")
auto_updates = Cask::CaskLoader.load("auto-updates")
auto_updates_path = Cask::Config.global.appdir.join("MyFancyApp.app")
local_transmission = Cask::CaskLoader.load("local-transmission")
local_transmission_path = Cask::Config.global.appdir.join("Transmission.app")
version_latest = Cask::CaskLoader.load("version-latest")
version_latest_path_1 = Cask::Config.global.appdir.join("Caffeine Mini.app")
version_latest_path_2 = Cask::Config.global.appdir.join("Caffeine Pro.app")
expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory
expect(local_caffeine.versions).to include("1.2.2")
expect(auto_updates).to be_installed
expect(auto_updates_path).to be_a_directory
expect(auto_updates.versions).to include("2.57")
expect(local_transmission).to be_installed
expect(local_transmission_path).to be_a_directory
expect(local_transmission.versions).to include("2.60")
expect(version_latest).to be_installed
expect(version_latest_path_1).to be_a_directory
expect(version_latest.versions).to include("latest")
described_class.run("--greedy", "--dry-run")
expect(local_caffeine).to be_installed
expect(local_caffeine_path).to be_a_directory
expect(local_caffeine.versions).to include("1.2.2")
expect(local_caffeine.versions).not_to include("1.2.3")
expect(auto_updates).to be_installed
expect(auto_updates_path).to be_a_directory
expect(auto_updates.versions).to include("2.57")
expect(auto_updates.versions).not_to include("2.61")
expect(local_transmission).to be_installed
expect(local_transmission_path).to be_a_directory
expect(local_transmission.versions).to include("2.60")
expect(local_transmission.versions).not_to include("2.61")
expect(version_latest).to be_installed
expect(version_latest_path_2).to be_a_directory
end
it 'does not include the Casks with "auto_updates true" when the version did not change' do
cask = Cask::CaskLoader.load("auto-updates")
cask_path = cask.config.appdir.join("MyFancyApp.app")
expect(cask).to be_installed
expect(cask_path).to be_a_directory
expect(cask.versions).to include("2.57")
described_class.run("--dry-run", "auto-updates", "--greedy")
expect(cask).to be_installed
expect(cask_path).to be_a_directory
expect(cask.versions).to include("2.57")
expect(cask.versions).not_to include("2.61")
described_class.run("--dry-run", "auto-updates", "--greedy")
expect(cask).to be_installed
expect(cask_path).to be_a_directory
expect(cask.versions).to include("2.57")
expect(cask.versions).not_to include("2.61")
end
end
end
context "failed upgrade" do
let(:installed) {
[

View File

@ -6,6 +6,34 @@ describe Cask::Pkg, :cask do
let(:empty_response) { double(stdout: "", plist: { "volume" => "/", "install-location" => "", "paths" => {} }) }
let(:pkg) { described_class.new("my.fake.pkg", fake_system_command) }
it "removes files and dirs referenced by the pkg" do
some_files = Array.new(3) { Pathname.new(Tempfile.new("plain_file").path) }
allow(pkg).to receive(:pkgutil_bom_files).and_return(some_files)
some_specials = Array.new(3) { Pathname.new(Tempfile.new("special_file").path) }
allow(pkg).to receive(:pkgutil_bom_specials).and_return(some_specials)
some_dirs = Array.new(3) { mktmpdir }
allow(pkg).to receive(:pkgutil_bom_dirs).and_return(some_dirs)
root_dir = Pathname.new(mktmpdir)
allow(pkg).to receive(:root).and_return(root_dir)
allow(pkg).to receive(:forget)
pkg.uninstall
some_files.each do |file|
expect(file).not_to exist
end
some_dirs.each do |dir|
expect(dir).not_to exist
end
expect(root_dir).not_to exist
end
context "pkgutil" do
it "forgets the pkg" do
allow(fake_system_command).to receive(:run!).with(

View File

@ -77,6 +77,37 @@ describe RuboCop::Cop::FormulaAudit::ComponentsOrder do
RUBY
end
it "When `install` precedes `depends_on`" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
def install
end
depends_on "openssl"
^^^^^^^^^^^^^^^^^^^^ `depends_on` (line 7) should be put before `install` (line 4)
end
RUBY
end
it "When `test` precedes `depends_on`" do
expect_offense(<<~RUBY)
class Foo < Formula
url "https://brew.sh/foo-1.0.tgz"
def install
end
def test
end
depends_on "openssl"
^^^^^^^^^^^^^^^^^^^^ `depends_on` (line 10) should be put before `install` (line 4)
end
RUBY
end
it "When only one of many `depends_on` precedes `conflicts_with`" do
expect_offense(<<~RUBY)
class Foo < Formula

View File

@ -78,6 +78,17 @@ RSpec.configure do |config|
c.max_formatted_output_length = 200
end
# Use rspec-retry in CI.
if ENV["CI"]
config.verbose_retry = true
config.display_try_failure_messages = true
config.default_retry_count = 2
config.around(:each, :needs_network) do |example|
example.run_with_retry retry: 3, retry_wait: 3
end
end
# Never truncate output objects.
RSpec::Support::ObjectFormatter.default_instance.max_formatted_output_length = nil
@ -124,10 +135,6 @@ RSpec.configure do |config|
skip "Requires network connection." unless ENV["HOMEBREW_TEST_ONLINE"]
end
config.around(:each, :needs_network) do |example|
example.run_with_retry retry: 3, retry_wait: 1
end
config.before(:each, :needs_svn) do
skip "subversion not installed." unless quiet_system "#{HOMEBREW_SHIMS_PATH}/scm/svn", "--version"

View File

@ -173,6 +173,16 @@ describe Version do
expect(versions.sort_by { |v| described_class.create(v) }).to eq(versions)
end
describe "#empty?" do
it "returns true if version is empty" do
expect(described_class.create("").empty?).to eq(true)
end
it "returns false if version is not empty" do
expect(described_class.create("1.2.3").empty?).to eq(false)
end
end
specify "hash equality" do
v1 = described_class.create("0.1.0")
v2 = described_class.create("0.1.0")

View File

@ -293,10 +293,8 @@ module GitHub
search("code", **qualifiers)
end
def issues_for_formula(name, options = {})
tap = options[:tap] || CoreTap.instance
tap_full_name = options[:tap_full_name] || tap.full_name
search_issues(name, state: "open", repo: tap_full_name, in: "title")
def issues_for_formula(name, tap: CoreTap.instance, tap_full_name: tap.full_name, state: nil)
search_issues(name, repo: tap_full_name, state: state, in: "title")
end
def user

View File

@ -8,7 +8,7 @@ $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/i18n-1.8.3/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/minitest-5.14.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/thread_safe-0.3.6/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/tzinfo-1.2.7/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/zeitwerk-2.3.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/zeitwerk-2.3.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/activesupport-6.0.3.2/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ast-2.4.1/lib"
$:.unshift "#{path}/"
@ -25,7 +25,7 @@ $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/tins-1.25.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/term-ansicolor-1.7.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/thor-1.0.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/coveralls-0.8.23/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/diff-lcs-1.3/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/diff-lcs-1.4.2/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-19/2.6.0/unf_ext-0.0.7.7"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unf_ext-0.0.7.7/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unf-0.1.4/lib"
@ -62,7 +62,7 @@ $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec-3.9.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec-its-1.3.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec-retry-0.6.2/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec-wait-0.0.9/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-ast-0.0.3/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-ast-0.1.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-progressbar-1.10.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unicode-display_width-1.7.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-0.86.0/lib"

View File

@ -1,33 +0,0 @@
# frozen_string_literal: true
module Kernel
module_function
# We cannot decorate with prepend + super because Kernel has already been
# included in Object, and changes in ancestors don't get propagated into
# already existing ancestor chains.
alias_method :zeitwerk_original_require, :require
# @param path [String]
# @return [Boolean]
def require(path)
if loader = Zeitwerk::Registry.loader_for(path)
if path.end_with?(".rb")
zeitwerk_original_require(path).tap do |required|
loader.on_file_autoloaded(path) if required
end
else
loader.on_dir_autoloaded(path)
end
else
zeitwerk_original_require(path).tap do |required|
if required
realpath = $LOADED_FEATURES.last
if loader = Zeitwerk::Registry.loader_for(realpath)
loader.on_file_autoloaded(realpath)
end
end
end
end
end
end

View File

@ -0,0 +1,64 @@
# frozen_string_literal: true
module Kernel
module_function
# We are going to decorate Kerner#require with two goals.
#
# First, by intercepting Kernel#require calls, we are able to autovivify
# modules on required directories, and also do internal housekeeping when
# managed files are loaded.
#
# On the other hand, if you publish a new version of a gem that is now managed
# by Zeitwerk, client code can reference directly your classes and modules and
# should not require anything. But if someone has legacy require calls around,
# they will work as expected, and in a compatible way.
#
# We cannot decorate with prepend + super because Kernel has already been
# included in Object, and changes in ancestors don't get propagated into
# already existing ancestor chains.
alias_method :zeitwerk_original_require, :require
# @param path [String]
# @return [Boolean]
def require(path)
if loader = Zeitwerk::Registry.loader_for(path)
if path.end_with?(".rb")
zeitwerk_original_require(path).tap do |required|
loader.on_file_autoloaded(path) if required
end
else
loader.on_dir_autoloaded(path)
end
else
zeitwerk_original_require(path).tap do |required|
if required
realpath = $LOADED_FEATURES.last
if loader = Zeitwerk::Registry.loader_for(realpath)
loader.on_file_autoloaded(realpath)
end
end
end
end
end
# By now, I have seen no way so far to decorate require_relative.
#
# For starters, at least in CRuby, require_relative does not delegate to
# require. Both require and require_relative delegate the bulk of their work
# to an internal C function called rb_require_safe. So, our require wrapper is
# not executed.
#
# On the other hand, we cannot use the aliasing technique above because
# require_relative receives a path relative to the directory of the file in
# which the call is performed. If a wrapper here invoked the original method,
# Ruby would resolve the relative path taking lib/zeitwerk as base directory.
#
# A workaround could be to extract the base directory from caller_locations,
# but what if someone else decorated require_relative before us? You can't
# really know with certainty where's the original call site in the stack.
#
# However, the main use case for require_relative is to load files from your
# own project. Projects managed by Zeitwerk don't do this for files managed by
# Zeitwerk, precisely.
end

View File

@ -464,7 +464,7 @@ module Zeitwerk
# require "zeitwerk"
# loader = Zeitwerk::Loader.new
# loader.tag = File.basename(__FILE__, ".rb")
# loader.inflector = Zeitwerk::GemInflector.new
# loader.inflector = Zeitwerk::GemInflector.new(__FILE__)
# loader.push_dir(__dir__)
#
# except that this method returns the same object in subsequent calls from
@ -616,7 +616,10 @@ module Zeitwerk
# $LOADED_FEATURES stores real paths since Ruby 2.4.4. We set and save the
# real path to be able to delete it from $LOADED_FEATURES on unload, and to
# be able to do a lookup later in Kernel#require for manual require calls.
realpath = File.realpath(abspath)
#
# We freeze realpath because that saves allocations in Module#autoload.
# See #125.
realpath = File.realpath(abspath).freeze
parent.autoload(cname, realpath)
if logger
if ruby?(realpath)
@ -719,8 +722,13 @@ module Zeitwerk
def ls(dir)
Dir.foreach(dir) do |basename|
next if basename.start_with?(".")
abspath = File.join(dir, basename)
yield basename, abspath unless ignored_paths.member?(abspath)
next if ignored_paths.member?(abspath)
# We freeze abspath because that saves allocations when passed later to
# File methods. See #125.
yield basename, abspath.freeze
end
end

View File

@ -1,5 +1,5 @@
# frozen_string_literal: true
module Zeitwerk
VERSION = "2.3.0"
VERSION = "2.3.1"
end

View File

@ -429,6 +429,10 @@ class Version
end
alias eql? ==
def empty?
version.empty?
end
def hash
version.hash
end

View File

@ -261,7 +261,7 @@ We want tests that don't require any user input and test the basic functionality
See [`cmake`](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/cmake.rb) for an example of a formula with a good test. The formula writes a basic `CMakeLists.txt` file into the test directory then calls CMake to generate Makefiles. This test checks that CMake doesn't e.g. segfault during basic operation.
You can check that the output is as expected with `assert_equal` or `assert_match` on the output of shell_output such as in this example from the [envv formula](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/envv.rb):
You can check that the output is as expected with `assert_equal` or `assert_match` on the output of the [Formula assertions](https://rubydoc.brew.sh/Homebrew/Assertions.html) such as in this example from the [envv formula](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/envv.rb):
```ruby
assert_equal "mylist=A:C; export mylist", shell_output("#{bin}/envv del mylist B").strip

View File

@ -250,7 +250,7 @@ GEM
thread_safe (~> 0.1)
unicode-display_width (1.7.0)
yell (2.2.2)
zeitwerk (2.3.0)
zeitwerk (2.3.1)
PLATFORMS
ruby

View File

@ -340,6 +340,8 @@ Show install options specific to *`formula`*.
Show options for formulae that are currently installed.
* `--all`:
Show options for all available formulae.
* `--command`:
Show options for the specified *`command`*.
### `outdated` [*`options`*] [*`formula`*]

View File

@ -456,6 +456,10 @@ Show options for formulae that are currently installed\.
\fB\-\-all\fR
Show options for all available formulae\.
.
.TP
\fB\-\-command\fR
Show options for the specified \fIcommand\fR\.
.
.SS "\fBoutdated\fR [\fIoptions\fR] [\fIformula\fR]"
List installed formulae that have an updated version available\. By default, version information is displayed in interactive shells, and suppressed otherwise\.
.