diff --git a/Library/Homebrew/brew.sh b/Library/Homebrew/brew.sh index 590dde3632..98de43e286 100644 --- a/Library/Homebrew/brew.sh +++ b/Library/Homebrew/brew.sh @@ -32,7 +32,7 @@ onoe() { fi if [[ $# -eq 0 ]] then - /bin/cat >&2 + cat >&2 else echo "$*" >&2 fi diff --git a/Library/Homebrew/build.rb b/Library/Homebrew/build.rb index d61c3672a1..a2a62ccd77 100644 --- a/Library/Homebrew/build.rb +++ b/Library/Homebrew/build.rb @@ -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 diff --git a/Library/Homebrew/cask/lib/hbc/audit.rb b/Library/Homebrew/cask/lib/hbc/audit.rb index d757b0623d..d83bcd5e0f 100644 --- a/Library/Homebrew/cask/lib/hbc/audit.rb +++ b/Library/Homebrew/cask/lib/hbc/audit.rb @@ -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 diff --git a/Library/Homebrew/cask/lib/hbc/cask_loader.rb b/Library/Homebrew/cask/lib/hbc/cask_loader.rb index 640282ec36..1ac85af5fa 100644 --- a/Library/Homebrew/cask/lib/hbc/cask_loader.rb +++ b/Library/Homebrew/cask/lib/hbc/cask_loader.rb @@ -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 diff --git a/Library/Homebrew/cask/lib/hbc/cli/doctor.rb b/Library/Homebrew/cask/lib/hbc/cli/doctor.rb index 32b927218b..6f00951724 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/doctor.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/doctor.rb @@ -124,6 +124,7 @@ module Hbc BUNDLE_PATH PATH SHELL + HOMEBREW_CASK_OPTS ] locale_variables = ENV.keys.grep(/^(?:LC_\S+|LANG|LANGUAGE)\Z/).sort diff --git a/Library/Homebrew/cask/lib/hbc/download_strategy.rb b/Library/Homebrew/cask/lib/hbc/download_strategy.rb index 245ad4adeb..c6f4b78543 100644 --- a/Library/Homebrew/cask/lib/hbc/download_strategy.rb +++ b/Library/Homebrew/cask/lib/hbc/download_strategy.rb @@ -154,7 +154,7 @@ module Hbc end def ext - Pathname.new(@url).extname[/[^?]+/] + Pathname.new(@url).extname[/[^?&]+/] end end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/caveats.rb b/Library/Homebrew/cask/lib/hbc/dsl/caveats.rb index a6cbdd6bf3..e10575e0cf 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/caveats.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/caveats.rb @@ -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 diff --git a/Library/Homebrew/cask/lib/hbc/dsl/gpg.rb b/Library/Homebrew/cask/lib/hbc/dsl/gpg.rb index 99b39d43fd..ec7180436b 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/gpg.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/gpg.rb @@ -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 diff --git a/Library/Homebrew/cask/lib/hbc/verify/gpg.rb b/Library/Homebrew/cask/lib/hbc/verify/gpg.rb index f4996a5b5e..16798d7fa1 100644 --- a/Library/Homebrew/cask/lib/hbc/verify/gpg.rb +++ b/Library/Homebrew/cask/lib/hbc/verify/gpg.rb @@ -49,7 +49,7 @@ module Hbc end def verify - return unless available? + return unless available? && cask.gpg.signature != :embedded import_key sig = fetch_sig diff --git a/Library/Homebrew/checksum.rb b/Library/Homebrew/checksum.rb index 506885fce3..c1d0e70551 100644 --- a/Library/Homebrew/checksum.rb +++ b/Library/Homebrew/checksum.rb @@ -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 diff --git a/Library/Homebrew/cleanup.rb b/Library/Homebrew/cleanup.rb index 960bcb8b7b..0b4d97d59e 100644 --- a/Library/Homebrew/cleanup.rb +++ b/Library/Homebrew/cleanup.rb @@ -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 diff --git a/Library/Homebrew/cli_parser.rb b/Library/Homebrew/cli_parser.rb new file mode 100644 index 0000000000..8a6e15abb7 --- /dev/null +++ b/Library/Homebrew/cli_parser.rb @@ -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 diff --git a/Library/Homebrew/cmd/deps.rb b/Library/Homebrew/cmd/deps.rb index 40aa2f413d..a3bd2b8b58 100644 --- a/Library/Homebrew/cmd/deps.rb +++ b/Library/Homebrew/cmd/deps.rb @@ -18,7 +18,7 @@ #: By default, `deps` shows required and recommended dependencies for #: . 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,29 +75,39 @@ 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 - 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.sort! unless mode.topo_order? - puts all_deps + return end + + all_deps = deps_for_formulae(ARGV.formulae, !ARGV.one?, &(mode.union? ? :| : :&)) + all_deps = condense_requirements(all_deps) + 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 def condense_requirements(deps) - if ARGV.include?("--include-requirements") - deps - else - deps.select { |dep| dep.is_a? Dependency } - end + return deps if ARGV.include?("--include-requirements") + deps.select { |dep| dep.is_a? Dependency } end def dep_display_name(dep) @@ -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 diff --git a/Library/Homebrew/cmd/help.rb b/Library/Homebrew/cmd/help.rb index c85b92124a..2b1e7c5049 100644 --- a/Library/Homebrew/cmd/help.rb +++ b/Library/Homebrew/cmd/help.rb @@ -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}") diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb index bacdb18f02..e26499a21f 100644 --- a/Library/Homebrew/cmd/install.rb +++ b/Library/Homebrew/cmd/install.rb @@ -1,4 +1,4 @@ -#: * `install` [`--debug`] [`--env=`(`std`|`super`)] [`--ignore-dependencies`|`--only-dependencies`] [`--cc=`] [`--build-from-source`|`--force-bottle`] [`--devel`|`--HEAD`] [`--keep-tmp`] [`--build-bottle`] [`--force`] [`--verbose`] [ ...]: +#: * `install` [`--debug`] [`--env=`(`std`|`super`)] [`--ignore-dependencies`|`--only-dependencies`] [`--cc=`] [`--build-from-source`|`--force-bottle`] [`--include-test`] [`--devel`|`--HEAD`] [`--keep-tmp`] [`--build-bottle`] [`--force`] [`--verbose`] [ ...]: #: Install . #: #: 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 defines it, install the development version. #: #: If `--HEAD` is passed, and 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." diff --git a/Library/Homebrew/cmd/leaves.rb b/Library/Homebrew/cmd/leaves.rb index ecebedbb35..42fa18a28a 100644 --- a/Library/Homebrew/cmd/leaves.rb +++ b/Library/Homebrew/cmd/leaves.rb @@ -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 diff --git a/Library/Homebrew/cmd/style.rb b/Library/Homebrew/cmd/style.rb index 1f0d385dee..76d961a7fe 100644 --- a/Library/Homebrew/cmd/style.rb +++ b/Library/Homebrew/cmd/style.rb @@ -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=` will check for violations of only the listed #: RuboCop , while `--except-cops=` will skip checking the listed #: . For either option 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| diff --git a/Library/Homebrew/cmd/update.sh b/Library/Homebrew/cmd/update.sh index 3f287340ff..f0fbdffafa 100644 --- a/Library/Homebrew/cmd/update.sh +++ b/Library/Homebrew/cmd/update.sh @@ -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 + BREW_OFFICIAL_REMOTE="https://github.com/Homebrew/brew" + CORE_OFFICIAL_REMOTE="https://github.com/Homebrew/homebrew-core" safe_cd "$HOMEBREW_REPOSITORY" if [[ ! -d ".git" ]] diff --git a/Library/Homebrew/cmd/upgrade.rb b/Library/Homebrew/cmd/upgrade.rb index 7cbbecbb25..02bd489a43 100644 --- a/Library/Homebrew/cmd/upgrade.rb +++ b/Library/Homebrew/cmd/upgrade.rb @@ -1,15 +1,19 @@ -#: * `upgrade` [] [`--cleanup`] [`--fetch-HEAD`] []: +#: * `upgrade` [] [`--cleanup`] [`--fetch-HEAD`] [`--ignore-pinned`] []: #: 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 version(s). +#: If `--cleanup` is specified or `HOMEBREW_UPGRADE_CLEANUP` is set then remove +#: previously installed 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 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 diff --git a/Library/Homebrew/cmd/uses.rb b/Library/Homebrew/cmd/uses.rb index d5c9210f6b..98ecca0f5d 100644 --- a/Library/Homebrew/cmd/uses.rb +++ b/Library/Homebrew/cmd/uses.rb @@ -1,4 +1,4 @@ -#: * `uses` [`--installed`] [`--recursive`] [`--include-build`] [`--include-optional`] [`--skip-recommended`] [`--devel`|`--HEAD`] : +#: * `uses` [`--installed`] [`--recursive`] [`--include-build`] [`--include-test`] [`--include-optional`] [`--skip-recommended`] [`--devel`|`--HEAD`] : #: Show the formulae that specify as a dependency. When given #: multiple formula arguments, show the intersection of formulae that use #: . @@ -9,10 +9,12 @@ #: #: By default, `uses` shows all formulae that specify 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 by stable builds. To find +#: By default, `uses` shows usage of by stable builds. To find #: cases where 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 diff --git a/Library/Homebrew/cmd/vendor-install.sh b/Library/Homebrew/cmd/vendor-install.sh index 3b91dae5ca..8aba2174e5 100644 --- a/Library/Homebrew/cmd/vendor-install.sh +++ b/Library/Homebrew/cmd/vendor-install.sh @@ -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 <" 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 diff --git a/Library/Homebrew/dependency.rb b/Library/Homebrew/dependency.rb index 7ae0703609..0697ba7ff3 100644 --- a/Library/Homebrew/dependency.rb +++ b/Library/Homebrew/dependency.rb @@ -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?) - [:build] - elsif deps.all?(&:run?) - [:run] - else - [] # Means both build and runtime dependency. - end + # Means both build and runtime dependency. + return [] unless deps.all?(&:build?) + [:build] end end end diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index e3fb3a5809..5eaffe2afa 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -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 diff --git a/Library/Homebrew/dev-cmd/bottle.rb b/Library/Homebrew/dev-cmd/bottle.rb index a233dfb57a..b05277d054 100644 --- a/Library/Homebrew/dev-cmd/bottle.rb +++ b/Library/Homebrew/dev-cmd/bottle.rb @@ -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 diff --git a/Library/Homebrew/dev-cmd/create.rb b/Library/Homebrew/dev-cmd/create.rb index 3963e5a7bc..514d3b6c30 100644 --- a/Library/Homebrew/dev-cmd/create.rb +++ b/Library/Homebrew/dev-cmd/create.rb @@ -170,7 +170,7 @@ class FormulaCreator # Documentation: https://docs.brew.sh/Formula-Cookbook # http://www.rubydoc.info/github/Homebrew/brew/master/Formula # PLEASE REMOVE ALL GENERATED COMMENTS BEFORE SUBMITTING YOUR PULL REQUEST! - class #{Formulary.class_s(name)} < Formula + class #{Formulary.class_s(name)} < Formula desc "#{desc}" homepage "#{homepage}" <% if head? %> @@ -182,7 +182,7 @@ class FormulaCreator <% end %> sha256 "#{sha256}" <% end %> - <% if mode == :cmake %> + <% if mode == :cmake %> depends_on "cmake" => :build <% elsif mode == :meson %> depends_on "meson" => :build @@ -190,9 +190,10 @@ class FormulaCreator <% elsif mode.nil? %> # depends_on "cmake" => :build <% end %> - def install + + def install # ENV.deparallelize # if your formula fails when building in parallel - <% if mode == :cmake %> + <% if mode == :cmake %> system "cmake", ".", *std_cmake_args <% elsif mode == :autotools %> # Remove unrecognized options if warned by configure @@ -219,7 +220,8 @@ class FormulaCreator system "make", "install" # if this fails, try separate make/make install steps <% end %> end - test do + + test do # `test do` will create, run in and delete a temporary directory. # # This test will fail and we won't accept that! For Homebrew/homebrew-core diff --git a/Library/Homebrew/dev-cmd/edit.rb b/Library/Homebrew/dev-cmd/edit.rb index 0039b4cce6..0861a4bb1e 100644 --- a/Library/Homebrew/dev-cmd/edit.rb +++ b/Library/Homebrew/dev-cmd/edit.rb @@ -5,11 +5,16 @@ #: Open 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 diff --git a/Library/Homebrew/dev-cmd/irb.rb b/Library/Homebrew/dev-cmd/irb.rb index 700cbe0097..1d6b0a5142 100644 --- a/Library/Homebrew/dev-cmd/irb.rb +++ b/Library/Homebrew/dev-cmd/irb.rb @@ -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 diff --git a/Library/Homebrew/dev-cmd/man.rb b/Library/Homebrew/dev-cmd/man.rb index f06c89863d..a54ab89e3c 100644 --- a/Library/Homebrew/dev-cmd/man.rb +++ b/Library/Homebrew/dev-cmd/man.rb @@ -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"] diff --git a/Library/Homebrew/dev-cmd/pull.rb b/Library/Homebrew/dev-cmd/pull.rb index 959fbd6c75..c8006d7781 100644 --- a/Library/Homebrew/dev-cmd/pull.rb +++ b/Library/Homebrew/dev-cmd/pull.rb @@ -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 diff --git a/Library/Homebrew/dev-cmd/release-notes.rb b/Library/Homebrew/dev-cmd/release-notes.rb index 4960239565..892a4a83e1 100644 --- a/Library/Homebrew/dev-cmd/release-notes.rb +++ b/Library/Homebrew/dev-cmd/release-notes.rb @@ -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)})" diff --git a/Library/Homebrew/dev-cmd/tests.rb b/Library/Homebrew/dev-cmd/tests.rb index db2a6d33ea..57c00dafc7 100644 --- a/Library/Homebrew/dev-cmd/tests.rb +++ b/Library/Homebrew/dev-cmd/tests.rb @@ -1,4 +1,4 @@ -#: * `tests` [`--verbose`] [`--coverage`] [`--generic`] [`--no-compat`] [`--only=`[`:`]] [`--seed` ] [`--online`] [`--official-cmd-taps`]: +#: * `tests` [`--verbose`] [`--coverage`] [`--generic`] [`--no-compat`] [`--only=`[`:`]] [`--seed=`] [`--online`] [`--official-cmd-taps`]: #: Run Homebrew's unit and integration tests. If provided, #: `--only=` runs only _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[ diff --git a/Library/Homebrew/dev-cmd/update-test.rb b/Library/Homebrew/dev-cmd/update-test.rb index ee189ad5ef..c0e3f64a00 100644 --- a/Library/Homebrew/dev-cmd/update-test.rb +++ b/Library/Homebrew/dev-cmd/update-test.rb @@ -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..." diff --git a/Library/Homebrew/development_tools.rb b/Library/Homebrew/development_tools.rb index ba342c435c..1f0d77d148 100644 --- a/Library/Homebrew/development_tools.rb +++ b/Library/Homebrew/development_tools.rb @@ -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 diff --git a/Library/Homebrew/diagnostic.rb b/Library/Homebrew/diagnostic.rb index 706bb201a9..36df53794f 100644 --- a/Library/Homebrew/diagnostic.rb +++ b/Library/Homebrew/diagnostic.rb @@ -11,11 +11,9 @@ module Homebrew missing = {} ff.each do |f| missing_dependencies = f.missing_dependencies(hide: hide) - - unless missing_dependencies.empty? - yield f.full_name, missing_dependencies if block_given? - missing[f.full_name] = missing_dependencies - end + next if missing_dependencies.empty? + yield f.full_name, missing_dependencies if block_given? + missing[f.full_name] = missing_dependencies end missing end diff --git a/Library/Homebrew/download_strategy.rb b/Library/Homebrew/download_strategy.rb index 6e750806f0..b50ae317c7 100644 --- a/Library/Homebrew/download_strategy.rb +++ b/Library/Homebrew/download_strategy.rb @@ -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 diff --git a/Library/Homebrew/exceptions.rb b/Library/Homebrew/exceptions.rb index 20ad2a3788..b3acf821ec 100644 --- a/Library/Homebrew/exceptions.rb +++ b/Library/Homebrew/exceptions.rb @@ -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 diff --git a/Library/Homebrew/extend/ARGV.rb b/Library/Homebrew/extend/ARGV.rb index 2bc84620a4..0a66a0abe6 100644 --- a/Library/Homebrew/extend/ARGV.rb +++ b/Library/Homebrew/extend/ARGV.rb @@ -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 diff --git a/Library/Homebrew/extend/os/mac/requirements/java_requirement.rb b/Library/Homebrew/extend/os/mac/requirements/java_requirement.rb index 2a48f02bd8..b8cf502a5e 100644 --- a/Library/Homebrew/extend/os/mac/requirements/java_requirement.rb +++ b/Library/Homebrew/extend/os/mac/requirements/java_requirement.rb @@ -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 diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index e04ac1c936..75cb846103 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -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 - end - - def declared_runtime_dependencies - recursive_dependencies do |_, dependency| - Dependency.prune if dependency.build? - Dependency.prune if !dependency.required? && build.without?(dependency) + 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 + + 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)}", diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb index 8d7f0aae1c..8c7efc978b 100644 --- a/Library/Homebrew/formula_installer.rb +++ b/Library/Homebrew/formula_installer.rb @@ -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 diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb index 1b1987717a..5f6ae0723b 100644 --- a/Library/Homebrew/formulary.rb +++ b/Library/Homebrew/formulary.rb @@ -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 diff --git a/Library/Homebrew/keg.rb b/Library/Homebrew/keg.rb index 4c81de33aa..04c98c9556 100644 --- a/Library/Homebrew/keg.rb +++ b/Library/Homebrew/keg.rb @@ -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| - required = dependent.missing_dependencies(hide: keg_names) + 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 diff --git a/Library/Homebrew/linkage_checker.rb b/Library/Homebrew/linkage_checker.rb index f6beae295b..45812e31df 100644 --- a/Library/Homebrew/linkage_checker.rb +++ b/Library/Homebrew/linkage_checker.rb @@ -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 = [] diff --git a/Library/Homebrew/manpages/brew.1.md.erb b/Library/Homebrew/manpages/brew.1.md.erb index 618e050f63..a4854cc67c 100644 --- a/Library/Homebrew/manpages/brew.1.md.erb +++ b/Library/Homebrew/manpages/brew.1.md.erb @@ -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: - + <%= homebrew_bundle.join("\n ").strip %> - * `cask`: - Install macOS applications distributed as binaries: - - * `services`: - Integrates Homebrew formulae with macOS's `launchctl`(1) manager: - + Homebrew/homebrew-bundle + + * `cask` [`--version` | `audit` | `cat` | `cleanup` | `create` | `doctor` | `edit` | `fetch` | `home` | `info`]: + Install macOS applications distributed as binaries. + + + Caskroom/homebrew-cask + + <%= homebrew_services.join("\n ").strip %> + + + 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. diff --git a/Library/Homebrew/rubocops/dependency_order_cop.rb b/Library/Homebrew/rubocops/dependency_order_cop.rb index 1d1481f280..14f0f85957 100644 --- a/Library/Homebrew/rubocops/dependency_order_cop.rb +++ b/Library/Homebrew/rubocops/dependency_order_cop.rb @@ -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 diff --git a/Library/Homebrew/rubocops/extend/formula_cop.rb b/Library/Homebrew/rubocops/extend/formula_cop.rb index 2c20e62dec..ae343a9fc2 100644 --- a/Library/Homebrew/rubocops/extend/formula_cop.rb +++ b/Library/Homebrew/rubocops/extend/formula_cop.rb @@ -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 diff --git a/Library/Homebrew/shims/scm/git b/Library/Homebrew/shims/scm/git index f826e1b608..e1ef6c6a59 100755 --- a/Library/Homebrew/shims/scm/git +++ b/Library/Homebrew/shims/scm/git @@ -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 diff --git a/Library/Homebrew/shims/super/pod2man b/Library/Homebrew/shims/super/pod2man index 90145766ff..1ad2cd2018 100755 --- a/Library/Homebrew/shims/super/pod2man +++ b/Library/Homebrew/shims/super/pod2man @@ -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" "$@" diff --git a/Library/Homebrew/software_spec.rb b/Library/Homebrew/software_spec.rb index dd6026fcf4..df7b86770c 100644 --- a/Library/Homebrew/software_spec.rb +++ b/Library/Homebrew/software_spec.rb @@ -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 diff --git a/Library/Homebrew/system_config.rb b/Library/Homebrew/system_config.rb index 63e162075e..13867e7d4e 100644 --- a/Library/Homebrew/system_config.rb +++ b/Library/Homebrew/system_config.rb @@ -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}" diff --git a/Library/Homebrew/tab.rb b/Library/Homebrew/tab.rb index 0fed724a8d..7bfa2e36cd 100644 --- a/Library/Homebrew/tab.rb +++ b/Library/Homebrew/tab.rb @@ -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, diff --git a/Library/Homebrew/tap.rb b/Library/Homebrew/tap.rb index d128c68fbc..e13b9af754 100644 --- a/Library/Homebrew/tap.rb +++ b/Library/Homebrew/tap.rb @@ -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 + "https://github.com/Homebrew/homebrew-core".freeze end # @private diff --git a/Library/Homebrew/test/ARGV_spec.rb b/Library/Homebrew/test/ARGV_spec.rb index 89ef9cabc6..22a11f7523 100644 --- a/Library/Homebrew/test/ARGV_spec.rb +++ b/Library/Homebrew/test/ARGV_spec.rb @@ -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 diff --git a/Library/Homebrew/test/ENV_spec.rb b/Library/Homebrew/test/ENV_spec.rb index 8b39e52d78..b39ae374c7 100644 --- a/Library/Homebrew/test/ENV_spec.rb +++ b/Library/Homebrew/test/ENV_spec.rb @@ -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 diff --git a/Library/Homebrew/test/bash_spec.rb b/Library/Homebrew/test/bash_spec.rb index 5526078100..60ce8416ac 100644 --- a/Library/Homebrew/test/bash_spec.rb +++ b/Library/Homebrew/test/bash_spec.rb @@ -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 diff --git a/Library/Homebrew/test/build_environment_spec.rb b/Library/Homebrew/test/build_environment_spec.rb index 58bec6d1fd..0675b6aaeb 100644 --- a/Library/Homebrew/test/build_environment_spec.rb +++ b/Library/Homebrew/test/build_environment_spec.rb @@ -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 diff --git a/Library/Homebrew/test/build_options_spec.rb b/Library/Homebrew/test/build_options_spec.rb index 1e6c9ea35f..8c118c5515 100644 --- a/Library/Homebrew/test/build_options_spec.rb +++ b/Library/Homebrew/test/build_options_spec.rb @@ -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]) } diff --git a/Library/Homebrew/test/cask/accessibility_spec.rb b/Library/Homebrew/test/cask/accessibility_spec.rb index b77bcb0020..8832ed8d16 100644 --- a/Library/Homebrew/test/cask/accessibility_spec.rb +++ b/Library/Homebrew/test/cask/accessibility_spec.rb @@ -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 diff --git a/Library/Homebrew/test/cask/artifact/app_spec.rb b/Library/Homebrew/test/cask/artifact/app_spec.rb index 97e19165b3..aa6085bf16 100644 --- a/Library/Homebrew/test/cask/artifact/app_spec.rb +++ b/Library/Homebrew/test/cask/artifact/app_spec.rb @@ -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 diff --git a/Library/Homebrew/test/cask/artifact/binary_spec.rb b/Library/Homebrew/test/cask/artifact/binary_spec.rb index d072060cc6..448c10dd1e 100644 --- a/Library/Homebrew/test/cask/artifact/binary_spec.rb +++ b/Library/Homebrew/test/cask/artifact/binary_spec.rb @@ -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 diff --git a/Library/Homebrew/test/cask/artifact/pkg_spec.rb b/Library/Homebrew/test/cask/artifact/pkg_spec.rb index 89916d2836..6d1827bdbc 100644 --- a/Library/Homebrew/test/cask/artifact/pkg_spec.rb +++ b/Library/Homebrew/test/cask/artifact/pkg_spec.rb @@ -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 diff --git a/Library/Homebrew/test/cask/artifact/suite_spec.rb b/Library/Homebrew/test/cask/artifact/suite_spec.rb index 62a2fbfd7e..2602bb2ad0 100644 --- a/Library/Homebrew/test/cask/artifact/suite_spec.rb +++ b/Library/Homebrew/test/cask/artifact/suite_spec.rb @@ -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 diff --git a/Library/Homebrew/test/cask/artifact/two_apps_correct_spec.rb b/Library/Homebrew/test/cask/artifact/two_apps_correct_spec.rb index 0d6f47d13c..7c5f862141 100644 --- a/Library/Homebrew/test/cask/artifact/two_apps_correct_spec.rb +++ b/Library/Homebrew/test/cask/artifact/two_apps_correct_spec.rb @@ -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 diff --git a/Library/Homebrew/test/cask/artifact/uninstall_no_zap_spec.rb b/Library/Homebrew/test/cask/artifact/uninstall_no_zap_spec.rb index c6ff7d30e0..b2df115eb2 100644 --- a/Library/Homebrew/test/cask/artifact/uninstall_no_zap_spec.rb +++ b/Library/Homebrew/test/cask/artifact/uninstall_no_zap_spec.rb @@ -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 diff --git a/Library/Homebrew/test/cask/audit_spec.rb b/Library/Homebrew/test/cask/audit_spec.rb index ec051c1387..751a31241f 100644 --- a/Library/Homebrew/test/cask/audit_spec.rb +++ b/Library/Homebrew/test/cask/audit_spec.rb @@ -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 diff --git a/Library/Homebrew/test/cask/cask_spec.rb b/Library/Homebrew/test/cask/cask_spec.rb index 5858a7c6db..e8d5aff8f8 100644 --- a/Library/Homebrew/test/cask/cask_spec.rb +++ b/Library/Homebrew/test/cask/cask_spec.rb @@ -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)) diff --git a/Library/Homebrew/test/cask/cli/cleanup_spec.rb b/Library/Homebrew/test/cask/cli/cleanup_spec.rb index cbef71be8c..9fd21dd103 100644 --- a/Library/Homebrew/test/cask/cli/cleanup_spec.rb +++ b/Library/Homebrew/test/cask/cli/cleanup_spec.rb @@ -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 diff --git a/Library/Homebrew/test/cask/cli/create_spec.rb b/Library/Homebrew/test/cask/cli/create_spec.rb index 1b15ecd409..3efd17787d 100644 --- a/Library/Homebrew/test/cask/cli/create_spec.rb +++ b/Library/Homebrew/test/cask/cli/create_spec.rb @@ -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 diff --git a/Library/Homebrew/test/cask/cli/edit_spec.rb b/Library/Homebrew/test/cask/cli/edit_spec.rb index 3475220205..90e6ad3c50 100644 --- a/Library/Homebrew/test/cask/cli/edit_spec.rb +++ b/Library/Homebrew/test/cask/cli/edit_spec.rb @@ -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 diff --git a/Library/Homebrew/test/cask/cli/info_spec.rb b/Library/Homebrew/test/cask/cli/info_spec.rb index 0fc751e06d..803204171f 100644 --- a/Library/Homebrew/test/cask/cli/info_spec.rb +++ b/Library/Homebrew/test/cask/cli/info_spec.rb @@ -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 diff --git a/Library/Homebrew/test/cask/cli/list_spec.rb b/Library/Homebrew/test/cask/cli/list_spec.rb index 98eb6a8dad..fc1ffb5e2d 100644 --- a/Library/Homebrew/test/cask/cli/list_spec.rb +++ b/Library/Homebrew/test/cask/cli/list_spec.rb @@ -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 diff --git a/Library/Homebrew/test/cask/cli/search_spec.rb b/Library/Homebrew/test/cask/cli/search_spec.rb index cd1a7bd43c..5d8ad30e4f 100644 --- a/Library/Homebrew/test/cask/cli/search_spec.rb +++ b/Library/Homebrew/test/cask/cli/search_spec.rb @@ -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 diff --git a/Library/Homebrew/test/cask/cli/style_spec.rb b/Library/Homebrew/test/cask/cli/style_spec.rb index 850f04f8d5..aaf3248f17 100644 --- a/Library/Homebrew/test/cask/cli/style_spec.rb +++ b/Library/Homebrew/test/cask/cli/style_spec.rb @@ -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 diff --git a/Library/Homebrew/test/cask/cli/uninstall_spec.rb b/Library/Homebrew/test/cask/cli/uninstall_spec.rb index 38ee1bb73a..6c0b785b5e 100644 --- a/Library/Homebrew/test/cask/cli/uninstall_spec.rb +++ b/Library/Homebrew/test/cask/cli/uninstall_spec.rb @@ -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| diff --git a/Library/Homebrew/test/cask/cli/upgrade_spec.rb b/Library/Homebrew/test/cask/cli/upgrade_spec.rb index af026157eb..912bb8541f 100644 --- a/Library/Homebrew/test/cask/cli/upgrade_spec.rb +++ b/Library/Homebrew/test/cask/cli/upgrade_spec.rb @@ -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 diff --git a/Library/Homebrew/test/cask/depends_on_spec.rb b/Library/Homebrew/test/cask/depends_on_spec.rb index 453a761f7e..85279f96c7 100644 --- a/Library/Homebrew/test/cask/depends_on_spec.rb +++ b/Library/Homebrew/test/cask/depends_on_spec.rb @@ -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 diff --git a/Library/Homebrew/test/cask/download_strategy_spec.rb b/Library/Homebrew/test/cask/download_strategy_spec.rb index 17da1e36e4..ed8cd01ef6 100644 --- a/Library/Homebrew/test/cask/download_strategy_spec.rb +++ b/Library/Homebrew/test/cask/download_strategy_spec.rb @@ -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 diff --git a/Library/Homebrew/test/cask/dsl/stanza_proxy_spec.rb b/Library/Homebrew/test/cask/dsl/stanza_proxy_spec.rb index 8949c5bd93..8c87d4706f 100644 --- a/Library/Homebrew/test/cask/dsl/stanza_proxy_spec.rb +++ b/Library/Homebrew/test/cask/dsl/stanza_proxy_spec.rb @@ -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) } diff --git a/Library/Homebrew/test/cask/dsl/version_spec.rb b/Library/Homebrew/test/cask/dsl/version_spec.rb index 480504483d..497b91aa41 100644 --- a/Library/Homebrew/test/cask/dsl/version_spec.rb +++ b/Library/Homebrew/test/cask/dsl/version_spec.rb @@ -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", diff --git a/Library/Homebrew/test/cask/dsl_spec.rb b/Library/Homebrew/test/cask/dsl_spec.rb index 993c03bac8..3e16b915ea 100644 --- a/Library/Homebrew/test/cask/dsl_spec.rb +++ b/Library/Homebrew/test/cask/dsl_spec.rb @@ -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 diff --git a/Library/Homebrew/test/cask/staged_spec.rb b/Library/Homebrew/test/cask/staged_spec.rb index 0229018c77..b6dfc73765 100644 --- a/Library/Homebrew/test/cask/staged_spec.rb +++ b/Library/Homebrew/test/cask/staged_spec.rb @@ -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") diff --git a/Library/Homebrew/test/cask/system_command_result_spec.rb b/Library/Homebrew/test/cask/system_command_result_spec.rb index d09f1220ce..18dd2d910d 100644 --- a/Library/Homebrew/test/cask/system_command_result_spec.rb +++ b/Library/Homebrew/test/cask/system_command_result_spec.rb @@ -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 diff --git a/Library/Homebrew/test/cask/verify_spec.rb b/Library/Homebrew/test/cask/verify_spec.rb index 5d95fb3a29..79b23a0e3c 100644 --- a/Library/Homebrew/test/cask/verify_spec.rb +++ b/Library/Homebrew/test/cask/verify_spec.rb @@ -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) diff --git a/Library/Homebrew/test/caveats_spec.rb b/Library/Homebrew/test/caveats_spec.rb index ec256f3e61..ad260aebe4 100644 --- a/Library/Homebrew/test/caveats_spec.rb +++ b/Library/Homebrew/test/caveats_spec.rb @@ -3,6 +3,7 @@ require "caveats" describe Caveats do subject { described_class.new(f) } + let(:f) { formula { url "foo-1.0" } } specify "#f" do diff --git a/Library/Homebrew/test/checksum_spec.rb b/Library/Homebrew/test/checksum_spec.rb index acab348b7e..89658c483a 100644 --- a/Library/Homebrew/test/checksum_spec.rb +++ b/Library/Homebrew/test/checksum_spec.rb @@ -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 diff --git a/Library/Homebrew/test/cleaner_spec.rb b/Library/Homebrew/test/cleaner_spec.rb index f6c6cb17b9..62e4c36620 100644 --- a/Library/Homebrew/test/cleaner_spec.rb +++ b/Library/Homebrew/test/cleaner_spec.rb @@ -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 diff --git a/Library/Homebrew/test/cleanup_spec.rb b/Library/Homebrew/test/cleanup_spec.rb index da262c5ca0..9ec3a30479 100644 --- a/Library/Homebrew/test/cleanup_spec.rb +++ b/Library/Homebrew/test/cleanup_spec.rb @@ -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 diff --git a/Library/Homebrew/test/cli_parser_spec.rb b/Library/Homebrew/test/cli_parser_spec.rb new file mode 100644 index 0000000000..037f007a27 --- /dev/null +++ b/Library/Homebrew/test/cli_parser_spec.rb @@ -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 diff --git a/Library/Homebrew/test/cmd/analytics_spec.rb b/Library/Homebrew/test/cmd/analytics_spec.rb index f29c2bb7fc..e2818bb300 100644 --- a/Library/Homebrew/test/cmd/analytics_spec.rb +++ b/Library/Homebrew/test/cmd/analytics_spec.rb @@ -1,5 +1,5 @@ describe "brew analytics", :integration_test do - before(:each) do + before do HOMEBREW_REPOSITORY.cd do system "git", "init" end diff --git a/Library/Homebrew/test/cmd/commands_spec.rb b/Library/Homebrew/test/cmd/commands_spec.rb index 46ed3ddcfe..07844087f0 100644 --- a/Library/Homebrew/test/cmd/commands_spec.rb +++ b/Library/Homebrew/test/cmd/commands_spec.rb @@ -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 diff --git a/Library/Homebrew/test/cmd/migrate_spec.rb b/Library/Homebrew/test/cmd/migrate_spec.rb index 83dee0cb65..6b9bf07929 100644 --- a/Library/Homebrew/test/cmd/migrate_spec.rb +++ b/Library/Homebrew/test/cmd/migrate_spec.rb @@ -1,5 +1,5 @@ describe "brew migrate", :integration_test do - before(:each) do + before do setup_test_formula "testball1" setup_test_formula "testball2" end diff --git a/Library/Homebrew/test/cmd/missing_spec.rb b/Library/Homebrew/test/cmd/missing_spec.rb index 4668e72e03..f84dd66567 100644 --- a/Library/Homebrew/test/cmd/missing_spec.rb +++ b/Library/Homebrew/test/cmd/missing_spec.rb @@ -1,5 +1,5 @@ describe "brew missing", :integration_test do - before(:each) do + before do setup_test_formula "foo" setup_test_formula "bar" end diff --git a/Library/Homebrew/test/cmd/pin_spec.rb b/Library/Homebrew/test/cmd/pin_spec.rb index a8f680d717..9f2dad8a3d 100644 --- a/Library/Homebrew/test/cmd/pin_spec.rb +++ b/Library/Homebrew/test/cmd/pin_spec.rb @@ -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 diff --git a/Library/Homebrew/test/cmd/reinstall_spec.rb b/Library/Homebrew/test/cmd/reinstall_spec.rb index f5794049d4..317199fb0d 100644 --- a/Library/Homebrew/test/cmd/reinstall_spec.rb +++ b/Library/Homebrew/test/cmd/reinstall_spec.rb @@ -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 diff --git a/Library/Homebrew/test/cmd/search_spec.rb b/Library/Homebrew/test/cmd/search_spec.rb index aec23ae4c1..c55a51e4fe 100644 --- a/Library/Homebrew/test/cmd/search_spec.rb +++ b/Library/Homebrew/test/cmd/search_spec.rb @@ -1,5 +1,5 @@ describe "brew search", :integration_test do - before(:each) do + before do setup_test_formula "testball" setup_remote_tap "caskroom/cask" end diff --git a/Library/Homebrew/test/cmd/style_spec.rb b/Library/Homebrew/test/cmd/style_spec.rb index 5c118f32ec..ec0eccdff1 100644 --- a/Library/Homebrew/test/cmd/style_spec.rb +++ b/Library/Homebrew/test/cmd/style_spec.rb @@ -1,7 +1,7 @@ require "cmd/style" describe "brew style" do - around(:each) do |example| + around do |example| begin FileUtils.ln_s HOMEBREW_LIBRARY_PATH, HOMEBREW_LIBRARY/"Homebrew" FileUtils.ln_s HOMEBREW_LIBRARY_PATH.parent/".rubocop.yml", HOMEBREW_LIBRARY/".rubocop_audit.yml" diff --git a/Library/Homebrew/test/cmd/uninstall_spec.rb b/Library/Homebrew/test/cmd/uninstall_spec.rb index 27ab0e1f75..b944062109 100644 --- a/Library/Homebrew/test/cmd/uninstall_spec.rb +++ b/Library/Homebrew/test/cmd/uninstall_spec.rb @@ -22,7 +22,7 @@ describe Homebrew do let(:opts) { { dependency.rack => [Keg.new(dependency.installed_prefix)] } } - before(:each) do + before do [dependency, dependent].each do |f| f.installed_prefix.mkpath Keg.new(f.installed_prefix).optlink diff --git a/Library/Homebrew/test/cmd/update-report_spec.rb b/Library/Homebrew/test/cmd/update-report_spec.rb index 3665e3c78b..b98ff49916 100644 --- a/Library/Homebrew/test/cmd/update-report_spec.rb +++ b/Library/Homebrew/test/cmd/update-report_spec.rb @@ -13,6 +13,8 @@ describe Reporter do hub.add(subject) if subject.updated? end + subject { reporter_class.new(tap) } + let(:reporter_class) do Class.new(described_class) do def initialize(tap) @@ -25,7 +27,7 @@ describe Reporter do end end end - subject { reporter_class.new(tap) } + let(:tap) { CoreTap.new } let(:hub) { ReporterHub.new } @@ -83,11 +85,11 @@ describe Reporter do context "when updating a Tap other than the core Tap" do let(:tap) { Tap.new("foo", "bar") } - before(:each) do + before do (tap.path/"Formula").mkpath end - after(:each) do + after do tap.path.parent.rmtree end diff --git a/Library/Homebrew/test/compiler_selector_spec.rb b/Library/Homebrew/test/compiler_selector_spec.rb index 18efbfd424..aa8983c5ca 100644 --- a/Library/Homebrew/test/compiler_selector_spec.rb +++ b/Library/Homebrew/test/compiler_selector_spec.rb @@ -3,6 +3,7 @@ require "software_spec" describe CompilerSelector do subject { described_class.new(software_spec, versions, compilers) } + let(:compilers) { [:clang, :gcc, :gnu] } let(:software_spec) { SoftwareSpec.new } let(:cc) { :clang } @@ -15,7 +16,7 @@ describe CompilerSelector do ) end - before(:each) do + before do allow(versions).to receive(:non_apple_gcc_version) do |name| case name when "gcc-4.8" then Version.create("4.8.1") diff --git a/Library/Homebrew/test/cxxstdlib_spec.rb b/Library/Homebrew/test/cxxstdlib_spec.rb index dd2e4e1c69..4b2091b3b1 100644 --- a/Library/Homebrew/test/cxxstdlib_spec.rb +++ b/Library/Homebrew/test/cxxstdlib_spec.rb @@ -2,14 +2,14 @@ require "formula" require "cxxstdlib" describe CxxStdlib do - let(:clang) { CxxStdlib.create(:libstdcxx, :clang) } - let(:gcc) { CxxStdlib.create(:libstdcxx, :gcc) } - let(:gcc40) { CxxStdlib.create(:libstdcxx, :gcc_4_0) } - let(:gcc42) { CxxStdlib.create(:libstdcxx, :gcc_4_2) } - let(:gcc48) { CxxStdlib.create(:libstdcxx, "gcc-4.8") } - let(:gcc49) { CxxStdlib.create(:libstdcxx, "gcc-4.9") } - let(:lcxx) { CxxStdlib.create(:libcxx, :clang) } - let(:purec) { CxxStdlib.create(nil, :clang) } + let(:clang) { described_class.create(:libstdcxx, :clang) } + let(:gcc) { described_class.create(:libstdcxx, :gcc) } + let(:gcc40) { described_class.create(:libstdcxx, :gcc_4_0) } + let(:gcc42) { described_class.create(:libstdcxx, :gcc_4_2) } + let(:gcc48) { described_class.create(:libstdcxx, "gcc-4.8") } + let(:gcc49) { described_class.create(:libstdcxx, "gcc-4.9") } + let(:lcxx) { described_class.create(:libcxx, :clang) } + let(:purec) { described_class.create(nil, :clang) } describe "#compatible_with?" do specify "Apple libstdcxx intercompatibility" do diff --git a/Library/Homebrew/test/dependable_spec.rb b/Library/Homebrew/test/dependable_spec.rb index 172305aa0e..8ffc2506c7 100644 --- a/Library/Homebrew/test/dependable_spec.rb +++ b/Library/Homebrew/test/dependable_spec.rb @@ -4,6 +4,7 @@ describe Dependable do alias_matcher :be_a_build_dependency, :be_build subject { double(tags: tags).extend(described_class) } + let(:tags) { ["foo", "bar", :build] } specify "#options" do diff --git a/Library/Homebrew/test/dependencies_spec.rb b/Library/Homebrew/test/dependencies_spec.rb index 84ea531819..ed86cb630f 100644 --- a/Library/Homebrew/test/dependencies_spec.rb +++ b/Library/Homebrew/test/dependencies_spec.rb @@ -53,8 +53,8 @@ describe Dependencies do end specify "equality" do - a = Dependencies.new - b = Dependencies.new + a = described_class.new + b = described_class.new dep = Dependency.new("foo") diff --git a/Library/Homebrew/test/dependency_collector_spec.rb b/Library/Homebrew/test/dependency_collector_spec.rb index 46e859b2d8..7c37ba706a 100644 --- a/Library/Homebrew/test/dependency_collector_spec.rb +++ b/Library/Homebrew/test/dependency_collector_spec.rb @@ -11,7 +11,7 @@ describe DependencyCollector do subject.requirements.find { |req| req.is_a? klass } end - after(:each) do + after do described_class.clear_cache end @@ -51,7 +51,7 @@ describe DependencyCollector do specify "x11 with (ignored) minimum version" do subject.add x11: "2.5.1" - expect(find_requirement(X11Requirement).min_version.to_s).to_not eq("2.5.1") + expect(find_requirement(X11Requirement).min_version.to_s).not_to eq("2.5.1") end specify "x11 with tag" do @@ -62,7 +62,7 @@ describe DependencyCollector do specify "x11 with (ignored) minimum version and tag" do subject.add x11: ["2.5.1", :optional] dep = find_requirement(X11Requirement) - expect(dep.min_version.to_s).to_not eq("2.5.1") + expect(dep.min_version.to_s).not_to eq("2.5.1") expect(dep).to be_optional end diff --git a/Library/Homebrew/test/dependency_expansion_spec.rb b/Library/Homebrew/test/dependency_expansion_spec.rb index d6ecdf5527..16c37b9312 100644 --- a/Library/Homebrew/test/dependency_expansion_spec.rb +++ b/Library/Homebrew/test/dependency_expansion_spec.rb @@ -102,12 +102,12 @@ describe Dependency do end it "keeps dependency but prunes recursive dependencies with ::keep_but_prune_recursive_deps" do - foo = build_dep(:foo, [:build], bar) - baz = build_dep(:baz, [:build]) + foo = build_dep(:foo, [:test], bar) + baz = build_dep(:baz, [:test]) f = double(name: "f", deps: [foo, baz]) deps = described_class.expand(f) do |_dependent, dep| - described_class.keep_but_prune_recursive_deps if dep.build? + described_class.keep_but_prune_recursive_deps if dep.test? end expect(deps).to eq([foo, baz]) diff --git a/Library/Homebrew/test/dependency_spec.rb b/Library/Homebrew/test/dependency_spec.rb index 4f1e8d474c..6ac2acca2c 100644 --- a/Library/Homebrew/test/dependency_spec.rb +++ b/Library/Homebrew/test/dependency_spec.rb @@ -2,7 +2,6 @@ require "dependency" describe Dependency do alias_matcher :be_a_build_dependency, :be_build - alias_matcher :be_a_runtime_dependency, :be_run describe "::new" do it "accepts a single tag" do @@ -73,22 +72,10 @@ describe Dependency do it "merges temporality tags" do normal_dep = described_class.new("foo") build_dep = described_class.new("foo", [:build]) - run_dep = described_class.new("foo", [:run]) deps = described_class.merge_repeats([normal_dep, build_dep]) expect(deps.count).to eq(1) expect(deps.first).not_to be_a_build_dependency - expect(deps.first).not_to be_a_runtime_dependency - - deps = described_class.merge_repeats([normal_dep, run_dep]) - expect(deps.count).to eq(1) - expect(deps.first).not_to be_a_build_dependency - expect(deps.first).not_to be_a_runtime_dependency - - deps = described_class.merge_repeats([build_dep, run_dep]) - expect(deps.count).to eq(1) - expect(deps.first).not_to be_a_build_dependency - expect(deps.first).not_to be_a_runtime_dependency end end diff --git a/Library/Homebrew/test/deps_spec.rb b/Library/Homebrew/test/deps_spec.rb index f0ec514d91..d3330b6c40 100644 --- a/Library/Homebrew/test/deps_spec.rb +++ b/Library/Homebrew/test/deps_spec.rb @@ -1,5 +1,5 @@ describe "brew deps", :integration_test do - before(:each) do + before do setup_test_formula "foo" setup_test_formula "bar" setup_test_formula "baz", <<~EOS diff --git a/Library/Homebrew/test/descriptions_spec.rb b/Library/Homebrew/test/descriptions_spec.rb index c4f67cc4cf..7374068414 100644 --- a/Library/Homebrew/test/descriptions_spec.rb +++ b/Library/Homebrew/test/descriptions_spec.rb @@ -2,6 +2,7 @@ require "descriptions" describe Descriptions do subject { described_class.new(descriptions_hash) } + let(:descriptions_hash) { {} } it "can print description for a core Formula" do diff --git a/Library/Homebrew/test/dev-cmd/audit_spec.rb b/Library/Homebrew/test/dev-cmd/audit_spec.rb index 38884222d0..c9264f22b5 100644 --- a/Library/Homebrew/test/dev-cmd/audit_spec.rb +++ b/Library/Homebrew/test/dev-cmd/audit_spec.rb @@ -220,6 +220,8 @@ describe FormulaAuditor do describe "#audit_deps" do describe "a dependency on a macOS-provided keg-only formula" do describe "which is whitelisted" do + subject { fa } + let(:fa) do formula_auditor "foo", <<~EOS, new_formula: true class Foo < Formula @@ -246,12 +248,12 @@ describe FormulaAuditor do fa.audit_deps end - subject { fa } - its(:problems) { are_expected.to be_empty } end describe "which is not whitelisted" do + subject { fa } + let(:fa) do formula_auditor "foo", <<~EOS, new_formula: true class Foo < Formula @@ -278,8 +280,6 @@ describe FormulaAuditor do fa.audit_deps end - subject { fa } - its(:problems) { are_expected.to match([/unnecessary/]) } end end @@ -349,13 +349,19 @@ describe FormulaAuditor do end describe "#audit_revision_and_version_scheme" do + subject do + fa = described_class.new(Formulary.factory(formula_path)) + fa.audit_revision_and_version_scheme + fa.problems.first + end + let(:origin_tap_path) { Tap::TAP_DIRECTORY/"homebrew/homebrew-foo" } let(:formula_subpath) { "Formula/foo#{@foo_version}.rb" } let(:origin_formula_path) { origin_tap_path/formula_subpath } let(:tap_path) { Tap::TAP_DIRECTORY/"homebrew/homebrew-bar" } let(:formula_path) { tap_path/formula_subpath } - before(:each) do + before do @foo_version = Count.increment origin_formula_path.write <<~EOS @@ -379,12 +385,6 @@ describe FormulaAuditor do end end - subject do - fa = described_class.new(Formulary.factory(formula_path)) - fa.audit_revision_and_version_scheme - fa.problems.first - end - def formula_gsub(before, after = "") text = formula_path.read text.gsub! before, after diff --git a/Library/Homebrew/test/download_strategies_spec.rb b/Library/Homebrew/test/download_strategies_spec.rb index f1c64db717..08bbb58e89 100644 --- a/Library/Homebrew/test/download_strategies_spec.rb +++ b/Library/Homebrew/test/download_strategies_spec.rb @@ -2,9 +2,11 @@ require "download_strategy" describe AbstractDownloadStrategy do subject { described_class.new(name, resource) } + + let(:specs) { {} } let(:name) { "foo" } let(:url) { "http://example.com/foo.tar.gz" } - let(:resource) { double(Resource, url: url, mirrors: [], specs: {}, version: nil) } + let(:resource) { double(Resource, url: url, mirrors: [], specs: specs, version: nil) } let(:args) { %w[foo bar baz] } describe "#expand_safe_system_args" do @@ -34,6 +36,20 @@ describe AbstractDownloadStrategy do expect(subject.source_modified_time).to eq(File.mtime("foo")) end end + + context "when specs[:bottle]" do + let(:specs) { { bottle: true } } + + it "extends Pourable" do + expect(subject).to be_a_kind_of(AbstractDownloadStrategy::Pourable) + end + end + + context "without specs[:bottle]" do + it "is does not extend Pourable" do + expect(subject).not_to be_a_kind_of(AbstractDownloadStrategy::Pourable) + end + end end describe VCSDownloadStrategy do @@ -51,10 +67,11 @@ end describe GitHubPrivateRepositoryDownloadStrategy do subject { described_class.new("foo", resource) } + let(:url) { "https://github.com/owner/repo/archive/1.1.5.tar.gz" } let(:resource) { double(Resource, url: url, mirrors: [], specs: {}, version: nil) } - before(:each) do + before do ENV["HOMEBREW_GITHUB_API_TOKEN"] = "token" allow(GitHub).to receive(:repository).and_return({}) end @@ -74,10 +91,11 @@ end describe GitHubPrivateRepositoryReleaseDownloadStrategy do subject { described_class.new("foo", resource) } + let(:url) { "https://github.com/owner/repo/releases/download/tag/foo_v0.1.0_darwin_amd64.tar.gz" } let(:resource) { double(Resource, url: url, mirrors: [], specs: {}, version: nil) } - before(:each) do + before do ENV["HOMEBREW_GITHUB_API_TOKEN"] = "token" allow(GitHub).to receive(:repository).and_return({}) end @@ -124,6 +142,7 @@ end describe GitHubGitDownloadStrategy do subject { described_class.new(name, resource) } + let(:name) { "brew" } let(:url) { "https://github.com/homebrew/brew.git" } let(:resource) { double(Resource, url: url, mirrors: [], specs: {}, version: nil) } @@ -136,12 +155,13 @@ end describe GitDownloadStrategy do subject { described_class.new(name, resource) } + let(:name) { "baz" } let(:url) { "https://github.com/homebrew/foo" } let(:resource) { double(Resource, url: url, mirrors: [], specs: {}, version: nil) } let(:cached_location) { subject.cached_location } - before(:each) do + before do @commit_id = 1 FileUtils.mkpath cached_location end @@ -183,9 +203,9 @@ describe GitDownloadStrategy do let(:resource) { double(Resource, url: url, mirrors: [], specs: {}, version: version) } let(:remote_repo) { HOMEBREW_PREFIX/"remote_repo" } - before(:each) { remote_repo.mkpath } + before { remote_repo.mkpath } - after(:each) { FileUtils.rm_rf remote_repo } + after { FileUtils.rm_rf remote_repo } it "fetches the hash of the last commit" do remote_repo.cd do @@ -200,8 +220,31 @@ describe GitDownloadStrategy do end end +describe S3DownloadStrategy do + subject { described_class.new(name, resource) } + + let(:name) { "foo" } + let(:url) { "http://bucket.s3.amazonaws.com/foo.tar.gz" } + let(:resource) { double(Resource, url: url, mirrors: [], specs: {}, version: nil) } + + describe "#_fetch" do + subject { described_class.new(name, resource)._fetch } + + context "when given Bad S3 URL" do + let(:url) { "http://example.com/foo.tar.gz" } + + it "raises Bad S3 URL error" do + expect { + subject._fetch + }.to raise_error(RuntimeError) + end + end + end +end + describe CurlDownloadStrategy do subject { described_class.new(name, resource) } + let(:name) { "foo" } let(:url) { "http://example.com/foo.tar.gz" } let(:resource) { double(Resource, url: url, mirrors: [], specs: { user: "download:123456" }, version: nil) } @@ -219,6 +262,7 @@ describe CurlDownloadStrategy do context "when URL file is in middle" do let(:url) { "http://example.com/foo.tar.gz/from/this/mirror" } + it { is_expected.to eq(HOMEBREW_CACHE/"foo-.tar.gz") } end end @@ -226,19 +270,42 @@ end describe DownloadStrategyDetector do describe "::detect" do - subject { described_class.detect(url) } + subject { described_class.detect(url, strategy) } + let(:url) { Object.new } + let(:strategy) { nil } context "when given Git URL" do let(:url) { "git://example.com/foo.git" } + it { is_expected.to eq(GitDownloadStrategy) } end context "when given a GitHub Git URL" do let(:url) { "https://github.com/homebrew/brew.git" } + it { is_expected.to eq(GitHubGitDownloadStrategy) } end + context "when given an S3 URL" do + let(:url) { "s3://bucket/homebrew/brew.tar.gz" } + + it "returns S3DownloadStrategy" do + allow(described_class).to receive(:require_aws_sdk).and_return(true) + is_expected.to eq(S3DownloadStrategy) + end + end + + context "when given strategy = S3DownloadStrategy" do + let(:url) { "https://bkt.s3.amazonaws.com/key.tar.gz" } + let(:strategy) { S3DownloadStrategy } + + it "requires aws-sdk-s3" do + allow(described_class).to receive(:require_aws_sdk).and_return(true) + is_expected.to eq(S3DownloadStrategy) + end + end + it "defaults to cURL" do expect(subject).to eq(CurlDownloadStrategy) end diff --git a/Library/Homebrew/test/emoji_spec.rb b/Library/Homebrew/test/emoji_spec.rb index d6341968e9..371960ebc2 100644 --- a/Library/Homebrew/test/emoji_spec.rb +++ b/Library/Homebrew/test/emoji_spec.rb @@ -4,7 +4,7 @@ describe Emoji do describe "#install_badge" do subject { described_class.install_badge } - before(:each) do + before do ENV.delete("HOMEBREW_NO_EMOJI") ENV.delete("HOMEBREW_INSTALL_BADGE") end diff --git a/Library/Homebrew/test/exceptions_spec.rb b/Library/Homebrew/test/exceptions_spec.rb index 0a8313355f..1a09693a22 100644 --- a/Library/Homebrew/test/exceptions_spec.rb +++ b/Library/Homebrew/test/exceptions_spec.rb @@ -2,16 +2,19 @@ require "exceptions" describe MultipleVersionsInstalledError do subject { described_class.new("foo") } + its(:to_s) { is_expected.to eq("foo has multiple installed versions") } end describe NoSuchKegError do subject { described_class.new("foo") } + its(:to_s) { is_expected.to eq("No such keg: #{HOMEBREW_CELLAR}/foo") } end describe FormulaValidationError do subject { described_class.new("foo", "sha257", "magic") } + its(:to_s) { is_expected.to eq(%q(invalid attribute for formula 'foo': sha257 ("magic"))) } @@ -41,7 +44,7 @@ describe FormulaUnavailableError do end context "with a dependent" do - before(:each) do + before do subject.dependent = "foobar" end @@ -53,12 +56,15 @@ end describe TapFormulaUnavailableError do subject { described_class.new(tap, "foo") } + let(:tap) { double(Tap, user: "u", repo: "r", to_s: "u/r", installed?: false) } + its(:to_s) { is_expected.to match(%r{Please tap it and then try again: brew tap u/r}) } end describe FormulaClassUnavailableError do subject { described_class.new("foo", "foo.rb", "Foo", list) } + let(:mod) do Module.new do class Bar < Requirement; end @@ -68,6 +74,7 @@ describe FormulaClassUnavailableError do context "no classes" do let(:list) { [] } + its(:to_s) { is_expected.to match(/Expected to find class Foo, but found no classes\./) } @@ -75,6 +82,7 @@ describe FormulaClassUnavailableError do context "class not derived from Formula" do let(:list) { [mod.const_get(:Bar)] } + its(:to_s) { is_expected.to match(/Expected to find class Foo, but only found: Bar \(not derived from Formula!\)\./) } @@ -82,107 +90,134 @@ describe FormulaClassUnavailableError do context "class derived from Formula" do let(:list) { [mod.const_get(:Baz)] } + its(:to_s) { is_expected.to match(/Expected to find class Foo, but only found: Baz\./) } end end describe FormulaUnreadableError do subject { described_class.new("foo", formula_error) } + let(:formula_error) { LoadError.new("bar") } + its(:to_s) { is_expected.to eq("foo: bar") } end describe TapUnavailableError do subject { described_class.new("foo") } + its(:to_s) { is_expected.to eq("No available tap foo.\n") } end describe TapAlreadyTappedError do subject { described_class.new("foo") } + its(:to_s) { is_expected.to eq("Tap foo already tapped.\n") } end describe TapPinStatusError do context "pinned" do subject { described_class.new("foo", true) } + its(:to_s) { is_expected.to eq("foo is already pinned.") } end context "unpinned" do subject { described_class.new("foo", false) } + its(:to_s) { is_expected.to eq("foo is already unpinned.") } end end describe BuildError do subject { described_class.new(formula, "badprg", %w[arg1 arg2], {}) } + let(:formula) { double(Formula, name: "foo") } + its(:to_s) { is_expected.to eq("Failed executing: badprg arg1 arg2") } end describe OperationInProgressError do subject { described_class.new("foo") } + its(:to_s) { is_expected.to match(/Operation already in progress for foo/) } end describe FormulaInstallationAlreadyAttemptedError do subject { described_class.new(formula) } + let(:formula) { double(Formula, full_name: "foo/bar") } + its(:to_s) { is_expected.to eq("Formula installation already attempted: foo/bar") } end describe FormulaConflictError do subject { described_class.new(formula, [conflict]) } + let(:formula) { double(Formula, full_name: "foo/qux") } let(:conflict) { double(name: "bar", reason: "I decided to") } + its(:to_s) { is_expected.to match(/Please `brew unlink bar` before continuing\./) } end describe CompilerSelectionError do subject { described_class.new(formula) } + let(:formula) { double(Formula, full_name: "foo") } + its(:to_s) { is_expected.to match(/foo cannot be built with any available compilers\./) } end describe CurlDownloadStrategyError do context "file does not exist" do subject { described_class.new("file:///tmp/foo") } + its(:to_s) { is_expected.to eq("File does not exist: /tmp/foo") } end context "download failed" do subject { described_class.new("http://brew.sh") } + its(:to_s) { is_expected.to eq("Download failed: http://brew.sh") } end end describe ErrorDuringExecution do subject { described_class.new("badprg", %w[arg1 arg2]) } + its(:to_s) { is_expected.to eq("Failure while executing: badprg arg1 arg2") } end describe ChecksumMismatchError do subject { described_class.new("/file.tar.gz", hash1, hash2) } + let(:hash1) { double(hash_type: "sha256", to_s: "deadbeef") } let(:hash2) { double(hash_type: "sha256", to_s: "deadcafe") } + its(:to_s) { is_expected.to match(/SHA256 mismatch/) } end describe ResourceMissingError do subject { described_class.new(formula, resource) } + let(:formula) { double(Formula, full_name: "bar") } let(:resource) { double(inspect: "") } + its(:to_s) { is_expected.to eq("bar does not define resource ") } end describe DuplicateResourceError do subject { described_class.new(resource) } + let(:resource) { double(inspect: "") } + its(:to_s) { is_expected.to eq("Resource is defined more than once") } end describe BottleFormulaUnavailableError do subject { described_class.new("/foo.bottle.tar.gz", "foo/1.0/.brew/foo.rb") } + let(:formula) { double(Formula, full_name: "foo") } + its(:to_s) { is_expected.to match(/This bottle does not contain the formula file/) } end diff --git a/Library/Homebrew/test/formatter_spec.rb b/Library/Homebrew/test/formatter_spec.rb index 1a74e3405a..14c63b8c3a 100644 --- a/Library/Homebrew/test/formatter_spec.rb +++ b/Library/Homebrew/test/formatter_spec.rb @@ -3,6 +3,8 @@ require "utils/tty" describe Formatter do describe "::columns" do + subject { described_class.columns(input) } + let(:input) { %w[ aa @@ -11,7 +13,6 @@ describe Formatter do dd ] } - subject { described_class.columns(input) } it "doesn't output columns if $stdout is not a TTY." do allow_any_instance_of(IO).to receive(:tty?).and_return(false) diff --git a/Library/Homebrew/test/formula_installer_bottle_spec.rb b/Library/Homebrew/test/formula_installer_bottle_spec.rb index 6d9e27daa5..5ba7afb4c1 100644 --- a/Library/Homebrew/test/formula_installer_bottle_spec.rb +++ b/Library/Homebrew/test/formula_installer_bottle_spec.rb @@ -71,7 +71,7 @@ describe FormulaInstaller do expect(formula).not_to be_bottled expect { - FormulaInstaller.new(formula).install + described_class.new(formula).install }.to raise_error(BuildToolsError) expect(formula).not_to be_installed diff --git a/Library/Homebrew/test/formula_installer_spec.rb b/Library/Homebrew/test/formula_installer_spec.rb index 93f23b18ff..e9d07b05a1 100644 --- a/Library/Homebrew/test/formula_installer_spec.rb +++ b/Library/Homebrew/test/formula_installer_spec.rb @@ -126,7 +126,7 @@ describe FormulaInstaller do expect(dependency_keg).to be_linked expect(dependency).to be_pinned - fi = FormulaInstaller.new(dependent) + fi = described_class.new(dependent) expect { fi.check_install_sanity diff --git a/Library/Homebrew/test/formula_pin_spec.rb b/Library/Homebrew/test/formula_pin_spec.rb index ce952a9574..b06c5eff95 100644 --- a/Library/Homebrew/test/formula_pin_spec.rb +++ b/Library/Homebrew/test/formula_pin_spec.rb @@ -2,10 +2,11 @@ require "formula_pin" describe FormulaPin do subject { described_class.new(formula) } + let(:name) { "double" } let(:formula) { double(Formula, name: name, rack: HOMEBREW_CELLAR/name) } - before(:each) do + before do formula.rack.mkpath allow(formula).to receive(:installed_prefixes) do diff --git a/Library/Homebrew/test/formula_spec.rb b/Library/Homebrew/test/formula_spec.rb index 865ea38361..0680644c88 100644 --- a/Library/Homebrew/test/formula_spec.rb +++ b/Library/Homebrew/test/formula_spec.rb @@ -923,7 +923,7 @@ describe Formula do let(:tab) { Tab.empty } let(:alias_path) { "#{CoreTap.instance.alias_dir}/bar" } - before(:each) do + before do allow(described_class).to receive(:installed).and_return([f]) f.build = tab diff --git a/Library/Homebrew/test/formula_support_spec.rb b/Library/Homebrew/test/formula_support_spec.rb index 7239ef352a..f73d97cece 100644 --- a/Library/Homebrew/test/formula_support_spec.rb +++ b/Library/Homebrew/test/formula_support_spec.rb @@ -3,17 +3,17 @@ require "formula_support" describe KegOnlyReason do describe "#to_s" do it "returns the reason provided" do - r = KegOnlyReason.new :provided_by_macos, "test" + r = described_class.new :provided_by_macos, "test" expect(r.to_s).to eq("test") end it "returns a default message when no reason is provided" do - r = KegOnlyReason.new :provided_by_macos, "" + r = described_class.new :provided_by_macos, "" expect(r.to_s).to match(/^macOS already provides/) end it "is deprecated when reason mentions 'osx'", :needs_compat do - r = KegOnlyReason.new :provided_by_osx, "test" + r = described_class.new :provided_by_osx, "test" expect(r).to receive(:odeprecated) r.to_s end @@ -22,13 +22,13 @@ end describe BottleDisableReason do specify ":unneeded" do - bottle_disable_reason = BottleDisableReason.new :unneeded, nil + bottle_disable_reason = described_class.new :unneeded, nil expect(bottle_disable_reason).to be_unneeded expect(bottle_disable_reason.to_s).to eq("This formula doesn't require compiling.") end specify ":disabled" do - bottle_disable_reason = BottleDisableReason.new :disable, "reason" + bottle_disable_reason = described_class.new :disable, "reason" expect(bottle_disable_reason).not_to be_unneeded expect(bottle_disable_reason.to_s).to eq("reason") end diff --git a/Library/Homebrew/test/formulary_spec.rb b/Library/Homebrew/test/formulary_spec.rb index f091fdd03d..87124c60ce 100644 --- a/Library/Homebrew/test/formulary_spec.rb +++ b/Library/Homebrew/test/formulary_spec.rb @@ -45,7 +45,7 @@ describe Formulary do end describe "::factory" do - before(:each) do + before do formula_path.write formula_content end @@ -185,7 +185,7 @@ describe Formulary do let(:tap) { Tap.new("homebrew", "foo") } let(:tap_path) { tap.path/"#{formula_name}.rb" } - before(:each) do + before do core_path.write formula_content tap_path.write formula_content end diff --git a/Library/Homebrew/test/inreplace_spec.rb b/Library/Homebrew/test/inreplace_spec.rb index 330943be45..414d785186 100644 --- a/Library/Homebrew/test/inreplace_spec.rb +++ b/Library/Homebrew/test/inreplace_spec.rb @@ -216,7 +216,7 @@ end describe Utils::Inreplace do let(:file) { Tempfile.new("test") } - before(:each) do + before do file.write <<~EOS a b @@ -224,7 +224,7 @@ describe Utils::Inreplace do EOS end - after(:each) { file.unlink } + after { file.unlink } it "raises error if there is nothing to replace" do expect { diff --git a/Library/Homebrew/test/java_requirement_spec.rb b/Library/Homebrew/test/java_requirement_spec.rb index 685e250e08..433d41bb7d 100644 --- a/Library/Homebrew/test/java_requirement_spec.rb +++ b/Library/Homebrew/test/java_requirement_spec.rb @@ -3,7 +3,7 @@ require "requirements/java_requirement" describe JavaRequirement do subject { described_class.new([]) } - before(:each) do + before do ENV["JAVA_HOME"] = nil end @@ -13,6 +13,7 @@ describe JavaRequirement do describe "#inspect" do subject { described_class.new(%w[1.7+]) } + its(:inspect) { is_expected.to eq('#') } end @@ -23,11 +24,13 @@ describe JavaRequirement do context "with version 1.8" do subject { described_class.new(%w[1.8]) } + its(:display_s) { is_expected.to eq("java = 1.8") } end context "with version 1.8+" do subject { described_class.new(%w[1.8+]) } + its(:display_s) { is_expected.to eq("java >= 1.8") } end end @@ -57,7 +60,7 @@ describe JavaRequirement do FileUtils.chmod "+x", java end - before(:each) do + before do allow(subject).to receive(:possible_javas).and_return([java]) end diff --git a/Library/Homebrew/test/keg_spec.rb b/Library/Homebrew/test/keg_spec.rb index 3bf1257e65..b2ca62cff9 100644 --- a/Library/Homebrew/test/keg_spec.rb +++ b/Library/Homebrew/test/keg_spec.rb @@ -17,7 +17,7 @@ describe Keg do keg end - around(:each) do |example| + around do |example| begin @old_stdout = $stdout $stdout = StringIO.new @@ -34,12 +34,12 @@ describe Keg do let!(:keg) { setup_test_keg("foo", "1.0") } let(:kegs) { [] } - before(:each) do + before do (HOMEBREW_PREFIX/"bin").mkpath (HOMEBREW_PREFIX/"lib").mkpath end - after(:each) do + after do kegs.each(&:unlink) rmtree HOMEBREW_PREFIX/"lib" end @@ -345,7 +345,7 @@ describe Keg do keg end - before(:each) do + before do keg.link end @@ -373,29 +373,13 @@ describe Keg do let(:dependent) { setup_test_keg("bar", "1.0") } - # Test with a keg whose formula isn't known. - # This can happen if e.g. a formula is installed - # from a file path or URL. - specify "unknown Formula" do - allow(Formulary).to receive(:loader_for).and_call_original - alter_tab(keg) do |t| - t.source["tap"] = "some/tap" - t.source["path"] = nil - end - - dependencies [{ "full_name" => "some/tap/foo", "version" => "1.0" }] - expect(keg.installed_dependents).to eq([dependent]) - expect(described_class.find_some_installed_dependents([keg])).to eq([[keg], ["bar 1.0"]]) - - dependencies nil - # It doesn't make sense for a keg with no formula to have any dependents, - # so that can't really be tested. - expect(described_class.find_some_installed_dependents([keg])).to be nil - end - specify "a dependency with no Tap in Tab" do tap_dep = setup_test_keg("baz", "1.0") + # allow tap_dep to be linked too + FileUtils.rm_r tap_dep/"bin" + tap_dep.link + alter_tab(keg) { |t| t.source["tap"] = nil } dependencies nil @@ -408,21 +392,18 @@ describe Keg do specify "no dependencies anywhere" do dependencies nil - expect(keg.installed_dependents).to be_empty expect(described_class.find_some_installed_dependents([keg])).to be nil end specify "missing Formula dependency" do dependencies nil Formula["bar"].class.depends_on "foo" - expect(keg.installed_dependents).to be_empty expect(described_class.find_some_installed_dependents([keg])).to eq([[keg], ["bar"]]) end specify "uninstalling dependent and dependency" do dependencies nil Formula["bar"].class.depends_on "foo" - expect(keg.installed_dependents).to be_empty expect(described_class.find_some_installed_dependents([keg, dependent])).to be nil end @@ -442,40 +423,34 @@ describe Keg do specify "empty dependencies in Tab" do dependencies [] - expect(keg.installed_dependents).to be_empty expect(described_class.find_some_installed_dependents([keg])).to be nil end specify "same name but different version in Tab" do dependencies [{ "full_name" => "foo", "version" => "1.1" }] - expect(keg.installed_dependents).to eq([dependent]) - expect(described_class.find_some_installed_dependents([keg])).to eq([[keg], ["bar 1.0"]]) + expect(described_class.find_some_installed_dependents([keg])).to eq([[keg], ["bar"]]) end specify "different name and same version in Tab" do stub_formula_name("baz") dependencies [{ "full_name" => "baz", "version" => keg.version.to_s }] - expect(keg.installed_dependents).to be_empty expect(described_class.find_some_installed_dependents([keg])).to be nil end specify "same name and version in Tab" do dependencies [{ "full_name" => "foo", "version" => "1.0" }] - expect(keg.installed_dependents).to eq([dependent]) - expect(described_class.find_some_installed_dependents([keg])).to eq([[keg], ["bar 1.0"]]) + expect(described_class.find_some_installed_dependents([keg])).to eq([[keg], ["bar"]]) end specify "fallback for old versions" do unreliable_dependencies [{ "full_name" => "baz", "version" => "1.0" }] Formula["bar"].class.depends_on "foo" - expect(keg.installed_dependents).to be_empty expect(described_class.find_some_installed_dependents([keg])).to eq([[keg], ["bar"]]) end specify "non-opt-linked" do keg.remove_opt_record dependencies [{ "full_name" => "foo", "version" => "1.0" }] - expect(keg.installed_dependents).to be_empty expect(described_class.find_some_installed_dependents([keg])).to be nil end @@ -483,8 +458,7 @@ describe Keg do keg.unlink Formula["foo"].class.keg_only "a good reason" dependencies [{ "full_name" => "foo", "version" => "1.1" }] # different version - expect(keg.installed_dependents).to eq([dependent]) - expect(described_class.find_some_installed_dependents([keg])).to eq([[keg], ["bar 1.0"]]) + expect(described_class.find_some_installed_dependents([keg])).to eq([[keg], ["bar"]]) end end end diff --git a/Library/Homebrew/test/language/node_spec.rb b/Library/Homebrew/test/language/node_spec.rb index fdc3871af0..7632a5dc07 100644 --- a/Library/Homebrew/test/language/node_spec.rb +++ b/Library/Homebrew/test/language/node_spec.rb @@ -26,19 +26,19 @@ describe Language::Node do npm_pack_cmd = "npm pack --ignore-scripts" it "raises error with non zero exitstatus" do - allow(Utils).to receive(:popen_read).with(npm_pack_cmd) { `false` } + allow(Utils).to receive(:popen_read).with(npm_pack_cmd).and_return(`false`) expect { subject.std_npm_install_args(npm_install_arg) }.to \ raise_error("npm failed to pack #{Dir.pwd}") end it "raises error with empty npm pack output" do - allow(Utils).to receive(:popen_read).with(npm_pack_cmd) { `true` } + allow(Utils).to receive(:popen_read).with(npm_pack_cmd).and_return(`true`) expect { subject.std_npm_install_args(npm_install_arg) }.to \ raise_error("npm failed to pack #{Dir.pwd}") end it "does not raise error with a zero exitstatus" do - allow(Utils).to receive(:popen_read).with(npm_pack_cmd) { `echo pack.tgz` } + allow(Utils).to receive(:popen_read).with(npm_pack_cmd).and_return(`echo pack.tgz`) resp = subject.std_npm_install_args(npm_install_arg) expect(resp).to include("--prefix=#{npm_install_arg}", "#{Dir.pwd}/pack.tgz") end diff --git a/Library/Homebrew/test/language_module_requirement_spec.rb b/Library/Homebrew/test/language_module_requirement_spec.rb index 74d092bac9..43a57ebb59 100644 --- a/Library/Homebrew/test/language_module_requirement_spec.rb +++ b/Library/Homebrew/test/language_module_requirement_spec.rb @@ -10,6 +10,7 @@ describe LanguageModuleRequirement, :needs_compat do context "when module and import name differ" do subject { described_class.new(:python, mod_name, import_name) } + let(:mod_name) { "foo" } let(:import_name) { "bar" } diff --git a/Library/Homebrew/test/locale_spec.rb b/Library/Homebrew/test/locale_spec.rb index 9c684f0e7f..aa2b122204 100644 --- a/Library/Homebrew/test/locale_spec.rb +++ b/Library/Homebrew/test/locale_spec.rb @@ -60,11 +60,11 @@ describe Locale do end context "only some parts match" do - it { is_expected.to_not eql("zh") } - it { is_expected.to_not eql("zh-CN") } - it { is_expected.to_not eql("CN") } - it { is_expected.to_not eql("CN-Hans") } - it { is_expected.to_not eql("Hans") } + it { is_expected.not_to eql("zh") } + it { is_expected.not_to eql("zh-CN") } + it { is_expected.not_to eql("CN") } + it { is_expected.not_to eql("CN-Hans") } + it { is_expected.not_to eql("Hans") } end it "does not raise if 'other' cannot be parsed" do diff --git a/Library/Homebrew/test/migrator_spec.rb b/Library/Homebrew/test/migrator_spec.rb index 490e413f5c..833333bac0 100644 --- a/Library/Homebrew/test/migrator_spec.rb +++ b/Library/Homebrew/test/migrator_spec.rb @@ -17,7 +17,7 @@ describe Migrator do let(:keg) { Keg.new(old_keg_record) } let(:old_pin) { HOMEBREW_PINNED_KEGS/"oldname" } - before(:each) do |example| + before do |example| allow(new_formula).to receive(:oldname).and_return("oldname") # do not create directories for error tests @@ -43,7 +43,7 @@ describe Migrator do (HOMEBREW_PREFIX/"bin").mkpath end - after(:each) do + after do keg.unlink if !old_keg_record.parent.symlink? && old_keg_record.directory? if new_keg_record.directory? @@ -210,14 +210,14 @@ describe Migrator do tab.tabfile = HOMEBREW_CELLAR/"oldname/0.1/INSTALL_RECEIPT.json" tab.source["path"] = "/should/be/the/same" tab.write - migrator = Migrator.new(new_formula) + migrator = described_class.new(new_formula) tab.tabfile.delete migrator.backup_old_tabs expect(Tab.for_keg(old_keg_record).source["path"]).to eq("/should/be/the/same") end describe "#backup_oldname" do - after(:each) do + after do expect(old_keg_record.parent).to be_a_directory expect(old_keg_record.parent.subdirs).not_to be_empty expect(HOMEBREW_LINKED_KEGS/"oldname").to exist diff --git a/Library/Homebrew/test/missing_formula_spec.rb b/Library/Homebrew/test/missing_formula_spec.rb index d16c6116f6..a9d0083d09 100644 --- a/Library/Homebrew/test/missing_formula_spec.rb +++ b/Library/Homebrew/test/missing_formula_spec.rb @@ -4,12 +4,14 @@ describe Homebrew::MissingFormula do context "::reason" do subject { described_class.reason("gem") } - it { is_expected.to_not be_nil } + it { is_expected.not_to be_nil } end context "::blacklisted_reason" do matcher(:be_blacklisted) do - match(&Homebrew::MissingFormula.method(:blacklisted_reason)) + match do |expected| + described_class.blacklisted_reason(expected) + end end context "rubygems" do @@ -123,11 +125,13 @@ describe Homebrew::MissingFormula do context "with a migrated formula" do let(:formula) { "migrated-formula" } - it { is_expected.to_not be_nil } + + it { is_expected.not_to be_nil } end context "with a missing formula" do let(:formula) { "missing-formula" } + it { is_expected.to be_nil } end end @@ -154,11 +158,13 @@ describe Homebrew::MissingFormula do context "with a deleted formula" do let(:formula) { "homebrew/foo/deleted-formula" } - it { is_expected.to_not be_nil } + + it { is_expected.not_to be_nil } end context "with a formula that never existed" do let(:formula) { "homebrew/foo/missing-formula" } + it { is_expected.to be_nil } end end diff --git a/Library/Homebrew/test/mpi_requirement_spec.rb b/Library/Homebrew/test/mpi_requirement_spec.rb index aecdb1b66b..d88156e520 100644 --- a/Library/Homebrew/test/mpi_requirement_spec.rb +++ b/Library/Homebrew/test/mpi_requirement_spec.rb @@ -3,6 +3,7 @@ require "compat/requirements" describe MPIRequirement, :needs_compat do describe "::new" do subject { described_class.new(wrappers + tags) } + let(:wrappers) { [:cc, :cxx, :f77] } let(:tags) { [:optional, "some-other-tag"] } diff --git a/Library/Homebrew/test/options_spec.rb b/Library/Homebrew/test/options_spec.rb index a05bb139ec..73d90305b0 100644 --- a/Library/Homebrew/test/options_spec.rb +++ b/Library/Homebrew/test/options_spec.rb @@ -8,8 +8,8 @@ describe Option do end specify "equality" do - foo = Option.new("foo") - bar = Option.new("bar") + foo = described_class.new("foo") + bar = described_class.new("bar") expect(subject).to eq(foo) expect(subject).not_to eq(bar) expect(subject).to eql(foo) @@ -18,7 +18,7 @@ describe Option do specify "#description" do expect(subject.description).to be_empty - expect(Option.new("foo", "foo").description).to eq("foo") + expect(described_class.new("foo", "foo").description).to eq("foo") end specify "#inspect" do @@ -46,8 +46,8 @@ describe DeprecatedOption do end specify "equality" do - foobar = DeprecatedOption.new("foo", "bar") - boofar = DeprecatedOption.new("boo", "far") + foobar = described_class.new("foo", "bar") + boofar = described_class.new("boo", "far") expect(foobar).to eq(subject) expect(subject).to eq(foobar) expect(boofar).not_to eq(subject) @@ -81,26 +81,26 @@ describe Options do describe "#+" do it "returns options" do - expect(subject + Options.new).to be_an_instance_of(Options) + expect(subject + described_class.new).to be_an_instance_of(described_class) end end describe "#-" do it "returns options" do - expect(subject - Options.new).to be_an_instance_of(Options) + expect(subject - described_class.new).to be_an_instance_of(described_class) end end specify "#&" do foo, bar, baz = %w[foo bar baz].map { |o| Option.new(o) } - options = Options.new << foo << bar + options = described_class.new << foo << bar subject << foo << baz expect((subject & options).to_a).to eq([foo]) end specify "#|" do foo, bar, baz = %w[foo bar baz].map { |o| Option.new(o) } - options = Options.new << foo << bar + options = described_class.new << foo << bar subject << foo << baz expect((subject | options).sort).to eq([foo, bar, baz].sort) end @@ -137,7 +137,7 @@ describe Options do array = %w[--foo --bar] option1 = Option.new("foo") option2 = Option.new("bar") - expect(Options.create(array).sort).to eq([option1, option2].sort) + expect(described_class.create(array).sort).to eq([option1, option2].sort) end specify "#inspect" do diff --git a/Library/Homebrew/test/os/linux/dependency_collector_spec.rb b/Library/Homebrew/test/os/linux/dependency_collector_spec.rb index a8f85b4cac..285f8a169c 100644 --- a/Library/Homebrew/test/os/linux/dependency_collector_spec.rb +++ b/Library/Homebrew/test/os/linux/dependency_collector_spec.rb @@ -3,7 +3,7 @@ require "dependency_collector" describe DependencyCollector do alias_matcher :be_a_build_requirement, :be_build - after(:each) do + after do described_class.clear_cache end diff --git a/Library/Homebrew/test/os/mac/dependency_collector_spec.rb b/Library/Homebrew/test/os/mac/dependency_collector_spec.rb index a8fe8ba54c..41301ff78c 100644 --- a/Library/Homebrew/test/os/mac/dependency_collector_spec.rb +++ b/Library/Homebrew/test/os/mac/dependency_collector_spec.rb @@ -3,7 +3,7 @@ require "dependency_collector" describe DependencyCollector do alias_matcher :need_tar_xz_dependency, :be_tar_needs_xz_dependency - after(:each) do + after do described_class.clear_cache end diff --git a/Library/Homebrew/test/os/mac/hardware_spec.rb b/Library/Homebrew/test/os/mac/hardware_spec.rb index fa577ba7d6..4d5bbd3390 100644 --- a/Library/Homebrew/test/os/mac/hardware_spec.rb +++ b/Library/Homebrew/test/os/mac/hardware_spec.rb @@ -4,53 +4,53 @@ require "extend/os/mac/hardware/cpu" describe Hardware::CPU do describe "::can_run?" do it "reports that Intel Macs can run Intel executables" do - allow(Hardware::CPU).to receive(:type).and_return :intel - allow(Hardware::CPU).to receive(:bits).and_return 64 - expect(Hardware::CPU.can_run?(:i386)).to be true - expect(Hardware::CPU.can_run?(:x86_64)).to be true + allow(described_class).to receive(:type).and_return :intel + allow(described_class).to receive(:bits).and_return 64 + expect(described_class.can_run?(:i386)).to be true + expect(described_class.can_run?(:x86_64)).to be true end it "reports that PowerPC Macs can run PowerPC executables" do - allow(Hardware::CPU).to receive(:type).and_return :ppc - allow(Hardware::CPU).to receive(:bits).and_return 64 - expect(Hardware::CPU.can_run?(:ppc)).to be true - expect(Hardware::CPU.can_run?(:ppc64)).to be true + allow(described_class).to receive(:type).and_return :ppc + allow(described_class).to receive(:bits).and_return 64 + expect(described_class.can_run?(:ppc)).to be true + expect(described_class.can_run?(:ppc64)).to be true end it "reports that 32-bit Intel Macs can't run x86_64 executables" do - allow(Hardware::CPU).to receive(:type).and_return :intel - allow(Hardware::CPU).to receive(:bits).and_return 32 - expect(Hardware::CPU.can_run?(:x86_64)).to be false + allow(described_class).to receive(:type).and_return :intel + allow(described_class).to receive(:bits).and_return 32 + expect(described_class.can_run?(:x86_64)).to be false end it "reports that 32-bit PowerPC Macs can't run ppc64 executables" do - allow(Hardware::CPU).to receive(:type).and_return :ppc - allow(Hardware::CPU).to receive(:bits).and_return 32 - expect(Hardware::CPU.can_run?(:ppc64)).to be false + allow(described_class).to receive(:type).and_return :ppc + allow(described_class).to receive(:bits).and_return 32 + expect(described_class.can_run?(:ppc64)).to be false end it "reports that Intel Macs can only run 32-bit PowerPC executables on 10.6 and older" do - allow(Hardware::CPU).to receive(:type).and_return :intel + allow(described_class).to receive(:type).and_return :intel allow(OS::Mac).to receive(:version).and_return OS::Mac::Version.new "10.6" - expect(Hardware::CPU.can_run?(:ppc)).to be true + expect(described_class.can_run?(:ppc)).to be true allow(OS::Mac).to receive(:version).and_return OS::Mac::Version.new "10.7" - expect(Hardware::CPU.can_run?(:ppc)).to be false + expect(described_class.can_run?(:ppc)).to be false end it "reports that PowerPC Macs can't run Intel executables" do - allow(Hardware::CPU).to receive(:type).and_return :ppc - expect(Hardware::CPU.can_run?(:i386)).to be false - expect(Hardware::CPU.can_run?(:x86_64)).to be false + allow(described_class).to receive(:type).and_return :ppc + expect(described_class.can_run?(:i386)).to be false + expect(described_class.can_run?(:x86_64)).to be false end it "returns false for unknown CPU types" do - allow(Hardware::CPU).to receive(:type).and_return :dunno - expect(Hardware::CPU.can_run?(:i386)).to be false + allow(described_class).to receive(:type).and_return :dunno + expect(described_class.can_run?(:i386)).to be false end it "returns false for unknown arches" do - expect(Hardware::CPU.can_run?(:blah)).to be false + expect(described_class.can_run?(:blah)).to be false end end end diff --git a/Library/Homebrew/test/os/mac/java_requirement_spec.rb b/Library/Homebrew/test/os/mac/java_requirement_spec.rb index 1b46fe6b64..22120c3b83 100644 --- a/Library/Homebrew/test/os/mac/java_requirement_spec.rb +++ b/Library/Homebrew/test/os/mac/java_requirement_spec.rb @@ -3,9 +3,10 @@ require "fileutils" describe JavaRequirement do subject { described_class.new(%w[1.8]) } + let(:java_home) { mktmpdir } - before(:each) do + before do FileUtils.mkdir java_home/"bin" FileUtils.touch java_home/"bin/java" allow(subject).to receive(:preferred_java).and_return(java_home/"bin/java") diff --git a/Library/Homebrew/test/os/mac/keg_spec.rb b/Library/Homebrew/test/os/mac/keg_spec.rb index 562c2ba6a6..c1786f5d3a 100644 --- a/Library/Homebrew/test/os/mac/keg_spec.rb +++ b/Library/Homebrew/test/os/mac/keg_spec.rb @@ -8,9 +8,9 @@ describe Keg do describe "#mach_o_files" do let(:keg_path) { HOMEBREW_CELLAR/"a/1.0" } - before(:each) { (keg_path/"lib").mkpath } + before { (keg_path/"lib").mkpath } - after(:each) { subject.unlink } + after { subject.unlink } it "skips hardlinks" do cp dylib_path("i386"), keg_path/"lib/i386.dylib" diff --git a/Library/Homebrew/test/os/mac/mach_spec.rb b/Library/Homebrew/test/os/mac/mach_spec.rb index 5c9aafcbb9..f64ea1631e 100644 --- a/Library/Homebrew/test/os/mac/mach_spec.rb +++ b/Library/Homebrew/test/os/mac/mach_spec.rb @@ -152,7 +152,7 @@ end describe "text executables" do let(:pn) { HOMEBREW_PREFIX/"an_executable" } - after(:each) { pn.unlink } + after { pn.unlink } specify "simple shebang" do pn.write "#!/bin/sh" diff --git a/Library/Homebrew/test/patch_spec.rb b/Library/Homebrew/test/patch_spec.rb index 56f8f7ea84..dc30024cb1 100644 --- a/Library/Homebrew/test/patch_spec.rb +++ b/Library/Homebrew/test/patch_spec.rb @@ -4,6 +4,7 @@ describe Patch do describe "#create" do context "simple patch" do subject { described_class.create(:p2, nil) } + it { is_expected.to be_kind_of ExternalPatch } it { is_expected.to be_external } its(:strip) { is_expected.to eq(:p2) } @@ -11,24 +12,28 @@ describe Patch do context "string patch" do subject { described_class.create(:p0, "foo") } + it { is_expected.to be_kind_of StringPatch } its(:strip) { is_expected.to eq(:p0) } end context "string patch without strip" do subject { described_class.create("foo", nil) } + it { is_expected.to be_kind_of StringPatch } its(:strip) { is_expected.to eq(:p1) } end context "data patch" do subject { described_class.create(:p0, :DATA) } + it { is_expected.to be_kind_of DATAPatch } its(:strip) { is_expected.to eq(:p0) } end context "data patch without strip" do subject { described_class.create(:DATA, nil) } + it { is_expected.to be_kind_of DATAPatch } its(:strip) { is_expected.to eq(:p1) } end @@ -86,7 +91,7 @@ describe Patch do end it "can create patches from a :p0 hash" do - patches = Patch.normalize_legacy_patches( + patches = described_class.normalize_legacy_patches( p0: "http://example.com/patch.diff", ) @@ -95,7 +100,7 @@ describe Patch do end it "can create patches from a :p1 hash" do - patches = Patch.normalize_legacy_patches( + patches = described_class.normalize_legacy_patches( p1: "http://example.com/patch.diff", ) @@ -104,7 +109,7 @@ describe Patch do end it "can create patches from a mixed hash" do - patches = Patch.normalize_legacy_patches( + patches = described_class.normalize_legacy_patches( p1: "http://example.com/patch1.diff", p0: "http://example.com/patch0.diff", ) @@ -115,7 +120,7 @@ describe Patch do end it "can create patches from a mixed hash with array" do - patches = Patch.normalize_legacy_patches( + patches = described_class.normalize_legacy_patches( p1: [ "http://example.com/patch10.diff", "http://example.com/patch11.diff", @@ -132,7 +137,7 @@ describe Patch do end it "returns an empty array if given nil" do - expect(Patch.normalize_legacy_patches(nil)).to be_empty + expect(described_class.normalize_legacy_patches(nil)).to be_empty end end end @@ -140,6 +145,7 @@ end describe EmbeddedPatch do describe "#new" do subject { described_class.new(:p1) } + its(:inspect) { is_expected.to eq("#") } end end @@ -156,7 +162,7 @@ describe ExternalPatch do end describe "#cached_download" do - before(:each) do + before do allow(subject.resource).to receive(:cached_download).and_return("/tmp/foo.tar.gz") end diff --git a/Library/Homebrew/test/pathname_spec.rb b/Library/Homebrew/test/pathname_spec.rb index 1349e602b7..ac568d27fb 100644 --- a/Library/Homebrew/test/pathname_spec.rb +++ b/Library/Homebrew/test/pathname_spec.rb @@ -11,7 +11,7 @@ describe Pathname do let(:dir) { src/"bar" } describe DiskUsageExtension do - before(:each) do + before do mkdir_p dir/"a-directory" touch [dir/".DS_Store", dir/"a-file"] File.truncate(dir/"a-file", 1_048_576) @@ -41,7 +41,7 @@ describe Pathname do end describe "#rmdir_if_possible" do - before(:each) { mkdir_p dir } + before { mkdir_p dir } it "returns true and removes a directory if it doesn't contain files" do expect(dir.rmdir_if_possible).to be true @@ -131,8 +131,8 @@ describe Pathname do describe "#extname" do it "supports common multi-level archives" do - expect(Pathname.new("foo-0.1.tar.gz").extname).to eq(".tar.gz") - expect(Pathname.new("foo-0.1.cpio.gz").extname).to eq(".cpio.gz") + expect(described_class.new("foo-0.1.tar.gz").extname).to eq(".tar.gz") + expect(described_class.new("foo-0.1.cpio.gz").extname).to eq(".cpio.gz") end end @@ -144,7 +144,7 @@ describe Pathname do end describe "#install" do - before(:each) do + before do (src/"a.txt").write "This is sample file a." (src/"b.txt").write "This is sample file b." end @@ -233,12 +233,12 @@ describe Pathname do it "can install relative paths as symlinks" do dst.install_symlink "foo" => "bar" - expect((dst/"bar").readlink).to eq(Pathname.new("foo")) + expect((dst/"bar").readlink).to eq(described_class.new("foo")) end end describe InstallRenamed do - before(:each) do + before do dst.extend(InstallRenamed) end diff --git a/Library/Homebrew/test/requirement_spec.rb b/Library/Homebrew/test/requirement_spec.rb index 1f3d872f31..43a3e34feb 100644 --- a/Library/Homebrew/test/requirement_spec.rb +++ b/Library/Homebrew/test/requirement_spec.rb @@ -160,11 +160,11 @@ describe Requirement do let(:const) { :FooRequirement } let(:klass) { self.class.const_get(const) } - before(:each) do + before do self.class.const_set(const, Class.new(described_class)) end - after(:each) do + after do self.class.send(:remove_const, const) end diff --git a/Library/Homebrew/test/rubocops/dependency_order_cop_spec.rb b/Library/Homebrew/test/rubocops/dependency_order_cop_spec.rb index 92ca724750..cc5b0460a5 100644 --- a/Library/Homebrew/test/rubocops/dependency_order_cop_spec.rb +++ b/Library/Homebrew/test/rubocops/dependency_order_cop_spec.rb @@ -46,6 +46,18 @@ describe RuboCop::Cop::NewFormulaAudit::DependencyOrder do end RUBY end + + it "correct depends_on order for multiple tags" do + expect_no_offenses(<<~RUBY) + class Foo < Formula + homepage "http://example.com" + url "http://example.com/foo-1.0.tgz" + depends_on "bar" => [:build, :test] + depends_on "foo" => :build + depends_on "apple" + end + RUBY + end end context "autocorrect" do diff --git a/Library/Homebrew/test/sandbox_spec.rb b/Library/Homebrew/test/sandbox_spec.rb index 7743379673..965646c45d 100644 --- a/Library/Homebrew/test/sandbox_spec.rb +++ b/Library/Homebrew/test/sandbox_spec.rb @@ -6,7 +6,7 @@ describe Sandbox do let(:dir) { mktmpdir } let(:file) { dir/"foo" } - before(:each) do + before do skip "Sandbox not implemented." unless described_class.available? end diff --git a/Library/Homebrew/test/string_spec.rb b/Library/Homebrew/test/string_spec.rb index 6de89dc99a..d698d35ef6 100644 --- a/Library/Homebrew/test/string_spec.rb +++ b/Library/Homebrew/test/string_spec.rb @@ -2,6 +2,7 @@ require "extend/string" describe StringInreplaceExtension do subject { string.extend(described_class) } + let(:string) { "foobar" } describe "#sub!" do diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/github-with-appcast.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/github-with-appcast.rb new file mode 100644 index 0000000000..3024ced934 --- /dev/null +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/github-with-appcast.rb @@ -0,0 +1,14 @@ +cask 'github-with-appcast' do + version '1.0' + sha256 'a69e7357bea014f4c14ac9699274f559086844ffa46563c4619bf1addfd72ad9' + + url "https://github.com/user/project/releases/download/#{version}/github.pkg" + appcast 'https://github.com/user/project/releases.atom', + checkpoint: '56d1707d3065bf0c75d75d7738571285273b7bf366d8f0f5a53eb8b457ad2453' + name 'github' + homepage 'https://github.com/user/project' + + pkg 'github.pkg' + + uninstall pkgutil: 'com.github' +end diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/github-without-appcast.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/github-without-appcast.rb new file mode 100644 index 0000000000..9e7e17864d --- /dev/null +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/github-without-appcast.rb @@ -0,0 +1,12 @@ +cask 'github-without-appcast' do + version '1.0' + sha256 'a69e7357bea014f4c14ac9699274f559086844ffa46563c4619bf1addfd72ad9' + + url "https://github.com/user/project/releases/download/#{version}/github.pkg" + name 'github' + homepage 'https://github.com/user/project' + + pkg 'github.pkg' + + uninstall pkgutil: 'com.github' +end diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/latest-with-appcast.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/latest-with-appcast.rb new file mode 100644 index 0000000000..12b0b3e619 --- /dev/null +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/latest-with-appcast.rb @@ -0,0 +1,11 @@ +cask 'latest-with-appcast' do + version :latest + sha256 :no_check + + url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip" + appcast 'http://example.com/appcast.xml', + checkpoint: '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' + homepage 'http://example.com/with-appcast' + + app 'Caffeine.app' +end diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/with-allow-untrusted.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-allow-untrusted.rb new file mode 100644 index 0000000000..3f2c294ed7 --- /dev/null +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-allow-untrusted.rb @@ -0,0 +1,11 @@ +cask 'with-allow-untrusted' do + version '1.2.3' + sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' + + url "file://#{TEST_FIXTURE_DIR}/cask/MyFancyPkg.zip" + homepage 'http://example.com/fancy-pkg' + + pkg 'Fancy.pkg', allow_untrusted: true + + uninstall pkgutil: 'my.fancy.package.*' +end diff --git a/Library/Homebrew/test/support/helper/spec/shared_context/homebrew_cask.rb b/Library/Homebrew/test/support/helper/spec/shared_context/homebrew_cask.rb index 46303a46ea..e7a5e561fe 100644 --- a/Library/Homebrew/test/support/helper/spec/shared_context/homebrew_cask.rb +++ b/Library/Homebrew/test/support/helper/spec/shared_context/homebrew_cask.rb @@ -14,13 +14,13 @@ HOMEBREW_CASK_DIRS = { }.freeze RSpec.shared_context "Homebrew-Cask" do - before(:each) do + before do HOMEBREW_CASK_DIRS.each do |method, path| allow(Hbc::Config.global).to receive(method).and_return(path) end end - around(:each) do |example| + around do |example| third_party_tap = Tap.fetch("third-party", "tap") begin HOMEBREW_CASK_DIRS.values.each(&:mkpath) diff --git a/Library/Homebrew/test/support/helper/spec/shared_context/integration_test.rb b/Library/Homebrew/test/support/helper/spec/shared_context/integration_test.rb index 6ee6a33451..a92c27fc49 100644 --- a/Library/Homebrew/test/support/helper/spec/shared_context/integration_test.rb +++ b/Library/Homebrew/test/support/helper/spec/shared_context/integration_test.rb @@ -36,7 +36,7 @@ RSpec.shared_context "integration test" do end end - around(:each) do |example| + around do |example| begin (HOMEBREW_PREFIX/"bin").mkpath FileUtils.touch HOMEBREW_PREFIX/"bin/brew" diff --git a/Library/Homebrew/test/support/helper/spec/shared_examples/hbc_staged.rb b/Library/Homebrew/test/support/helper/spec/shared_examples/hbc_staged.rb index e7fa172c48..1a010f579a 100644 --- a/Library/Homebrew/test/support/helper/spec/shared_examples/hbc_staged.rb +++ b/Library/Homebrew/test/support/helper/spec/shared_examples/hbc_staged.rb @@ -4,7 +4,7 @@ shared_examples Hbc::Staged do let(:existing_path) { Pathname.new("/path/to/file/that/exists") } let(:non_existent_path) { Pathname.new("/path/to/file/that/does/not/exist") } - before(:each) do + before do allow(existing_path).to receive(:exist?).and_return(true) allow(existing_path).to receive(:expand_path) .and_return(existing_path) diff --git a/Library/Homebrew/test/tab_spec.rb b/Library/Homebrew/test/tab_spec.rb index 93ae42ce49..b44749e220 100644 --- a/Library/Homebrew/test/tab_spec.rb +++ b/Library/Homebrew/test/tab_spec.rb @@ -42,6 +42,7 @@ describe Tab do }, ) } + let(:time) { Time.now.to_i } let(:unused_options) { Options.create(%w[--with-baz --without-qux]) } let(:used_options) { Options.create(%w[--with-foo --without-bar]) } @@ -68,7 +69,7 @@ describe Tab do expect(tab.tap).to be nil expect(tab.time).to be nil expect(tab.HEAD).to be nil - expect(tab.runtime_dependencies).to be_empty + expect(tab.runtime_dependencies).to be nil expect(tab.stable_version).to be nil expect(tab.devel_version).to be nil expect(tab.head_version).to be nil diff --git a/Library/Homebrew/test/tap_spec.rb b/Library/Homebrew/test/tap_spec.rb index cb908da9ff..5e82370aac 100644 --- a/Library/Homebrew/test/tap_spec.rb +++ b/Library/Homebrew/test/tap_spec.rb @@ -3,6 +3,7 @@ describe Tap do alias_matcher :have_custom_remote, :be_custom_remote subject { described_class.new("Homebrew", "foo") } + let(:path) { Tap::TAP_DIRECTORY/"homebrew/homebrew-foo" } let(:formula_file) { path/"Formula/foo.rb" } let(:alias_file) { path/"Aliases/bar" } @@ -12,7 +13,7 @@ describe Tap do let(:zsh_completion_file) { path/"completions/zsh/_brew-tap-cmd" } let(:fish_completion_file) { path/"completions/fish/brew-tap-cmd.fish" } - before(:each) do + before do path.mkpath end @@ -62,7 +63,7 @@ describe Tap do expect(described_class.fetch("Homebrew", "core")).to be_kind_of(CoreTap) expect(described_class.fetch("Homebrew", "homebrew")).to be_kind_of(CoreTap) tap = described_class.fetch("Homebrew", "foo") - expect(tap).to be_kind_of(Tap) + expect(tap).to be_kind_of(described_class) expect(tap.name).to eq("homebrew/foo") expect { @@ -232,7 +233,7 @@ describe Tap do setup_tap_files setup_git_repo - tap = Tap.new("Homebrew", "bar") + tap = described_class.new("Homebrew", "bar") tap.install clone_target: subject.path/".git" @@ -259,7 +260,7 @@ describe Tap do begin setup_tap_files setup_git_repo - tap = Tap.new("Homebrew", "baz") + tap = described_class.new("Homebrew", "baz") tap.install clone_target: subject.path/".git" (HOMEBREW_PREFIX/"share/man/man1/brew-tap-cmd.1").delete (HOMEBREW_PREFIX/"etc/bash_completion.d/brew-tap-cmd").delete diff --git a/Library/Homebrew/test/utils/analytics_spec.rb b/Library/Homebrew/test/utils/analytics_spec.rb index 4526194d81..2224c7e40d 100644 --- a/Library/Homebrew/test/utils/analytics_spec.rb +++ b/Library/Homebrew/test/utils/analytics_spec.rb @@ -4,7 +4,7 @@ require "formula_installer" describe Utils::Analytics do describe "::os_prefix_ci" do context "when os_prefix_ci is not set" do - before(:each) do + before do described_class.clear_os_prefix_ci end diff --git a/Library/Homebrew/test/utils/git_spec.rb b/Library/Homebrew/test/utils/git_spec.rb index 48fc1338e6..9cb4206f04 100644 --- a/Library/Homebrew/test/utils/git_spec.rb +++ b/Library/Homebrew/test/utils/git_spec.rb @@ -1,7 +1,7 @@ require "utils/git" describe Git do - before(:each) do + before do git = HOMEBREW_SHIMS_PATH/"scm/git" HOMEBREW_CACHE.cd do @@ -57,18 +57,18 @@ describe Git do end describe Utils do - before(:each) do + before do described_class.clear_git_available_cache end describe "::git_available?" do it "returns true if git --version command succeeds" do - expect(described_class.git_available?).to be_truthy + expect(described_class).to be_git_available end it "returns false if git --version command does not succeed" do stub_const("HOMEBREW_SHIMS_PATH", HOMEBREW_PREFIX/"bin/shim") - expect(described_class.git_available?).to be_falsey + expect(described_class).not_to be_git_available end end @@ -121,10 +121,10 @@ describe Utils do end end - describe "::git_remote_exists" do + describe "::git_remote_exists?" do it "returns true when git is not available" do stub_const("HOMEBREW_SHIMS_PATH", HOMEBREW_PREFIX/"bin/shim") - expect(described_class.git_remote_exists("blah")).to be_truthy + expect(described_class).to be_git_remote_exists("blah") end context "when git is available" do @@ -139,11 +139,11 @@ describe Utils do system git, "remote", "add", "origin", url end - expect(described_class.git_remote_exists(url)).to be_truthy + expect(described_class).to be_git_remote_exists(url) end it "returns false when git remote does not exist" do - expect(described_class.git_remote_exists("blah")).to be_falsey + expect(described_class).not_to be_git_remote_exists("blah") end end end diff --git a/Library/Homebrew/test/utils/svn_spec.rb b/Library/Homebrew/test/utils/svn_spec.rb index f527a614f2..f7ea91ec87 100644 --- a/Library/Homebrew/test/utils/svn_spec.rb +++ b/Library/Homebrew/test/utils/svn_spec.rb @@ -2,32 +2,32 @@ require "utils/svn" describe Utils do describe "#self.svn_available?" do - before(:each) do + before do described_class.clear_svn_version_cache end it "returns svn version if svn available" do if File.executable? "/usr/bin/svn" - expect(described_class.svn_available?).to be_truthy + expect(described_class).to be_svn_available else - expect(described_class.svn_available?).to be_falsey + expect(described_class).not_to be_svn_available end end end - describe "#self.svn_remote_exists" do + describe "#self.svn_remote_exists?" do it "returns true when svn is not available" do - allow(Utils).to receive(:svn_available?).and_return(false) - expect(described_class.svn_remote_exists("blah")).to be_truthy + allow(described_class).to receive(:svn_available?).and_return(false) + expect(described_class).to be_svn_remote_exists("blah") end context "when svn is available" do before do - allow(Utils).to receive(:svn_available?).and_return(true) + allow(described_class).to receive(:svn_available?).and_return(true) end it "returns false when remote does not exist" do - expect(described_class.svn_remote_exists(HOMEBREW_CACHE/"install")).to be_falsey + expect(described_class).not_to be_svn_remote_exists(HOMEBREW_CACHE/"install") end it "returns true when remote exists", :needs_network, :needs_svn do @@ -36,7 +36,7 @@ describe Utils do HOMEBREW_CACHE.cd { system svn, "checkout", remote } - expect(described_class.svn_remote_exists(HOMEBREW_CACHE/"install")).to be_truthy + expect(described_class).to be_svn_remote_exists(HOMEBREW_CACHE/"install") end end end diff --git a/Library/Homebrew/test/utils/tty_spec.rb b/Library/Homebrew/test/utils/tty_spec.rb index e6c9168f31..e4b61a61ca 100644 --- a/Library/Homebrew/test/utils/tty_spec.rb +++ b/Library/Homebrew/test/utils/tty_spec.rb @@ -32,7 +32,7 @@ describe Tty do end context "when $stdout is not a TTY" do - before(:each) do + before do allow($stdout).to receive(:tty?).and_return(false) end @@ -49,7 +49,7 @@ describe Tty do end context "when $stdout is a TTY" do - before(:each) do + before do allow($stdout).to receive(:tty?).and_return(true) end diff --git a/Library/Homebrew/test/utils_spec.rb b/Library/Homebrew/test/utils_spec.rb index 037a80b646..21fcc3249f 100644 --- a/Library/Homebrew/test/utils_spec.rb +++ b/Library/Homebrew/test/utils_spec.rb @@ -30,10 +30,10 @@ describe "globally-scoped helper methods" do subject { pretty_installed("foo") } context "when $stdout is a TTY" do - before(:each) { allow($stdout).to receive(:tty?).and_return(true) } + before { allow($stdout).to receive(:tty?).and_return(true) } context "with HOMEBREW_NO_EMOJI unset" do - before(:each) { ENV.delete("HOMEBREW_NO_EMOJI") } + before { ENV.delete("HOMEBREW_NO_EMOJI") } it "returns a string with a colored checkmark" do expect(subject) @@ -42,7 +42,7 @@ describe "globally-scoped helper methods" do end context "with HOMEBREW_NO_EMOJI set" do - before(:each) { ENV["HOMEBREW_NO_EMOJI"] = "1" } + before { ENV["HOMEBREW_NO_EMOJI"] = "1" } it "returns a string with colored info" do expect(subject) @@ -52,7 +52,7 @@ describe "globally-scoped helper methods" do end context "when $stdout is not a TTY" do - before(:each) { allow($stdout).to receive(:tty?).and_return(false) } + before { allow($stdout).to receive(:tty?).and_return(false) } it "returns plain text" do expect(subject).to eq("foo") @@ -64,10 +64,10 @@ describe "globally-scoped helper methods" do subject { pretty_uninstalled("foo") } context "when $stdout is a TTY" do - before(:each) { allow($stdout).to receive(:tty?).and_return(true) } + before { allow($stdout).to receive(:tty?).and_return(true) } context "with HOMEBREW_NO_EMOJI unset" do - before(:each) { ENV.delete("HOMEBREW_NO_EMOJI") } + before { ENV.delete("HOMEBREW_NO_EMOJI") } it "returns a string with a colored checkmark" do expect(subject) @@ -76,7 +76,7 @@ describe "globally-scoped helper methods" do end context "with HOMEBREW_NO_EMOJI set" do - before(:each) { ENV["HOMEBREW_NO_EMOJI"] = "1" } + before { ENV["HOMEBREW_NO_EMOJI"] = "1" } it "returns a string with colored info" do expect(subject) @@ -86,7 +86,7 @@ describe "globally-scoped helper methods" do end context "when $stdout is not a TTY" do - before(:each) { allow($stdout).to receive(:tty?).and_return(false) } + before { allow($stdout).to receive(:tty?).and_return(false) } it "returns plain text" do expect(subject).to eq("foo") @@ -139,7 +139,7 @@ describe "globally-scoped helper methods" do describe "#which" do let(:cmd) { dir/"foo" } - before(:each) { FileUtils.touch cmd } + before { FileUtils.touch cmd } it "returns the first executable that is found" do cmd.chmod 0744 @@ -166,7 +166,7 @@ describe "globally-scoped helper methods" do let(:cmd2) { dir/"bar/foo" } let(:cmd3) { dir/"bar/baz/foo" } - before(:each) do + before do (dir/"bar/baz").mkpath FileUtils.touch cmd2 diff --git a/Library/Homebrew/test/version_spec.rb b/Library/Homebrew/test/version_spec.rb index 7d3e129f69..a713d6369b 100644 --- a/Library/Homebrew/test/version_spec.rb +++ b/Library/Homebrew/test/version_spec.rb @@ -2,34 +2,34 @@ require "version" describe Version::Token do specify "#inspect" do - expect(Version::Token.new("foo").inspect).to eq('#') + expect(described_class.new("foo").inspect).to eq('#') end specify "#to_s" do - expect(Version::Token.new("foo").to_s).to eq("foo") + expect(described_class.new("foo").to_s).to eq("foo") end end describe Version::NULL do it "is always smaller" do - expect(Version::NULL).to be < Version.create("1") + expect(described_class).to be < Version.create("1") end it "is never greater" do - expect(Version::NULL).not_to be > Version.create("0") + expect(described_class).not_to be > Version.create("0") end it "isn't equal to itself" do - expect(Version::NULL).not_to eql(Version::NULL) + expect(described_class).not_to eql(described_class) end it "creates an empty string" do - expect(Version::NULL.to_s).to eq("") + expect(described_class.to_s).to eq("") end it "produces NaN as a Float" do # Float::NAN is not equal to itself so compare object IDs - expect(Version::NULL.to_f.object_id).to eql(Float::NAN.object_id) + expect(described_class.to_f.object_id).to eql(Float::NAN.object_id) end end @@ -45,112 +45,112 @@ end describe Version do specify "comparison" do - expect(Version.create("0.1")).to be == Version.create("0.1.0") - expect(Version.create("0.1")).to be < Version.create("0.2") - expect(Version.create("1.2.3")).to be > Version.create("1.2.2") - expect(Version.create("1.2.4")).to be < Version.create("1.2.4.1") + expect(described_class.create("0.1")).to be == described_class.create("0.1.0") + expect(described_class.create("0.1")).to be < described_class.create("0.2") + expect(described_class.create("1.2.3")).to be > described_class.create("1.2.2") + expect(described_class.create("1.2.4")).to be < described_class.create("1.2.4.1") - expect(Version.create("1.2.3")).to be > Version.create("1.2.3alpha4") - expect(Version.create("1.2.3")).to be > Version.create("1.2.3beta2") - expect(Version.create("1.2.3")).to be > Version.create("1.2.3rc3") - expect(Version.create("1.2.3")).to be < Version.create("1.2.3-p34") + expect(described_class.create("1.2.3")).to be > described_class.create("1.2.3alpha4") + expect(described_class.create("1.2.3")).to be > described_class.create("1.2.3beta2") + expect(described_class.create("1.2.3")).to be > described_class.create("1.2.3rc3") + expect(described_class.create("1.2.3")).to be < described_class.create("1.2.3-p34") end specify "HEAD" do - expect(Version.create("HEAD")).to be > Version.create("1.2.3") - expect(Version.create("HEAD-abcdef")).to be > Version.create("1.2.3") - expect(Version.create("1.2.3")).to be < Version.create("HEAD") - expect(Version.create("1.2.3")).to be < Version.create("HEAD-fedcba") - expect(Version.create("HEAD-abcdef")).to be == Version.create("HEAD-fedcba") - expect(Version.create("HEAD")).to be == Version.create("HEAD-fedcba") + expect(described_class.create("HEAD")).to be > described_class.create("1.2.3") + expect(described_class.create("HEAD-abcdef")).to be > described_class.create("1.2.3") + expect(described_class.create("1.2.3")).to be < described_class.create("HEAD") + expect(described_class.create("1.2.3")).to be < described_class.create("HEAD-fedcba") + expect(described_class.create("HEAD-abcdef")).to be == described_class.create("HEAD-fedcba") + expect(described_class.create("HEAD")).to be == described_class.create("HEAD-fedcba") end specify "comparing alpha versions" do - expect(Version.create("1.2.3alpha")).to be < Version.create("1.2.3") - expect(Version.create("1.2.3")).to be < Version.create("1.2.3a") - expect(Version.create("1.2.3alpha4")).to be == Version.create("1.2.3a4") - expect(Version.create("1.2.3alpha4")).to be == Version.create("1.2.3A4") - expect(Version.create("1.2.3alpha4")).to be > Version.create("1.2.3alpha3") - expect(Version.create("1.2.3alpha4")).to be < Version.create("1.2.3alpha5") - expect(Version.create("1.2.3alpha4")).to be < Version.create("1.2.3alpha10") + expect(described_class.create("1.2.3alpha")).to be < described_class.create("1.2.3") + expect(described_class.create("1.2.3")).to be < described_class.create("1.2.3a") + expect(described_class.create("1.2.3alpha4")).to be == described_class.create("1.2.3a4") + expect(described_class.create("1.2.3alpha4")).to be == described_class.create("1.2.3A4") + expect(described_class.create("1.2.3alpha4")).to be > described_class.create("1.2.3alpha3") + expect(described_class.create("1.2.3alpha4")).to be < described_class.create("1.2.3alpha5") + expect(described_class.create("1.2.3alpha4")).to be < described_class.create("1.2.3alpha10") - expect(Version.create("1.2.3alpha4")).to be < Version.create("1.2.3beta2") - expect(Version.create("1.2.3alpha4")).to be < Version.create("1.2.3rc3") - expect(Version.create("1.2.3alpha4")).to be < Version.create("1.2.3") - expect(Version.create("1.2.3alpha4")).to be < Version.create("1.2.3-p34") + expect(described_class.create("1.2.3alpha4")).to be < described_class.create("1.2.3beta2") + expect(described_class.create("1.2.3alpha4")).to be < described_class.create("1.2.3rc3") + expect(described_class.create("1.2.3alpha4")).to be < described_class.create("1.2.3") + expect(described_class.create("1.2.3alpha4")).to be < described_class.create("1.2.3-p34") end specify "comparing beta versions" do - expect(Version.create("1.2.3beta2")).to be == Version.create("1.2.3b2") - expect(Version.create("1.2.3beta2")).to be == Version.create("1.2.3B2") - expect(Version.create("1.2.3beta2")).to be > Version.create("1.2.3beta1") - expect(Version.create("1.2.3beta2")).to be < Version.create("1.2.3beta3") - expect(Version.create("1.2.3beta2")).to be < Version.create("1.2.3beta10") + expect(described_class.create("1.2.3beta2")).to be == described_class.create("1.2.3b2") + expect(described_class.create("1.2.3beta2")).to be == described_class.create("1.2.3B2") + expect(described_class.create("1.2.3beta2")).to be > described_class.create("1.2.3beta1") + expect(described_class.create("1.2.3beta2")).to be < described_class.create("1.2.3beta3") + expect(described_class.create("1.2.3beta2")).to be < described_class.create("1.2.3beta10") - expect(Version.create("1.2.3beta2")).to be > Version.create("1.2.3alpha4") - expect(Version.create("1.2.3beta2")).to be < Version.create("1.2.3rc3") - expect(Version.create("1.2.3beta2")).to be < Version.create("1.2.3") - expect(Version.create("1.2.3beta2")).to be < Version.create("1.2.3-p34") + expect(described_class.create("1.2.3beta2")).to be > described_class.create("1.2.3alpha4") + expect(described_class.create("1.2.3beta2")).to be < described_class.create("1.2.3rc3") + expect(described_class.create("1.2.3beta2")).to be < described_class.create("1.2.3") + expect(described_class.create("1.2.3beta2")).to be < described_class.create("1.2.3-p34") end specify "comparing pre versions" do - expect(Version.create("1.2.3pre9")).to be == Version.create("1.2.3PRE9") - expect(Version.create("1.2.3pre9")).to be > Version.create("1.2.3pre8") - expect(Version.create("1.2.3pre8")).to be < Version.create("1.2.3pre9") - expect(Version.create("1.2.3pre9")).to be < Version.create("1.2.3pre10") + expect(described_class.create("1.2.3pre9")).to be == described_class.create("1.2.3PRE9") + expect(described_class.create("1.2.3pre9")).to be > described_class.create("1.2.3pre8") + expect(described_class.create("1.2.3pre8")).to be < described_class.create("1.2.3pre9") + expect(described_class.create("1.2.3pre9")).to be < described_class.create("1.2.3pre10") - expect(Version.create("1.2.3pre3")).to be > Version.create("1.2.3alpha2") - expect(Version.create("1.2.3pre3")).to be > Version.create("1.2.3alpha4") - expect(Version.create("1.2.3pre3")).to be > Version.create("1.2.3beta3") - expect(Version.create("1.2.3pre3")).to be > Version.create("1.2.3beta5") - expect(Version.create("1.2.3pre3")).to be < Version.create("1.2.3rc2") - expect(Version.create("1.2.3pre3")).to be < Version.create("1.2.3") - expect(Version.create("1.2.3pre3")).to be < Version.create("1.2.3-p2") + expect(described_class.create("1.2.3pre3")).to be > described_class.create("1.2.3alpha2") + expect(described_class.create("1.2.3pre3")).to be > described_class.create("1.2.3alpha4") + expect(described_class.create("1.2.3pre3")).to be > described_class.create("1.2.3beta3") + expect(described_class.create("1.2.3pre3")).to be > described_class.create("1.2.3beta5") + expect(described_class.create("1.2.3pre3")).to be < described_class.create("1.2.3rc2") + expect(described_class.create("1.2.3pre3")).to be < described_class.create("1.2.3") + expect(described_class.create("1.2.3pre3")).to be < described_class.create("1.2.3-p2") end specify "comparing RC versions" do - expect(Version.create("1.2.3rc3")).to be == Version.create("1.2.3RC3") - expect(Version.create("1.2.3rc3")).to be > Version.create("1.2.3rc2") - expect(Version.create("1.2.3rc3")).to be < Version.create("1.2.3rc4") - expect(Version.create("1.2.3rc3")).to be < Version.create("1.2.3rc10") + expect(described_class.create("1.2.3rc3")).to be == described_class.create("1.2.3RC3") + expect(described_class.create("1.2.3rc3")).to be > described_class.create("1.2.3rc2") + expect(described_class.create("1.2.3rc3")).to be < described_class.create("1.2.3rc4") + expect(described_class.create("1.2.3rc3")).to be < described_class.create("1.2.3rc10") - expect(Version.create("1.2.3rc3")).to be > Version.create("1.2.3alpha4") - expect(Version.create("1.2.3rc3")).to be > Version.create("1.2.3beta2") - expect(Version.create("1.2.3rc3")).to be < Version.create("1.2.3") - expect(Version.create("1.2.3rc3")).to be < Version.create("1.2.3-p34") + expect(described_class.create("1.2.3rc3")).to be > described_class.create("1.2.3alpha4") + expect(described_class.create("1.2.3rc3")).to be > described_class.create("1.2.3beta2") + expect(described_class.create("1.2.3rc3")).to be < described_class.create("1.2.3") + expect(described_class.create("1.2.3rc3")).to be < described_class.create("1.2.3-p34") end specify "comparing patch-level versions" do - expect(Version.create("1.2.3-p34")).to be == Version.create("1.2.3-P34") - expect(Version.create("1.2.3-p34")).to be > Version.create("1.2.3-p33") - expect(Version.create("1.2.3-p34")).to be < Version.create("1.2.3-p35") - expect(Version.create("1.2.3-p34")).to be > Version.create("1.2.3-p9") + expect(described_class.create("1.2.3-p34")).to be == described_class.create("1.2.3-P34") + expect(described_class.create("1.2.3-p34")).to be > described_class.create("1.2.3-p33") + expect(described_class.create("1.2.3-p34")).to be < described_class.create("1.2.3-p35") + expect(described_class.create("1.2.3-p34")).to be > described_class.create("1.2.3-p9") - expect(Version.create("1.2.3-p34")).to be > Version.create("1.2.3alpha4") - expect(Version.create("1.2.3-p34")).to be > Version.create("1.2.3beta2") - expect(Version.create("1.2.3-p34")).to be > Version.create("1.2.3rc3") - expect(Version.create("1.2.3-p34")).to be > Version.create("1.2.3") + expect(described_class.create("1.2.3-p34")).to be > described_class.create("1.2.3alpha4") + expect(described_class.create("1.2.3-p34")).to be > described_class.create("1.2.3beta2") + expect(described_class.create("1.2.3-p34")).to be > described_class.create("1.2.3rc3") + expect(described_class.create("1.2.3-p34")).to be > described_class.create("1.2.3") end specify "comparing unevenly-padded versions" do - expect(Version.create("2.1.0-p194")).to be < Version.create("2.1-p195") - expect(Version.create("2.1-p195")).to be > Version.create("2.1.0-p194") - expect(Version.create("2.1-p194")).to be < Version.create("2.1.0-p195") - expect(Version.create("2.1.0-p195")).to be > Version.create("2.1-p194") - expect(Version.create("2-p194")).to be < Version.create("2.1-p195") + expect(described_class.create("2.1.0-p194")).to be < described_class.create("2.1-p195") + expect(described_class.create("2.1-p195")).to be > described_class.create("2.1.0-p194") + expect(described_class.create("2.1-p194")).to be < described_class.create("2.1.0-p195") + expect(described_class.create("2.1.0-p195")).to be > described_class.create("2.1-p194") + expect(described_class.create("2-p194")).to be < described_class.create("2.1-p195") end it "can be compared against nil" do - expect(Version.create("2.1.0-p194")).to be > nil + expect(described_class.create("2.1.0-p194")).to be > nil end it "can be compared against strings" do - expect(Version.create("2.1.0-p194")).to be == "2.1.0-p194" - expect(Version.create("1")).to be == 1 + expect(described_class.create("2.1.0-p194")).to be == "2.1.0-p194" + expect(described_class.create("1")).to be == 1 end specify "comparison returns nil for non-version" do - v = Version.create("1.0") + v = described_class.create("1.0") expect(v <=> Object.new).to be nil expect { v > Object.new }.to raise_error(ArgumentError) end @@ -158,13 +158,13 @@ describe Version do specify "erlang versions" do versions = %w[R16B R15B03-1 R15B03 R15B02 R15B01 R14B04 R14B03 R14B02 R14B01 R14B R13B04 R13B03 R13B02-1].reverse - expect(versions.sort_by { |v| Version.create(v) }).to eq(versions) + expect(versions.sort_by { |v| described_class.create(v) }).to eq(versions) end specify "hash equality" do - v1 = Version.create("0.1.0") - v2 = Version.create("0.1.0") - v3 = Version.create("0.1.1") + v1 = described_class.create("0.1.0") + v2 = described_class.create("0.1.0") + v3 = described_class.create("0.1.1") expect(v1).to eql(v2) expect(v1).not_to eql(v3) @@ -178,50 +178,50 @@ describe Version do describe "::create" do it "accepts objects responding to #to_str" do value = double(to_str: "0.1") - expect(Version.create(value).to_s).to eq("0.1") + expect(described_class.create(value).to_s).to eq("0.1") end it "raises a TypeError for non-string objects" do - expect { Version.create(1.1) }.to raise_error(TypeError) - expect { Version.create(1) }.to raise_error(TypeError) - expect { Version.create(:symbol) }.to raise_error(TypeError) + expect { described_class.create(1.1) }.to raise_error(TypeError) + expect { described_class.create(1) }.to raise_error(TypeError) + expect { described_class.create(:symbol) }.to raise_error(TypeError) end it "parses a version from a string" do - v = Version.create("1.20") + v = described_class.create("1.20") expect(v).not_to be_head expect(v.to_str).to eq("1.20") end specify "HEAD with commit" do - v = Version.create("HEAD-abcdef") + v = described_class.create("HEAD-abcdef") expect(v.commit).to eq("abcdef") expect(v.to_str).to eq("HEAD-abcdef") end specify "HEAD without commit" do - v = Version.create("HEAD") + v = described_class.create("HEAD") expect(v.commit).to be nil expect(v.to_str).to eq("HEAD") end end specify "#detected_from_url?" do - expect(Version.create("1.0")).not_to be_detected_from_url + expect(described_class.create("1.0")).not_to be_detected_from_url expect(Version::FromURL.new("1.0")).to be_detected_from_url end specify "#head?" do - v1 = Version.create("HEAD-abcdef") - v2 = Version.create("HEAD") + v1 = described_class.create("HEAD-abcdef") + v2 = described_class.create("HEAD") expect(v1).to be_head expect(v2).to be_head end specify "#update_commit" do - v1 = Version.create("HEAD-abcdef") - v2 = Version.create("HEAD") + v1 = described_class.create("HEAD-abcdef") + v2 = described_class.create("HEAD") v1.update_commit("ffffff") expect(v1.commit).to eq("ffffff") @@ -234,17 +234,16 @@ describe Version do describe "::parse" do it "returns a NULL version when the URL cannot be parsed" do - expect(Version.parse("http://example.com/blah.tar")).to be_null - expect(Version.parse("foo")).to be_null + expect(described_class.parse("http://example.com/blah.tar")).to be_null + expect(described_class.parse("foo")).to be_null end end describe "::detect" do matcher :be_detected_from do |url, specs = {}| - detected = Version.detect(url, specs) - match do |expected| - detected == expected + @detected = described_class.detect(url, specs) + @detected == expected end failure_message do |expected| @@ -252,410 +251,410 @@ describe Version do expected: %s detected: %s EOS - format(message, expected, detected) + format(message, expected, @detected) end end specify "version all dots" do - expect(Version.create("1.14")) + expect(described_class.create("1.14")) .to be_detected_from("http://example.com/foo.bar.la.1.14.zip") end specify "version underscore separator" do - expect(Version.create("1.1")) + expect(described_class.create("1.1")) .to be_detected_from("http://example.com/grc_1.1.tar.gz") end specify "boost version style" do - expect(Version.create("1.39.0")) + expect(described_class.create("1.39.0")) .to be_detected_from("http://example.com/boost_1_39_0.tar.bz2") end specify "erlang version style" do - expect(Version.create("R13B")) + expect(described_class.create("R13B")) .to be_detected_from("http://erlang.org/download/otp_src_R13B.tar.gz") end specify "another erlang version style" do - expect(Version.create("R15B01")) + expect(described_class.create("R15B01")) .to be_detected_from("https://github.com/erlang/otp/tarball/OTP_R15B01") end specify "yet another erlang version style" do - expect(Version.create("R15B03-1")) + expect(described_class.create("R15B03-1")) .to be_detected_from("https://github.com/erlang/otp/tarball/OTP_R15B03-1") end specify "p7zip version style" do - expect(Version.create("9.04")) + expect(described_class.create("9.04")) .to be_detected_from("http://kent.dl.sourceforge.net/sourceforge/p7zip/p7zip_9.04_src_all.tar.bz2") end specify "new github style" do - expect(Version.create("1.1.4")) + expect(described_class.create("1.1.4")) .to be_detected_from("https://github.com/sam-github/libnet/tarball/libnet-1.1.4") end specify "codeload style" do - expect(Version.create("0.7.1")) + expect(described_class.create("0.7.1")) .to be_detected_from("https://codeload.github.com/gsamokovarov/jump/tar.gz/v0.7.1") end specify "elasticsearch alpha style" do - expect(Version.create("5.0.0-alpha5")) + expect(described_class.create("5.0.0-alpha5")) .to be_detected_from("https://download.elastic.co/elasticsearch/release/org/elasticsearch/distribution/tar/elasticsearch/5.0.0-alpha5/elasticsearch-5.0.0-alpha5.tar.gz") end specify "gloox beta style" do - expect(Version.create("1.0-beta7")) + expect(described_class.create("1.0-beta7")) .to be_detected_from("http://camaya.net/download/gloox-1.0-beta7.tar.bz2") end specify "sphinx beta style" do - expect(Version.create("1.10-beta")) + expect(described_class.create("1.10-beta")) .to be_detected_from("http://sphinxsearch.com/downloads/sphinx-1.10-beta.tar.gz") end specify "astyle version style" do - expect(Version.create("1.23")) + expect(described_class.create("1.23")) .to be_detected_from("http://kent.dl.sourceforge.net/sourceforge/astyle/astyle_1.23_macosx.tar.gz") end specify "version dos2unix" do - expect(Version.create("3.1")) + expect(described_class.create("3.1")) .to be_detected_from("http://www.sfr-fresh.com/linux/misc/dos2unix-3.1.tar.gz") end specify "version internal dash" do - expect(Version.create("1.1-2")) + expect(described_class.create("1.1-2")) .to be_detected_from("http://example.com/foo-arse-1.1-2.tar.gz") end specify "version single digit" do - expect(Version.create("45")) + expect(described_class.create("45")) .to be_detected_from("http://example.com/foo_bar.45.tar.gz") end specify "noseparator single digit" do - expect(Version.create("45")) + expect(described_class.create("45")) .to be_detected_from("http://example.com/foo_bar45.tar.gz") end specify "version developer that hates us format" do - expect(Version.create("1.2.3")) + expect(described_class.create("1.2.3")) .to be_detected_from("http://example.com/foo-bar-la.1.2.3.tar.gz") end specify "version regular" do - expect(Version.create("1.21")) + expect(described_class.create("1.21")) .to be_detected_from("http://example.com/foo_bar-1.21.tar.gz") end specify "version sourceforge download" do - expect(Version.create("1.21")) + expect(described_class.create("1.21")) .to be_detected_from("http://sourceforge.net/foo_bar-1.21.tar.gz/download") - expect(Version.create("1.21")) + expect(described_class.create("1.21")) .to be_detected_from("http://sf.net/foo_bar-1.21.tar.gz/download") end specify "version github" do - expect(Version.create("1.0.5")) + expect(described_class.create("1.0.5")) .to be_detected_from("http://github.com/lloyd/yajl/tarball/1.0.5") end specify "version github with high patch number" do - expect(Version.create("1.2.34")) + expect(described_class.create("1.2.34")) .to be_detected_from("http://github.com/lloyd/yajl/tarball/v1.2.34") end specify "yet another version" do - expect(Version.create("0.15.1b")) + expect(described_class.create("0.15.1b")) .to be_detected_from("http://example.com/mad-0.15.1b.tar.gz") end specify "lame version style" do - expect(Version.create("398-2")) + expect(described_class.create("398-2")) .to be_detected_from("http://kent.dl.sourceforge.net/sourceforge/lame/lame-398-2.tar.gz") end specify "ruby version style" do - expect(Version.create("1.9.1-p243")) + expect(described_class.create("1.9.1-p243")) .to be_detected_from("ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.1-p243.tar.gz") end specify "omega version style" do - expect(Version.create("0.80.2")) + expect(described_class.create("0.80.2")) .to be_detected_from("http://www.alcyone.com/binaries/omega/omega-0.80.2-src.tar.gz") end specify "rc style" do - expect(Version.create("1.2.2rc1")) + expect(described_class.create("1.2.2rc1")) .to be_detected_from("http://downloads.xiph.org/releases/vorbis/libvorbis-1.2.2rc1.tar.bz2") end specify "dash rc style" do - expect(Version.create("1.8.0-rc1")) + expect(described_class.create("1.8.0-rc1")) .to be_detected_from("http://ftp.mozilla.org/pub/mozilla.org/js/js-1.8.0-rc1.tar.gz") end specify "angband version style" do - expect(Version.create("3.0.9b")) + expect(described_class.create("3.0.9b")) .to be_detected_from("http://rephial.org/downloads/3.0/angband-3.0.9b-src.tar.gz") end specify "stable suffix" do - expect(Version.create("1.4.14b")) + expect(described_class.create("1.4.14b")) .to be_detected_from("http://www.monkey.org/~provos/libevent-1.4.14b-stable.tar.gz") end specify "debian style 1" do - expect(Version.create("3.03")) + expect(described_class.create("3.03")) .to be_detected_from("http://ftp.de.debian.org/debian/pool/main/s/sl/sl_3.03.orig.tar.gz") end specify "debian style 2" do - expect(Version.create("1.01b")) + expect(described_class.create("1.01b")) .to be_detected_from("http://ftp.de.debian.org/debian/pool/main/m/mmv/mmv_1.01b.orig.tar.gz") end specify "bottle style" do - expect(Version.create("4.8.0")) + expect(described_class.create("4.8.0")) .to be_detected_from("https://homebrew.bintray.com/bottles/qt-4.8.0.lion.bottle.tar.gz") end specify "versioned bottle style" do - expect(Version.create("4.8.1")) + expect(described_class.create("4.8.1")) .to be_detected_from("https://homebrew.bintray.com/bottles/qt-4.8.1.lion.bottle.1.tar.gz") end specify "erlang bottle style" do - expect(Version.create("R15B")) + expect(described_class.create("R15B")) .to be_detected_from("https://homebrew.bintray.com/bottles/erlang-R15B.lion.bottle.tar.gz") end specify "another erlang bottle style" do - expect(Version.create("R15B01")) + expect(described_class.create("R15B01")) .to be_detected_from("https://homebrew.bintray.com/bottles/erlang-R15B01.mountain_lion.bottle.tar.gz") end specify "yet another erlang bottle style" do - expect(Version.create("R15B03-1")) + expect(described_class.create("R15B03-1")) .to be_detected_from("https://homebrew.bintray.com/bottles/erlang-R15B03-1.mountainlion.bottle.tar.gz") end specify "imagemagick style" do - expect(Version.create("6.7.5-7")) + expect(described_class.create("6.7.5-7")) .to be_detected_from("http://downloads.sf.net/project/machomebrew/mirror/ImageMagick-6.7.5-7.tar.bz2") end specify "imagemagick bottle style" do - expect(Version.create("6.7.5-7")) + expect(described_class.create("6.7.5-7")) .to be_detected_from("https://homebrew.bintray.com/bottles/imagemagick-6.7.5-7.lion.bottle.tar.gz") end specify "imagemagick versioned bottle style" do - expect(Version.create("6.7.5-7")) + expect(described_class.create("6.7.5-7")) .to be_detected_from("https://homebrew.bintray.com/bottles/imagemagick-6.7.5-7.lion.bottle.1.tar.gz") end specify "date-based version style" do - expect(Version.create("2017-04-17")) + expect(described_class.create("2017-04-17")) .to be_detected_from("https://example.com/dada-v2017-04-17.tar.gz") end specify "devel spec version style" do - expect(Version.create("1.3.0-beta.1")) + expect(described_class.create("1.3.0-beta.1")) .to be_detected_from("https://registry.npmjs.org/@angular/cli/-/cli-1.3.0-beta.1.tgz") - expect(Version.create("2.074.0-beta1")) + expect(described_class.create("2.074.0-beta1")) .to be_detected_from("https://github.com/dlang/dmd/archive/v2.074.0-beta1.tar.gz") - expect(Version.create("2.074.0-rc1")) + expect(described_class.create("2.074.0-rc1")) .to be_detected_from("https://github.com/dlang/dmd/archive/v2.074.0-rc1.tar.gz") - expect(Version.create("5.0.0-alpha10")) + expect(described_class.create("5.0.0-alpha10")) .to be_detected_from("https://github.com/premake/premake-core/releases/download/v5.0.0-alpha10/premake-5.0.0-alpha10-src.zip") end specify "jenkins version style" do - expect(Version.create("1.486")) + expect(described_class.create("1.486")) .to be_detected_from("http://mirrors.jenkins-ci.org/war/1.486/jenkins.war") - expect(Version.create("0.10.11")) + expect(described_class.create("0.10.11")) .to be_detected_from("https://github.com/hechoendrupal/DrupalConsole/releases/download/0.10.11/drupal.phar") end specify "char prefixed, url-only version style" do - expect(Version.create("1.9.293")) + expect(described_class.create("1.9.293")) .to be_detected_from("https://github.com/clojure/clojurescript/releases/download/r1.9.293/cljs.jar") - expect(Version.create("0.6.1")) + expect(described_class.create("0.6.1")) .to be_detected_from("https://github.com/fibjs/fibjs/releases/download/v0.6.1/fullsrc.zip") - expect(Version.create("1.9")) + expect(described_class.create("1.9")) .to be_detected_from("https://wwwlehre.dhbw-stuttgart.de/~sschulz/WORK/E_DOWNLOAD/V_1.9/E.tgz") end specify "w.x.y.z url-only version style" do - expect(Version.create("2.3.2.0")) + expect(described_class.create("2.3.2.0")) .to be_detected_from("https://github.com/JustArchi/ArchiSteamFarm/releases/download/2.3.2.0/ASF.zip") - expect(Version.create("1.7.5.2")) + expect(described_class.create("1.7.5.2")) .to be_detected_from("https://people.gnome.org/~newren/eg/download/1.7.5.2/eg") end specify "dash version style" do - expect(Version.create("3.4")) + expect(described_class.create("3.4")) .to be_detected_from("http://www.antlr.org/download/antlr-3.4-complete.jar") - expect(Version.create("9.2")) + expect(described_class.create("9.2")) .to be_detected_from("https://cdn.nuxeo.com/nuxeo-9.2/nuxeo-server-9.2-tomcat.zip") - expect(Version.create("0.181")) + expect(described_class.create("0.181")) .to be_detected_from("https://search.maven.org/remotecontent?filepath=com/facebook/presto/presto-cli/0.181/presto-cli-0.181-executable.jar") - expect(Version.create("1.2.3")) + expect(described_class.create("1.2.3")) .to be_detected_from("https://search.maven.org/remotecontent?filepath=org/apache/orc/orc-tools/1.2.3/orc-tools-1.2.3-uber.jar") end specify "apache version style" do - expect(Version.create("1.2.0-rc2")) + expect(described_class.create("1.2.0-rc2")) .to be_detected_from("http://www.apache.org/dyn/closer.cgi?path=/cassandra/1.2.0/apache-cassandra-1.2.0-rc2-bin.tar.gz") end specify "jpeg version style" do - expect(Version.create("8d")) + expect(described_class.create("8d")) .to be_detected_from("http://www.ijg.org/files/jpegsrc.v8d.tar.gz") end specify "ghc version style" do - expect(Version.create("7.0.4")) + expect(described_class.create("7.0.4")) .to be_detected_from("http://www.haskell.org/ghc/dist/7.0.4/ghc-7.0.4-x86_64-apple-darwin.tar.bz2") - expect(Version.create("7.0.4")) + expect(described_class.create("7.0.4")) .to be_detected_from("http://www.haskell.org/ghc/dist/7.0.4/ghc-7.0.4-i386-apple-darwin.tar.bz2") end specify "pypy version style" do - expect(Version.create("1.4.1")) + expect(described_class.create("1.4.1")) .to be_detected_from("http://pypy.org/download/pypy-1.4.1-osx.tar.bz2") end specify "openssl version style" do - expect(Version.create("0.9.8s")) + expect(described_class.create("0.9.8s")) .to be_detected_from("http://www.openssl.org/source/openssl-0.9.8s.tar.gz") end specify "xaw3d version style" do - expect(Version.create("1.5E")) + expect(described_class.create("1.5E")) .to be_detected_from("ftp://ftp.visi.com/users/hawkeyd/X/Xaw3d-1.5E.tar.gz") end specify "assimp version style" do - expect(Version.create("2.0.863")) + expect(described_class.create("2.0.863")) .to be_detected_from("http://downloads.sourceforge.net/project/assimp/assimp-2.0/assimp--2.0.863-sdk.zip") end specify "cmucl version style" do - expect(Version.create("20c")) + expect(described_class.create("20c")) .to be_detected_from("http://common-lisp.net/project/cmucl/downloads/release/20c/cmucl-20c-x86-darwin.tar.bz2") end specify "fann version style" do - expect(Version.create("2.1.0beta")) + expect(described_class.create("2.1.0beta")) .to be_detected_from("http://downloads.sourceforge.net/project/fann/fann/2.1.0beta/fann-2.1.0beta.zip") end specify "grads version style" do - expect(Version.create("2.0.1")) + expect(described_class.create("2.0.1")) .to be_detected_from("ftp://iges.org/grads/2.0/grads-2.0.1-bin-darwin9.8-intel.tar.gz") end specify "haxe version style" do - expect(Version.create("2.08")) + expect(described_class.create("2.08")) .to be_detected_from("http://haxe.org/file/haxe-2.08-osx.tar.gz") end specify "imap version style" do - expect(Version.create("2007f")) + expect(described_class.create("2007f")) .to be_detected_from("ftp://ftp.cac.washington.edu/imap/imap-2007f.tar.gz") end specify "suite3270 version style" do - expect(Version.create("3.3.12ga7")) + expect(described_class.create("3.3.12ga7")) .to be_detected_from("http://downloads.sourceforge.net/project/x3270/x3270/3.3.12ga7/suite3270-3.3.12ga7-src.tgz") end specify "wwwoffle version style" do - expect(Version.create("2.9h")) + expect(described_class.create("2.9h")) .to be_detected_from("http://www.gedanken.demon.co.uk/download-wwwoffle/wwwoffle-2.9h.tgz") end specify "synergy version style" do - expect(Version.create("1.3.6p2")) + expect(described_class.create("1.3.6p2")) .to be_detected_from("http://synergy.googlecode.com/files/synergy-1.3.6p2-MacOSX-Universal.zip") end specify "fontforge version style" do - expect(Version.create("20120731")) + expect(described_class.create("20120731")) .to be_detected_from("http://downloads.sourceforge.net/project/fontforge/fontforge-source/fontforge_full-20120731-b.tar.bz2") end specify "ezlupdate version style" do - expect(Version.create("2011.10")) + expect(described_class.create("2011.10")) .to be_detected_from("https://github.com/downloads/ezsystems/ezpublish-legacy/ezpublish_community_project-2011.10-with_ezc.tar.bz2") end specify "aespipe version style" do - expect(Version.create("2.4c")) + expect(described_class.create("2.4c")) .to be_detected_from("http://loop-aes.sourceforge.net/aespipe/aespipe-v2.4c.tar.bz2") end specify "win version style" do - expect(Version.create("0.9.17")) + expect(described_class.create("0.9.17")) .to be_detected_from("http://ftpmirror.gnu.org/libmicrohttpd/libmicrohttpd-0.9.17-w32.zip") - expect(Version.create("1.29")) + expect(described_class.create("1.29")) .to be_detected_from("http://ftpmirror.gnu.org/libidn/libidn-1.29-win64.zip") end specify "with arch" do - expect(Version.create("4.0.18-1")) + expect(described_class.create("4.0.18-1")) .to be_detected_from("http://ftpmirror.gnu.org/mtools/mtools-4.0.18-1.i686.rpm") - expect(Version.create("5.5.7-5")) + expect(described_class.create("5.5.7-5")) .to be_detected_from("http://ftpmirror.gnu.org/autogen/autogen-5.5.7-5.i386.rpm") - expect(Version.create("2.8")) + expect(described_class.create("2.8")) .to be_detected_from("http://ftpmirror.gnu.org/libtasn1/libtasn1-2.8-x86.zip") - expect(Version.create("2.8")) + expect(described_class.create("2.8")) .to be_detected_from("http://ftpmirror.gnu.org/libtasn1/libtasn1-2.8-x64.zip") - expect(Version.create("4.0.18")) + expect(described_class.create("4.0.18")) .to be_detected_from("http://ftpmirror.gnu.org/mtools/mtools_4.0.18_i386.deb") end specify "opam version" do - expect(Version.create("2.18.3")) + expect(described_class.create("2.18.3")) .to be_detected_from("https://opam.ocaml.org/archives/lablgtk.2.18.3+opam.tar.gz") - expect(Version.create("1.9")) + expect(described_class.create("1.9")) .to be_detected_from("https://opam.ocaml.org/archives/sha.1.9+opam.tar.gz") - expect(Version.create("0.99.2")) + expect(described_class.create("0.99.2")) .to be_detected_from("https://opam.ocaml.org/archives/ppx_tools.0.99.2+opam.tar.gz") - expect(Version.create("1.0.2")) + expect(described_class.create("1.0.2")) .to be_detected_from("https://opam.ocaml.org/archives/easy-format.1.0.2+opam.tar.gz") end specify "no extension version" do - expect(Version.create("1.8.12")) + expect(described_class.create("1.8.12")) .to be_detected_from("https://waf.io/waf-1.8.12") - expect(Version.create("0.7.1")) + expect(described_class.create("0.7.1")) .to be_detected_from("https://codeload.github.com/gsamokovarov/jump/tar.gz/v0.7.1") - expect(Version.create("0.9.1234")) + expect(described_class.create("0.9.1234")) .to be_detected_from("https://my.datomic.com/downloads/free/0.9.1234") - expect(Version.create("0.9")) + expect(described_class.create("0.9")) .to be_detected_from("https://my.datomic.com/downloads/free/0.9.1t34") - expect(Version.create("1.2.3")) + expect(described_class.create("1.2.3")) .to be_detected_from("https://my.datomic.com/downloads/free/1.2.3") end specify "dash separated version" do - expect(Version.create("6-20151227")) + expect(described_class.create("6-20151227")) .to be_detected_from("ftp://gcc.gnu.org/pub/gcc/snapshots/6-20151227/gcc-6-20151227.tar.bz2") end specify "semver in middle of URL" do - expect(Version.create("7.1.10")) + expect(described_class.create("7.1.10")) .to be_detected_from("https://php.net/get/php-7.1.10.tar.gz/from/this/mirror") end specify "from URL" do - expect(Version.create("1.2.3")) + expect(described_class.create("1.2.3")) .to be_detected_from("http://github.com/foo/bar.git", tag: "v1.2.3") end end diff --git a/Library/Homebrew/utils.rb b/Library/Homebrew/utils.rb index 8d57c12d60..dcc69ecb30 100644 --- a/Library/Homebrew/utils.rb +++ b/Library/Homebrew/utils.rb @@ -110,9 +110,9 @@ def odeprecated(method, replacement = nil, disable: false, disable_on: nil, call if ARGV.homebrew_developer? || disable || Homebrew.raise_deprecation_exceptions? if replacement || tap_message - developer_message = message + "Or, even better, submit a PR to fix it!" + message += "Or, even better, submit a PR to fix it!" end - raise MethodDeprecatedError, developer_message + raise MethodDeprecatedError, message elsif !Homebrew.auditing? opoo "#{message}\n" end @@ -199,7 +199,7 @@ module Homebrew _system(cmd, *args) end - def install_gem_setup_path!(name, version = nil, executable = name) + def install_gem!(name, version = nil) # Match where our bundler gems are. ENV["GEM_HOME"] = "#{ENV["HOMEBREW_LIBRARY"]}/Homebrew/vendor/bundle/ruby/#{RbConfig::CONFIG["ruby_version"]}" ENV["GEM_PATH"] = ENV["GEM_HOME"] @@ -214,24 +214,28 @@ module Homebrew path.prepend(Gem.bindir) ENV["PATH"] = path - if Gem::Specification.find_all_by_name(name, version).empty? - ohai "Installing or updating '#{name}' gem" - install_args = %W[--no-ri --no-rdoc #{name}] - install_args << "--version" << version if version + return unless Gem::Specification.find_all_by_name(name, version).empty? - # Do `gem install [...]` without having to spawn a separate process or - # having to find the right `gem` binary for the running Ruby interpreter. - require "rubygems/commands/install_command" - install_cmd = Gem::Commands::InstallCommand.new - install_cmd.handle_options(install_args) - exit_code = 1 # Should not matter as `install_cmd.execute` always throws. - begin - install_cmd.execute - rescue Gem::SystemExitException => e - exit_code = e.exit_code - end - odie "Failed to install/update the '#{name}' gem." if exit_code.nonzero? + ohai "Installing or updating '#{name}' gem" + install_args = %W[--no-ri --no-rdoc #{name}] + install_args << "--version" << version if version + + # Do `gem install [...]` without having to spawn a separate process or + # having to find the right `gem` binary for the running Ruby interpreter. + require "rubygems/commands/install_command" + install_cmd = Gem::Commands::InstallCommand.new + install_cmd.handle_options(install_args) + exit_code = 1 # Should not matter as `install_cmd.execute` always throws. + begin + install_cmd.execute + rescue Gem::SystemExitException => e + exit_code = e.exit_code end + odie "Failed to install/update the '#{name}' gem." if exit_code.nonzero? + end + + def install_gem_setup_path!(name, version = nil, executable = name) + install_gem!(name, version) return if which(executable) odie <<~EOS @@ -572,3 +576,7 @@ def tap_and_name_comparison end end end + +def command_help_lines(path) + path.read.lines.grep(/^#:/).map { |line| line.slice(2..-1) } +end diff --git a/Library/Homebrew/utils/curl.rb b/Library/Homebrew/utils/curl.rb index 65edd85df4..7b2488ec72 100644 --- a/Library/Homebrew/utils/curl.rb +++ b/Library/Homebrew/utils/curl.rb @@ -6,8 +6,8 @@ def curl_executable ENV["HOMEBREW_CURL"], which("curl"), "/usr/bin/curl", - ].map { |c| Pathname(c) }.find(&:executable?) - raise "curl is not executable" unless @curl + ].compact.map { |c| Pathname(c) }.find(&:executable?) + raise "no executable curl was found" unless @curl @curl end diff --git a/Library/Homebrew/utils/git.rb b/Library/Homebrew/utils/git.rb index 0ffcab7b1d..7846389c8a 100644 --- a/Library/Homebrew/utils/git.rb +++ b/Library/Homebrew/utils/git.rb @@ -8,9 +8,10 @@ module Git out, = Open3.capture3( HOMEBREW_SHIMS_PATH/"scm/git", "-C", repo, - "log", "--oneline", "--max-count=1", *args, "--", file + "log", "--format=%h", "--abbrev=7", "--max-count=1", + *args, "--", file ) - out.split(" ").first + out.chomp end def last_revision_of_file(repo, file, before_commit: nil) @@ -66,7 +67,7 @@ module Utils @git_version = nil end - def self.git_remote_exists(url) + def self.git_remote_exists?(url) return true unless git_available? quiet_system "git", "ls-remote", url end diff --git a/Library/Homebrew/utils/lock.sh b/Library/Homebrew/utils/lock.sh index e7fe348aa4..d8651cd754 100644 --- a/Library/Homebrew/utils/lock.sh +++ b/Library/Homebrew/utils/lock.sh @@ -39,13 +39,13 @@ _create_lock() { local name="$2" local ruby="/usr/bin/ruby" local python="/usr/bin/python" - [[ -x "$ruby" ]] || ruby="$(which ruby 2>/dev/null)" - [[ -x "$python" ]] || python="$(which python 2>/dev/null)" + [[ -x "$ruby" ]] || ruby="$(type -P ruby)" + [[ -x "$python" ]] || python="$(type -P python)" if [[ -x "$ruby" ]] && "$ruby" -e "exit(RUBY_VERSION >= '1.8.7')" then "$ruby" -e "File.new($lock_fd).flock(File::LOCK_EX | File::LOCK_NB) || exit(1)" - elif [[ -x "$(which flock 2>/dev/null)" ]] + elif [[ -x "$(type -P flock)" ]] then flock -n "$lock_fd" elif [[ -x "$python" ]] diff --git a/Library/Homebrew/utils/ruby.sh b/Library/Homebrew/utils/ruby.sh index 2fb780c65a..e242cd6514 100644 --- a/Library/Homebrew/utils/ruby.sh +++ b/Library/Homebrew/utils/ruby.sh @@ -32,7 +32,7 @@ setup-ruby-path() { then HOMEBREW_RUBY_PATH="/System/Library/Frameworks/Ruby.framework/Versions/Current/usr/bin/ruby" else - HOMEBREW_RUBY_PATH="$(which ruby)" + HOMEBREW_RUBY_PATH="$(type -P ruby)" fi if [[ -n "$HOMEBREW_RUBY_PATH" && -z "$HOMEBREW_FORCE_VENDOR_RUBY" ]] diff --git a/Library/Homebrew/utils/svn.rb b/Library/Homebrew/utils/svn.rb index 150b7eee74..e316a1344f 100644 --- a/Library/Homebrew/utils/svn.rb +++ b/Library/Homebrew/utils/svn.rb @@ -8,7 +8,7 @@ module Utils @svn = quiet_system HOMEBREW_SHIMS_PATH/"scm/svn", "--version" end - def self.svn_remote_exists(url) + def self.svn_remote_exists?(url) return true unless svn_available? quiet_system "svn", "ls", url, "--depth", "empty" end diff --git a/docs/Formula-Cookbook.md b/docs/Formula-Cookbook.md index 1f2b2e89e2..3f6902409a 100644 --- a/docs/Formula-Cookbook.md +++ b/docs/Formula-Cookbook.md @@ -130,7 +130,7 @@ to favour finding `keg_only` formulae first. ```ruby class Foo < Formula - depends_on "pkg-config" => :run + depends_on "pkg-config" depends_on "jpeg" depends_on "readline" => :recommended depends_on "gtk+" => :optional @@ -144,16 +144,13 @@ A Symbol (e.g. `:x11`) specifies a [`Requirement`](http://www.rubydoc.info/githu A Hash (e.g. `=>`) specifies a formula dependency with some additional information. Given a single string key, the value can take several forms: -* a Symbol (currently one of `:build`, `:optional`, `:run` or `:recommended`) +* a Symbol (currently one of `:build`, `:test`, `:optional` or `:recommended`) - `:build` means that dependency is a build-time only dependency so it can be skipped when installing from a bottle or when listing missing dependencies using `brew missing`. + - `:test` means that dependency is only required when running `brew test`. - `:optional` generates an implicit `with-foo` option for the formula. This means that, given `depends_on "foo" => :optional`, the user must pass `--with-foo` in order to use the dependency. - - `:run` can mean the dependency is only required at runtime, or it can be used - to declare build dependencies such as `pkg-config` that are needed at - runtime as well, which will silence the audit warning. `:run` dependencies - are currently available at build time. - `:recommended` generates an implicit `without-foo` option, meaning that the dependency is enabled by default and the user must pass `--without-foo` to disable this dependency. The default diff --git a/docs/Manpage.md b/docs/Manpage.md index 388b886b45..3479ec771d 100644 --- a/docs/Manpage.md +++ b/docs/Manpage.md @@ -97,7 +97,7 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note 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`. @@ -216,7 +216,7 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note See the docs for examples of using the JSON output: - * `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 @@ -254,6 +254,9 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note 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, @@ -433,6 +436,8 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note 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. @@ -549,22 +554,26 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note their latest `origin/master`. Note this will destroy all your uncommitted or committed changes. - * `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`). - * `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`. @@ -575,10 +584,12 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note 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`. @@ -871,7 +882,7 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note Example: `brew install jruby && brew test jruby` - * `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. @@ -906,17 +917,137 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note ## OFFICIAL EXTERNAL COMMANDS - * `bundle`: - Bundler for non-Ruby dependencies from Homebrew: - + * `bundle` `command`: - * `cask`: - Install macOS applications distributed as binaries: - + Bundler for non-Ruby dependencies from Homebrew. - * `services`: - Integrates Homebrew formulae with macOS's `launchctl`(1) manager: - + + + `bundle` [`install`] [`-v`|`--verbose`] [`--no-upgrade`] [`--file=``path`|`--global`]: + + Install or upgrade all dependencies in a Brewfile. + + + + `brew bundle dump` [`--force`] [`--describe`] [`--file=``path`|`--global`] + + Write all installed casks/formulae/taps into a Brewfile. + + + + `brew bundle cleanup` [`--force`] [`--zap`] [`--file=``path`|`--global`] + + Uninstall all dependencies not listed in a Brewfile. + + + + `brew bundle check` [`--no-upgrade`] [`--file`=`path`|`--global`] + + Check if all dependencies are installed in a Brewfile. + + + + `brew bundle exec` `command` + + Run an external command in an isolated build environment. + + + + `brew bundle list` [`--all`|`--brews`|`--casks`|`--taps`|`--mas`] [`--file=``path`|`--global`] + + List all dependencies present in a Brewfile, optionally limiting by types. + + By default, only brew dependencies are output. + + + + If `-v` or `--verbose` are passed, print verbose output. + + + + If `--no-upgrade` is passed, don't run `brew upgrade` outdated dependencies. + + Note they may still be upgraded by `brew install` if needed. + + + + If `--force` is passed, uninstall dependencies or overwrite an existing Brewfile. + + + + If `--file=`path is passed, the Brewfile path is set accordingly + + Use `--file=-` to output to console. + + + + If `--global` is passed, set Brewfile path to `$HOME/.Brewfile`. + + + + If `--describe` is passed, output a description comment above each line. + + This comment will not be output if the dependency does not have a description. + + + + If `-h` or `--help` are passed, print this help message and exit. + + Homebrew/homebrew-bundle + + * `cask` [`--version` | `audit` | `cat` | `cleanup` | `create` | `doctor` | `edit` | `fetch` | `home` | `info`]: + Install macOS applications distributed as binaries. + + + Caskroom/homebrew-cask + + * `services` `command`: + + Integrates Homebrew formulae with macOS' `launchctl` manager. + + + + [`sudo`] `brew services list` + + List all running services for the current user (or `root`) + + + + [`sudo`] `brew services run` `formula|--all` + + Run the service `formula` without starting at login (or boot). + + + + [`sudo`] `brew services` `start` `formula|--all` + + Start the service `formula` immediately and register it to launch at login (or `boot`). + + + + [`sudo`] `brew services` `stop` `formula|--all` + + Stop the service `formula` immediately and unregister it from launching at login (or `boot`). + + + + [`sudo`] `brew services` `restart` `formula|--all` + + Stop (if necessary) and start the service immediately and register it to launch at login (or `boot`). + + + + [`sudo`] `brew services` `cleanup` + + Remove all unused services. + + + + If `sudo` is passed, operate on `/Library/LaunchDaemons` (started at boot). + + Otherwise, operate on `~/Library/LaunchAgents (started at login)`. + + Homebrew/homebrew-services ## CUSTOM EXTERNAL COMMANDS @@ -1092,6 +1223,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. diff --git a/manpages/brew.1 b/manpages/brew.1 index 2ac999dd58..ca8c6f5f14 100644 --- a/manpages/brew.1 +++ b/manpages/brew.1 @@ -107,7 +107,7 @@ If \fB\-\-full\-name\fR is passed, list dependencies by their full name\. If \fB\-\-installed\fR is passed, only list those dependencies that are currently installed\. . .IP -By default, \fBdeps\fR shows required and recommended dependencies for \fIformulae\fR\. To include the \fB:build\fR type dependencies, pass \fB\-\-include\-build\fR\. Similarly, pass \fB\-\-include\-optional\fR to include \fB:optional\fR dependencies or \fB\-\-include\-test\fR to include \fB:test\fR dependencies\. To skip \fB:recommended\fR type dependencies, pass \fB\-\-skip\-recommended\fR\. To include requirements in addition to dependencies, pass \fB\-\-include\-requirements\fR\. +By default, \fBdeps\fR shows required and recommended dependencies for \fIformulae\fR\. To include the \fB:build\fR type dependencies, pass \fB\-\-include\-build\fR\. Similarly, pass \fB\-\-include\-optional\fR to include \fB:optional\fR dependencies or \fB\-\-include\-test\fR to include (non\-recursive) \fB:test\fR dependencies\. To skip \fB:recommended\fR type dependencies, pass \fB\-\-skip\-recommended\fR\. To include requirements in addition to dependencies, pass \fB\-\-include\-requirements\fR\. . .TP \fBdeps\fR \fB\-\-tree\fR [\fB\-\-1\fR] [\fIfilters\fR] [\fB\-\-annotate\fR] (\fIformulae\fR|\fB\-\-installed\fR) @@ -229,7 +229,7 @@ Pass \fB\-\-all\fR to get information on all formulae, or \fB\-\-installed\fR to See the docs for examples of using the JSON output: \fIhttps://docs\.brew\.sh/Querying\-Brew\fR . .TP -\fBinstall\fR [\fB\-\-debug\fR] [\fB\-\-env=\fR(\fBstd\fR|\fBsuper\fR)] [\fB\-\-ignore\-dependencies\fR|\fB\-\-only\-dependencies\fR] [\fB\-\-cc=\fR\fIcompiler\fR] [\fB\-\-build\-from\-source\fR|\fB\-\-force\-bottle\fR] [\fB\-\-devel\fR|\fB\-\-HEAD\fR] [\fB\-\-keep\-tmp\fR] [\fB\-\-build\-bottle\fR] [\fB\-\-force\fR] [\fB\-\-verbose\fR] \fIformula\fR [\fIoptions\fR \.\.\.] +\fBinstall\fR [\fB\-\-debug\fR] [\fB\-\-env=\fR(\fBstd\fR|\fBsuper\fR)] [\fB\-\-ignore\-dependencies\fR|\fB\-\-only\-dependencies\fR] [\fB\-\-cc=\fR\fIcompiler\fR] [\fB\-\-build\-from\-source\fR|\fB\-\-force\-bottle\fR] [\fB\-\-include\-test\fR] [\fB\-\-devel\fR|\fB\-\-HEAD\fR] [\fB\-\-keep\-tmp\fR] [\fB\-\-build\-bottle\fR] [\fB\-\-force\fR] [\fB\-\-verbose\fR] \fIformula\fR [\fIoptions\fR \.\.\.] Install \fIformula\fR\. . .IP @@ -263,6 +263,9 @@ If \fBHOMEBREW_BUILD_FROM_SOURCE\fR is set, regardless of whether \fB\-\-build\- If \fB\-\-force\-bottle\fR is passed, install from a bottle if it exists for the current or newest version of macOS, even if it would not normally be used for installation\. . .IP +If \fB\-\-include\-test\fR is passed, install testing dependencies\. These are only needed by formulae maintainers to run \fBbrew test\fR\. +. +.IP If \fB\-\-devel\fR is passed, and \fIformula\fR defines it, install the development version\. . .IP @@ -443,6 +446,9 @@ If \fB\-\-fix\fR is passed, automatically fix style violations using RuboCop\'s If \fB\-\-display\-cop\-names\fR is passed, include the RuboCop cop name for each violation in the output\. . .IP +If \fB\-\-rspec\fR is passed, install and use the RuboCop RSpec gem\. +. +.IP Passing \fB\-\-only\-cops=\fR\fIcops\fR will check for violations of only the listed RuboCop \fIcops\fR, while \fB\-\-except\-cops=\fR\fIcops\fR will skip checking the listed \fIcops\fR\. For either option \fIcops\fR should be a comma\-separated list of cop names\. . .IP @@ -563,23 +569,26 @@ If \fB\-\-force\fR (or \fB\-f\fR) is specified then always do a slower, full upd Fetches and resets Homebrew and all tap repositories using \fBgit\fR(1) to their latest \fBorigin/master\fR\. Note this will destroy all your uncommitted or committed changes\. . .TP -\fBupgrade\fR [\fIinstall\-options\fR] [\fB\-\-cleanup\fR] [\fB\-\-fetch\-HEAD\fR] [\fIformulae\fR] +\fBupgrade\fR [\fIinstall\-options\fR] [\fB\-\-cleanup\fR] [\fB\-\-fetch\-HEAD\fR] [\fB\-\-ignore\-pinned\fR] [\fIformulae\fR] Upgrade outdated, unpinned brews (with existing install options)\. . .IP Options for the \fBinstall\fR command are also valid here\. . .IP -If \fB\-\-cleanup\fR is specified then remove previously installed \fIformula\fR version(s)\. +If \fB\-\-cleanup\fR is specified or \fBHOMEBREW_UPGRADE_CLEANUP\fR is set then remove previously installed \fIformula\fR version(s)\. . .IP If \fB\-\-fetch\-HEAD\fR 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\. . .IP +If \fB\-\-ignore\-pinned\fR is passed, set a 0 exit code even if pinned formulae are not upgraded\. +. +.IP If \fIformulae\fR are given, upgrade only the specified brews (unless they are pinned; see \fBpin\fR, \fBunpin\fR)\. . .TP -\fBuses\fR [\fB\-\-installed\fR] [\fB\-\-recursive\fR] [\fB\-\-include\-build\fR] [\fB\-\-include\-optional\fR] [\fB\-\-skip\-recommended\fR] [\fB\-\-devel\fR|\fB\-\-HEAD\fR] \fIformulae\fR +\fBuses\fR [\fB\-\-installed\fR] [\fB\-\-recursive\fR] [\fB\-\-include\-build\fR] [\fB\-\-include\-test\fR] [\fB\-\-include\-optional\fR] [\fB\-\-skip\-recommended\fR] [\fB\-\-devel\fR|\fB\-\-HEAD\fR] \fIformulae\fR Show the formulae that specify \fIformulae\fR as a dependency\. When given multiple formula arguments, show the intersection of formulae that use \fIformulae\fR\. . .IP @@ -589,10 +598,10 @@ Use \fB\-\-recursive\fR to resolve more than one level of dependencies\. If \fB\-\-installed\fR is passed, only list installed formulae\. . .IP -By default, \fBuses\fR shows all formulae that specify \fIformulae\fR as a required or recommended dependency\. To include the \fB:build\fR type dependencies, pass \fB\-\-include\-build\fR\. Similarly, pass \fB\-\-include\-optional\fR to include \fB:optional\fR dependencies\. To skip \fB:recommended\fR type dependencies, pass \fB\-\-skip\-recommended\fR\. +By default, \fBuses\fR shows all formulae that specify \fIformulae\fR as a required or recommended dependency\. To include the \fB:build\fR type dependencies, pass \fB\-\-include\-build\fR, to include the \fB:test\fR type dependencies, pass \fB\-\-include\-test\fR and to include \fB:optional\fR dependencies pass \fB\-\-include\-optional\fR\. To skip \fB:recommended\fR type dependencies, pass \fB\-\-skip\-recommended\fR\. . .IP -By default, \fBuses\fR shows usages of \fIformulae\fR by stable builds\. To find cases where \fIformulae\fR is used by development or HEAD build, pass \fB\-\-devel\fR or \fB\-\-HEAD\fR\. +By default, \fBuses\fR shows usage of \fIformulae\fR by stable builds\. To find cases where \fIformulae\fR is used by development or HEAD build, pass \fB\-\-devel\fR or \fB\-\-HEAD\fR\. . .TP \fB\-\-cache\fR @@ -890,7 +899,7 @@ If \fB\-\-keep\-tmp\fR is passed, the temporary files created for the test are n Example: \fBbrew install jruby && brew test jruby\fR . .TP -\fBtests\fR [\fB\-\-verbose\fR] [\fB\-\-coverage\fR] [\fB\-\-generic\fR] [\fB\-\-no\-compat\fR] [\fB\-\-only=\fR\fItest_script\fR[\fB:\fR\fIline_number\fR]] [\fB\-\-seed\fR \fIseed\fR] [\fB\-\-online\fR] [\fB\-\-official\-cmd\-taps\fR] +\fBtests\fR [\fB\-\-verbose\fR] [\fB\-\-coverage\fR] [\fB\-\-generic\fR] [\fB\-\-no\-compat\fR] [\fB\-\-only=\fR\fItest_script\fR[\fB:\fR\fIline_number\fR]] [\fB\-\-seed=\fR\fIseed\fR] [\fB\-\-online\fR] [\fB\-\-official\-cmd\-taps\fR] Run Homebrew\'s unit and integration tests\. If provided, \fB\-\-only=\fR\fItest_script\fR runs only \fItest_script\fR_spec\.rb, and \fB\-\-seed\fR randomizes tests with the provided value instead of a random seed\. . .IP @@ -930,16 +939,140 @@ If \fB\-\-keep\-tmp\fR is passed, retain the temporary directory containing the .SH "OFFICIAL EXTERNAL COMMANDS" . .TP -\fBbundle\fR -Bundler for non\-Ruby dependencies from Homebrew: \fIhttps://github\.com/Homebrew/homebrew\-bundle\fR +\fBbundle\fR \fIcommand\fR: +. +.IP +Bundler for non\-Ruby dependencies from Homebrew\. +. +.IP +\fBbundle\fR [\fBinstall\fR] [\fB\-v\fR|\fB\-\-verbose\fR] [\fB\-\-no\-upgrade\fR] [\fB\-\-file=\fR\fIpath\fR|\fB\-\-global\fR]: +. +.IP +Install or upgrade all dependencies in a Brewfile\. +. +.IP +\fBbrew bundle dump\fR [\fB\-\-force\fR] [\fB\-\-describe\fR] [\fB\-\-file=\fR\fIpath\fR|\fB\-\-global\fR] +. +.IP +Write all installed casks/formulae/taps into a Brewfile\. +. +.IP +\fBbrew bundle cleanup\fR [\fB\-\-force\fR] [\fB\-\-zap\fR] [\fB\-\-file=\fR\fIpath\fR|\fB\-\-global\fR] +. +.IP +Uninstall all dependencies not listed in a Brewfile\. +. +.IP +\fBbrew bundle check\fR [\fB\-\-no\-upgrade\fR] [\fB\-\-file\fR=\fIpath\fR|\fB\-\-global\fR] +. +.IP +Check if all dependencies are installed in a Brewfile\. +. +.IP +\fBbrew bundle exec\fR \fIcommand\fR +. +.IP +Run an external command in an isolated build environment\. +. +.IP +\fBbrew bundle list\fR [\fB\-\-all\fR|\fB\-\-brews\fR|\fB\-\-casks\fR|\fB\-\-taps\fR|\fB\-\-mas\fR] [\fB\-\-file=\fR\fIpath\fR|\fB\-\-global\fR] +. +.IP +List all dependencies present in a Brewfile, optionally limiting by types\. +. +.IP +By default, only brew dependencies are output\. +. +.IP +If \fB\-v\fR or \fB\-\-verbose\fR are passed, print verbose output\. +. +.IP +If \fB\-\-no\-upgrade\fR is passed, don\'t run \fBbrew upgrade\fR outdated dependencies\. +. +.IP +Note they may still be upgraded by \fBbrew install\fR if needed\. +. +.IP +If \fB\-\-force\fR is passed, uninstall dependencies or overwrite an existing Brewfile\. +. +.IP +If \fB\-\-file=\fR is passed, the Brewfile path is set accordingly +. +.IP +Use \fB\-\-file=\-\fR to output to console\. +. +.IP +If \fB\-\-global\fR is passed, set Brewfile path to \fB$HOME/\.Brewfile\fR\. +. +.IP +If \fB\-\-describe\fR is passed, output a description comment above each line\. +. +.IP +This comment will not be output if the dependency does not have a description\. +. +.IP +If \fB\-h\fR or \fB\-\-help\fR are passed, print this help message and exit\. +. +.P +Homebrew/homebrew\-bundle \fIhttps://github\.com/Homebrew/homebrew\-bundle\fR . .TP -\fBcask\fR -Install macOS applications distributed as binaries: \fIhttps://github\.com/caskroom/homebrew\-cask\fR +\fBcask\fR [\fB\-\-version\fR | \fBaudit\fR | \fBcat\fR | \fBcleanup\fR | \fBcreate\fR | \fBdoctor\fR | \fBedit\fR | \fBfetch\fR | \fBhome\fR | \fBinfo\fR] +Install macOS applications distributed as binaries\. +. +.P +Caskroom/homebrew\-cask \fIhttps://github\.com/caskroom/homebrew\-cask\fR . .TP -\fBservices\fR -Integrates Homebrew formulae with macOS\'s \fBlaunchctl\fR(1) manager: \fIhttps://github\.com/Homebrew/homebrew\-services\fR +\fBservices\fR \fIcommand\fR: +. +.IP +Integrates Homebrew formulae with macOS\' \fBlaunchctl\fR manager\. +. +.IP +[\fIsudo\fR] \fBbrew services list\fR +. +.IP +List all running services for the current user (or \fIroot\fR) +. +.IP +[\fIsudo\fR] \fBbrew services run\fR \fIformula|\-\-all\fR +. +.IP +Run the service \fIformula\fR without starting at login (or boot)\. +. +.IP +[\fIsudo\fR] \fBbrew services\fR \fBstart\fR \fIformula|\-\-all\fR +. +.IP +Start the service \fIformula\fR immediately and register it to launch at login (or \fIboot\fR)\. +. +.IP +[\fIsudo\fR] \fBbrew services\fR \fBstop\fR \fIformula|\-\-all\fR +. +.IP +Stop the service \fIformula\fR immediately and unregister it from launching at login (or \fIboot\fR)\. +. +.IP +[\fIsudo\fR] \fBbrew services\fR \fBrestart\fR \fIformula|\-\-all\fR +. +.IP +Stop (if necessary) and start the service immediately and register it to launch at login (or \fIboot\fR)\. +. +.IP +[\fIsudo\fR] \fBbrew services\fR \fBcleanup\fR +. +.IP +Remove all unused services\. +. +.IP +If \fBsudo\fR is passed, operate on \fB/Library/LaunchDaemons\fR (started at boot)\. +. +.IP +Otherwise, operate on \fB~/Library/LaunchAgents (started at login)\fR\. +. +.P +Homebrew/homebrew\-services \fIhttps://github\.com/Homebrew/homebrew\-services\fR . .SH "CUSTOM EXTERNAL COMMANDS" Homebrew, like \fBgit\fR(1), supports external commands\. These are executable scripts that reside somewhere in the \fBPATH\fR, named \fBbrew\-\fR\fIcmdname\fR or \fBbrew\-\fR\fIcmdname\fR\fB\.rb\fR, which can be invoked like \fBbrew\fR \fIcmdname\fR\. This allows you to create your own commands without modifying Homebrew\'s internals\. @@ -1111,6 +1244,10 @@ If set, instructs Homebrew to use \fBHOMEBREW_TEMP\fR as the temporary directory This issue typically occurs when using FileVault or custom SSD configurations\. . .TP +\fBHOMEBREW_UPGRADE_CLEANUP\fR +If set, \fBbrew upgrade\fR always assumes \fB\-\-cleanup\fR has been passed\. +. +.TP \fBHOMEBREW_VERBOSE\fR If set, Homebrew always assumes \fB\-\-verbose\fR when running commands\. .