Merge branch 'master' into undeclared_runtime_dependencies
This commit is contained in:
commit
6bbc56c3a9
@ -32,7 +32,7 @@ onoe() {
|
||||
fi
|
||||
if [[ $# -eq 0 ]]
|
||||
then
|
||||
/bin/cat >&2
|
||||
cat >&2
|
||||
else
|
||||
echo "$*" >&2
|
||||
fi
|
||||
|
||||
@ -44,9 +44,9 @@ class Build
|
||||
def expand_reqs
|
||||
formula.recursive_requirements do |dependent, req|
|
||||
build = effective_build_options_for(dependent)
|
||||
if (req.optional? || req.recommended?) && build.without?(req)
|
||||
if req.prune_from_option?(build)
|
||||
Requirement.prune
|
||||
elsif req.build? && dependent != formula
|
||||
elsif req.prune_if_build_and_not_dependent?(dependent, formula)
|
||||
Requirement.prune
|
||||
end
|
||||
end
|
||||
@ -55,9 +55,9 @@ class Build
|
||||
def expand_deps
|
||||
formula.recursive_dependencies do |dependent, dep|
|
||||
build = effective_build_options_for(dependent)
|
||||
if (dep.optional? || dep.recommended?) && build.without?(dep)
|
||||
if dep.prune_from_option?(build)
|
||||
Dependency.prune
|
||||
elsif dep.build? && dependent != formula
|
||||
elsif dep.prune_if_build_and_not_dependent?(dependent, formula)
|
||||
Dependency.prune
|
||||
elsif dep.build?
|
||||
Dependency.keep_but_prune_recursive_deps
|
||||
|
||||
@ -33,6 +33,9 @@ module Hbc
|
||||
check_download
|
||||
check_single_pre_postflight
|
||||
check_single_uninstall_zap
|
||||
check_untrusted_pkg
|
||||
check_github_releases_appcast
|
||||
check_latest_with_appcast
|
||||
self
|
||||
rescue StandardError => e
|
||||
odebug "#{e.message}\n#{e.backtrace.join("\n")}"
|
||||
@ -50,6 +53,18 @@ module Hbc
|
||||
|
||||
private
|
||||
|
||||
def check_untrusted_pkg
|
||||
odebug "Auditing pkg stanza: allow_untrusted"
|
||||
|
||||
return if @cask.sourcefile_path.nil?
|
||||
|
||||
tap = @cask.tap
|
||||
return if tap.nil? || tap.user != "caskroom"
|
||||
|
||||
return unless cask.artifacts.any? { |k| k.is_a?(Hbc::Artifact::Pkg) && k.stanza_options.key?(:allow_untrusted) }
|
||||
add_warning "allow_untrusted is not permitted in official Homebrew-Cask taps"
|
||||
end
|
||||
|
||||
def check_single_pre_postflight
|
||||
odebug "Auditing preflight and postflight stanzas"
|
||||
|
||||
@ -95,7 +110,7 @@ module Hbc
|
||||
def check_version_and_checksum
|
||||
return if @cask.sourcefile_path.nil?
|
||||
|
||||
tap = Tap.select { |t| t.cask_file?(@cask.sourcefile_path) }.first
|
||||
tap = @cask.tap
|
||||
return if tap.nil?
|
||||
|
||||
return if commit_range.nil?
|
||||
@ -214,6 +229,20 @@ module Hbc
|
||||
end
|
||||
end
|
||||
|
||||
def check_latest_with_appcast
|
||||
return unless cask.version.latest?
|
||||
return unless cask.appcast
|
||||
|
||||
add_warning "Casks with an appcast should not use version :latest"
|
||||
end
|
||||
|
||||
def check_github_releases_appcast
|
||||
return if cask.appcast
|
||||
return unless cask.url.to_s =~ %r{github.com/([^/]+)/([^/]+)/releases/download/(\S+)}
|
||||
|
||||
add_warning "Cask uses GitHub releases, please add an appcast. See https://github.com/caskroom/homebrew-cask/blob/master/doc/cask_language_reference/stanzas/appcast.md"
|
||||
end
|
||||
|
||||
def check_url
|
||||
return unless cask.url
|
||||
check_download_url_format
|
||||
|
||||
@ -97,14 +97,14 @@ module Hbc
|
||||
|
||||
class FromTapPathLoader < FromPathLoader
|
||||
def self.can_load?(ref)
|
||||
ref.to_s.match?(HOMEBREW_TAP_PATH_REGEX) && super
|
||||
super && !Tap.from_path(ref).nil?
|
||||
end
|
||||
|
||||
attr_reader :tap
|
||||
|
||||
def initialize(tap_path)
|
||||
@tap = Tap.from_path(tap_path)
|
||||
super tap_path
|
||||
def initialize(path)
|
||||
@tap = Tap.from_path(path)
|
||||
super(path)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@ -124,6 +124,7 @@ module Hbc
|
||||
BUNDLE_PATH
|
||||
PATH
|
||||
SHELL
|
||||
HOMEBREW_CASK_OPTS
|
||||
]
|
||||
|
||||
locale_variables = ENV.keys.grep(/^(?:LC_\S+|LANG|LANGUAGE)\Z/).sort
|
||||
|
||||
@ -154,7 +154,7 @@ module Hbc
|
||||
end
|
||||
|
||||
def ext
|
||||
Pathname.new(@url).extname[/[^?]+/]
|
||||
Pathname.new(@url).extname[/[^?&]+/]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -90,7 +90,7 @@ module Hbc
|
||||
|
||||
brew cask install java
|
||||
EOS
|
||||
elsif java_version.include?("9") || java_version.include?("+")
|
||||
elsif java_version.include?("10") || java_version.include?("+")
|
||||
<<~EOS
|
||||
#{@cask} requires Java #{java_version}. You can install the latest version with
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ module Hbc
|
||||
|
||||
def initialize(signature, parameters = {})
|
||||
@parameters = parameters
|
||||
@signature = URI(signature)
|
||||
@signature = URI(signature) unless signature == :embedded
|
||||
parameters.each do |hkey, hvalue|
|
||||
raise "invalid 'gpg' parameter: '#{hkey.inspect}'" unless VALID_PARAMETERS.include?(hkey)
|
||||
writer_method = "#{hkey}=".to_sym
|
||||
|
||||
@ -49,7 +49,7 @@ module Hbc
|
||||
end
|
||||
|
||||
def verify
|
||||
return unless available?
|
||||
return unless available? && cask.gpg.signature != :embedded
|
||||
import_key
|
||||
sig = fetch_sig
|
||||
|
||||
|
||||
@ -13,6 +13,6 @@ class Checksum
|
||||
delegate [:empty?, :to_s] => :@hexdigest
|
||||
|
||||
def ==(other)
|
||||
hash_type == other.hash_type && hexdigest == other.hexdigest
|
||||
hash_type == other&.hash_type && hexdigest == other.hexdigest
|
||||
end
|
||||
end
|
||||
|
||||
@ -122,7 +122,7 @@ module Homebrew
|
||||
lockfiles = candidates.select(&:file?)
|
||||
lockfiles.each do |file|
|
||||
next unless file.readable?
|
||||
file.open.flock(File::LOCK_EX | File::LOCK_NB) && file.unlink
|
||||
file.open(File::RDWR).flock(File::LOCK_EX | File::LOCK_NB) && file.unlink
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
76
Library/Homebrew/cli_parser.rb
Normal file
76
Library/Homebrew/cli_parser.rb
Normal file
@ -0,0 +1,76 @@
|
||||
require "optparse"
|
||||
require "ostruct"
|
||||
|
||||
module Homebrew
|
||||
module CLI
|
||||
class Parser
|
||||
def self.parse(&block)
|
||||
new(&block).parse
|
||||
end
|
||||
|
||||
def initialize(&block)
|
||||
@parser = OptionParser.new
|
||||
@parsed_args = OpenStruct.new
|
||||
instance_eval(&block)
|
||||
end
|
||||
|
||||
def switch(*names, description: nil, env: nil)
|
||||
description = option_to_description(*names) if description.nil?
|
||||
names, env = common_switch(*names) if names.first.is_a?(Symbol)
|
||||
@parser.on(*names, description) do
|
||||
enable_switch(*names)
|
||||
end
|
||||
enable_switch(*names) if !env.nil? && !ENV["HOMEBREW_#{env.to_s.upcase}"].nil?
|
||||
end
|
||||
|
||||
def comma_array(name, description: nil)
|
||||
description = option_to_description(name) if description.nil?
|
||||
@parser.on(name, OptionParser::REQUIRED_ARGUMENT, Array, description) do |list|
|
||||
@parsed_args[option_to_name(name)] = list
|
||||
end
|
||||
end
|
||||
|
||||
def flag(name, description: nil, required: false)
|
||||
if required
|
||||
option_required = OptionParser::REQUIRED_ARGUMENT
|
||||
else
|
||||
option_required = OptionParser::OPTIONAL_ARGUMENT
|
||||
end
|
||||
description = option_to_description(name) if description.nil?
|
||||
@parser.on(name, description, option_required) do |option_value|
|
||||
@parsed_args[option_to_name(name)] = option_value
|
||||
end
|
||||
end
|
||||
|
||||
def option_to_name(name)
|
||||
name.sub(/\A--?/, "").tr("-", "_")
|
||||
end
|
||||
|
||||
def option_to_description(*names)
|
||||
names.map { |name| name.to_s.sub(/\A--?/, "").tr("-", " ") }.sort.last
|
||||
end
|
||||
|
||||
def parse(cmdline_args = ARGV)
|
||||
@parser.parse!(cmdline_args)
|
||||
@parsed_args
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def enable_switch(*names)
|
||||
names.each do |name|
|
||||
@parsed_args["#{option_to_name(name)}?"] = true
|
||||
end
|
||||
end
|
||||
|
||||
def common_switch(name)
|
||||
case name
|
||||
when :quiet then [["-q", "--quiet"], :quiet]
|
||||
when :verbose then [["-v", "--verbose"], :verbose]
|
||||
when :debug then [["-d", "--debug"], :debug]
|
||||
else name
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -18,7 +18,7 @@
|
||||
#: By default, `deps` shows required and recommended dependencies for
|
||||
#: <formulae>. To include the `:build` type dependencies, pass `--include-build`.
|
||||
#: Similarly, pass `--include-optional` to include `:optional` dependencies or
|
||||
#: `--include-test` to include `:test` dependencies.
|
||||
#: `--include-test` to include (non-recursive) `:test` dependencies.
|
||||
#: To skip `:recommended` type dependencies, pass `--skip-recommended`.
|
||||
#: To include requirements in addition to dependencies, pass `--include-requirements`.
|
||||
#:
|
||||
@ -75,30 +75,40 @@ module Homebrew
|
||||
raise FormulaUnspecifiedError if ARGV.named.empty?
|
||||
puts_deps_tree ARGV.formulae, !ARGV.one?
|
||||
end
|
||||
return
|
||||
elsif mode.all?
|
||||
puts_deps Formula.sort
|
||||
elsif ARGV.named.empty?
|
||||
return
|
||||
elsif !ARGV.named.empty? && mode.for_each?
|
||||
puts_deps ARGV.formulae
|
||||
return
|
||||
end
|
||||
|
||||
@only_installed_arg = ARGV.include?("--installed") &&
|
||||
!ARGV.include?("--include-build") &&
|
||||
!ARGV.include?("--include-test") &&
|
||||
!ARGV.include?("--include-optional") &&
|
||||
!ARGV.include?("--skip-recommended")
|
||||
|
||||
if ARGV.named.empty?
|
||||
raise FormulaUnspecifiedError unless mode.installed?
|
||||
puts_deps Formula.installed.sort
|
||||
elsif mode.for_each?
|
||||
puts_deps ARGV.formulae
|
||||
else
|
||||
return
|
||||
end
|
||||
|
||||
all_deps = deps_for_formulae(ARGV.formulae, !ARGV.one?, &(mode.union? ? :| : :&))
|
||||
all_deps = condense_requirements(all_deps)
|
||||
all_deps = all_deps.select(&:installed?) if mode.installed?
|
||||
all_deps = all_deps.map(&method(:dep_display_name)).uniq
|
||||
all_deps.select!(&:installed?) if mode.installed?
|
||||
all_deps.map!(&method(:dep_display_name))
|
||||
all_deps.uniq!
|
||||
all_deps.sort! unless mode.topo_order?
|
||||
puts all_deps
|
||||
end
|
||||
end
|
||||
|
||||
def condense_requirements(deps)
|
||||
if ARGV.include?("--include-requirements")
|
||||
deps
|
||||
else
|
||||
return deps if ARGV.include?("--include-requirements")
|
||||
deps.select { |dep| dep.is_a? Dependency }
|
||||
end
|
||||
end
|
||||
|
||||
def dep_display_name(dep)
|
||||
str = if dep.is_a? Requirement
|
||||
@ -108,70 +118,33 @@ module Homebrew
|
||||
# This shouldn't happen, but we'll put something here to help debugging
|
||||
"::#{dep.name}"
|
||||
end
|
||||
elsif ARGV.include?("--full-name")
|
||||
dep.to_formula.full_name
|
||||
else
|
||||
ARGV.include?("--full-name") ? dep.to_formula.full_name : dep.name
|
||||
dep.name
|
||||
end
|
||||
|
||||
if ARGV.include?("--annotate")
|
||||
str = "#{str} [build]" if dep.build?
|
||||
str = "#{str} [test]" if dep.test?
|
||||
str = "#{str} [optional" if dep.optional?
|
||||
str = "#{str} [recommended]" if dep.recommended?
|
||||
end
|
||||
|
||||
str
|
||||
end
|
||||
|
||||
def deps_for_formula(f, recursive = false)
|
||||
includes = []
|
||||
ignores = []
|
||||
if ARGV.include?("--include-build")
|
||||
includes << "build?"
|
||||
else
|
||||
ignores << "build?"
|
||||
end
|
||||
if ARGV.include?("--include-test")
|
||||
includes << "test?"
|
||||
else
|
||||
ignores << "test?"
|
||||
end
|
||||
if ARGV.include?("--include-optional")
|
||||
includes << "optional?"
|
||||
else
|
||||
ignores << "optional?"
|
||||
end
|
||||
ignores << "recommended?" if ARGV.include?("--skip-recommended")
|
||||
includes, ignores = argv_includes_ignores(ARGV)
|
||||
|
||||
deps = f.runtime_dependencies if @only_installed_arg
|
||||
|
||||
if recursive
|
||||
deps = f.recursive_dependencies do |dependent, dep|
|
||||
if dep.recommended?
|
||||
Dependency.prune if ignores.include?("recommended?") || dependent.build.without?(dep)
|
||||
elsif dep.test?
|
||||
next if includes.include?("test?")
|
||||
Dependency.prune
|
||||
elsif dep.optional?
|
||||
Dependency.prune if !includes.include?("optional?") && !dependent.build.with?(dep)
|
||||
elsif dep.build?
|
||||
Dependency.prune unless includes.include?("build?")
|
||||
end
|
||||
end
|
||||
reqs = f.recursive_requirements do |dependent, req|
|
||||
if req.recommended?
|
||||
Requirement.prune if ignores.include?("recommended?") || dependent.build.without?(req)
|
||||
elsif req.test?
|
||||
next if includes.include?("test?")
|
||||
Requirement.prune
|
||||
elsif req.optional?
|
||||
Requirement.prune if !includes.include?("optional?") && !dependent.build.with?(req)
|
||||
elsif req.build?
|
||||
Requirement.prune unless includes.include?("build?")
|
||||
end
|
||||
end
|
||||
deps ||= recursive_includes(Dependency, f, includes, ignores)
|
||||
reqs = recursive_includes(Requirement, f, includes, ignores)
|
||||
else
|
||||
deps = f.deps.reject do |dep|
|
||||
ignores.any? { |ignore| dep.send(ignore) } && includes.none? { |include| dep.send(include) }
|
||||
end
|
||||
reqs = f.requirements.reject do |req|
|
||||
ignores.any? { |ignore| req.send(ignore) } && includes.none? { |include| req.send(include) }
|
||||
end
|
||||
deps ||= reject_ignores(f.deps, ignores, includes)
|
||||
reqs = reject_ignores(f.requirements, ignores, includes)
|
||||
end
|
||||
|
||||
deps + reqs.to_a
|
||||
@ -185,7 +158,8 @@ module Homebrew
|
||||
formulae.each do |f|
|
||||
deps = deps_for_formula(f)
|
||||
deps = condense_requirements(deps)
|
||||
deps = deps.sort_by(&:name).map(&method(:dep_display_name))
|
||||
deps.sort_by!(&:name)
|
||||
deps.map!(&method(:dep_display_name))
|
||||
puts "#{f.full_name}: #{deps.join(" ")}"
|
||||
end
|
||||
end
|
||||
@ -203,33 +177,39 @@ module Homebrew
|
||||
reqs = f.requirements
|
||||
deps = f.deps
|
||||
dependables = reqs + deps
|
||||
dependables = dependables.reject(&:optional?) unless ARGV.include?("--include-optional")
|
||||
dependables = dependables.reject(&:build?) unless ARGV.include?("--include-build")
|
||||
dependables = dependables.reject(&:test?) unless ARGV.include?("--include-test")
|
||||
dependables = dependables.reject(&:recommended?) if ARGV.include?("--skip-recommended")
|
||||
dependables.reject!(&:optional?) unless ARGV.include?("--include-optional")
|
||||
dependables.reject!(&:build?) unless ARGV.include?("--include-build")
|
||||
dependables.reject!(&:test?) unless ARGV.include?("--include-test")
|
||||
dependables.reject!(&:recommended?) if ARGV.include?("--skip-recommended")
|
||||
max = dependables.length - 1
|
||||
@dep_stack.push f.name
|
||||
dependables.each_with_index do |dep, i|
|
||||
next if !ARGV.include?("--include-requirements") && dep.is_a?(Requirement)
|
||||
|
||||
tree_lines = if i == max
|
||||
"└──"
|
||||
else
|
||||
"├──"
|
||||
end
|
||||
|
||||
display_s = "#{tree_lines} #{dep_display_name(dep)}"
|
||||
is_circular = @dep_stack.include?(dep.name)
|
||||
display_s = "#{display_s} (CIRCULAR DEPENDENCY)" if is_circular
|
||||
puts "#{prefix}#{display_s}"
|
||||
|
||||
next if !recursive || is_circular
|
||||
|
||||
prefix_addition = if i == max
|
||||
" "
|
||||
else
|
||||
"│ "
|
||||
end
|
||||
|
||||
if dep.is_a? Dependency
|
||||
recursive_deps_tree(Formulary.factory(dep.name), prefix + prefix_addition, true)
|
||||
end
|
||||
end
|
||||
|
||||
@dep_stack.pop
|
||||
end
|
||||
end
|
||||
|
||||
@ -74,14 +74,13 @@ module Homebrew
|
||||
end
|
||||
|
||||
def command_help(path)
|
||||
help_lines = path.read.lines.grep(/^#:/)
|
||||
help_lines = command_help_lines(path)
|
||||
if help_lines.empty?
|
||||
opoo "No help text in: #{path}" if ARGV.homebrew_developer?
|
||||
HOMEBREW_HELP
|
||||
else
|
||||
help_lines.map do |line|
|
||||
line.slice(2..-1)
|
||||
.sub(/^ \* /, "#{Tty.bold}brew#{Tty.reset} ")
|
||||
line.sub(/^ \* /, "#{Tty.bold}brew#{Tty.reset} ")
|
||||
.gsub(/`(.*?)`/, "#{Tty.bold}\\1#{Tty.reset}")
|
||||
.gsub(%r{<([^\s]+?://[^\s]+?)>}) { |url| Formatter.url(url) }
|
||||
.gsub(/<(.*?)>/, "#{Tty.underline}\\1#{Tty.reset}")
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#: * `install` [`--debug`] [`--env=`(`std`|`super`)] [`--ignore-dependencies`|`--only-dependencies`] [`--cc=`<compiler>] [`--build-from-source`|`--force-bottle`] [`--devel`|`--HEAD`] [`--keep-tmp`] [`--build-bottle`] [`--force`] [`--verbose`] <formula> [<options> ...]:
|
||||
#: * `install` [`--debug`] [`--env=`(`std`|`super`)] [`--ignore-dependencies`|`--only-dependencies`] [`--cc=`<compiler>] [`--build-from-source`|`--force-bottle`] [`--include-test`] [`--devel`|`--HEAD`] [`--keep-tmp`] [`--build-bottle`] [`--force`] [`--verbose`] <formula> [<options> ...]:
|
||||
#: Install <formula>.
|
||||
#:
|
||||
#: <formula> is usually the name of the formula to install, but it can be specified
|
||||
@ -36,6 +36,9 @@
|
||||
#: current or newest version of macOS, even if it would not normally be used
|
||||
#: for installation.
|
||||
#:
|
||||
#: If `--include-test` is passed, install testing dependencies. These are only
|
||||
#: needed by formulae maintainers to run `brew test`.
|
||||
#:
|
||||
#: If `--devel` is passed, and <formula> defines it, install the development version.
|
||||
#:
|
||||
#: If `--HEAD` is passed, and <formula> defines it, install the HEAD version,
|
||||
@ -159,6 +162,8 @@ module Homebrew
|
||||
#{f.full_name} #{optlinked_version} is already installed
|
||||
To upgrade to #{f.version}, run `brew upgrade #{f.name}`
|
||||
EOS
|
||||
elsif ARGV.only_deps?
|
||||
formulae << f
|
||||
else
|
||||
opoo <<~EOS
|
||||
#{f.full_name} #{f.pkg_version} is already installed
|
||||
@ -188,8 +193,11 @@ module Homebrew
|
||||
#{msg}, it's just not linked.
|
||||
You can use `brew link #{f}` to link this version.
|
||||
EOS
|
||||
elsif ARGV.only_deps?
|
||||
msg = nil
|
||||
formulae << f
|
||||
end
|
||||
opoo msg
|
||||
opoo msg if msg
|
||||
elsif !f.any_version_installed? && old_formula = f.old_installed_formulae.first
|
||||
msg = "#{old_formula.full_name} #{old_formula.installed_version} already installed"
|
||||
if !old_formula.linked? && !old_formula.keg_only?
|
||||
@ -249,10 +257,10 @@ module Homebrew
|
||||
return
|
||||
end
|
||||
|
||||
query = query_regexp(e.name)
|
||||
regex = query_regexp(e.name)
|
||||
|
||||
ohai "Searching for similarly named formulae..."
|
||||
formulae_search_results = search_formulae(query)
|
||||
formulae_search_results = search_formulae(regex)
|
||||
case formulae_search_results.length
|
||||
when 0
|
||||
ofail "No similarly named formulae found."
|
||||
@ -269,7 +277,7 @@ module Homebrew
|
||||
# Do not search taps if the formula name is qualified
|
||||
return if e.name.include?("/")
|
||||
ohai "Searching taps..."
|
||||
taps_search_results = search_taps(query)
|
||||
taps_search_results = search_taps(e.name)
|
||||
case taps_search_results.length
|
||||
when 0
|
||||
ofail "No formulae found in taps."
|
||||
|
||||
@ -10,15 +10,18 @@ module Homebrew
|
||||
|
||||
def leaves
|
||||
installed = Formula.installed.sort
|
||||
deps_of_installed = Set.new
|
||||
|
||||
installed.each do |f|
|
||||
deps = f.runtime_dependencies.map { |d| d.to_formula.full_name }
|
||||
deps_of_installed.merge(deps)
|
||||
deps_of_installed = installed.flat_map do |f|
|
||||
f.runtime_dependencies.map do |dep|
|
||||
begin
|
||||
dep.to_formula.full_name
|
||||
rescue FormulaUnavailableError
|
||||
dep.name
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
installed.each do |f|
|
||||
puts f.full_name unless deps_of_installed.include? f.full_name
|
||||
end
|
||||
leaves = installed.map(&:full_name) - deps_of_installed
|
||||
leaves.each(&method(:puts))
|
||||
end
|
||||
end
|
||||
|
||||
@ -11,6 +11,8 @@
|
||||
#: If `--display-cop-names` is passed, include the RuboCop cop name for each
|
||||
#: violation in the output.
|
||||
#:
|
||||
#: If `--rspec` is passed, install and use the RuboCop RSpec gem.
|
||||
#:
|
||||
#: Passing `--only-cops=`<cops> will check for violations of only the listed
|
||||
#: RuboCop <cops>, while `--except-cops=`<cops> will skip checking the listed
|
||||
#: <cops>. For either option <cops> should be a comma-separated list of cop names.
|
||||
@ -83,6 +85,11 @@ module Homebrew
|
||||
args << "--parallel"
|
||||
end
|
||||
|
||||
if ARGV.include?("--rspec")
|
||||
Homebrew.install_gem! "rubocop-rspec"
|
||||
args += %w[--require rubocop-rspec]
|
||||
end
|
||||
|
||||
if options[:except_cops]
|
||||
options[:except_cops].map! { |cop| RuboCop::Cop::Cop.registry.qualified_cop_name(cop.to_s, "") }
|
||||
cops_to_exclude = options[:except_cops].select do |cop|
|
||||
|
||||
@ -23,15 +23,8 @@ git() {
|
||||
}
|
||||
|
||||
git_init_if_necessary() {
|
||||
if [[ -n "$HOMEBREW_MACOS" ]] || [[ -n "$HOMEBREW_FORCE_HOMEBREW_ORG" ]]
|
||||
then
|
||||
BREW_OFFICIAL_REMOTE="https://github.com/Homebrew/brew"
|
||||
CORE_OFFICIAL_REMOTE="https://github.com/Homebrew/homebrew-core"
|
||||
elif [[ -n "$HOMEBREW_LINUX" ]]
|
||||
then
|
||||
BREW_OFFICIAL_REMOTE="https://github.com/Linuxbrew/brew"
|
||||
CORE_OFFICIAL_REMOTE="https://github.com/Linuxbrew/homebrew-core"
|
||||
fi
|
||||
|
||||
safe_cd "$HOMEBREW_REPOSITORY"
|
||||
if [[ ! -d ".git" ]]
|
||||
|
||||
@ -1,15 +1,19 @@
|
||||
#: * `upgrade` [<install-options>] [`--cleanup`] [`--fetch-HEAD`] [<formulae>]:
|
||||
#: * `upgrade` [<install-options>] [`--cleanup`] [`--fetch-HEAD`] [`--ignore-pinned`] [<formulae>]:
|
||||
#: Upgrade outdated, unpinned brews (with existing install options).
|
||||
#:
|
||||
#: Options for the `install` command are also valid here.
|
||||
#:
|
||||
#: If `--cleanup` is specified then remove previously installed <formula> version(s).
|
||||
#: If `--cleanup` is specified or `HOMEBREW_UPGRADE_CLEANUP` is set then remove
|
||||
#: previously installed <formula> version(s).
|
||||
#:
|
||||
#: If `--fetch-HEAD` is passed, fetch the upstream repository to detect if
|
||||
#: the HEAD installation of the formula is outdated. Otherwise, the
|
||||
#: repository's HEAD will be checked for updates when a new stable or devel
|
||||
#: version has been released.
|
||||
#:
|
||||
#: If `--ignore-pinned` is passed, set a 0 exit code even if pinned formulae
|
||||
#: are not upgraded.
|
||||
#:
|
||||
#: If <formulae> are given, upgrade only the specified brews (unless they
|
||||
#: are pinned; see `pin`, `unpin`).
|
||||
|
||||
@ -54,6 +58,11 @@ module Homebrew
|
||||
outdated -= pinned
|
||||
formulae_to_install = outdated.map(&:latest_formula)
|
||||
|
||||
if !pinned.empty? && !ARGV.include?("--ignore-pinned")
|
||||
ofail "Not upgrading #{Formatter.pluralize(pinned.length, "pinned package")}:"
|
||||
puts pinned.map { |f| "#{f.full_specified_name} #{f.pkg_version}" } * ", "
|
||||
end
|
||||
|
||||
if formulae_to_install.empty?
|
||||
oh1 "No packages to upgrade"
|
||||
else
|
||||
@ -61,11 +70,6 @@ module Homebrew
|
||||
puts formulae_to_install.map { |f| "#{f.full_specified_name} #{f.pkg_version}" } * ", "
|
||||
end
|
||||
|
||||
unless pinned.empty?
|
||||
onoe "Not upgrading #{Formatter.pluralize(pinned.length, "pinned package")}:"
|
||||
puts pinned.map { |f| "#{f.full_specified_name} #{f.pkg_version}" } * ", "
|
||||
end
|
||||
|
||||
# Sort keg_only before non-keg_only formulae to avoid any needless conflicts
|
||||
# with outdated, non-keg_only versions of formulae being upgraded.
|
||||
formulae_to_install.sort! do |a, b|
|
||||
@ -82,7 +86,7 @@ module Homebrew
|
||||
Migrator.migrate_if_needed(f)
|
||||
begin
|
||||
upgrade_formula(f)
|
||||
next unless ARGV.include?("--cleanup")
|
||||
next if !ARGV.include?("--cleanup") && !ENV["HOMEBREW_UPGRADE_CLEANUP"]
|
||||
next unless f.installed?
|
||||
Homebrew::Cleanup.cleanup_formula f
|
||||
rescue UnsatisfiedRequirements => e
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#: * `uses` [`--installed`] [`--recursive`] [`--include-build`] [`--include-optional`] [`--skip-recommended`] [`--devel`|`--HEAD`] <formulae>:
|
||||
#: * `uses` [`--installed`] [`--recursive`] [`--include-build`] [`--include-test`] [`--include-optional`] [`--skip-recommended`] [`--devel`|`--HEAD`] <formulae>:
|
||||
#: Show the formulae that specify <formulae> as a dependency. When given
|
||||
#: multiple formula arguments, show the intersection of formulae that use
|
||||
#: <formulae>.
|
||||
@ -9,10 +9,12 @@
|
||||
#:
|
||||
#: By default, `uses` shows all formulae that specify <formulae> as a required
|
||||
#: or recommended dependency. To include the `:build` type dependencies, pass
|
||||
#: `--include-build`. Similarly, pass `--include-optional` to include `:optional`
|
||||
#: dependencies. To skip `:recommended` type dependencies, pass `--skip-recommended`.
|
||||
#: `--include-build`, to include the `:test` type dependencies, pass
|
||||
#: `--include-test` and to include `:optional` dependencies pass
|
||||
#: `--include-optional`. To skip `:recommended` type dependencies, pass
|
||||
#: `--skip-recommended`.
|
||||
#:
|
||||
#: By default, `uses` shows usages of <formulae> by stable builds. To find
|
||||
#: By default, `uses` shows usage of <formulae> by stable builds. To find
|
||||
#: cases where <formulae> is used by development or HEAD build, pass
|
||||
#: `--devel` or `--HEAD`.
|
||||
|
||||
@ -40,39 +42,20 @@ module Homebrew
|
||||
|
||||
formulae = ARGV.include?("--installed") ? Formula.installed : Formula
|
||||
recursive = ARGV.flag? "--recursive"
|
||||
includes = []
|
||||
ignores = []
|
||||
if ARGV.include? "--include-build"
|
||||
includes << "build?"
|
||||
else
|
||||
ignores << "build?"
|
||||
end
|
||||
if ARGV.include? "--include-optional"
|
||||
includes << "optional?"
|
||||
else
|
||||
ignores << "optional?"
|
||||
end
|
||||
ignores << "recommended?" if ARGV.include? "--skip-recommended"
|
||||
only_installed_arg = ARGV.include?("--installed") &&
|
||||
!ARGV.include?("--include-build") &&
|
||||
!ARGV.include?("--include-test") &&
|
||||
!ARGV.include?("--include-optional") &&
|
||||
!ARGV.include?("--skip-recommended")
|
||||
|
||||
includes, ignores = argv_includes_ignores(ARGV)
|
||||
|
||||
uses = formulae.select do |f|
|
||||
used_formulae.all? do |ff|
|
||||
begin
|
||||
deps = f.runtime_dependencies if only_installed_arg
|
||||
if recursive
|
||||
deps = f.recursive_dependencies do |dependent, dep|
|
||||
if dep.recommended?
|
||||
Dependency.prune if ignores.include?("recommended?") || dependent.build.without?(dep)
|
||||
elsif dep.optional?
|
||||
Dependency.prune if !includes.include?("optional?") && !dependent.build.with?(dep)
|
||||
elsif dep.build?
|
||||
Dependency.prune unless includes.include?("build?")
|
||||
end
|
||||
|
||||
# If a tap isn't installed, we can't find the dependencies of one
|
||||
# its formulae, and an exception will be thrown if we try.
|
||||
if dep.is_a?(TapDependency) && !dep.tap.installed?
|
||||
Dependency.keep_but_prune_recursive_deps
|
||||
end
|
||||
end
|
||||
deps ||= recursive_includes(Dependency, f, includes, ignores)
|
||||
|
||||
dep_formulae = deps.flat_map do |dep|
|
||||
begin
|
||||
@ -89,6 +72,8 @@ module Homebrew
|
||||
reqs_by_formula.reject! do |dependent, req|
|
||||
if req.recommended?
|
||||
ignores.include?("recommended?") || dependent.build.without?(req)
|
||||
elsif req.test?
|
||||
!includes.include?("test?")
|
||||
elsif req.optional?
|
||||
!includes.include?("optional?") && !dependent.build.with?(req)
|
||||
elsif req.build?
|
||||
@ -98,13 +83,10 @@ module Homebrew
|
||||
|
||||
reqs = reqs_by_formula.map(&:last)
|
||||
else
|
||||
deps = f.deps.reject do |dep|
|
||||
ignores.any? { |ignore| dep.send(ignore) } && includes.none? { |include| dep.send(include) }
|
||||
end
|
||||
reqs = f.requirements.reject do |req|
|
||||
ignores.any? { |ignore| req.send(ignore) } && includes.none? { |include| req.send(include) }
|
||||
end
|
||||
deps ||= reject_ignores(f.deps, ignores, includes)
|
||||
reqs = reject_ignores(f.requirements, ignores, includes)
|
||||
end
|
||||
|
||||
next true if deps.any? do |dep|
|
||||
begin
|
||||
dep.to_formula.full_name == ff.full_name
|
||||
|
||||
@ -114,10 +114,10 @@ EOS
|
||||
if [[ -x "/usr/bin/shasum" ]]
|
||||
then
|
||||
sha="$(/usr/bin/shasum -a 256 "$CACHED_LOCATION" | cut -d' ' -f1)"
|
||||
elif [[ -x "$(which sha256sum)" ]]
|
||||
elif [[ -x "$(type -P sha256sum)" ]]
|
||||
then
|
||||
sha="$(sha256sum "$CACHED_LOCATION" | cut -d' ' -f1)"
|
||||
elif [[ -x "$(which ruby)" ]]
|
||||
elif [[ -x "$(type -P ruby)" ]]
|
||||
then
|
||||
sha="$(ruby <<EOSCRIPT
|
||||
require 'digest/sha2'
|
||||
|
||||
@ -29,3 +29,4 @@ require "compat/ENV/super"
|
||||
require "compat/utils/shell"
|
||||
require "compat/extend/string"
|
||||
require "compat/gpg"
|
||||
require "compat/dependable"
|
||||
|
||||
5
Library/Homebrew/compat/dependable.rb
Normal file
5
Library/Homebrew/compat/dependable.rb
Normal file
@ -0,0 +1,5 @@
|
||||
module Dependable
|
||||
def run?
|
||||
tags.include? :run
|
||||
end
|
||||
end
|
||||
@ -33,7 +33,6 @@ class DependencyCollector
|
||||
output_deprecation(spec)
|
||||
Dependency.new(spec.to_s, tags)
|
||||
when :libltdl
|
||||
tags << :run
|
||||
output_deprecation("libtool")
|
||||
Dependency.new("libtool", tags)
|
||||
when :apr
|
||||
@ -68,7 +67,7 @@ class DependencyCollector
|
||||
private
|
||||
|
||||
def autotools_dep(spec, tags)
|
||||
tags << :build unless tags.include? :run
|
||||
tags << :build
|
||||
Dependency.new(spec.to_s, tags)
|
||||
end
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# RuboCop version used for `brew style` and `brew cask style`
|
||||
HOMEBREW_RUBOCOP_VERSION = "0.53.0"
|
||||
HOMEBREW_RUBOCOP_CASK_VERSION = "~> 0.17.0" # has to be updated when RuboCop version changes
|
||||
HOMEBREW_RUBOCOP_VERSION = "0.54.0"
|
||||
HOMEBREW_RUBOCOP_CASK_VERSION = "~> 0.18.0" # has to be updated when RuboCop version changes
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
require "options"
|
||||
|
||||
module Dependable
|
||||
# :run and :linked are no longer used but keep them here to avoid them being
|
||||
# misused in future.
|
||||
RESERVED_TAGS = [:build, :optional, :recommended, :run, :test, :linked].freeze
|
||||
|
||||
def build?
|
||||
@ -15,10 +17,6 @@ module Dependable
|
||||
tags.include? :recommended
|
||||
end
|
||||
|
||||
def run?
|
||||
tags.include? :run
|
||||
end
|
||||
|
||||
def test?
|
||||
tags.include? :test
|
||||
end
|
||||
@ -34,4 +32,15 @@ module Dependable
|
||||
def options
|
||||
Options.create(option_tags)
|
||||
end
|
||||
|
||||
def prune_from_option?(build)
|
||||
return if !optional? && !recommended?
|
||||
build.without?(self)
|
||||
end
|
||||
|
||||
def prune_if_build_and_not_dependent?(dependent, formula = nil)
|
||||
return false unless build?
|
||||
return dependent.installed? unless formula
|
||||
dependent != formula
|
||||
end
|
||||
end
|
||||
|
||||
@ -52,3 +52,81 @@ class Requirements < DelegateClass(Set)
|
||||
"#<#{self.class.name}: {#{to_a.join(", ")}}>"
|
||||
end
|
||||
end
|
||||
|
||||
module Homebrew
|
||||
module_function
|
||||
|
||||
def argv_includes_ignores(argv)
|
||||
includes = []
|
||||
ignores = []
|
||||
|
||||
if argv.include? "--include-build"
|
||||
includes << "build?"
|
||||
else
|
||||
ignores << "build?"
|
||||
end
|
||||
|
||||
if argv.include? "--include-test"
|
||||
includes << "test?"
|
||||
else
|
||||
ignores << "test?"
|
||||
end
|
||||
|
||||
if argv.include? "--include-optional"
|
||||
includes << "optional?"
|
||||
else
|
||||
ignores << "optional?"
|
||||
end
|
||||
|
||||
ignores << "recommended?" if ARGV.include? "--skip-recommended"
|
||||
|
||||
[includes, ignores]
|
||||
end
|
||||
|
||||
def recursive_includes(klass, formula, includes, ignores)
|
||||
type = if klass == Dependency
|
||||
:dependencies
|
||||
elsif klass == Requirement
|
||||
:requirements
|
||||
else
|
||||
raise ArgumentError, "Invalid class argument: #{klass}"
|
||||
end
|
||||
|
||||
formula.send("recursive_#{type}") do |dependent, dep|
|
||||
if dep.recommended?
|
||||
if ignores.include?("recommended?") || dependent.build.without?(dep)
|
||||
klass.prune
|
||||
end
|
||||
elsif dep.test?
|
||||
if includes.include?("test?")
|
||||
if type == :dependencies
|
||||
Dependency.keep_but_prune_recursive_deps
|
||||
end
|
||||
else
|
||||
klass.prune
|
||||
end
|
||||
elsif dep.optional?
|
||||
if !includes.include?("optional?") && !dependent.build.with?(dep)
|
||||
klass.prune
|
||||
end
|
||||
elsif dep.build?
|
||||
klass.prune unless includes.include?("build?")
|
||||
end
|
||||
|
||||
# If a tap isn't installed, we can't find the dependencies of one
|
||||
# its formulae, and an exception will be thrown if we try.
|
||||
if type == :dependencies &&
|
||||
dep.is_a?(TapDependency) &&
|
||||
!dep.tap.installed?
|
||||
Dependency.keep_but_prune_recursive_deps
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def reject_ignores(dependables, ignores, includes)
|
||||
dependables.reject do |dep|
|
||||
next false unless ignores.any? { |ignore| dep.send(ignore) }
|
||||
includes.none? { |include| dep.send(include) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -83,6 +83,9 @@ class Dependency
|
||||
deps.each do |dep|
|
||||
next if dependent.name == dep.name
|
||||
|
||||
# we only care about one level of test dependencies.
|
||||
next if dep.test? && @expand_stack.length > 1
|
||||
|
||||
case action(dependent, dep, &block)
|
||||
when :prune
|
||||
next
|
||||
@ -160,13 +163,9 @@ class Dependency
|
||||
end
|
||||
|
||||
def merge_temporality(deps)
|
||||
if deps.all?(&:build?)
|
||||
# Means both build and runtime dependency.
|
||||
return [] unless deps.all?(&:build?)
|
||||
[:build]
|
||||
elsif deps.all?(&:run?)
|
||||
[:run]
|
||||
else
|
||||
[] # Means both build and runtime dependency.
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -49,20 +49,36 @@ require "cmd/style"
|
||||
require "date"
|
||||
require "missing_formula"
|
||||
require "digest"
|
||||
require "cli_parser"
|
||||
|
||||
module Homebrew
|
||||
module_function
|
||||
|
||||
def audit
|
||||
inject_dump_stats!(FormulaAuditor, /^audit_/) if ARGV.switch? "D"
|
||||
args = Homebrew::CLI::Parser.parse do
|
||||
switch "--strict"
|
||||
switch "--online"
|
||||
switch "--new-formula"
|
||||
switch "--fix"
|
||||
switch "--display-cop-names"
|
||||
switch "--display-filename"
|
||||
switch "-D", "--audit-debug", description: "Activates debugging and profiling"
|
||||
switch :verbose
|
||||
switch :debug
|
||||
comma_array "--only"
|
||||
comma_array "--except"
|
||||
comma_array "--only-cops"
|
||||
comma_array "--except-cops"
|
||||
end
|
||||
|
||||
Homebrew.auditing = true
|
||||
inject_dump_stats!(FormulaAuditor, /^audit_/) if args.audit_debug?
|
||||
|
||||
formula_count = 0
|
||||
problem_count = 0
|
||||
|
||||
new_formula = ARGV.include? "--new-formula"
|
||||
strict = new_formula || ARGV.include?("--strict")
|
||||
online = new_formula || ARGV.include?("--online")
|
||||
new_formula = args.new_formula?
|
||||
strict = new_formula || args.strict?
|
||||
online = new_formula || args.online?
|
||||
|
||||
ENV.activate_extensions!
|
||||
ENV.setup_build_environment
|
||||
@ -75,35 +91,36 @@ module Homebrew
|
||||
files = ARGV.resolved_formulae.map(&:path)
|
||||
end
|
||||
|
||||
only_cops = ARGV.value("only-cops").to_s.split(",")
|
||||
except_cops = ARGV.value("except-cops").to_s.split(",")
|
||||
only_cops = args.only_cops
|
||||
except_cops = args.except_cops
|
||||
|
||||
if !only_cops.empty? && !except_cops.empty?
|
||||
if only_cops && except_cops
|
||||
odie "--only-cops and --except-cops cannot be used simultaneously!"
|
||||
elsif (!only_cops.empty? || !except_cops.empty?) && (strict || ARGV.value("only"))
|
||||
elsif (only_cops || except_cops) && (strict || args.only)
|
||||
odie "--only-cops/--except-cops and --strict/--only cannot be used simultaneously"
|
||||
end
|
||||
|
||||
options = { fix: ARGV.flag?("--fix"), realpath: true }
|
||||
options = { fix: args.fix?, realpath: true }
|
||||
|
||||
if !only_cops.empty?
|
||||
if only_cops
|
||||
options[:only_cops] = only_cops
|
||||
ARGV.push("--only=style")
|
||||
elsif new_formula
|
||||
args.only = ["style"]
|
||||
elsif args.new_formula?
|
||||
nil
|
||||
elsif strict
|
||||
options[:except_cops] = [:NewFormulaAudit]
|
||||
elsif !except_cops.empty?
|
||||
elsif except_cops
|
||||
options[:except_cops] = except_cops
|
||||
elsif !strict
|
||||
options[:only_cops] = [:FormulaAudit]
|
||||
end
|
||||
|
||||
options[:display_cop_names] = args.display_cop_names?
|
||||
# Check style in a single batch run up front for performance
|
||||
style_results = check_style_json(files, options)
|
||||
|
||||
ff.sort.each do |f|
|
||||
options = { new_formula: new_formula, strict: strict, online: online }
|
||||
options = { new_formula: new_formula, strict: strict, online: online, only: args.only, except: args.except }
|
||||
options[:style_offenses] = style_results.file_offenses(f.path)
|
||||
fa = FormulaAuditor.new(f, options)
|
||||
fa.audit
|
||||
@ -113,7 +130,7 @@ module Homebrew
|
||||
formula_count += 1
|
||||
problem_count += fa.problems.size
|
||||
problem_lines = fa.problems.map { |p| "* #{p.chomp.gsub("\n", "\n ")}" }
|
||||
if ARGV.include? "--display-filename"
|
||||
if args.display_filename?
|
||||
puts problem_lines.map { |s| "#{f.path}: #{s}" }
|
||||
else
|
||||
puts "#{f.full_name}:", problem_lines.map { |s| " #{s}" }
|
||||
@ -172,28 +189,14 @@ class FormulaAuditor
|
||||
|
||||
attr_reader :formula, :text, :problems
|
||||
|
||||
BUILD_TIME_DEPS = %w[
|
||||
autoconf
|
||||
automake
|
||||
boost-build
|
||||
bsdmake
|
||||
cmake
|
||||
godep
|
||||
imake
|
||||
intltool
|
||||
libtool
|
||||
pkg-config
|
||||
scons
|
||||
smake
|
||||
sphinx-doc
|
||||
swig
|
||||
].freeze
|
||||
|
||||
def initialize(formula, options = {})
|
||||
@formula = formula
|
||||
@new_formula = options[:new_formula]
|
||||
@strict = options[:strict]
|
||||
@online = options[:online]
|
||||
@display_cop_names = options[:display_cop_names]
|
||||
@only = options[:only]
|
||||
@except = options[:except]
|
||||
# Accept precomputed style offense results, for efficiency
|
||||
@style_offenses = options[:style_offenses]
|
||||
# Allow the actual official-ness of a formula to be overridden, for testing purposes
|
||||
@ -205,9 +208,8 @@ class FormulaAuditor
|
||||
|
||||
def audit_style
|
||||
return unless @style_offenses
|
||||
display_cop_names = ARGV.include?("--display-cop-names")
|
||||
@style_offenses.each do |offense|
|
||||
problem offense.to_s(display_cop_name: display_cop_names)
|
||||
problem offense.to_s(display_cop_name: @display_cop_names)
|
||||
end
|
||||
end
|
||||
|
||||
@ -377,17 +379,12 @@ class FormulaAuditor
|
||||
problem "Dependency #{dep} does not define option #{opt.name.inspect}"
|
||||
end
|
||||
|
||||
case dep.name
|
||||
when "git"
|
||||
if dep.name == "git"
|
||||
problem "Don't use git as a dependency (it's always available)"
|
||||
when *BUILD_TIME_DEPS
|
||||
next if dep.build? || dep.run?
|
||||
problem <<~EOS
|
||||
#{dep} dependency should be
|
||||
depends_on "#{dep}" => :build
|
||||
Or if it is indeed a runtime dependency
|
||||
depends_on "#{dep}" => :run
|
||||
EOS
|
||||
end
|
||||
|
||||
if dep.tags.include?(:run)
|
||||
problem "Dependency '#{dep.name}' is marked as :run. Remove :run; it is a no-op."
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -569,6 +566,7 @@ class FormulaAuditor
|
||||
gtk-doc 1.25
|
||||
libart 2.3.21
|
||||
pygtkglext 1.1.0
|
||||
libepoxy 1.5.0
|
||||
].each_slice(2).to_a.map do |formula, version|
|
||||
[formula, version.split(".")[0..1].join(".")]
|
||||
end
|
||||
@ -789,17 +787,17 @@ class FormulaAuditor
|
||||
end
|
||||
|
||||
def audit
|
||||
only_audits = ARGV.value("only").to_s.split(",")
|
||||
except_audits = ARGV.value("except").to_s.split(",")
|
||||
if !only_audits.empty? && !except_audits.empty?
|
||||
only_audits = @only
|
||||
except_audits = @except
|
||||
if only_audits && except_audits
|
||||
odie "--only and --except cannot be used simultaneously!"
|
||||
end
|
||||
|
||||
methods.map(&:to_s).grep(/^audit_/).each do |audit_method_name|
|
||||
name = audit_method_name.gsub(/^audit_/, "")
|
||||
if !only_audits.empty?
|
||||
if only_audits
|
||||
next unless only_audits.include?(name)
|
||||
elsif !except_audits.empty?
|
||||
elsif except_audits
|
||||
next if except_audits.include?(name)
|
||||
end
|
||||
send(audit_method_name)
|
||||
@ -949,13 +947,13 @@ class ResourceAuditor
|
||||
problem http_content_problem
|
||||
end
|
||||
elsif strategy <= GitDownloadStrategy
|
||||
unless Utils.git_remote_exists url
|
||||
unless Utils.git_remote_exists? url
|
||||
problem "The URL #{url} is not a valid git URL"
|
||||
end
|
||||
elsif strategy <= SubversionDownloadStrategy
|
||||
next unless DevelopmentTools.subversion_handles_most_https_certificates?
|
||||
next unless Utils.svn_available?
|
||||
unless Utils.svn_remote_exists url
|
||||
unless Utils.svn_remote_exists? url
|
||||
problem "The URL #{url} is not a valid svn URL"
|
||||
end
|
||||
end
|
||||
|
||||
@ -34,6 +34,7 @@ require "utils/bottles"
|
||||
require "tab"
|
||||
require "keg"
|
||||
require "formula_versions"
|
||||
require "cli_parser"
|
||||
require "utils/inreplace"
|
||||
require "erb"
|
||||
require "extend/pathname"
|
||||
@ -68,6 +69,26 @@ MAXIMUM_STRING_MATCHES = 100
|
||||
module Homebrew
|
||||
module_function
|
||||
|
||||
def bottle
|
||||
@args = Homebrew::CLI::Parser.parse do
|
||||
switch "--merge"
|
||||
switch "--skip-relocation"
|
||||
switch "--force-core-tap"
|
||||
switch "--no-rebuild"
|
||||
switch "--keep-old"
|
||||
switch "--write"
|
||||
switch "--no-commit"
|
||||
switch "--json"
|
||||
switch :verbose
|
||||
flag "--root-url"
|
||||
end
|
||||
|
||||
return merge if @args.merge?
|
||||
ARGV.resolved_formulae.each do |f|
|
||||
bottle_formula f
|
||||
end
|
||||
end
|
||||
|
||||
def keg_contain?(string, keg, ignores)
|
||||
@put_string_exists_header, @put_filenames = nil
|
||||
|
||||
@ -93,7 +114,7 @@ module Homebrew
|
||||
linked_libraries = Keg.file_linked_libraries(file, string)
|
||||
result ||= !linked_libraries.empty?
|
||||
|
||||
if ARGV.verbose?
|
||||
if @args.verbose?
|
||||
print_filename.call(string, file) unless linked_libraries.empty?
|
||||
linked_libraries.each do |lib|
|
||||
puts " #{Tty.bold}-->#{Tty.reset} links to #{lib}"
|
||||
@ -116,7 +137,7 @@ module Homebrew
|
||||
end
|
||||
end
|
||||
|
||||
next unless ARGV.verbose? && !text_matches.empty?
|
||||
next unless @args.verbose? && !text_matches.empty?
|
||||
print_filename.call(string, file)
|
||||
text_matches.first(MAXIMUM_STRING_MATCHES).each do |match, offset|
|
||||
puts " #{Tty.bold}-->#{Tty.reset} match '#{match}' at offset #{Tty.bold}0x#{offset}#{Tty.reset}"
|
||||
@ -137,7 +158,7 @@ module Homebrew
|
||||
absolute_symlinks_start_with_string << pn if link.to_s.start_with?(string)
|
||||
end
|
||||
|
||||
if ARGV.verbose?
|
||||
if @args.verbose?
|
||||
unless absolute_symlinks_start_with_string.empty?
|
||||
opoo "Absolute symlink starting with #{string}:"
|
||||
absolute_symlinks_start_with_string.each do |pn|
|
||||
@ -160,7 +181,7 @@ module Homebrew
|
||||
end
|
||||
|
||||
unless tap = f.tap
|
||||
unless ARGV.include?("--force-core-tap")
|
||||
unless @args.force_core_tap?
|
||||
return ofail "Formula not from core or any taps: #{f.full_name}"
|
||||
end
|
||||
|
||||
@ -179,9 +200,9 @@ module Homebrew
|
||||
|
||||
return ofail "Formula has no stable version: #{f.full_name}" unless f.stable
|
||||
|
||||
if ARGV.include?("--no-rebuild") || !f.tap
|
||||
if @args.no_rebuild? || !f.tap
|
||||
rebuild = 0
|
||||
elsif ARGV.include? "--keep-old"
|
||||
elsif @args.keep_old?
|
||||
rebuild = f.bottle_specification.rebuild
|
||||
else
|
||||
ohai "Determining #{f.full_name} bottle rebuild..."
|
||||
@ -214,7 +235,7 @@ module Homebrew
|
||||
begin
|
||||
keg.delete_pyc_files!
|
||||
|
||||
unless ARGV.include? "--skip-relocation"
|
||||
unless @args.skip_relocation?
|
||||
changed_files = keg.replace_locations_with_placeholders
|
||||
end
|
||||
|
||||
@ -265,7 +286,7 @@ module Homebrew
|
||||
end
|
||||
|
||||
relocatable = true
|
||||
if ARGV.include? "--skip-relocation"
|
||||
if @args.skip_relocation?
|
||||
skip_relocation = true
|
||||
else
|
||||
relocatable = false if keg_contain?(prefix_check, keg, ignores)
|
||||
@ -278,23 +299,21 @@ module Homebrew
|
||||
end
|
||||
skip_relocation = relocatable && !keg.require_relocation?
|
||||
end
|
||||
puts if !relocatable && ARGV.verbose?
|
||||
puts if !relocatable && @args.verbose?
|
||||
rescue Interrupt
|
||||
ignore_interrupts { bottle_path.unlink if bottle_path.exist? }
|
||||
raise
|
||||
ensure
|
||||
ignore_interrupts do
|
||||
original_tab&.write
|
||||
unless ARGV.include? "--skip-relocation"
|
||||
unless @args.skip_relocation?
|
||||
keg.replace_placeholders_with_locations changed_files
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
root_url = ARGV.value("root-url")
|
||||
# Use underscored version for legacy reasons. Remove at some point.
|
||||
root_url ||= ARGV.value("root_url")
|
||||
root_url = @args.root_url
|
||||
|
||||
bottle = BottleSpecification.new
|
||||
bottle.tap = tap
|
||||
@ -314,7 +333,7 @@ module Homebrew
|
||||
bottle.sha256 sha256 => Utils::Bottles.tag
|
||||
|
||||
old_spec = f.bottle_specification
|
||||
if ARGV.include?("--keep-old") && !old_spec.checksums.empty?
|
||||
if @args.keep_old? && !old_spec.checksums.empty?
|
||||
mismatches = [:root_url, :prefix, :cellar, :rebuild].reject do |key|
|
||||
old_spec.send(key) == bottle.send(key)
|
||||
end
|
||||
@ -340,7 +359,7 @@ module Homebrew
|
||||
puts "./#{filename}"
|
||||
puts output
|
||||
|
||||
return unless ARGV.include? "--json"
|
||||
return unless @args.json?
|
||||
json = {
|
||||
f.full_name => {
|
||||
"formula" => {
|
||||
@ -371,7 +390,7 @@ module Homebrew
|
||||
end
|
||||
|
||||
def merge
|
||||
write = ARGV.include? "--write"
|
||||
write = @args.write?
|
||||
|
||||
bottles_hash = ARGV.named.reduce({}) do |hash, json_file|
|
||||
deep_merge_hashes hash, JSON.parse(IO.read(json_file))
|
||||
@ -400,7 +419,7 @@ module Homebrew
|
||||
Utils::Inreplace.inreplace(path) do |s|
|
||||
if s.include? "bottle do"
|
||||
update_or_add = "update"
|
||||
if ARGV.include? "--keep-old"
|
||||
if @args.keep_old?
|
||||
mismatches = []
|
||||
bottle_block_contents = s[/ bottle do(.+?)end\n/m, 1]
|
||||
bottle_block_contents.lines.each do |line|
|
||||
@ -443,7 +462,7 @@ module Homebrew
|
||||
string = s.sub!(/ bottle do.+?end\n/m, output)
|
||||
odie "Bottle block update failed!" unless string
|
||||
else
|
||||
if ARGV.include? "--keep-old"
|
||||
if @args.keep_old?
|
||||
odie "--keep-old was passed but there was no existing bottle block!"
|
||||
end
|
||||
puts output
|
||||
@ -472,7 +491,7 @@ module Homebrew
|
||||
end
|
||||
end
|
||||
|
||||
unless ARGV.include? "--no-commit"
|
||||
unless @args.no_commit?
|
||||
if ENV["HOMEBREW_GIT_NAME"]
|
||||
ENV["GIT_AUTHOR_NAME"] =
|
||||
ENV["GIT_COMMITTER_NAME"] =
|
||||
@ -498,14 +517,4 @@ module Homebrew
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def bottle
|
||||
if ARGV.include? "--merge"
|
||||
merge
|
||||
else
|
||||
ARGV.resolved_formulae.each do |f|
|
||||
bottle_formula f
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -190,6 +190,7 @@ class FormulaCreator
|
||||
<% elsif mode.nil? %>
|
||||
# depends_on "cmake" => :build
|
||||
<% end %>
|
||||
|
||||
def install
|
||||
# ENV.deparallelize # if your formula fails when building in parallel
|
||||
<% if mode == :cmake %>
|
||||
@ -219,6 +220,7 @@ class FormulaCreator
|
||||
system "make", "install" # if this fails, try separate make/make install steps
|
||||
<% end %>
|
||||
end
|
||||
|
||||
test do
|
||||
# `test do` will create, run in and delete a temporary directory.
|
||||
#
|
||||
|
||||
@ -5,11 +5,16 @@
|
||||
#: Open <formula> in the editor.
|
||||
|
||||
require "formula"
|
||||
require "cli_parser"
|
||||
|
||||
module Homebrew
|
||||
module_function
|
||||
|
||||
def edit
|
||||
args = Homebrew::CLI::Parser.parse do
|
||||
switch "--force"
|
||||
end
|
||||
|
||||
unless (HOMEBREW_REPOSITORY/".git").directory?
|
||||
raise <<~EOS
|
||||
Changes will be lost!
|
||||
@ -36,7 +41,7 @@ module Homebrew
|
||||
paths = ARGV.named.map do |name|
|
||||
path = Formulary.path(name)
|
||||
|
||||
raise FormulaUnavailableError, name unless path.file? || ARGV.force?
|
||||
raise FormulaUnavailableError, name unless path.file? || args.force?
|
||||
|
||||
path
|
||||
end
|
||||
|
||||
@ -5,6 +5,8 @@
|
||||
#: If `--pry` is passed or HOMEBREW_PRY is set, pry will be
|
||||
#: used instead of irb.
|
||||
|
||||
require "cli_parser"
|
||||
|
||||
class Symbol
|
||||
def f(*args)
|
||||
Formulary.factory(to_s, *args)
|
||||
@ -21,7 +23,12 @@ module Homebrew
|
||||
module_function
|
||||
|
||||
def irb
|
||||
if ARGV.include? "--examples"
|
||||
args = Homebrew::CLI::Parser.parse do
|
||||
switch "--examples"
|
||||
switch "--pry", env: :pry
|
||||
end
|
||||
|
||||
if args.examples?
|
||||
puts "'v8'.f # => instance of the v8 formula"
|
||||
puts ":hub.f.installed?"
|
||||
puts ":lua.f.methods - 1.methods"
|
||||
@ -29,7 +36,7 @@ module Homebrew
|
||||
return
|
||||
end
|
||||
|
||||
if ARGV.pry?
|
||||
if args.pry?
|
||||
Homebrew.install_gem_setup_path! "pry"
|
||||
require "pry"
|
||||
Pry.config.prompt_name = "brew"
|
||||
@ -45,7 +52,7 @@ module Homebrew
|
||||
|
||||
ohai "Interactive Homebrew Shell"
|
||||
puts "Example commands available with: brew irb --examples"
|
||||
if ARGV.pry?
|
||||
if args.pry?
|
||||
Pry.start
|
||||
else
|
||||
IRB.start
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
require "formula"
|
||||
require "erb"
|
||||
require "ostruct"
|
||||
require "cli_parser"
|
||||
|
||||
module Homebrew
|
||||
module_function
|
||||
@ -19,9 +20,14 @@ module Homebrew
|
||||
TARGET_DOC_PATH = HOMEBREW_REPOSITORY/"docs"
|
||||
|
||||
def man
|
||||
@args = Homebrew::CLI::Parser.parse do
|
||||
switch "--fail-if-changed"
|
||||
switch "--link"
|
||||
end
|
||||
|
||||
raise UsageError unless ARGV.named.empty?
|
||||
|
||||
if ARGV.flag? "--link"
|
||||
if @args.link?
|
||||
odie "`brew man --link` is now done automatically by `brew update`."
|
||||
end
|
||||
|
||||
@ -29,7 +35,7 @@ module Homebrew
|
||||
|
||||
if system "git", "-C", HOMEBREW_REPOSITORY, "diff", "--quiet", "docs/Manpage.md", "manpages"
|
||||
puts "No changes to manpage output detected."
|
||||
elsif ARGV.include?("--fail-if-changed")
|
||||
elsif @args.fail_if_changed?
|
||||
Homebrew.failed = true
|
||||
end
|
||||
end
|
||||
@ -71,6 +77,9 @@ module Homebrew
|
||||
variables[:former_maintainers] = readme.read[/(Former maintainers .*\.)/, 1]
|
||||
.gsub(/\[([^\]]+)\]\([^)]+\)/, '\1')
|
||||
|
||||
variables[:homebrew_bundle] = help_output(:bundle)
|
||||
variables[:homebrew_services] = help_output(:services)
|
||||
|
||||
ERB.new(template, nil, ">").result(variables.instance_eval { binding })
|
||||
end
|
||||
|
||||
@ -85,7 +94,7 @@ module Homebrew
|
||||
|
||||
# Set the manpage date to the existing one if we're checking for changes.
|
||||
# This avoids the only change being e.g. a new date.
|
||||
date = if ARGV.include?("--fail-if-changed") &&
|
||||
date = if @args.fail_if_changed? &&
|
||||
target.extname == ".1" && target.exist?
|
||||
/"(\d{1,2})" "([A-Z][a-z]+) (\d{4})" "#{organisation}" "#{manual}"/ =~ target.read
|
||||
Date.parse("#{Regexp.last_match(1)} #{Regexp.last_match(2)} #{Regexp.last_match(3)}")
|
||||
@ -113,6 +122,12 @@ module Homebrew
|
||||
end
|
||||
end
|
||||
|
||||
def help_output(command)
|
||||
tap = Tap.fetch("Homebrew/homebrew-#{command}")
|
||||
tap.install unless tap.installed?
|
||||
command_help_lines(which("brew-#{command}.rb", Tap.cmd_directories))
|
||||
end
|
||||
|
||||
def target_path_to_format(target)
|
||||
case target.basename
|
||||
when /\.md$/ then ["--markdown", "markdown"]
|
||||
|
||||
@ -52,6 +52,7 @@ require "net/http"
|
||||
require "net/https"
|
||||
require "utils"
|
||||
require "json"
|
||||
require "cli_parser"
|
||||
require "formula"
|
||||
require "formulary"
|
||||
require "tap"
|
||||
@ -62,8 +63,7 @@ module GitHub
|
||||
module_function
|
||||
|
||||
# Return the corresponding test-bot user name for the given GitHub organization.
|
||||
def test_bot_user(user)
|
||||
test_bot = ARGV.value "test-bot-user"
|
||||
def test_bot_user(user, test_bot)
|
||||
return test_bot if test_bot
|
||||
return "BrewTestBot" if user.casecmp("homebrew").zero?
|
||||
"#{user.capitalize}TestBot"
|
||||
@ -76,6 +76,20 @@ module Homebrew
|
||||
def pull
|
||||
odie "You meant `git pull --rebase`." if ARGV[0] == "--rebase"
|
||||
|
||||
@args = Homebrew::CLI::Parser.parse do
|
||||
switch "--bottle"
|
||||
switch "--bump"
|
||||
switch "--clean"
|
||||
switch "--ignore-whitespace"
|
||||
switch "--resolve"
|
||||
switch "--branch-okay"
|
||||
switch "--no-pbcopy"
|
||||
switch "--no-publish"
|
||||
switch "--warn-on-publish-failure"
|
||||
flag "--bintray-org", required: true
|
||||
flag "--test-bot-user", required: true
|
||||
end
|
||||
|
||||
if ARGV.named.empty?
|
||||
odie "This command requires at least one argument containing a URL or pull request number"
|
||||
end
|
||||
@ -88,7 +102,7 @@ module Homebrew
|
||||
ENV["GIT_COMMITTER_EMAIL"] = ENV["HOMEBREW_GIT_EMAIL"]
|
||||
end
|
||||
|
||||
do_bump = ARGV.include?("--bump") && !ARGV.include?("--clean")
|
||||
do_bump = @args.bump? && !@args.clean?
|
||||
|
||||
# Formulae with affected bottles that were published
|
||||
bintray_published_formulae = []
|
||||
@ -107,7 +121,7 @@ module Homebrew
|
||||
end
|
||||
_, testing_job = *testing_match
|
||||
url = "https://github.com/Homebrew/homebrew-#{tap.repo}/compare/master...BrewTestBot:testing-#{testing_job}"
|
||||
odie "Testing URLs require `--bottle`!" unless ARGV.include?("--bottle")
|
||||
odie "Testing URLs require `--bottle`!" unless @args.bottle?
|
||||
elsif (api_match = arg.match HOMEBREW_PULL_API_REGEX)
|
||||
_, user, repo, issue = *api_match
|
||||
url = "https://github.com/#{user}/#{repo}/pull/#{issue}"
|
||||
@ -119,7 +133,7 @@ module Homebrew
|
||||
odie "Not a GitHub pull request or commit: #{arg}"
|
||||
end
|
||||
|
||||
if !testing_job && ARGV.include?("--bottle") && issue.nil?
|
||||
if !testing_job && @args.bottle? && issue.nil?
|
||||
odie "No pull request detected!"
|
||||
end
|
||||
|
||||
@ -137,11 +151,11 @@ module Homebrew
|
||||
orig_revision = `git rev-parse --short HEAD`.strip
|
||||
branch = `git symbolic-ref --short HEAD`.strip
|
||||
|
||||
unless branch == "master" || ARGV.include?("--clean") || ARGV.include?("--branch-okay")
|
||||
unless branch == "master" || @args.clean? || @args.branch_okay?
|
||||
opoo "Current branch is #{branch}: do you need to pull inside master?"
|
||||
end
|
||||
|
||||
patch_puller = PatchPuller.new(url)
|
||||
patch_puller = PatchPuller.new(url, @args)
|
||||
patch_puller.fetch_patch
|
||||
patch_changes = files_changed_in_patch(patch_puller.patchpath, tap)
|
||||
|
||||
@ -189,7 +203,7 @@ module Homebrew
|
||||
end
|
||||
end
|
||||
|
||||
if ARGV.include? "--bottle"
|
||||
if @args.bottle?
|
||||
if f.bottle_unneeded?
|
||||
ohai "#{f}: skipping unneeded bottle."
|
||||
elsif f.bottle_disabled?
|
||||
@ -204,7 +218,7 @@ module Homebrew
|
||||
end
|
||||
|
||||
orig_message = message = `git log HEAD^.. --format=%B`
|
||||
if issue && !ARGV.include?("--clean")
|
||||
if issue && !@args.clean?
|
||||
ohai "Patch closes issue ##{issue}"
|
||||
close_message = "Closes ##{issue}."
|
||||
# If this is a pull request, append a close message.
|
||||
@ -216,7 +230,7 @@ module Homebrew
|
||||
is_bumpable = false
|
||||
end
|
||||
|
||||
is_bumpable = false if ARGV.include?("--clean")
|
||||
is_bumpable = false if @args.clean?
|
||||
is_bumpable = false if ENV["HOMEBREW_DISABLE_LOAD_FORMULA"]
|
||||
|
||||
if is_bumpable
|
||||
@ -228,7 +242,7 @@ module Homebrew
|
||||
odie "No version changes found for #{formula.name}" if bump_subject.nil?
|
||||
unless orig_subject == bump_subject
|
||||
ohai "New bump commit subject: #{bump_subject}"
|
||||
pbcopy bump_subject unless ARGV.include? "--no-pbcopy"
|
||||
pbcopy bump_subject unless @args.no_pbcopy?
|
||||
message = "#{bump_subject}\n\n#{message}"
|
||||
end
|
||||
elsif bump_subject != orig_subject && !bump_subject.nil?
|
||||
@ -237,7 +251,7 @@ module Homebrew
|
||||
end
|
||||
end
|
||||
|
||||
if message != orig_message && !ARGV.include?("--clean")
|
||||
if message != orig_message && !@args.clean?
|
||||
safe_system "git", "commit", "--amend", "--signoff", "--allow-empty", "-q", "-m", message
|
||||
end
|
||||
|
||||
@ -248,7 +262,8 @@ module Homebrew
|
||||
url
|
||||
else
|
||||
bottle_branch = "pull-bottle-#{issue}"
|
||||
"https://github.com/#{GitHub.test_bot_user user}/homebrew-#{tap.repo}/compare/#{user}:master...pr-#{issue}"
|
||||
bot_username = GitHub.test_bot_user(user, @args.test_bot_user)
|
||||
"https://github.com/#{bot_username}/homebrew-#{tap.repo}/compare/#{user}:master...pr-#{issue}"
|
||||
end
|
||||
|
||||
curl "--silent", "--fail", "--output", "/dev/null", "--head", bottle_commit_url
|
||||
@ -261,7 +276,7 @@ module Homebrew
|
||||
safe_system "git", "branch", "--quiet", "-D", bottle_branch
|
||||
|
||||
# Publish bottles on Bintray
|
||||
unless ARGV.include? "--no-publish"
|
||||
unless @args.no_publish?
|
||||
published = publish_changed_formula_bottles(tap, changed_formulae_names)
|
||||
bintray_published_formulae.concat(published)
|
||||
end
|
||||
@ -291,7 +306,7 @@ module Homebrew
|
||||
changed_formulae_names.each do |name|
|
||||
f = Formula[name]
|
||||
next if f.bottle_unneeded? || f.bottle_disabled?
|
||||
bintray_org = ARGV.value("bintray-org") || tap.user.downcase
|
||||
bintray_org = @args.bintray_org || tap.user.downcase
|
||||
next unless publish_bottle_file_on_bintray(f, bintray_org, bintray_creds)
|
||||
published << f.full_name
|
||||
end
|
||||
@ -302,7 +317,7 @@ module Homebrew
|
||||
end
|
||||
|
||||
def pull_patch(url, description = nil)
|
||||
PatchPuller.new(url, description).pull_patch
|
||||
PatchPuller.new(url, @args, description).pull_patch
|
||||
end
|
||||
|
||||
class PatchPuller
|
||||
@ -310,12 +325,13 @@ module Homebrew
|
||||
attr_reader :patch_url
|
||||
attr_reader :patchpath
|
||||
|
||||
def initialize(url, description = nil)
|
||||
def initialize(url, args, description = nil)
|
||||
@base_url = url
|
||||
# GitHub provides commits/pull-requests raw patches using this URL.
|
||||
@patch_url = url + ".patch"
|
||||
@patchpath = HOMEBREW_CACHE + File.basename(patch_url)
|
||||
@description = description
|
||||
@args = args
|
||||
end
|
||||
|
||||
def pull_patch
|
||||
@ -338,7 +354,7 @@ module Homebrew
|
||||
patch_args = []
|
||||
# Normally we don't want whitespace errors, but squashing them can break
|
||||
# patches so an option is provided to skip this step.
|
||||
if ARGV.include?("--ignore-whitespace") || ARGV.include?("--clean")
|
||||
if @args.ignore_whitespace? || @args.clean?
|
||||
patch_args << "--whitespace=nowarn"
|
||||
else
|
||||
patch_args << "--whitespace=fix"
|
||||
@ -351,7 +367,7 @@ module Homebrew
|
||||
begin
|
||||
safe_system "git", "am", *patch_args
|
||||
rescue ErrorDuringExecution
|
||||
if ARGV.include? "--resolve"
|
||||
if @args.resolve?
|
||||
odie "Patch failed to apply: try to resolve it."
|
||||
else
|
||||
system "git", "am", "--abort"
|
||||
@ -464,7 +480,7 @@ module Homebrew
|
||||
"https://api.bintray.com/content/#{bintray_org}/#{repo}/#{package}/#{version}/publish"
|
||||
true
|
||||
rescue => e
|
||||
raise unless ARGV.include?("--warn-on-publish-failure")
|
||||
raise unless @args.warn_on_publish_failure?
|
||||
onoe e
|
||||
false
|
||||
end
|
||||
|
||||
@ -5,10 +5,16 @@
|
||||
#:
|
||||
#: If `--markdown` is passed, output as a Markdown list.
|
||||
|
||||
require "cli_parser"
|
||||
|
||||
module Homebrew
|
||||
module_function
|
||||
|
||||
def release_notes
|
||||
args = Homebrew::CLI::Parser.parse do
|
||||
switch "--markdown"
|
||||
end
|
||||
|
||||
previous_tag = ARGV.named.first
|
||||
previous_tag ||= Utils.popen_read("git tag --list --sort=-version:refname")
|
||||
.lines.first.chomp
|
||||
@ -28,7 +34,7 @@ module Homebrew
|
||||
s.gsub(%r{.*Merge pull request #(\d+) from ([^/]+)/[^>]*(>>)*},
|
||||
"https://github.com/Homebrew/brew/pull/\\1 (@\\2)")
|
||||
end
|
||||
if ARGV.include?("--markdown")
|
||||
if args.markdown?
|
||||
output.map! do |s|
|
||||
/(.*\d)+ \(@(.+)\) - (.*)/ =~ s
|
||||
"- [#{Regexp.last_match(3)}](#{Regexp.last_match(1)}) (@#{Regexp.last_match(2)})"
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#: * `tests` [`--verbose`] [`--coverage`] [`--generic`] [`--no-compat`] [`--only=`<test_script>[`:`<line_number>]] [`--seed` <seed>] [`--online`] [`--official-cmd-taps`]:
|
||||
#: * `tests` [`--verbose`] [`--coverage`] [`--generic`] [`--no-compat`] [`--only=`<test_script>[`:`<line_number>]] [`--seed=`<seed>] [`--online`] [`--official-cmd-taps`]:
|
||||
#: Run Homebrew's unit and integration tests. If provided,
|
||||
#: `--only=`<test_script> runs only <test_script>_spec.rb, and `--seed`
|
||||
#: randomizes tests with the provided value instead of a random seed.
|
||||
@ -15,6 +15,7 @@
|
||||
#: If `--online` is passed, include tests that use the GitHub API and tests
|
||||
#: that use any of the taps for official external commands.
|
||||
|
||||
require "cli_parser"
|
||||
require "fileutils"
|
||||
require "tap"
|
||||
|
||||
@ -22,6 +23,16 @@ module Homebrew
|
||||
module_function
|
||||
|
||||
def tests
|
||||
args = Homebrew::CLI::Parser.parse do
|
||||
switch "--no-compat"
|
||||
switch "--generic"
|
||||
switch "-v", "--verbose"
|
||||
switch "--coverage"
|
||||
switch "--online"
|
||||
flag "--only", required: true
|
||||
flag "--seed", required: true
|
||||
end
|
||||
|
||||
HOMEBREW_LIBRARY_PATH.cd do
|
||||
ENV.delete("HOMEBREW_VERBOSE")
|
||||
ENV.delete("VERBOSE")
|
||||
@ -29,16 +40,16 @@ module Homebrew
|
||||
ENV.delete("HOMEBREW_TEMP")
|
||||
ENV["HOMEBREW_NO_ANALYTICS_THIS_RUN"] = "1"
|
||||
ENV["HOMEBREW_DEVELOPER"] = "1"
|
||||
ENV["HOMEBREW_NO_COMPAT"] = "1" if ARGV.include? "--no-compat"
|
||||
ENV["HOMEBREW_TEST_GENERIC_OS"] = "1" if ARGV.include? "--generic"
|
||||
ENV["HOMEBREW_NO_COMPAT"] = "1" if args.no_compat?
|
||||
ENV["HOMEBREW_TEST_GENERIC_OS"] = "1" if args.generic?
|
||||
|
||||
if ARGV.include? "--online"
|
||||
if args.online?
|
||||
ENV["HOMEBREW_TEST_ONLINE"] = "1"
|
||||
else
|
||||
ENV["HOMEBREW_NO_GITHUB_API"] = "1"
|
||||
end
|
||||
|
||||
if ARGV.include? "--coverage"
|
||||
if args.coverage?
|
||||
ENV["HOMEBREW_TESTS_COVERAGE"] = "1"
|
||||
FileUtils.rm_f "test/coverage/.resultset.json"
|
||||
end
|
||||
@ -58,8 +69,8 @@ module Homebrew
|
||||
|
||||
parallel = true
|
||||
|
||||
files = if ARGV.value("only")
|
||||
test_name, line = ARGV.value("only").split(":", 2)
|
||||
files = if args.only
|
||||
test_name, line = args.only.split(":", 2)
|
||||
|
||||
if line.nil?
|
||||
Dir.glob("test/{#{test_name},#{test_name}/**/*}_spec.rb")
|
||||
@ -84,7 +95,7 @@ module Homebrew
|
||||
|
||||
# Generate seed ourselves and output later to avoid multiple different
|
||||
# seeds being output when running parallel tests.
|
||||
seed = ARGV.include?("--seed") ? ARGV.next : rand(0xFFFF).to_i
|
||||
seed = args.seed ? args.seed : rand(0xFFFF).to_i
|
||||
|
||||
args = ["-I", HOMEBREW_LIBRARY_PATH/"test"]
|
||||
args += %W[
|
||||
|
||||
@ -14,13 +14,22 @@
|
||||
#: If `--keep-tmp` is passed, retain the temporary directory containing
|
||||
#: the new repository clone.
|
||||
|
||||
require "cli_parser"
|
||||
|
||||
module Homebrew
|
||||
module_function
|
||||
|
||||
def update_test
|
||||
args = Homebrew::CLI::Parser.parse do
|
||||
switch "--to-tag"
|
||||
switch "--keep-tmp"
|
||||
flag "--commit", required: true
|
||||
flag "--before", required: true
|
||||
end
|
||||
|
||||
ENV["HOMEBREW_UPDATE_TEST"] = "1"
|
||||
|
||||
if ARGV.include?("--to-tag")
|
||||
if args.to_tag?
|
||||
ENV["HOMEBREW_UPDATE_TO_TAG"] = "1"
|
||||
branch = "stable"
|
||||
else
|
||||
@ -28,11 +37,11 @@ module Homebrew
|
||||
end
|
||||
|
||||
cd HOMEBREW_REPOSITORY
|
||||
start_commit = if commit = ARGV.value("commit")
|
||||
start_commit = if commit = args.commit
|
||||
commit
|
||||
elsif date = ARGV.value("before")
|
||||
elsif date = args.before
|
||||
Utils.popen_read("git", "rev-list", "-n1", "--before=#{date}", "origin/master").chomp
|
||||
elsif ARGV.include?("--to-tag")
|
||||
elsif args.to_tag?
|
||||
tags = Utils.popen_read("git", "tag", "--list", "--sort=-version:refname")
|
||||
previous_tag = tags.lines[1]
|
||||
previous_tag ||= begin
|
||||
@ -62,7 +71,7 @@ module Homebrew
|
||||
puts "End commit: #{end_commit}"
|
||||
|
||||
mktemp("update-test") do |staging|
|
||||
staging.retain! if ARGV.keep_tmp?
|
||||
staging.retain! if args.keep_tmp?
|
||||
curdir = Pathname.new(Dir.pwd)
|
||||
|
||||
oh1 "Setup test environment..."
|
||||
|
||||
@ -74,7 +74,7 @@ class DevelopmentTools
|
||||
def clang_build_version
|
||||
@clang_build_version ||= begin
|
||||
if (path = locate("clang")) &&
|
||||
build_version = `#{path} --version`[/clang-(\d{2,})/, 1]
|
||||
build_version = `#{path} --version`[%r{clang(-| version [^ ]+ \(tags/RELEASE_)(\d{2,})}, 2]
|
||||
Version.new build_version
|
||||
else
|
||||
Version::NULL
|
||||
|
||||
@ -11,12 +11,10 @@ module Homebrew
|
||||
missing = {}
|
||||
ff.each do |f|
|
||||
missing_dependencies = f.missing_dependencies(hide: hide)
|
||||
|
||||
unless missing_dependencies.empty?
|
||||
next if missing_dependencies.empty?
|
||||
yield f.full_name, missing_dependencies if block_given?
|
||||
missing[f.full_name] = missing_dependencies
|
||||
end
|
||||
end
|
||||
missing
|
||||
end
|
||||
|
||||
|
||||
@ -6,6 +6,13 @@ class AbstractDownloadStrategy
|
||||
extend Forwardable
|
||||
include FileUtils
|
||||
|
||||
module Pourable
|
||||
def stage
|
||||
ohai "Pouring #{cached_location.basename}"
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
attr_reader :meta, :name, :version, :resource
|
||||
attr_reader :shutup
|
||||
|
||||
@ -15,6 +22,7 @@ class AbstractDownloadStrategy
|
||||
@url = resource.url
|
||||
@version = resource.version
|
||||
@meta = resource.specs
|
||||
extend Pourable if meta[:bottle]
|
||||
end
|
||||
|
||||
# Download and cache the resource as {#cached_location}.
|
||||
@ -442,14 +450,6 @@ class NoUnzipCurlDownloadStrategy < CurlDownloadStrategy
|
||||
end
|
||||
end
|
||||
|
||||
# This strategy extracts our binary packages.
|
||||
class CurlBottleDownloadStrategy < CurlDownloadStrategy
|
||||
def stage
|
||||
ohai "Pouring #{cached_location.basename}"
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
# This strategy extracts local binary packages.
|
||||
class LocalBottleDownloadStrategy < AbstractFileDownloadStrategy
|
||||
attr_reader :cached_location
|
||||
@ -457,11 +457,6 @@ class LocalBottleDownloadStrategy < AbstractFileDownloadStrategy
|
||||
def initialize(path)
|
||||
@cached_location = path
|
||||
end
|
||||
|
||||
def stage
|
||||
ohai "Pouring #{cached_location.basename}"
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
# S3DownloadStrategy downloads tarballs from AWS S3.
|
||||
@ -473,17 +468,8 @@ end
|
||||
# distribution. (It will work for public buckets as well.)
|
||||
class S3DownloadStrategy < CurlDownloadStrategy
|
||||
def _fetch
|
||||
# Put the aws gem requirement here (vs top of file) so it's only
|
||||
# a dependency of S3 users, not all Homebrew users
|
||||
require "rubygems"
|
||||
begin
|
||||
require "aws-sdk-v1"
|
||||
rescue LoadError
|
||||
onoe "Install the aws-sdk gem into the gem repo used by brew."
|
||||
raise
|
||||
end
|
||||
|
||||
if @url !~ %r{^https?://([^.].*)\.s3\.amazonaws\.com/(.+)$}
|
||||
if @url !~ %r{^https?://([^.].*)\.s3\.amazonaws\.com/(.+)$} &&
|
||||
@url !~ %r{^s3://([^.].*?)/(.+)$}
|
||||
raise "Bad S3 URL: " + @url
|
||||
end
|
||||
bucket = Regexp.last_match(1)
|
||||
@ -492,12 +478,12 @@ class S3DownloadStrategy < CurlDownloadStrategy
|
||||
ENV["AWS_ACCESS_KEY_ID"] = ENV["HOMEBREW_AWS_ACCESS_KEY_ID"]
|
||||
ENV["AWS_SECRET_ACCESS_KEY"] = ENV["HOMEBREW_AWS_SECRET_ACCESS_KEY"]
|
||||
|
||||
obj = AWS::S3.new.buckets[bucket].objects[key]
|
||||
begin
|
||||
s3url = obj.url_for(:get)
|
||||
rescue AWS::Errors::MissingCredentialsError
|
||||
signer = Aws::S3::Presigner.new
|
||||
s3url = signer.presigned_url :get_object, bucket: bucket, key: key
|
||||
rescue Aws::Sigv4::Errors::MissingCredentialsError
|
||||
ohai "AWS credentials missing, trying public URL instead."
|
||||
s3url = obj.public_url
|
||||
s3url = @url
|
||||
end
|
||||
|
||||
curl_download s3url, to: temporary_path
|
||||
@ -1116,6 +1102,9 @@ class DownloadStrategyDetector
|
||||
def self.detect(url, strategy = nil)
|
||||
if strategy.nil?
|
||||
detect_from_url(url)
|
||||
elsif strategy == S3DownloadStrategy
|
||||
require_aws_sdk
|
||||
strategy
|
||||
elsif strategy.is_a?(Class) && strategy < AbstractDownloadStrategy
|
||||
strategy
|
||||
elsif strategy.is_a?(Symbol)
|
||||
@ -1148,6 +1137,9 @@ class DownloadStrategyDetector
|
||||
SubversionDownloadStrategy
|
||||
when %r{^https?://(.+?\.)?sourceforge\.net/hgweb/}
|
||||
MercurialDownloadStrategy
|
||||
when %r{^s3://}
|
||||
require_aws_sdk
|
||||
S3DownloadStrategy
|
||||
else
|
||||
CurlDownloadStrategy
|
||||
end
|
||||
@ -1169,4 +1161,9 @@ class DownloadStrategyDetector
|
||||
raise "Unknown download strategy #{symbol} was requested."
|
||||
end
|
||||
end
|
||||
|
||||
def self.require_aws_sdk
|
||||
Homebrew.install_gem! "aws-sdk-s3", "~> 1.8"
|
||||
require "aws-sdk-s3"
|
||||
end
|
||||
end
|
||||
|
||||
@ -181,8 +181,7 @@ class TapFormulaAmbiguityError < RuntimeError
|
||||
@name = name
|
||||
@paths = paths
|
||||
@formulae = paths.map do |path|
|
||||
match = path.to_s.match(HOMEBREW_TAP_PATH_REGEX)
|
||||
"#{Tap.fetch(match[:user], match[:repo])}/#{path.basename(".rb")}"
|
||||
"#{Tap.from_path(path).name}/#{path.basename(".rb")}"
|
||||
end
|
||||
|
||||
super <<~EOS
|
||||
|
||||
@ -15,6 +15,7 @@ module HomebrewArgvExtension
|
||||
--no-sandbox
|
||||
--build-bottle
|
||||
--force-bottle
|
||||
--include-test
|
||||
--verbose
|
||||
--force
|
||||
-i
|
||||
@ -267,10 +268,6 @@ module HomebrewArgvExtension
|
||||
include? "--fetch-HEAD"
|
||||
end
|
||||
|
||||
def pry?
|
||||
include?("--pry") || !ENV["HOMEBREW_PRY"].nil?
|
||||
end
|
||||
|
||||
# eg. `foo -ns -i --bar` has three switches, n, s and i
|
||||
def switch?(char)
|
||||
return false if char.length > 1
|
||||
|
||||
@ -5,10 +5,10 @@ class JavaRequirement < Requirement
|
||||
end
|
||||
|
||||
# A strict Java 8 requirement (1.8) should prompt the user to install
|
||||
# the legacy java8 cask because the current version, Java 9, is not
|
||||
# completely backwards compatible, and contains breaking changes such as
|
||||
# the legacy java8 cask because versions newer than Java 8 are not
|
||||
# completely backwards compatible, and contain breaking changes such as
|
||||
# strong encapsulation of JDK-internal APIs and a modified version scheme
|
||||
# (9.0 not 1.9).
|
||||
# (*.0 not 1.*).
|
||||
def cask
|
||||
if @version.nil? || @version.to_s.end_with?("+") ||
|
||||
@version.to_f >= JAVA_CASK_MAP.keys.max.to_f
|
||||
@ -22,7 +22,7 @@ class JavaRequirement < Requirement
|
||||
|
||||
JAVA_CASK_MAP = {
|
||||
"1.8" => "caskroom/versions/java8",
|
||||
"9.0" => "java",
|
||||
"10.0" => "java",
|
||||
}.freeze
|
||||
|
||||
def possible_javas
|
||||
|
||||
@ -16,6 +16,7 @@ require "migrator"
|
||||
require "linkage_checker"
|
||||
require "extend/ENV"
|
||||
require "language/python"
|
||||
require "tab"
|
||||
|
||||
# A formula provides instructions and metadata for Homebrew to install a piece
|
||||
# of software. Every Homebrew formula is a {Formula}.
|
||||
@ -179,8 +180,8 @@ class Formula
|
||||
|
||||
@tap = if path == Formulary.core_path(name)
|
||||
CoreTap.instance
|
||||
elsif match = path.to_s.match(HOMEBREW_TAP_PATH_REGEX)
|
||||
Tap.fetch(match[:user], match[:repo])
|
||||
else
|
||||
Tap.from_path(path)
|
||||
end
|
||||
|
||||
@full_name = full_name_with_optional_tap(name)
|
||||
@ -439,7 +440,6 @@ class Formula
|
||||
# If at least one version of {Formula} is installed.
|
||||
# @private
|
||||
def any_version_installed?
|
||||
require "tab"
|
||||
installed_prefixes.any? { |keg| (keg/Tab::FILENAME).file? }
|
||||
end
|
||||
|
||||
@ -1487,15 +1487,15 @@ class Formula
|
||||
|
||||
# Returns a list of Dependency objects that are required at runtime.
|
||||
# @private
|
||||
def runtime_dependencies
|
||||
declared_runtime_dependencies | undeclared_runtime_dependencies
|
||||
def runtime_dependencies(read_from_tab: true)
|
||||
if read_from_tab &&
|
||||
installed_prefix.directory? &&
|
||||
(keg = Keg.new(installed_prefix)) &&
|
||||
(tab_deps = keg.runtime_dependencies)
|
||||
return tab_deps.map { |d| Dependency.new d["full_name"] }.compact
|
||||
end
|
||||
|
||||
def declared_runtime_dependencies
|
||||
recursive_dependencies do |_, dependency|
|
||||
Dependency.prune if dependency.build?
|
||||
Dependency.prune if !dependency.required? && build.without?(dependency)
|
||||
end
|
||||
declared_runtime_dependencies | undeclared_runtime_dependencies
|
||||
end
|
||||
|
||||
def undeclared_runtime_dependencies
|
||||
@ -1515,26 +1515,17 @@ class Formula
|
||||
# installed
|
||||
def missing_dependencies(hide: nil)
|
||||
hide ||= []
|
||||
missing_dependencies = recursive_dependencies do |dependent, dep|
|
||||
if dep.build?
|
||||
Dependency.prune
|
||||
elsif dep.optional? || dep.recommended?
|
||||
tab = Tab.for_formula(dependent)
|
||||
Dependency.prune unless tab.with?(dep)
|
||||
end
|
||||
end
|
||||
|
||||
missing_dependencies.map!(&:to_formula)
|
||||
missing_dependencies.select! do |d|
|
||||
runtime_dependencies.map(&:to_formula).select do |d|
|
||||
hide.include?(d.name) || d.installed_prefixes.empty?
|
||||
end
|
||||
missing_dependencies
|
||||
rescue FormulaUnavailableError
|
||||
[]
|
||||
end
|
||||
|
||||
# @private
|
||||
def to_hash
|
||||
dependencies = deps
|
||||
|
||||
hsh = {
|
||||
"name" => name,
|
||||
"full_name" => full_name,
|
||||
@ -1544,21 +1535,21 @@ class Formula
|
||||
"aliases" => aliases,
|
||||
"versions" => {
|
||||
"stable" => stable&.version&.to_s,
|
||||
"bottle" => bottle ? true : false,
|
||||
"bottle" => !bottle.nil?,
|
||||
"devel" => devel&.version&.to_s,
|
||||
"head" => head&.version&.to_s,
|
||||
},
|
||||
"revision" => revision,
|
||||
"version_scheme" => version_scheme,
|
||||
"installed" => [],
|
||||
"linked_keg" => (linked_version.to_s if linked_keg.exist?),
|
||||
"linked_keg" => linked_version&.to_s,
|
||||
"pinned" => pinned?,
|
||||
"outdated" => outdated?,
|
||||
"keg_only" => keg_only?,
|
||||
"dependencies" => deps.map(&:name).uniq,
|
||||
"recommended_dependencies" => deps.select(&:recommended?).map(&:name).uniq,
|
||||
"optional_dependencies" => deps.select(&:optional?).map(&:name).uniq,
|
||||
"build_dependencies" => deps.select(&:build?).map(&:name).uniq,
|
||||
"dependencies" => dependencies.map(&:name).uniq,
|
||||
"recommended_dependencies" => dependencies.select(&:recommended?).map(&:name).uniq,
|
||||
"optional_dependencies" => dependencies.select(&:optional?).map(&:name).uniq,
|
||||
"build_dependencies" => dependencies.select(&:build?).map(&:name).uniq,
|
||||
"conflicts_with" => conflicts.map(&:name),
|
||||
"caveats" => caveats,
|
||||
}
|
||||
@ -1587,7 +1578,7 @@ class Formula
|
||||
"root_url" => bottle_spec.root_url,
|
||||
}
|
||||
bottle_info["files"] = {}
|
||||
bottle_spec.collector.keys.each do |os| # rubocop:disable Performance/HashEachMethods
|
||||
bottle_spec.collector.keys.each do |os|
|
||||
checksum = bottle_spec.collector[os]
|
||||
bottle_info["files"][os] = {
|
||||
"url" => "#{bottle_spec.root_url}/#{Bottle::Filename.create(self, os, bottle_spec.rebuild)}",
|
||||
|
||||
@ -34,7 +34,7 @@ class FormulaInstaller
|
||||
attr_accessor :options, :build_bottle, :invalid_option_names
|
||||
attr_accessor :installed_as_dependency, :installed_on_request, :link_keg
|
||||
mode_attr_accessor :show_summary_heading, :show_header
|
||||
mode_attr_accessor :build_from_source, :force_bottle
|
||||
mode_attr_accessor :build_from_source, :force_bottle, :include_test
|
||||
mode_attr_accessor :ignore_deps, :only_deps, :interactive, :git
|
||||
mode_attr_accessor :verbose, :debug, :quieter
|
||||
|
||||
@ -47,6 +47,7 @@ class FormulaInstaller
|
||||
@build_from_source = ARGV.build_from_source? || ARGV.build_all_from_source?
|
||||
@build_bottle = false
|
||||
@force_bottle = ARGV.force_bottle?
|
||||
@include_test = ARGV.include?("--include-test")
|
||||
@interactive = false
|
||||
@git = false
|
||||
@verbose = ARGV.verbose?
|
||||
@ -224,17 +225,19 @@ class FormulaInstaller
|
||||
message = <<~EOS
|
||||
#{formula.name} #{formula.linked_version} is already installed
|
||||
EOS
|
||||
message += if formula.outdated? && !formula.head?
|
||||
<<~EOS
|
||||
if formula.outdated? && !formula.head?
|
||||
message += <<~EOS
|
||||
To upgrade to #{formula.pkg_version}, run `brew upgrade #{formula.name}`
|
||||
EOS
|
||||
elsif only_deps?
|
||||
message = nil
|
||||
else
|
||||
# some other version is already installed *and* linked
|
||||
<<~EOS
|
||||
message += <<~EOS
|
||||
To install #{formula.pkg_version}, first run `brew unlink #{formula.name}`
|
||||
EOS
|
||||
end
|
||||
raise CannotInstallFormulaError, message
|
||||
raise CannotInstallFormulaError, message if message
|
||||
end
|
||||
|
||||
# Warn if a more recent version of this formula is available in the tap.
|
||||
@ -436,10 +439,12 @@ class FormulaInstaller
|
||||
build = effective_build_options_for(dependent)
|
||||
install_bottle_for_dependent = install_bottle_for?(dependent, build)
|
||||
|
||||
if (req.optional? || req.recommended?) && build.without?(req)
|
||||
if req.prune_from_option?(build)
|
||||
Requirement.prune
|
||||
elsif req.satisfied?
|
||||
Requirement.prune
|
||||
elsif include_test? && req.test?
|
||||
next
|
||||
elsif !runtime_requirements.include?(req) && install_bottle_for_dependent
|
||||
Requirement.prune
|
||||
else
|
||||
@ -464,11 +469,13 @@ class FormulaInstaller
|
||||
inherited_options.fetch(dependent.name, []),
|
||||
)
|
||||
|
||||
if (dep.optional? || dep.recommended?) && build.without?(dep)
|
||||
if dep.prune_from_option?(build)
|
||||
Dependency.prune
|
||||
elsif include_test? && dep.test? && !dep.installed?
|
||||
Dependency.keep_but_prune_recursive_deps
|
||||
elsif dep.build? && install_bottle_for?(dependent, build)
|
||||
Dependency.prune
|
||||
elsif dep.build? && dependent.installed?
|
||||
elsif dep.prune_if_build_and_not_dependent?(dependent)
|
||||
Dependency.prune
|
||||
elsif dep.satisfied?(inherited_options[dep.name])
|
||||
Dependency.skip
|
||||
|
||||
@ -111,7 +111,8 @@ module Formulary
|
||||
# The name of the formula is found between the last slash and the last hyphen.
|
||||
formula_name = File.basename(bottle_name)[/(.+)-/, 1]
|
||||
resource = Resource.new(formula_name) { url bottle_name }
|
||||
downloader = CurlBottleDownloadStrategy.new resource.name, resource
|
||||
resource.specs[:bottle] = true
|
||||
downloader = CurlDownloadStrategy.new resource.name, resource
|
||||
@bottle_filename = downloader.cached_location
|
||||
cached = @bottle_filename.exist?
|
||||
downloader.fetch
|
||||
|
||||
@ -102,47 +102,30 @@ class Keg
|
||||
#
|
||||
# For efficiency, we don't bother trying to get complete data.
|
||||
def self.find_some_installed_dependents(kegs)
|
||||
# First, check in the tabs of installed Formulae.
|
||||
kegs.each do |keg|
|
||||
# Don't include dependencies of kegs that were in the given array.
|
||||
dependents = keg.installed_dependents - kegs
|
||||
dependents.map! { |d| "#{d.name} #{d.version}" }
|
||||
return [keg], dependents if dependents.any?
|
||||
end
|
||||
|
||||
# Some kegs won't have modern Tabs with the dependencies listed.
|
||||
# In this case, fall back to Formula#missing_dependencies.
|
||||
|
||||
# Find formulae that didn't have dependencies saved in all of their kegs,
|
||||
# so need them to be calculated now.
|
||||
#
|
||||
# This happens after the initial dependency check because it's sloooow.
|
||||
remaining_formulae = Formula.installed.select do |f|
|
||||
installed_kegs = f.installed_kegs
|
||||
|
||||
# Don't include dependencies of kegs that were in the given array.
|
||||
next false if (installed_kegs - kegs).empty?
|
||||
|
||||
installed_kegs.any? { |k| Tab.for_keg(k).runtime_dependencies.nil? }
|
||||
end
|
||||
|
||||
keg_names = kegs.map(&:name)
|
||||
keg_names = kegs.select(&:optlinked?).map(&:name)
|
||||
keg_formulae = []
|
||||
kegs_by_source = kegs.group_by do |keg|
|
||||
begin
|
||||
# First, attempt to resolve the keg to a formula
|
||||
# to get up-to-date name and tap information.
|
||||
f = keg.to_formula
|
||||
keg_formulae << f
|
||||
[f.name, f.tap]
|
||||
rescue FormulaUnavailableError
|
||||
# If the formula for the keg can't be found,
|
||||
# fall back to the information in the tab.
|
||||
[keg.name, Tab.for_keg(keg).tap]
|
||||
[keg.name, keg.tab.tap]
|
||||
end
|
||||
end
|
||||
|
||||
remaining_formulae.each do |dependent|
|
||||
all_required_kegs = Set.new
|
||||
all_dependents = []
|
||||
|
||||
# Don't include dependencies of kegs that were in the given array.
|
||||
formulae_to_check = Formula.installed - keg_formulae
|
||||
|
||||
formulae_to_check.each do |dependent|
|
||||
required = dependent.missing_dependencies(hide: keg_names)
|
||||
|
||||
required_kegs = required.map do |f|
|
||||
f_kegs = kegs_by_source[[f.name, f.tap]]
|
||||
next unless f_kegs
|
||||
@ -150,12 +133,16 @@ class Keg
|
||||
f_kegs.sort_by(&:version).last
|
||||
end.compact
|
||||
|
||||
next unless required_kegs.any?
|
||||
next if required_kegs.empty?
|
||||
|
||||
return required_kegs, [dependent.to_s]
|
||||
all_required_kegs += required_kegs
|
||||
all_dependents << dependent.to_s
|
||||
end
|
||||
|
||||
nil
|
||||
return if all_required_kegs.empty?
|
||||
return if all_dependents.empty?
|
||||
|
||||
[all_required_kegs.to_a, all_dependents.sort]
|
||||
end
|
||||
|
||||
# if path is a file in a keg then this will return the containing Keg object
|
||||
@ -390,25 +377,6 @@ class Keg
|
||||
Formulary.from_keg(self)
|
||||
end
|
||||
|
||||
def installed_dependents
|
||||
return [] unless optlinked?
|
||||
tap = Tab.for_keg(self).source["tap"]
|
||||
Keg.all.select do |keg|
|
||||
tab = Tab.for_keg(keg)
|
||||
next if tab.runtime_dependencies.nil?
|
||||
tab.runtime_dependencies.any? do |dep|
|
||||
# Resolve formula rather than directly comparing names
|
||||
# in case of conflicts between formulae from different taps.
|
||||
begin
|
||||
dep_formula = Formulary.factory(dep["full_name"])
|
||||
dep_formula == to_formula
|
||||
rescue FormulaUnavailableError
|
||||
next dep["full_name"] == "#{tap}/#{name}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def oldname_opt_record
|
||||
@oldname_opt_record ||= if (opt_dir = HOMEBREW_PREFIX/"opt").directory?
|
||||
opt_dir.subdirs.detect do |dir|
|
||||
@ -503,8 +471,16 @@ class Keg
|
||||
@oldname_opt_record = nil
|
||||
end
|
||||
|
||||
def tab
|
||||
Tab.for_keg(self)
|
||||
end
|
||||
|
||||
def runtime_dependencies
|
||||
tab.runtime_dependencies
|
||||
end
|
||||
|
||||
def aliases
|
||||
Tab.for_keg(self).aliases || []
|
||||
tab.aliases || []
|
||||
end
|
||||
|
||||
def optlink(mode = OpenStruct.new)
|
||||
@ -523,7 +499,7 @@ class Keg
|
||||
|
||||
def delete_pyc_files!
|
||||
find { |pn| pn.delete if %w[.pyc .pyo].include?(pn.extname) }
|
||||
find { |pn| pn.delete if pn.basename.to_s == "__pycache__" }
|
||||
find { |pn| FileUtils.rm_rf pn if pn.basename.to_s == "__pycache__" }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@ -63,7 +63,8 @@ class LinkageChecker
|
||||
formula.build.without?(dep)
|
||||
end
|
||||
declared_deps = formula.deps.reject { |dep| filter_out.call(dep) }.map(&:name)
|
||||
recursive_deps = keg.to_formula.declared_runtime_dependencies.map { |dep| dep.to_formula.name }
|
||||
runtime_deps = keg.to_formula.declared_runtime_dependencies
|
||||
recursive_deps = runtime_deps.map { |dep| dep.to_formula.name }
|
||||
declared_dep_names = declared_deps.map { |dep| dep.split("/").last }
|
||||
indirect_deps = []
|
||||
undeclared_deps = []
|
||||
|
||||
@ -56,17 +56,21 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note
|
||||
|
||||
## OFFICIAL EXTERNAL COMMANDS
|
||||
|
||||
* `bundle`:
|
||||
Bundler for non-Ruby dependencies from Homebrew:
|
||||
<https://github.com/Homebrew/homebrew-bundle>
|
||||
<%= homebrew_bundle.join("\n ").strip %>
|
||||
|
||||
* `cask`:
|
||||
Install macOS applications distributed as binaries:
|
||||
<https://github.com/caskroom/homebrew-cask>
|
||||
|
||||
* `services`:
|
||||
Integrates Homebrew formulae with macOS's `launchctl`(1) manager:
|
||||
<https://github.com/Homebrew/homebrew-services>
|
||||
Homebrew/homebrew-bundle <https://github.com/Homebrew/homebrew-bundle>
|
||||
|
||||
* `cask` [`--version` | `audit` | `cat` | `cleanup` | `create` | `doctor` | `edit` | `fetch` | `home` | `info`]:
|
||||
Install macOS applications distributed as binaries.
|
||||
|
||||
|
||||
Caskroom/homebrew-cask <https://github.com/caskroom/homebrew-cask>
|
||||
|
||||
<%= homebrew_services.join("\n ").strip %>
|
||||
|
||||
|
||||
Homebrew/homebrew-services <https://github.com/Homebrew/homebrew-services>
|
||||
|
||||
## CUSTOM EXTERNAL COMMANDS
|
||||
|
||||
@ -242,6 +246,9 @@ can take several different forms:
|
||||
This issue typically occurs when using FileVault or custom SSD
|
||||
configurations.
|
||||
|
||||
* `HOMEBREW_UPGRADE_CLEANUP`:
|
||||
If set, `brew upgrade` always assumes `--cleanup` has been passed.
|
||||
|
||||
* `HOMEBREW_VERBOSE`:
|
||||
If set, Homebrew always assumes `--verbose` when running commands.
|
||||
|
||||
|
||||
@ -44,14 +44,19 @@ module RuboCop
|
||||
end
|
||||
|
||||
# Separate dependencies according to precedence order:
|
||||
# build-time > run-time > normal > recommended > optional
|
||||
# build-time > test > normal > recommended > optional
|
||||
def sort_dependencies_by_type(dependency_nodes)
|
||||
unsorted_deps = dependency_nodes.to_a
|
||||
ordered = []
|
||||
ordered.concat(dependency_nodes.select { |dep| buildtime_dependency? dep }.to_a)
|
||||
ordered.concat(dependency_nodes.select { |dep| runtime_dependency? dep }.to_a)
|
||||
ordered.concat(dependency_nodes.reject { |dep| negate_normal_dependency? dep }.to_a)
|
||||
ordered.concat(dependency_nodes.select { |dep| recommended_dependency? dep }.to_a)
|
||||
ordered.concat(dependency_nodes.select { |dep| optional_dependency? dep }.to_a)
|
||||
ordered.concat(unsorted_deps.select { |dep| buildtime_dependency? dep })
|
||||
unsorted_deps -= ordered
|
||||
ordered.concat(unsorted_deps.select { |dep| test_dependency? dep })
|
||||
unsorted_deps -= ordered
|
||||
ordered.concat(unsorted_deps.reject { |dep| negate_normal_dependency? dep })
|
||||
unsorted_deps -= ordered
|
||||
ordered.concat(unsorted_deps.select { |dep| recommended_dependency? dep })
|
||||
unsorted_deps -= ordered
|
||||
ordered.concat(unsorted_deps.select { |dep| optional_dependency? dep })
|
||||
end
|
||||
|
||||
# `depends_on :apple if build.with? "foo"` should always be defined
|
||||
@ -106,11 +111,11 @@ module RuboCop
|
||||
|
||||
def_node_search :recommended_dependency?, "(sym :recommended)"
|
||||
|
||||
def_node_search :runtime_dependency?, "(sym :run)"
|
||||
def_node_search :test_dependency?, "(sym :test)"
|
||||
|
||||
def_node_search :optional_dependency?, "(sym :optional)"
|
||||
|
||||
def_node_search :negate_normal_dependency?, "(sym {:build :recommended :run :optional})"
|
||||
def_node_search :negate_normal_dependency?, "(sym {:build :recommended :test :optional})"
|
||||
|
||||
# Node pattern method to extract `name` in `depends_on :name`
|
||||
def_node_search :dependency_name_node, <<~EOS
|
||||
|
||||
@ -171,7 +171,7 @@ module RuboCop
|
||||
when :required
|
||||
type_match = required_dependency?(node)
|
||||
name_match ||= required_dependency_name?(node, name) if type_match
|
||||
when :build, :optional, :recommended, :run
|
||||
when :build, :test, :optional, :recommended
|
||||
type_match = dependency_type_hash_match?(node, type)
|
||||
name_match ||= dependency_name_hash_match?(node, name) if type_match
|
||||
when :any
|
||||
|
||||
@ -85,10 +85,10 @@ fi
|
||||
|
||||
case "$(lowercase "$SCM_FILE")" in
|
||||
git)
|
||||
[[ -n "$HOMEBREW_GIT" ]] && safe_exec "$(which "$HOMEBREW_GIT")" "$@"
|
||||
[[ -n "$HOMEBREW_GIT" ]] && safe_exec "$(type -P "$HOMEBREW_GIT")" "$@"
|
||||
;;
|
||||
svn)
|
||||
[[ -n "$HOMEBREW_SVN" ]] && safe_exec "$(which "$HOMEBREW_SVN")" "$@"
|
||||
[[ -n "$HOMEBREW_SVN" ]] && safe_exec "$(type -P "$HOMEBREW_SVN")" "$@"
|
||||
;;
|
||||
esac
|
||||
|
||||
@ -99,7 +99,7 @@ brew_repo_version="$(quiet_safe_cd "$SCM_DIR/../../../../bin" && pwd -P)/$SCM_FI
|
||||
safe_exec "$brew_repo_version" "$@"
|
||||
|
||||
IFS=$'\n'
|
||||
for path in $(/usr/bin/which -a "$SCM_FILE" 2>/dev/null)
|
||||
for path in $(type -aP "$SCM_FILE")
|
||||
do
|
||||
if [[ "$path" != "/usr/bin/$SCM_FILE" ]]
|
||||
then
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
POD2MAN="$(/usr/bin/which pod2man5.18 ||
|
||||
/usr/bin/which pod2man5.16 ||
|
||||
/usr/bin/which pod2man5.12 ||
|
||||
/usr/bin/which "$HOMEBREW_PREFIX/opt/pod2man/bin/pod2man" ||
|
||||
POD2MAN="$(type -P pod2man5.18 ||
|
||||
type -P pod2man5.16 ||
|
||||
type -P pod2man5.12 ||
|
||||
type -P "$HOMEBREW_PREFIX/opt/pod2man/bin/pod2man" ||
|
||||
echo /usr/bin/pod2man)"
|
||||
exec "$POD2MAN" "$@"
|
||||
|
||||
@ -283,13 +283,14 @@ class Bottle
|
||||
@name = formula.name
|
||||
@resource = Resource.new
|
||||
@resource.owner = formula
|
||||
@resource.specs[:bottle] = true
|
||||
@spec = spec
|
||||
|
||||
checksum, tag = spec.checksum_for(Utils::Bottles.tag)
|
||||
|
||||
filename = Filename.create(formula, tag, spec.rebuild)
|
||||
@resource.url(build_url(spec.root_url, filename))
|
||||
@resource.download_strategy = CurlBottleDownloadStrategy
|
||||
@resource.url(build_url(spec.root_url, filename),
|
||||
select_download_strategy(spec.root_url_specs))
|
||||
@resource.version = formula.pkg_version
|
||||
@resource.checksum = checksum
|
||||
@prefix = spec.prefix
|
||||
@ -315,6 +316,11 @@ class Bottle
|
||||
def build_url(root_url, filename)
|
||||
"#{root_url}/#{filename}"
|
||||
end
|
||||
|
||||
def select_download_strategy(specs)
|
||||
specs[:using] ||= DownloadStrategyDetector.detect(@spec.root_url)
|
||||
specs
|
||||
end
|
||||
end
|
||||
|
||||
class BottleSpecification
|
||||
@ -324,20 +330,22 @@ class BottleSpecification
|
||||
|
||||
attr_rw :prefix, :cellar, :rebuild
|
||||
attr_accessor :tap
|
||||
attr_reader :checksum, :collector
|
||||
attr_reader :checksum, :collector, :root_url_specs
|
||||
|
||||
def initialize
|
||||
@rebuild = 0
|
||||
@prefix = DEFAULT_PREFIX
|
||||
@cellar = DEFAULT_CELLAR
|
||||
@collector = Utils::Bottles::Collector.new
|
||||
@root_url_specs = {}
|
||||
end
|
||||
|
||||
def root_url(var = nil)
|
||||
def root_url(var = nil, specs = {})
|
||||
if var.nil?
|
||||
@root_url ||= "#{DEFAULT_DOMAIN}/#{Utils::Bottles::Bintray.repository(tap)}"
|
||||
else
|
||||
@root_url = var
|
||||
@root_url_specs.merge!(specs)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -183,6 +183,7 @@ class SystemConfig
|
||||
HOMEBREW_LIBRARY
|
||||
HOMEBREW_MACOS_VERSION
|
||||
HOMEBREW_RUBY_PATH
|
||||
HOMEBREW_RUBY_WARNINGS
|
||||
HOMEBREW_SYSTEM
|
||||
HOMEBREW_OS_VERSION
|
||||
HOMEBREW_PATH
|
||||
@ -199,10 +200,13 @@ class SystemConfig
|
||||
if defaults_hash[:HOMEBREW_CELLAR] != HOMEBREW_CELLAR.to_s
|
||||
f.puts "HOMEBREW_CELLAR: #{HOMEBREW_CELLAR}"
|
||||
end
|
||||
if defaults_hash[:HOMEBREW_CACHE] != HOMEBREW_CACHE.to_s
|
||||
f.puts "HOMEBREW_CACHE: #{HOMEBREW_CACHE}"
|
||||
end
|
||||
ENV.sort.each do |key, value|
|
||||
next unless key.start_with?("HOMEBREW_")
|
||||
next if boring_keys.include?(key)
|
||||
next if defaults_hash[key.to_sym] == value
|
||||
next if defaults_hash[key.to_sym]
|
||||
value = "set" if key =~ /(cookie|key|token|password)/i
|
||||
f.puts "#{key}: #{value}"
|
||||
end
|
||||
@ -210,7 +214,17 @@ class SystemConfig
|
||||
f.puts "Homebrew Ruby: #{describe_homebrew_ruby}"
|
||||
f.puts "GCC-4.0: build #{gcc_4_0}" unless gcc_4_0.null?
|
||||
f.puts "GCC-4.2: build #{gcc_4_2}" unless gcc_4_2.null?
|
||||
f.puts "Clang: #{clang.null? ? "N/A" : "#{clang} build #{clang_build}"}"
|
||||
f.print "Clang: "
|
||||
if clang.null?
|
||||
f.puts "N/A"
|
||||
else
|
||||
f.print "#{clang} build "
|
||||
if clang_build.null?
|
||||
f.puts "(parse error)"
|
||||
else
|
||||
f.puts clang_build
|
||||
end
|
||||
end
|
||||
f.puts "Git: #{describe_git}"
|
||||
f.puts "Curl: #{describe_curl}"
|
||||
f.puts "Perl: #{describe_perl}"
|
||||
|
||||
@ -17,6 +17,7 @@ class Tab < OpenStruct
|
||||
# Instantiates a Tab for a new installation of a formula.
|
||||
def self.create(formula, compiler, stdlib)
|
||||
build = formula.build
|
||||
runtime_deps = formula.runtime_dependencies(read_from_tab: false)
|
||||
attributes = {
|
||||
"homebrew_version" => HOMEBREW_VERSION,
|
||||
"used_options" => build.used_options.as_flags,
|
||||
@ -32,18 +33,18 @@ class Tab < OpenStruct
|
||||
"compiler" => compiler,
|
||||
"stdlib" => stdlib,
|
||||
"aliases" => formula.aliases,
|
||||
"runtime_dependencies" => formula.runtime_dependencies.map do |dep|
|
||||
"runtime_dependencies" => runtime_deps.map do |dep|
|
||||
f = dep.to_formula
|
||||
{ "full_name" => f.full_name, "version" => f.version.to_s }
|
||||
end,
|
||||
"source" => {
|
||||
"path" => formula.specified_path.to_s,
|
||||
"tap" => formula.tap ? formula.tap.name : nil,
|
||||
"tap" => formula.tap&.name,
|
||||
"spec" => formula.active_spec_sym.to_s,
|
||||
"versions" => {
|
||||
"stable" => formula.stable ? formula.stable.version.to_s : nil,
|
||||
"devel" => formula.devel ? formula.devel.version.to_s : nil,
|
||||
"head" => formula.head ? formula.head.version.to_s : nil,
|
||||
"stable" => formula.stable&.version.to_s,
|
||||
"devel" => formula.devel&.version.to_s,
|
||||
"head" => formula.head&.version.to_s,
|
||||
"version_scheme" => formula.version_scheme,
|
||||
},
|
||||
},
|
||||
@ -66,7 +67,7 @@ class Tab < OpenStruct
|
||||
attributes["source"] ||= {}
|
||||
|
||||
tapped_from = attributes["tapped_from"]
|
||||
unless tapped_from.nil? || tapped_from == "path or URL"
|
||||
if !tapped_from.nil? && tapped_from != "path or URL"
|
||||
attributes["source"]["tap"] = attributes.delete("tapped_from")
|
||||
end
|
||||
|
||||
@ -156,12 +157,12 @@ class Tab < OpenStruct
|
||||
tab.unused_options = f.options.as_flags
|
||||
tab.source = {
|
||||
"path" => f.specified_path.to_s,
|
||||
"tap" => f.tap ? f.tap.name : f.tap,
|
||||
"tap" => f.tap&.name,
|
||||
"spec" => f.active_spec_sym.to_s,
|
||||
"versions" => {
|
||||
"stable" => f.stable ? f.stable.version.to_s : nil,
|
||||
"devel" => f.devel ? f.devel.version.to_s : nil,
|
||||
"head" => f.head ? f.head.version.to_s : nil,
|
||||
"stable" => f.stable&.version.to_s,
|
||||
"devel" => f.devel&.version.to_s,
|
||||
"head" => f.head&.version.to_s,
|
||||
"version_scheme" => f.version_scheme,
|
||||
},
|
||||
}
|
||||
@ -185,7 +186,7 @@ class Tab < OpenStruct
|
||||
"stdlib" => nil,
|
||||
"compiler" => DevelopmentTools.default_compiler,
|
||||
"aliases" => [],
|
||||
"runtime_dependencies" => [],
|
||||
"runtime_dependencies" => nil,
|
||||
"source" => {
|
||||
"path" => nil,
|
||||
"tap" => nil,
|
||||
|
||||
@ -39,7 +39,7 @@ class Tap
|
||||
end
|
||||
|
||||
def self.from_path(path)
|
||||
match = path.to_s.match(HOMEBREW_TAP_PATH_REGEX)
|
||||
match = File.expand_path(path).match(HOMEBREW_TAP_PATH_REGEX)
|
||||
raise "Invalid tap path '#{path}'" unless match
|
||||
fetch(match[:user], match[:repo])
|
||||
rescue
|
||||
@ -543,11 +543,7 @@ end
|
||||
# A specialized {Tap} class for the core formulae
|
||||
class CoreTap < Tap
|
||||
def default_remote
|
||||
if OS.mac? || ENV["HOMEBREW_FORCE_HOMEBREW_ORG"]
|
||||
"https://github.com/Homebrew/homebrew-core".freeze
|
||||
else
|
||||
"https://github.com/Linuxbrew/homebrew-core".freeze
|
||||
end
|
||||
end
|
||||
|
||||
# @private
|
||||
|
||||
@ -2,6 +2,7 @@ require "extend/ARGV"
|
||||
|
||||
describe HomebrewArgvExtension do
|
||||
subject { argv.extend(described_class) }
|
||||
|
||||
let(:argv) { ["mxcl"] }
|
||||
|
||||
describe "#formulae" do
|
||||
@ -26,7 +27,7 @@ describe HomebrewArgvExtension do
|
||||
|
||||
describe "#kegs" do
|
||||
context "when there are matching Kegs" do
|
||||
before(:each) do
|
||||
before do
|
||||
keg = HOMEBREW_CELLAR + "mxcl/10.0"
|
||||
keg.mkpath
|
||||
end
|
||||
|
||||
@ -2,6 +2,7 @@ require "extend/ENV"
|
||||
|
||||
shared_examples EnvActivation do
|
||||
subject { env.extend(described_class) }
|
||||
|
||||
let(:env) { {}.extend(EnvActivation) }
|
||||
|
||||
it "supports switching compilers" do
|
||||
|
||||
@ -17,6 +17,7 @@ describe "Bash" do
|
||||
|
||||
context "brew" do
|
||||
subject { HOMEBREW_LIBRARY_PATH.parent.parent/"bin/brew" }
|
||||
|
||||
it { is_expected.to have_valid_bash_syntax }
|
||||
end
|
||||
|
||||
@ -33,6 +34,7 @@ describe "Bash" do
|
||||
|
||||
context "Bash completion" do
|
||||
subject { HOMEBREW_LIBRARY_PATH.parent.parent/"completions/bash/brew" }
|
||||
|
||||
it { is_expected.to have_valid_bash_syntax }
|
||||
end
|
||||
|
||||
|
||||
@ -43,7 +43,7 @@ describe BuildEnvironment do
|
||||
subject { double.extend(described_class) }
|
||||
|
||||
context "single argument" do
|
||||
before(:each) do
|
||||
before do
|
||||
subject.instance_eval do
|
||||
env :userpaths
|
||||
end
|
||||
@ -53,7 +53,7 @@ describe BuildEnvironment do
|
||||
end
|
||||
|
||||
context "multiple arguments" do
|
||||
before(:each) do
|
||||
before do
|
||||
subject.instance_eval do
|
||||
env :userpaths, :std
|
||||
end
|
||||
|
||||
@ -6,6 +6,7 @@ describe BuildOptions do
|
||||
alias_matcher :be_built_without, :be_without
|
||||
|
||||
subject { described_class.new(args, opts) }
|
||||
|
||||
let(:bad_build) { described_class.new(bad_args, opts) }
|
||||
let(:args) { Options.create(%w[--with-foo --with-bar --without-qux]) }
|
||||
let(:opts) { Options.create(%w[--with-foo --with-bar --without-baz --without-qux]) }
|
||||
|
||||
@ -5,7 +5,7 @@ describe "Accessibility Access", :cask do
|
||||
let(:fake_system_command) { class_double(Hbc::SystemCommand) }
|
||||
let(:installer) { Hbc::Installer.new(cask, command: fake_system_command) }
|
||||
|
||||
before(:each) do
|
||||
before do
|
||||
allow(MacOS).to receive(:version).and_return(MacOS::Version.new(macos_version))
|
||||
allow(installer).to receive(:bundle_identifier).and_return("com.example.BasicCask")
|
||||
end
|
||||
|
||||
@ -10,7 +10,7 @@ describe Hbc::Artifact::App, :cask do
|
||||
let(:install_phase) { app.install_phase(command: command, force: force) }
|
||||
let(:uninstall_phase) { app.uninstall_phase(command: command, force: force) }
|
||||
|
||||
before(:each) do
|
||||
before do
|
||||
InstallHelper.install_without_artifacts(cask)
|
||||
end
|
||||
|
||||
@ -58,7 +58,7 @@ describe Hbc::Artifact::App, :cask do
|
||||
end
|
||||
|
||||
describe "when the target already exists" do
|
||||
before(:each) do
|
||||
before do
|
||||
target_path.mkpath
|
||||
end
|
||||
|
||||
@ -76,7 +76,7 @@ describe Hbc::Artifact::App, :cask do
|
||||
describe "given the force option" do
|
||||
let(:force) { true }
|
||||
|
||||
before(:each) do
|
||||
before do
|
||||
allow(Hbc::Utils).to receive(:current_user).and_return("fake_user")
|
||||
end
|
||||
|
||||
@ -104,7 +104,7 @@ describe Hbc::Artifact::App, :cask do
|
||||
end
|
||||
|
||||
describe "target is user-owned but contains read-only files" do
|
||||
before(:each) do
|
||||
before do
|
||||
FileUtils.touch "#{target_path}/foo"
|
||||
FileUtils.chmod 0555, target_path
|
||||
end
|
||||
@ -137,7 +137,7 @@ describe Hbc::Artifact::App, :cask do
|
||||
expect(contents_path).to exist
|
||||
end
|
||||
|
||||
after(:each) do
|
||||
after do
|
||||
FileUtils.chmod 0755, target_path
|
||||
end
|
||||
end
|
||||
@ -147,7 +147,7 @@ describe Hbc::Artifact::App, :cask do
|
||||
describe "when the target is a broken symlink" do
|
||||
let(:deleted_path) { cask.staged_path.join("Deleted.app") }
|
||||
|
||||
before(:each) do
|
||||
before do
|
||||
deleted_path.mkdir
|
||||
File.symlink(deleted_path, target_path)
|
||||
deleted_path.rmdir
|
||||
|
||||
@ -7,7 +7,7 @@ describe Hbc::Artifact::Binary, :cask do
|
||||
let(:artifacts) { cask.artifacts.select { |a| a.is_a?(described_class) } }
|
||||
let(:expected_path) { Hbc::Config.global.binarydir.join("binary") }
|
||||
|
||||
after(:each) do
|
||||
after do
|
||||
FileUtils.rm expected_path if expected_path.exist?
|
||||
end
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ describe Hbc::Artifact::Pkg, :cask do
|
||||
let(:cask) { Hbc::CaskLoader.load(cask_path("with-installable")) }
|
||||
let(:fake_system_command) { class_double(Hbc::SystemCommand) }
|
||||
|
||||
before(:each) do
|
||||
before do
|
||||
InstallHelper.install_without_artifacts(cask)
|
||||
end
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ describe Hbc::Artifact::Suite, :cask do
|
||||
let(:target_path) { Hbc::Config.global.appdir.join("Caffeine") }
|
||||
let(:source_path) { cask.staged_path.join("Caffeine") }
|
||||
|
||||
before(:each) do
|
||||
before do
|
||||
InstallHelper.install_without_artifacts(cask)
|
||||
end
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ describe Hbc::Artifact::App, :cask do
|
||||
let(:source_path_pro) { cask.staged_path.join("Caffeine Pro.app") }
|
||||
let(:target_path_pro) { Hbc::Config.global.appdir.join("Caffeine Pro.app") }
|
||||
|
||||
before(:each) do
|
||||
before do
|
||||
InstallHelper.install_without_artifacts(cask)
|
||||
end
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ describe Hbc::Artifact::Zap, :cask do
|
||||
cask.artifacts.find { |a| a.is_a?(described_class) }
|
||||
}
|
||||
|
||||
before(:each) do
|
||||
before do
|
||||
InstallHelper.install_without_artifacts(cask)
|
||||
end
|
||||
|
||||
|
||||
@ -79,33 +79,60 @@ describe Hbc::Audit, :cask do
|
||||
end
|
||||
|
||||
describe "#run!" do
|
||||
let(:cask) { Hbc::CaskLoader.load(cask_token) }
|
||||
subject { audit.run! }
|
||||
|
||||
let(:cask) { Hbc::CaskLoader.load(cask_token) }
|
||||
|
||||
describe "required stanzas" do
|
||||
%w[version sha256 url name homepage].each do |stanza|
|
||||
context "when missing #{stanza}" do
|
||||
let(:cask_token) { "missing-#{stanza}" }
|
||||
|
||||
it { is_expected.to fail_with(/#{stanza} stanza is required/) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "pkg allow_untrusted checks" do
|
||||
let(:error_msg) { "allow_untrusted is not permitted in official Homebrew-Cask taps" }
|
||||
|
||||
context "when the Cask has no pkg stanza" do
|
||||
let(:cask_token) { "basic-cask" }
|
||||
|
||||
it { is_expected.not_to warn_with(error_msg) }
|
||||
end
|
||||
|
||||
context "when the Cask does not have allow_untrusted" do
|
||||
let(:cask_token) { "with-uninstall-pkgutil" }
|
||||
|
||||
it { is_expected.not_to warn_with(error_msg) }
|
||||
end
|
||||
|
||||
context "when the Cask has allow_untrusted" do
|
||||
let(:cask_token) { "with-allow-untrusted" }
|
||||
|
||||
it { is_expected.to warn_with(error_msg) }
|
||||
end
|
||||
end
|
||||
|
||||
describe "preflight stanza checks" do
|
||||
let(:error_msg) { "only a single preflight stanza is allowed" }
|
||||
|
||||
context "when the cask has no preflight stanza" do
|
||||
context "when the Cask has no preflight stanza" do
|
||||
let(:cask_token) { "with-zap-rmdir" }
|
||||
it { should_not warn_with(error_msg) }
|
||||
|
||||
it { is_expected.not_to warn_with(error_msg) }
|
||||
end
|
||||
|
||||
context "when the cask has only one preflight stanza" do
|
||||
context "when the Cask has only one preflight stanza" do
|
||||
let(:cask_token) { "with-preflight" }
|
||||
it { should_not warn_with(error_msg) }
|
||||
|
||||
it { is_expected.not_to warn_with(error_msg) }
|
||||
end
|
||||
|
||||
context "when the cask has multiple preflight stanzas" do
|
||||
context "when the Cask has multiple preflight stanzas" do
|
||||
let(:cask_token) { "with-preflight-multi" }
|
||||
|
||||
it { is_expected.to warn_with(error_msg) }
|
||||
end
|
||||
end
|
||||
@ -113,18 +140,21 @@ describe Hbc::Audit, :cask do
|
||||
describe "uninstall_postflight stanza checks" do
|
||||
let(:error_msg) { "only a single postflight stanza is allowed" }
|
||||
|
||||
context "when the cask has no postflight stanza" do
|
||||
context "when the Cask has no postflight stanza" do
|
||||
let(:cask_token) { "with-zap-rmdir" }
|
||||
it { should_not warn_with(error_msg) }
|
||||
|
||||
it { is_expected.not_to warn_with(error_msg) }
|
||||
end
|
||||
|
||||
context "when the cask has only one postflight stanza" do
|
||||
context "when the Cask has only one postflight stanza" do
|
||||
let(:cask_token) { "with-postflight" }
|
||||
it { should_not warn_with(error_msg) }
|
||||
|
||||
it { is_expected.not_to warn_with(error_msg) }
|
||||
end
|
||||
|
||||
context "when the cask has multiple postflight stanzas" do
|
||||
context "when the Cask has multiple postflight stanzas" do
|
||||
let(:cask_token) { "with-postflight-multi" }
|
||||
|
||||
it { is_expected.to warn_with(error_msg) }
|
||||
end
|
||||
end
|
||||
@ -132,18 +162,21 @@ describe Hbc::Audit, :cask do
|
||||
describe "uninstall stanza checks" do
|
||||
let(:error_msg) { "only a single uninstall stanza is allowed" }
|
||||
|
||||
context "when the cask has no uninstall stanza" do
|
||||
context "when the Cask has no uninstall stanza" do
|
||||
let(:cask_token) { "with-zap-rmdir" }
|
||||
it { should_not warn_with(error_msg) }
|
||||
|
||||
it { is_expected.not_to warn_with(error_msg) }
|
||||
end
|
||||
|
||||
context "when the cask has only one uninstall stanza" do
|
||||
context "when the Cask has only one uninstall stanza" do
|
||||
let(:cask_token) { "with-uninstall-rmdir" }
|
||||
it { should_not warn_with(error_msg) }
|
||||
|
||||
it { is_expected.not_to warn_with(error_msg) }
|
||||
end
|
||||
|
||||
context "when the cask has multiple uninstall stanzas" do
|
||||
context "when the Cask has multiple uninstall stanzas" do
|
||||
let(:cask_token) { "with-uninstall-multi" }
|
||||
|
||||
it { is_expected.to warn_with(error_msg) }
|
||||
end
|
||||
end
|
||||
@ -151,18 +184,21 @@ describe Hbc::Audit, :cask do
|
||||
describe "uninstall_preflight stanza checks" do
|
||||
let(:error_msg) { "only a single uninstall_preflight stanza is allowed" }
|
||||
|
||||
context "when the cask has no uninstall_preflight stanza" do
|
||||
context "when the Cask has no uninstall_preflight stanza" do
|
||||
let(:cask_token) { "with-zap-rmdir" }
|
||||
it { should_not warn_with(error_msg) }
|
||||
|
||||
it { is_expected.not_to warn_with(error_msg) }
|
||||
end
|
||||
|
||||
context "when the cask has only one uninstall_preflight stanza" do
|
||||
context "when the Cask has only one uninstall_preflight stanza" do
|
||||
let(:cask_token) { "with-uninstall-preflight" }
|
||||
it { should_not warn_with(error_msg) }
|
||||
|
||||
it { is_expected.not_to warn_with(error_msg) }
|
||||
end
|
||||
|
||||
context "when the cask has multiple uninstall_preflight stanzas" do
|
||||
context "when the Cask has multiple uninstall_preflight stanzas" do
|
||||
let(:cask_token) { "with-uninstall-preflight-multi" }
|
||||
|
||||
it { is_expected.to warn_with(error_msg) }
|
||||
end
|
||||
end
|
||||
@ -170,18 +206,21 @@ describe Hbc::Audit, :cask do
|
||||
describe "uninstall_postflight stanza checks" do
|
||||
let(:error_msg) { "only a single uninstall_postflight stanza is allowed" }
|
||||
|
||||
context "when the cask has no uninstall_postflight stanza" do
|
||||
context "when the Cask has no uninstall_postflight stanza" do
|
||||
let(:cask_token) { "with-zap-rmdir" }
|
||||
it { should_not warn_with(error_msg) }
|
||||
|
||||
it { is_expected.not_to warn_with(error_msg) }
|
||||
end
|
||||
|
||||
context "when the cask has only one uninstall_postflight stanza" do
|
||||
context "when the Cask has only one uninstall_postflight stanza" do
|
||||
let(:cask_token) { "with-uninstall-postflight" }
|
||||
it { should_not warn_with(error_msg) }
|
||||
|
||||
it { is_expected.not_to warn_with(error_msg) }
|
||||
end
|
||||
|
||||
context "when the cask has multiple uninstall_postflight stanzas" do
|
||||
context "when the Cask has multiple uninstall_postflight stanzas" do
|
||||
let(:cask_token) { "with-uninstall-postflight-multi" }
|
||||
|
||||
it { is_expected.to warn_with(error_msg) }
|
||||
end
|
||||
end
|
||||
@ -189,18 +228,21 @@ describe Hbc::Audit, :cask do
|
||||
describe "zap stanza checks" do
|
||||
let(:error_msg) { "only a single zap stanza is allowed" }
|
||||
|
||||
context "when the cask has no zap stanza" do
|
||||
context "when the Cask has no zap stanza" do
|
||||
let(:cask_token) { "with-uninstall-rmdir" }
|
||||
it { should_not warn_with(error_msg) }
|
||||
|
||||
it { is_expected.not_to warn_with(error_msg) }
|
||||
end
|
||||
|
||||
context "when the cask has only one zap stanza" do
|
||||
context "when the Cask has only one zap stanza" do
|
||||
let(:cask_token) { "with-zap-rmdir" }
|
||||
it { should_not warn_with(error_msg) }
|
||||
|
||||
it { is_expected.not_to warn_with(error_msg) }
|
||||
end
|
||||
|
||||
context "when the cask has multiple zap stanzas" do
|
||||
context "when the Cask has multiple zap stanzas" do
|
||||
let(:cask_token) { "with-zap-multi" }
|
||||
|
||||
it { is_expected.to warn_with(error_msg) }
|
||||
end
|
||||
end
|
||||
@ -210,28 +252,33 @@ describe Hbc::Audit, :cask do
|
||||
|
||||
context "when version is 'latest'" do
|
||||
let(:cask_token) { "version-latest-string" }
|
||||
|
||||
it { is_expected.to fail_with(error_msg) }
|
||||
end
|
||||
|
||||
context "when version is :latest" do
|
||||
let(:cask_token) { "version-latest-with-checksum" }
|
||||
it { should_not fail_with(error_msg) }
|
||||
|
||||
it { is_expected.not_to fail_with(error_msg) }
|
||||
end
|
||||
end
|
||||
|
||||
describe "sha256 checks" do
|
||||
context "when version is :latest and sha256 is not :no_check" do
|
||||
let(:cask_token) { "version-latest-with-checksum" }
|
||||
|
||||
it { is_expected.to fail_with("you should use sha256 :no_check when version is :latest") }
|
||||
end
|
||||
|
||||
context "when sha256 is not a legal SHA-256 digest" do
|
||||
let(:cask_token) { "invalid-sha256" }
|
||||
|
||||
it { is_expected.to fail_with("sha256 string must be of 64 hexadecimal characters") }
|
||||
end
|
||||
|
||||
context "when sha256 is sha256 for empty string" do
|
||||
let(:cask_token) { "sha256-for-empty-string" }
|
||||
|
||||
it { is_expected.to fail_with(/cannot use the sha256 for an empty string/) }
|
||||
end
|
||||
end
|
||||
@ -239,22 +286,26 @@ describe Hbc::Audit, :cask do
|
||||
describe "appcast checks" do
|
||||
context "when appcast has no sha256" do
|
||||
let(:cask_token) { "appcast-missing-checkpoint" }
|
||||
|
||||
it { is_expected.to fail_with(/checkpoint sha256 is required for appcast/) }
|
||||
end
|
||||
|
||||
context "when appcast checkpoint is not a string of 64 hexadecimal characters" do
|
||||
let(:cask_token) { "appcast-invalid-checkpoint" }
|
||||
|
||||
it { is_expected.to fail_with(/string must be of 64 hexadecimal characters/) }
|
||||
end
|
||||
|
||||
context "when appcast checkpoint is sha256 for empty string" do
|
||||
let(:cask_token) { "appcast-checkpoint-sha256-for-empty-string" }
|
||||
|
||||
it { is_expected.to fail_with(/cannot use the sha256 for an empty string/) }
|
||||
end
|
||||
|
||||
context "when appcast checkpoint is valid sha256" do
|
||||
let(:cask_token) { "appcast-valid-checkpoint" }
|
||||
it { should_not fail_with(/appcast :checkpoint/) }
|
||||
|
||||
it { is_expected.not_to fail_with(/appcast :checkpoint/) }
|
||||
end
|
||||
|
||||
context "when verifying appcast HTTP code" do
|
||||
@ -279,11 +330,13 @@ describe Hbc::Audit, :cask do
|
||||
|
||||
context "when HTTP code is 200" do
|
||||
let(:stdout) { "200" }
|
||||
it { should_not warn_with(wrong_code_msg) }
|
||||
|
||||
it { is_expected.not_to warn_with(wrong_code_msg) }
|
||||
end
|
||||
|
||||
context "when HTTP code is not 200" do
|
||||
let(:stdout) { "404" }
|
||||
|
||||
it { is_expected.to warn_with(wrong_code_msg) }
|
||||
end
|
||||
end
|
||||
@ -326,14 +379,16 @@ describe Hbc::Audit, :cask do
|
||||
|
||||
context "when appcast checkpoint is out of date" do
|
||||
let(:actual_checkpoint) { "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" }
|
||||
|
||||
it { is_expected.to warn_with(mismatch_msg) }
|
||||
it { should_not warn_with(curl_error_msg) }
|
||||
it { is_expected.not_to warn_with(curl_error_msg) }
|
||||
end
|
||||
|
||||
context "when appcast checkpoint is up to date" do
|
||||
let(:actual_checkpoint) { expected_checkpoint }
|
||||
it { should_not warn_with(mismatch_msg) }
|
||||
it { should_not warn_with(curl_error_msg) }
|
||||
|
||||
it { is_expected.not_to warn_with(mismatch_msg) }
|
||||
it { is_expected.not_to warn_with(curl_error_msg) }
|
||||
end
|
||||
end
|
||||
|
||||
@ -349,44 +404,95 @@ describe Hbc::Audit, :cask do
|
||||
end
|
||||
end
|
||||
|
||||
describe "GitHub releases appcast check" do
|
||||
let(:error_msg) { /Cask uses GitHub releases/ }
|
||||
|
||||
context "when the Cask does not use GitHub releases" do
|
||||
let(:cask_token) { "basic-cask" }
|
||||
|
||||
it { is_expected.not_to warn_with(error_msg) }
|
||||
end
|
||||
|
||||
context "when the Cask uses GitHub releases and has an appcast" do
|
||||
let(:cask_token) { "github-with-appcast" }
|
||||
|
||||
it { is_expected.not_to warn_with(error_msg) }
|
||||
end
|
||||
|
||||
context "when the Cask uses GitHub releases and does not have an appcast" do
|
||||
let(:cask_token) { "github-without-appcast" }
|
||||
|
||||
it { is_expected.to warn_with(error_msg) }
|
||||
end
|
||||
end
|
||||
|
||||
describe "latest with appcast checks" do
|
||||
let(:error_msg) { "Casks with an appcast should not use version :latest" }
|
||||
|
||||
context "when the Cask is :latest and does not have an appcast" do
|
||||
let(:cask_token) { "version-latest" }
|
||||
|
||||
it { is_expected.not_to warn_with(error_msg) }
|
||||
end
|
||||
|
||||
context "when the Cask is versioned and has an appcast" do
|
||||
let(:cask_token) { "with-appcast" }
|
||||
|
||||
it { is_expected.not_to warn_with(error_msg) }
|
||||
end
|
||||
|
||||
context "when the Cask is :latest and has an appcast" do
|
||||
let(:cask_token) { "latest-with-appcast" }
|
||||
|
||||
it { is_expected.to warn_with(error_msg) }
|
||||
end
|
||||
end
|
||||
|
||||
describe "preferred download URL formats" do
|
||||
let(:warning_msg) { /URL format incorrect/ }
|
||||
|
||||
context "with incorrect SourceForge URL format" do
|
||||
let(:cask_token) { "sourceforge-incorrect-url-format" }
|
||||
|
||||
it { is_expected.to warn_with(warning_msg) }
|
||||
end
|
||||
|
||||
context "with correct SourceForge URL format" do
|
||||
let(:cask_token) { "sourceforge-correct-url-format" }
|
||||
it { should_not warn_with(warning_msg) }
|
||||
|
||||
it { is_expected.not_to warn_with(warning_msg) }
|
||||
end
|
||||
|
||||
context "with correct SourceForge URL format for version :latest" do
|
||||
let(:cask_token) { "sourceforge-version-latest-correct-url-format" }
|
||||
it { should_not warn_with(warning_msg) }
|
||||
|
||||
it { is_expected.not_to warn_with(warning_msg) }
|
||||
end
|
||||
|
||||
context "with incorrect OSDN URL format" do
|
||||
let(:cask_token) { "osdn-incorrect-url-format" }
|
||||
|
||||
it { is_expected.to warn_with(warning_msg) }
|
||||
end
|
||||
|
||||
context "with correct OSDN URL format" do
|
||||
let(:cask_token) { "osdn-correct-url-format" }
|
||||
it { should_not warn_with(warning_msg) }
|
||||
|
||||
it { is_expected.not_to warn_with(warning_msg) }
|
||||
end
|
||||
end
|
||||
|
||||
describe "generic artifact checks" do
|
||||
context "with relative target" do
|
||||
let(:cask_token) { "generic-artifact-relative-target" }
|
||||
|
||||
it { is_expected.to fail_with(/target must be absolute path for Generic Artifact/) }
|
||||
end
|
||||
|
||||
context "with absolute target" do
|
||||
let(:cask_token) { "generic-artifact-absolute-target" }
|
||||
it { should_not fail_with(/target required for Generic Artifact/) }
|
||||
|
||||
it { is_expected.not_to fail_with(/target required for Generic Artifact/) }
|
||||
end
|
||||
end
|
||||
|
||||
@ -418,12 +524,14 @@ describe Hbc::Audit, :cask do
|
||||
|
||||
context "when cask token conflicts with a core formula" do
|
||||
let(:formula_names) { %w[with-binary other-formula] }
|
||||
|
||||
it { is_expected.to warn_with(/possible duplicate/) }
|
||||
end
|
||||
|
||||
context "when cask token does not conflict with a core formula" do
|
||||
let(:formula_names) { %w[other-formula] }
|
||||
it { should_not warn_with(/possible duplicate/) }
|
||||
|
||||
it { is_expected.not_to warn_with(/possible duplicate/) }
|
||||
end
|
||||
end
|
||||
|
||||
@ -440,7 +548,7 @@ describe Hbc::Audit, :cask do
|
||||
expect(verify).to receive(:all)
|
||||
end
|
||||
|
||||
it { should_not fail_with(/#{error_msg}/) }
|
||||
it { is_expected.not_to fail_with(/#{error_msg}/) }
|
||||
end
|
||||
|
||||
context "when download fails" do
|
||||
@ -463,6 +571,7 @@ describe Hbc::Audit, :cask do
|
||||
|
||||
context "when an exception is raised" do
|
||||
let(:cask) { instance_double(Hbc::Cask) }
|
||||
|
||||
before do
|
||||
expect(cask).to receive(:version).and_raise(StandardError.new)
|
||||
end
|
||||
|
||||
@ -101,9 +101,10 @@ describe Hbc::Cask, :cask do
|
||||
end
|
||||
|
||||
describe "versioned casks" do
|
||||
let(:cask) { described_class.new("basic-cask") }
|
||||
subject { cask.outdated_versions }
|
||||
|
||||
let(:cask) { described_class.new("basic-cask") }
|
||||
|
||||
shared_examples "versioned casks" do |tap_version, expectations|
|
||||
expectations.each do |installed_versions, expected_output|
|
||||
context "when versions #{installed_versions.inspect} are installed and the tap version is #{tap_version}" do
|
||||
@ -139,6 +140,7 @@ describe Hbc::Cask, :cask do
|
||||
expectations.each do |installed_version, expected_output|
|
||||
context "when versions #{installed_version} are installed and the tap version is #{tap_version}, #{greedy ? "" : "not"} greedy" do
|
||||
subject { cask.outdated_versions greedy }
|
||||
|
||||
it {
|
||||
allow(cask).to receive(:versions).and_return(installed_version)
|
||||
allow(cask).to receive(:version).and_return(Hbc::DSL::Version.new(tap_version))
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
require_relative "shared_examples/invalid_option"
|
||||
|
||||
describe Hbc::CLI::Cleanup, :cask do
|
||||
subject { described_class.new(*cask_tokens, cache_location: cache_location) }
|
||||
|
||||
let(:cache_location) { Pathname.new(Dir.mktmpdir).realpath }
|
||||
let(:outdated_only) { false }
|
||||
|
||||
subject { described_class.new(*cask_tokens, cache_location: cache_location) }
|
||||
|
||||
before(:each) do
|
||||
before do
|
||||
allow_any_instance_of(described_class).to receive(:outdated_only?).and_return(outdated_only)
|
||||
end
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ require_relative "shared_examples/requires_cask_token"
|
||||
require_relative "shared_examples/invalid_option"
|
||||
|
||||
describe Hbc::CLI::Create, :cask do
|
||||
around(:each) do |example|
|
||||
around do |example|
|
||||
begin
|
||||
example.run
|
||||
ensure
|
||||
@ -12,7 +12,7 @@ describe Hbc::CLI::Create, :cask do
|
||||
end
|
||||
end
|
||||
|
||||
before(:each) do
|
||||
before do
|
||||
allow_any_instance_of(described_class).to receive(:exec_editor)
|
||||
end
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ require_relative "shared_examples/requires_cask_token"
|
||||
require_relative "shared_examples/invalid_option"
|
||||
|
||||
describe Hbc::CLI::Edit, :cask do
|
||||
before(:each) do
|
||||
before do
|
||||
allow_any_instance_of(described_class).to receive(:exec_editor)
|
||||
end
|
||||
|
||||
|
||||
@ -49,7 +49,7 @@ describe Hbc::CLI::Info, :cask do
|
||||
end
|
||||
end
|
||||
|
||||
it "should print caveats if the Cask provided one" do
|
||||
it "prints caveats if the Cask provided one" do
|
||||
expect {
|
||||
described_class.run("with-caveats")
|
||||
}.to output(<<~EOS).to_stdout
|
||||
@ -75,7 +75,7 @@ describe Hbc::CLI::Info, :cask do
|
||||
EOS
|
||||
end
|
||||
|
||||
it 'should not print "Caveats" section divider if the caveats block has no output' do
|
||||
it 'does not print "Caveats" section divider if the caveats block has no output' do
|
||||
expect {
|
||||
described_class.run("with-conditional-caveats")
|
||||
}.to output(<<~EOS).to_stdout
|
||||
|
||||
@ -47,7 +47,7 @@ describe Hbc::CLI::List, :cask do
|
||||
EOS
|
||||
}
|
||||
|
||||
before(:each) do
|
||||
before do
|
||||
casks.map(&Hbc::CaskLoader.method(:load)).each(&InstallHelper.method(:install_with_caskfile))
|
||||
end
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
require_relative "shared_examples/invalid_option"
|
||||
|
||||
describe Hbc::CLI::Search, :cask do
|
||||
before(:each) do
|
||||
before do
|
||||
allow(Tty).to receive(:width).and_return(0)
|
||||
end
|
||||
|
||||
|
||||
@ -92,6 +92,7 @@ describe Hbc::CLI::Style, :cask do
|
||||
|
||||
context "when at least one cask token is a path that exists" do
|
||||
let(:tokens) { ["adium", "Casks/dropbox.rb"] }
|
||||
|
||||
before do
|
||||
allow(File).to receive(:exist?).and_return(false, true)
|
||||
end
|
||||
@ -103,6 +104,7 @@ describe Hbc::CLI::Style, :cask do
|
||||
|
||||
context "when no cask tokens are paths that exist" do
|
||||
let(:tokens) { %w[adium dropbox] }
|
||||
|
||||
before do
|
||||
allow(File).to receive(:exist?).and_return(false)
|
||||
end
|
||||
@ -123,11 +125,13 @@ describe Hbc::CLI::Style, :cask do
|
||||
|
||||
context "when fix? is true" do
|
||||
let(:fix) { true }
|
||||
|
||||
it { is_expected.to include("--auto-correct") }
|
||||
end
|
||||
|
||||
context "when fix? is false" do
|
||||
let(:fix) { false }
|
||||
|
||||
it { is_expected.not_to include("--auto-correct") }
|
||||
end
|
||||
end
|
||||
@ -140,9 +144,10 @@ describe Hbc::CLI::Style, :cask do
|
||||
|
||||
describe "#autocorrect_args" do
|
||||
subject { cli.autocorrect_args }
|
||||
|
||||
let(:default_args) { ["--format", "simple"] }
|
||||
|
||||
it "should add --auto-correct to default args" do
|
||||
it "adds --auto-correct to default args" do
|
||||
allow(cli).to receive(:default_args).and_return(default_args)
|
||||
expect(subject).to include("--auto-correct", *default_args)
|
||||
end
|
||||
|
||||
@ -105,7 +105,7 @@ describe Hbc::CLI::Uninstall, :cask do
|
||||
}
|
||||
let(:caskroom_path) { Hbc.caskroom.join(token).tap(&:mkpath) }
|
||||
|
||||
before(:each) do
|
||||
before do
|
||||
timestamped_versions.each do |timestamped_version|
|
||||
caskroom_path.join(".metadata", *timestamped_version, "Casks").tap(&:mkpath)
|
||||
.join("#{token}.rb").open("w") do |caskfile|
|
||||
|
||||
@ -13,7 +13,7 @@ describe Hbc::CLI::Upgrade, :cask do
|
||||
]
|
||||
}
|
||||
|
||||
before(:example) do
|
||||
before do
|
||||
installed.each { |cask| Hbc::CLI::Install.run(cask) }
|
||||
|
||||
allow_any_instance_of(described_class).to receive(:verbose?).and_return(true)
|
||||
@ -176,7 +176,7 @@ describe Hbc::CLI::Upgrade, :cask do
|
||||
]
|
||||
}
|
||||
|
||||
before(:example) do
|
||||
before do
|
||||
installed.each { |cask| Hbc::CLI::Install.run(cask) }
|
||||
|
||||
allow_any_instance_of(described_class).to receive(:verbose?).and_return(true)
|
||||
@ -201,7 +201,7 @@ describe Hbc::CLI::Upgrade, :cask do
|
||||
expect(will_fail_if_upgraded).to be_installed
|
||||
expect(will_fail_if_upgraded_path).to be_a_file
|
||||
expect(will_fail_if_upgraded.versions).to include("1.2.2")
|
||||
expect(will_fail_if_upgraded.staged_path).to_not exist
|
||||
expect(will_fail_if_upgraded.staged_path).not_to exist
|
||||
end
|
||||
|
||||
it "does not restore the old Cask if the upgrade failed pre-install" do
|
||||
@ -219,7 +219,7 @@ describe Hbc::CLI::Upgrade, :cask do
|
||||
expect(bad_checksum).to be_installed
|
||||
expect(bad_checksum_path).to be_a_directory
|
||||
expect(bad_checksum.versions).to include("1.2.2")
|
||||
expect(bad_checksum.staged_path).to_not exist
|
||||
expect(bad_checksum.staged_path).not_to exist
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -10,6 +10,7 @@ describe "Satisfy Dependencies and Requirements", :cask do
|
||||
describe "depends_on cask" do
|
||||
context "when depends_on cask is cyclic" do
|
||||
let(:cask) { Hbc::CaskLoader.load(cask_path("with-depends-on-cask-cyclic")) }
|
||||
|
||||
it {
|
||||
is_expected.to raise_error(Hbc::CaskCyclicDependencyError,
|
||||
"Cask 'with-depends-on-cask-cyclic' includes cyclic dependencies on other Casks: with-depends-on-cask-cyclic-helper")
|
||||
@ -31,26 +32,31 @@ describe "Satisfy Dependencies and Requirements", :cask do
|
||||
describe "depends_on macos" do
|
||||
context "given an array" do
|
||||
let(:cask) { Hbc::CaskLoader.load(cask_path("with-depends-on-macos-array")) }
|
||||
|
||||
it { is_expected.not_to raise_error }
|
||||
end
|
||||
|
||||
context "given a comparison" do
|
||||
let(:cask) { Hbc::CaskLoader.load(cask_path("with-depends-on-macos-comparison")) }
|
||||
|
||||
it { is_expected.not_to raise_error }
|
||||
end
|
||||
|
||||
context "given a string" do
|
||||
let(:cask) { Hbc::CaskLoader.load(cask_path("with-depends-on-macos-string")) }
|
||||
|
||||
it { is_expected.not_to raise_error }
|
||||
end
|
||||
|
||||
context "given a symbol" do
|
||||
let(:cask) { Hbc::CaskLoader.load(cask_path("with-depends-on-macos-symbol")) }
|
||||
|
||||
it { is_expected.not_to raise_error }
|
||||
end
|
||||
|
||||
context "when not satisfied" do
|
||||
let(:cask) { Hbc::CaskLoader.load(cask_path("with-depends-on-macos-failure")) }
|
||||
|
||||
it { is_expected.to raise_error(Hbc::CaskError) }
|
||||
end
|
||||
end
|
||||
@ -58,12 +64,13 @@ describe "Satisfy Dependencies and Requirements", :cask do
|
||||
describe "depends_on arch" do
|
||||
context "when satisfied" do
|
||||
let(:cask) { Hbc::CaskLoader.load(cask_path("with-depends-on-arch")) }
|
||||
|
||||
it { is_expected.not_to raise_error }
|
||||
end
|
||||
end
|
||||
|
||||
describe "depends_on x11" do
|
||||
before(:each) do
|
||||
before do
|
||||
allow(MacOS::X11).to receive(:installed?).and_return(x11_installed)
|
||||
end
|
||||
|
||||
|
||||
@ -93,6 +93,71 @@ describe "download strategies", :cask do
|
||||
expect(curl_args.each_cons(2)).to include(["-e", "http://somehost/also"])
|
||||
end
|
||||
end
|
||||
|
||||
context "with a file name trailing the URL path" do
|
||||
describe "#tarball_path" do
|
||||
subject { downloader.tarball_path }
|
||||
|
||||
its(:extname) { is_expected.to eq(".dmg") }
|
||||
end
|
||||
end
|
||||
|
||||
context "with no discernible file name in it" do
|
||||
let(:url) { "http://example.com/download" }
|
||||
|
||||
describe "#tarball_path" do
|
||||
subject { downloader.tarball_path }
|
||||
|
||||
its(:to_path) { is_expected.to end_with("some-cask--1.2.3.4") }
|
||||
end
|
||||
end
|
||||
|
||||
context "with a file name trailing the first query parameter" do
|
||||
let(:url) { "http://example.com/download?file=cask.zip&a=1" }
|
||||
|
||||
describe "#tarball_path" do
|
||||
subject { downloader.tarball_path }
|
||||
|
||||
its(:extname) { is_expected.to eq(".zip") }
|
||||
end
|
||||
end
|
||||
|
||||
context "with a file name trailing the second query parameter" do
|
||||
let(:url) { "http://example.com/dl?a=1&file=cask.zip&b=2" }
|
||||
|
||||
describe "#tarball_path" do
|
||||
subject { downloader.tarball_path }
|
||||
|
||||
its(:extname) { is_expected.to eq(".zip") }
|
||||
end
|
||||
end
|
||||
|
||||
context "with an unusually long query string" do
|
||||
let(:url) do
|
||||
[
|
||||
"https://node49152.ssl.fancycdn.example.com",
|
||||
"/fancycdn/node/49152/file/upload/download",
|
||||
"?cask_class=zf920df",
|
||||
"&cask_group=2348779087242312",
|
||||
"&cask_archive_file_name=cask.zip",
|
||||
"&signature=CGmDulxL8pmutKTlCleNTUY%2FyO9Xyl5u9yVZUE0",
|
||||
"uWrjadjuz67Jp7zx3H7NEOhSyOhu8nzicEHRBjr3uSoOJzwkLC8L",
|
||||
"BLKnz%2B2X%2Biq5m6IdwSVFcLp2Q1Hr2kR7ETn3rF1DIq5o0lHC",
|
||||
"yzMmyNe5giEKJNW8WF0KXriULhzLTWLSA3ZTLCIofAdRiiGje1kN",
|
||||
"YY3C0SBqymQB8CG3ONn5kj7CIGbxrDOq5xI2ZSJdIyPysSX7SLvE",
|
||||
"DBw2KdR24q9t1wfjS9LUzelf5TWk6ojj8p9%2FHjl%2Fi%2FVCXN",
|
||||
"N4o1mW%2FMayy2tTY1qcC%2FTmqI1ulZS8SNuaSgr9Iys9oDF1%2",
|
||||
"BPK%2B4Sg==",
|
||||
].join("")
|
||||
end
|
||||
|
||||
describe "#tarball_path" do
|
||||
subject { downloader.tarball_path }
|
||||
|
||||
its(:extname) { is_expected.to eq(".zip") }
|
||||
its("to_path.length") { is_expected.to be_between(0, 255) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe Hbc::CurlPostDownloadStrategy do
|
||||
@ -142,6 +207,7 @@ describe "download strategies", :cask do
|
||||
let(:url_options) { { using: :svn } }
|
||||
let(:fake_system_command) { class_double(Hbc::SystemCommand) }
|
||||
let(:downloader) { Hbc::SubversionDownloadStrategy.new(cask, command: fake_system_command) }
|
||||
|
||||
before do
|
||||
allow(fake_system_command).to receive(:run!)
|
||||
end
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
describe Hbc::DSL::StanzaProxy, :cask do
|
||||
subject { stanza_proxy }
|
||||
|
||||
let(:stanza_proxy) {
|
||||
described_class.new(Array) { [:foo, :bar, :cake] }
|
||||
}
|
||||
|
||||
subject { stanza_proxy }
|
||||
it { is_expected.to be_a_proxy }
|
||||
it { is_expected.to respond_to(:pop) }
|
||||
its(:pop) { is_expected.to eq(:cake) }
|
||||
|
||||
@ -3,6 +3,7 @@ describe Hbc::DSL::Version, :cask do
|
||||
expectations.each do |input_value, expected_output|
|
||||
context "when #{input_name} is #{input_value.inspect}" do
|
||||
let(input_name.to_sym) { input_value }
|
||||
|
||||
it { is_expected.to eq expected_output }
|
||||
end
|
||||
end
|
||||
@ -13,17 +14,20 @@ describe Hbc::DSL::Version, :cask do
|
||||
|
||||
context "when other is nil" do
|
||||
let(:other) { nil }
|
||||
|
||||
it { is_expected.to be false }
|
||||
end
|
||||
|
||||
context "when other is a String" do
|
||||
context "when other == self.raw_version" do
|
||||
let(:other) { "1.2.3" }
|
||||
|
||||
it { is_expected.to be true }
|
||||
end
|
||||
|
||||
context "when other != self.raw_version" do
|
||||
let(:other) { "1.2.3.4" }
|
||||
|
||||
it { is_expected.to be false }
|
||||
end
|
||||
end
|
||||
@ -31,11 +35,13 @@ describe Hbc::DSL::Version, :cask do
|
||||
context "when other is a #{described_class}" do
|
||||
context "when other.raw_version == self.raw_version" do
|
||||
let(:other) { described_class.new("1.2.3") }
|
||||
|
||||
it { is_expected.to be true }
|
||||
end
|
||||
|
||||
context "when other.raw_version != self.raw_version" do
|
||||
let(:other) { described_class.new("1.2.3.4") }
|
||||
|
||||
it { is_expected.to be false }
|
||||
end
|
||||
end
|
||||
@ -45,16 +51,19 @@ describe Hbc::DSL::Version, :cask do
|
||||
|
||||
describe "#==" do
|
||||
subject { version == other }
|
||||
|
||||
include_examples "version equality"
|
||||
end
|
||||
|
||||
describe "#eql?" do
|
||||
subject { version.eql?(other) }
|
||||
|
||||
include_examples "version equality"
|
||||
end
|
||||
|
||||
shared_examples "version expectations hash" do |method, hash|
|
||||
subject { version.send(method) }
|
||||
|
||||
include_examples "expectations hash", :raw_version,
|
||||
{ :latest => "latest",
|
||||
"latest" => "latest",
|
||||
|
||||
@ -44,6 +44,7 @@ describe Hbc::DSL, :cask do
|
||||
describe "header line" do
|
||||
context "when invalid" do
|
||||
let(:token) { "invalid/invalid-header-format" }
|
||||
|
||||
it "raises an error" do
|
||||
expect { cask }.to raise_error(SyntaxError)
|
||||
end
|
||||
@ -273,6 +274,7 @@ describe Hbc::DSL, :cask do
|
||||
|
||||
describe "version stanza" do
|
||||
let(:token) { "invalid/invalid-two-version" }
|
||||
|
||||
it "prevents defining multiple versions" do
|
||||
expect { cask }.to raise_error(Hbc::CaskInvalidError, /'version' stanza may only appear once/)
|
||||
end
|
||||
@ -313,6 +315,7 @@ describe Hbc::DSL, :cask do
|
||||
|
||||
context "with :key_url" do
|
||||
let(:token) { "with-gpg-key-url" }
|
||||
|
||||
it "is allowed to be specified" do
|
||||
expect(cask.gpg.to_s).to match(/\S/)
|
||||
end
|
||||
@ -404,6 +407,7 @@ describe Hbc::DSL, :cask do
|
||||
describe "depends_on cask" do
|
||||
context "specifying one" do
|
||||
let(:token) { "with-depends-on-cask" }
|
||||
|
||||
it "is allowed" do
|
||||
expect(cask.depends_on.cask).not_to be nil
|
||||
end
|
||||
|
||||
@ -5,6 +5,7 @@ describe "Operations on staged Casks", :cask do
|
||||
describe "bundle ID" do
|
||||
let(:cask) { Hbc::CaskLoader.load(cask_path("local-transmission")) }
|
||||
let(:installer) { Hbc::Installer.new(cask) }
|
||||
|
||||
it "fetches the bundle ID from a staged cask" do
|
||||
installer.install
|
||||
expect(installer.bundle_identifier).to eq("org.m0k.transmission")
|
||||
|
||||
@ -3,6 +3,7 @@ require "hbc/system_command"
|
||||
describe Hbc::SystemCommand::Result, :cask do
|
||||
describe "::_parse_plist" do
|
||||
subject { described_class._parse_plist(command, input) }
|
||||
|
||||
let(:command) { Hbc::SystemCommand.new("/usr/bin/true", {}) }
|
||||
let(:plist) {
|
||||
<<~EOS
|
||||
|
||||
@ -41,12 +41,12 @@ describe Hbc::Verify, :cask do
|
||||
end
|
||||
|
||||
describe ".all" do
|
||||
subject { described_class.all(cask, downloaded_path) }
|
||||
|
||||
let(:downloaded_path) { double("downloaded_path") }
|
||||
let(:applicable_verification) { double("applicable_verification") }
|
||||
let(:inapplicable_verification) { double("inapplicable_verification") }
|
||||
|
||||
subject { described_class.all(cask, downloaded_path) }
|
||||
|
||||
before do
|
||||
allow(applicable_verification_class).to receive(:new)
|
||||
.and_return(applicable_verification)
|
||||
|
||||
@ -3,6 +3,7 @@ require "caveats"
|
||||
|
||||
describe Caveats do
|
||||
subject { described_class.new(f) }
|
||||
|
||||
let(:f) { formula { url "foo-1.0" } }
|
||||
|
||||
specify "#f" do
|
||||
|
||||
@ -3,11 +3,13 @@ require "checksum"
|
||||
describe Checksum do
|
||||
describe "#empty?" do
|
||||
subject { described_class.new(:sha256, "") }
|
||||
|
||||
it { is_expected.to be_empty }
|
||||
end
|
||||
|
||||
describe "#==" do
|
||||
subject { described_class.new(:sha256, TEST_SHA256) }
|
||||
|
||||
let(:other) { described_class.new(:sha256, TEST_SHA256) }
|
||||
let(:other_reversed) { described_class.new(:sha256, TEST_SHA256.reverse) }
|
||||
let(:other_sha1) { described_class.new(:sha1, TEST_SHA1) }
|
||||
@ -15,5 +17,6 @@ describe Checksum do
|
||||
it { is_expected.to eq(other) }
|
||||
it { is_expected.not_to eq(other_reversed) }
|
||||
it { is_expected.not_to eq(other_sha1) }
|
||||
it { is_expected.not_to eq(nil) }
|
||||
end
|
||||
end
|
||||
|
||||
@ -5,9 +5,10 @@ describe Cleaner do
|
||||
include FileUtils
|
||||
|
||||
subject { described_class.new(f) }
|
||||
|
||||
let(:f) { formula("cleaner_test") { url "foo-1.0" } }
|
||||
|
||||
before(:each) do
|
||||
before do
|
||||
f.prefix.mkpath
|
||||
end
|
||||
|
||||
|
||||
@ -5,23 +5,27 @@ require "pathname"
|
||||
|
||||
describe Homebrew::Cleanup do
|
||||
let(:ds_store) { Pathname.new("#{HOMEBREW_PREFIX}/Library/.DS_Store") }
|
||||
let(:lock_file) { Pathname.new("#{HOMEBREW_LOCK_DIR}/foo") }
|
||||
let(:sec_in_a_day) { 60 * 60 * 24 }
|
||||
|
||||
around(:each) do |example|
|
||||
around do |example|
|
||||
begin
|
||||
FileUtils.touch ds_store
|
||||
FileUtils.touch lock_file
|
||||
|
||||
example.run
|
||||
ensure
|
||||
FileUtils.rm_f ds_store
|
||||
FileUtils.rm_f lock_file
|
||||
end
|
||||
end
|
||||
|
||||
describe "::cleanup" do
|
||||
it "removes .DS_Store files" do
|
||||
it "removes .DS_Store and lock files" do
|
||||
described_class.cleanup
|
||||
|
||||
expect(ds_store).not_to exist
|
||||
expect(lock_file).not_to exist
|
||||
end
|
||||
|
||||
it "doesn't remove anything if `--dry-run` is specified" do
|
||||
@ -30,6 +34,15 @@ describe Homebrew::Cleanup do
|
||||
described_class.cleanup
|
||||
|
||||
expect(ds_store).to exist
|
||||
expect(lock_file).to exist
|
||||
end
|
||||
|
||||
it "doesn't remove the lock file if it is locked" do
|
||||
lock_file.open(File::RDWR | File::CREAT).flock(File::LOCK_EX | File::LOCK_NB)
|
||||
|
||||
described_class.cleanup
|
||||
|
||||
expect(lock_file).to exist
|
||||
end
|
||||
|
||||
context "when it can't remove a keg" do
|
||||
@ -37,7 +50,7 @@ describe Homebrew::Cleanup do
|
||||
let(:f2) { Class.new(Testball) { version "0.2" }.new }
|
||||
let(:unremovable_kegs) { [] }
|
||||
|
||||
before(:each) do
|
||||
before do
|
||||
described_class.instance_variable_set(:@unremovable_kegs, [])
|
||||
[f1, f2].each do |f|
|
||||
f.brew do
|
||||
@ -217,7 +230,7 @@ describe Homebrew::Cleanup do
|
||||
let(:bottle) { (HOMEBREW_CACHE/"testball-0.0.1.bottle.tar.gz") }
|
||||
let(:testball) { (HOMEBREW_CACHE/"testball-0.0.1") }
|
||||
|
||||
before(:each) do
|
||||
before do
|
||||
FileUtils.touch(bottle)
|
||||
FileUtils.touch(testball)
|
||||
(HOMEBREW_CELLAR/"testball"/"0.0.1").mkpath
|
||||
@ -247,6 +260,8 @@ describe Homebrew::Cleanup do
|
||||
end
|
||||
|
||||
describe "::prune?" do
|
||||
alias_matcher :be_pruned, :be_prune
|
||||
|
||||
before do
|
||||
foo.mkpath
|
||||
end
|
||||
@ -255,11 +270,11 @@ describe Homebrew::Cleanup do
|
||||
|
||||
it "returns true when path_modified_time < days_default" do
|
||||
allow_any_instance_of(Pathname).to receive(:mtime).and_return(Time.now - sec_in_a_day * 2)
|
||||
expect(described_class.prune?(foo, days_default: "1")).to be_truthy
|
||||
expect(described_class).to be_pruned(foo, days_default: "1")
|
||||
end
|
||||
|
||||
it "returns false when path_modified_time >= days_default" do
|
||||
expect(described_class.prune?(foo, days_default: "2")).to be_falsey
|
||||
expect(described_class).not_to be_pruned(foo, days_default: "2")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
72
Library/Homebrew/test/cli_parser_spec.rb
Normal file
72
Library/Homebrew/test/cli_parser_spec.rb
Normal file
@ -0,0 +1,72 @@
|
||||
require_relative "../cli_parser"
|
||||
|
||||
describe Homebrew::CLI::Parser do
|
||||
describe "test switch options" do
|
||||
before do
|
||||
allow(ENV).to receive(:[]).with("HOMEBREW_PRY").and_return("1")
|
||||
allow(ENV).to receive(:[]).with("HOMEBREW_VERBOSE")
|
||||
end
|
||||
|
||||
subject(:parser) {
|
||||
described_class.new do
|
||||
switch :verbose, description: "Flag for verbosity"
|
||||
switch "--more-verbose", description: "Flag for higher verbosity"
|
||||
switch "--pry", env: :pry
|
||||
end
|
||||
}
|
||||
|
||||
it "parses short option" do
|
||||
args = parser.parse(["-v"])
|
||||
expect(args).to be_verbose
|
||||
end
|
||||
|
||||
it "parses a single valid option" do
|
||||
args = parser.parse(["--verbose"])
|
||||
expect(args).to be_verbose
|
||||
end
|
||||
|
||||
it "parses a valid option along with few unnamed args" do
|
||||
args = %w[--verbose unnamed args]
|
||||
parser.parse(args)
|
||||
expect(args).to eq %w[unnamed args]
|
||||
end
|
||||
|
||||
it "parses a single option and checks other options to be nil" do
|
||||
args = parser.parse(["--verbose"])
|
||||
expect(args).to be_verbose
|
||||
expect(args.more_verbose?).to be nil
|
||||
end
|
||||
|
||||
it "raises an exception when an invalid option is passed" do
|
||||
expect { parser.parse(["--random"]) }.to raise_error(OptionParser::InvalidOption, /--random/)
|
||||
end
|
||||
|
||||
it "maps environment var to an option" do
|
||||
args = parser.parse([])
|
||||
expect(args.pry?).to be true
|
||||
end
|
||||
end
|
||||
|
||||
describe "test long flag options" do
|
||||
subject(:parser) {
|
||||
described_class.new do
|
||||
flag "--filename", description: "Name of the file", required: true
|
||||
comma_array "--files", description: "Comma separated filenames"
|
||||
end
|
||||
}
|
||||
|
||||
it "parses a long flag option with its argument" do
|
||||
args = parser.parse(["--filename=random.txt"])
|
||||
expect(args.filename).to eq "random.txt"
|
||||
end
|
||||
|
||||
it "raises an exception when a flag's required arg is not passed" do
|
||||
expect { parser.parse(["--filename"]) }.to raise_error(OptionParser::MissingArgument, /--filename/)
|
||||
end
|
||||
|
||||
it "parses a comma array flag option" do
|
||||
args = parser.parse(["--files=random1.txt,random2.txt"])
|
||||
expect(args.files).to eq %w[random1.txt random2.txt]
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,5 +1,5 @@
|
||||
describe "brew analytics", :integration_test do
|
||||
before(:each) do
|
||||
before do
|
||||
HOMEBREW_REPOSITORY.cd do
|
||||
system "git", "init"
|
||||
end
|
||||
|
||||
@ -23,7 +23,7 @@ RSpec.shared_context "custom internal commands" do
|
||||
]
|
||||
end
|
||||
|
||||
around(:each) do |example|
|
||||
around do |example|
|
||||
begin
|
||||
cmds.each do |f|
|
||||
FileUtils.touch f
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
describe "brew migrate", :integration_test do
|
||||
before(:each) do
|
||||
before do
|
||||
setup_test_formula "testball1"
|
||||
setup_test_formula "testball2"
|
||||
end
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
describe "brew missing", :integration_test do
|
||||
before(:each) do
|
||||
before do
|
||||
setup_test_formula "foo"
|
||||
setup_test_formula "bar"
|
||||
end
|
||||
|
||||
@ -4,7 +4,7 @@ describe "brew pin", :integration_test do
|
||||
(HOMEBREW_CELLAR/"testball/0.0.1/foo").mkpath
|
||||
|
||||
expect { brew "pin", "testball" }.to be_a_success
|
||||
expect { brew "upgrade" }.to be_a_success
|
||||
expect { brew "upgrade" }.to be_a_failure
|
||||
|
||||
expect(HOMEBREW_CELLAR/"testball/0.1").not_to be_a_directory
|
||||
end
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
require "extend/ENV"
|
||||
|
||||
describe "brew reinstall", :integration_test do
|
||||
before(:each) do
|
||||
before do
|
||||
setup_test_formula "testball"
|
||||
|
||||
expect { brew "install", "testball", "--with-foo" }.to be_a_success
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user