diff options
| author | Mike McQuaid | 2017-02-26 20:48:36 +0000 |
|---|---|---|
| committer | Mike McQuaid | 2017-02-26 20:48:36 +0000 |
| commit | c2a460ec6d857ba33c89174d8d93fcaa403c3717 (patch) | |
| tree | 089045fec4c46fb74e3b48868e2b335497df7b84 | |
| parent | d3ae1cc264dc9eb9b602dd6aa21c4282dc049c79 (diff) | |
| parent | ff93e1624b214c9b48731174a9135789fc3695a8 (diff) | |
| download | brew-c2a460ec6d857ba33c89174d8d93fcaa403c3717.tar.bz2 | |
Merge branch 'master' into filter_all_env_vars_932
628 files changed, 14629 insertions, 12288 deletions
diff --git a/Library/.rubocop.yml b/Library/.rubocop.yml index 097eff995..314467ef0 100644 --- a/Library/.rubocop.yml +++ b/Library/.rubocop.yml @@ -6,6 +6,11 @@ AllCops: - '**/Casks/**/*' - '**/vendor/**/*' +require: ./Homebrew/rubocops.rb + +Homebrew/CorrectBottleBlock: + Enabled: true + Metrics/AbcSize: Enabled: false @@ -41,7 +46,7 @@ Lint/AssignmentInCondition: Enabled: false Lint/EndAlignment: - AlignWith: variable + EnforcedStyleAlignWith: variable Lint/ParenthesesAsGroupedExpression: Enabled: false @@ -63,7 +68,7 @@ Style/BlockDelimiters: EnforcedStyle: line_count_based Style/CaseIndentation: - IndentWhenRelativeTo: end + EnforcedStyle: end Style/ClassAndModuleChildren: EnforcedStyle: nested @@ -163,6 +168,8 @@ Style/TernaryParentheses: # makes diffs nicer Style/TrailingCommaInLiteral: EnforcedStyleForMultiline: comma +Style/TrailingCommaInArguments: + EnforcedStyleForMultiline: comma Style/VariableNumber: Enabled: false diff --git a/Library/Homebrew/.rubocop.yml b/Library/Homebrew/.rubocop.yml index a85f0dcab..938bf21b7 100644 --- a/Library/Homebrew/.rubocop.yml +++ b/Library/Homebrew/.rubocop.yml @@ -12,7 +12,7 @@ AllCops: Style/BlockDelimiters: Exclude: - '**/cask/spec/**/*' - - '**/cask/test/**/*' + - '**/*_spec.rb' # so many of these in formulae but none in here Lint/AmbiguousRegexpLiteral: diff --git a/Library/Homebrew/.rubocop_todo.yml b/Library/Homebrew/.rubocop_todo.yml index c1b2ba6e7..37518a5f0 100644 --- a/Library/Homebrew/.rubocop_todo.yml +++ b/Library/Homebrew/.rubocop_todo.yml @@ -1,12 +1,12 @@ # This configuration was generated by # `rubocop --auto-gen-config --exclude-limit 100` -# on 2016-12-31 22:41:53 +0000 using RuboCop version 0.45.0. +# on 2017-01-27 21:44:55 +0000 using RuboCop version 0.47.1. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. -# Offense count: 16 +# Offense count: 17 Lint/HandleExceptions: Exclude: - 'cmd/install.rb' @@ -60,19 +60,26 @@ Lint/ShadowedException: - 'utils/fork.rb' # Offense count: 13 +# Configuration parameters: CountBlocks. Metrics/BlockNesting: Max: 5 # Offense count: 19 # Configuration parameters: CountComments. Metrics/ModuleLength: - Max: 363 + Max: 400 # Offense count: 1 # Configuration parameters: CountKeywordArgs. Metrics/ParameterLists: Max: 6 +# Offense count: 2 +Security/MarshalLoad: + Exclude: + - 'dependency.rb' + - 'utils/fork.rb' + # Offense count: 1 Style/AccessorMethodName: Exclude: @@ -86,6 +93,18 @@ Style/ClassVars: - 'test/support/helper/fs_leak_logger.rb' # Offense count: 13 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +# SupportedStyles: compact, expanded +Style/EmptyMethod: + Exclude: + - 'debrew/irb.rb' + - 'download_strategy.rb' + - 'extend/ENV/super.rb' + - 'formula.rb' + - 'patch.rb' + +# Offense count: 13 # Configuration parameters: AllowedVariables. Style/GlobalVars: Exclude: diff --git a/Library/Homebrew/.simplecov b/Library/Homebrew/.simplecov index 952bb466b..f74aec72e 100755 --- a/Library/Homebrew/.simplecov +++ b/Library/Homebrew/.simplecov @@ -1,6 +1,6 @@ #!/usr/bin/env ruby -require "english" +require "English" SimpleCov.start do coverage_dir File.expand_path("../test/coverage", File.realpath(__FILE__)) diff --git a/Library/Homebrew/brew.sh b/Library/Homebrew/brew.sh index 81a52f474..11c1a6c59 100644 --- a/Library/Homebrew/brew.sh +++ b/Library/Homebrew/brew.sh @@ -207,6 +207,7 @@ case "$HOMEBREW_COMMAND" in up) HOMEBREW_COMMAND="update" ;; ln) HOMEBREW_COMMAND="link" ;; instal) HOMEBREW_COMMAND="install" ;; # gem does the same + uninstal) HOMEBREW_COMMAND="uninstall" ;; rm) HOMEBREW_COMMAND="uninstall" ;; remove) HOMEBREW_COMMAND="uninstall" ;; configure) HOMEBREW_COMMAND="diy" ;; diff --git a/Library/Homebrew/build.rb b/Library/Homebrew/build.rb index c4e903642..c0f15158d 100644 --- a/Library/Homebrew/build.rb +++ b/Library/Homebrew/build.rb @@ -48,7 +48,7 @@ class Build Requirement.prune elsif req.build? && dependent != formula Requirement.prune - elsif req.satisfied? && req.default_formula? && (dep = req.to_dependency).installed? + elsif req.satisfied? && (dep = req.to_dependency) && dep.installed? deps << dep Requirement.prune end diff --git a/Library/Homebrew/cask/.gitattributes b/Library/Homebrew/cask/.gitattributes deleted file mode 100644 index 176a458f9..000000000 --- a/Library/Homebrew/cask/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -* text=auto diff --git a/Library/Homebrew/cask/Gemfile b/Library/Homebrew/cask/Gemfile index 5c99338b8..5572387cc 100644 --- a/Library/Homebrew/cask/Gemfile +++ b/Library/Homebrew/cask/Gemfile @@ -1,29 +1,13 @@ source "https://rubygems.org" -gem "rake" - -group :debug do - gem "pry" - gem "pry-byebug", platforms: :mri -end - group :test do - # This is SimpleCov v0.12.0 with two fixes merged on top, that finally resolve - # all issues with parallel tests, uncovered files, and tracked files. Switch - # back to stable as soon as v0.12.1 or v0.13.0 is released. For details, see: - # - https://github.com/colszowka/simplecov/pull/513 - # - https://github.com/colszowka/simplecov/pull/520 - gem "simplecov", "0.12.0", - git: "https://github.com/colszowka/simplecov.git", - branch: "master", - ref: "83d8031ddde0927f87ef9327200a98583ca18d77", - require: false + gem "simplecov", require: false gem "codecov", require: false - gem "minitest", "~> 5.9" + gem "minitest" gem "minitest-reporters" - gem "mocha", "~> 1.1", require: false + gem "mocha", require: false gem "parallel_tests" - gem "rspec", "~> 3.5" + gem "rspec" gem "rspec-its", require: false gem "rspec-wait", require: false end diff --git a/Library/Homebrew/cask/Gemfile.lock b/Library/Homebrew/cask/Gemfile.lock index 4bdf2d0f6..700f093d1 100644 --- a/Library/Homebrew/cask/Gemfile.lock +++ b/Library/Homebrew/cask/Gemfile.lock @@ -1,49 +1,27 @@ -GIT - remote: https://github.com/colszowka/simplecov.git - revision: 83d8031ddde0927f87ef9327200a98583ca18d77 - ref: 83d8031ddde0927f87ef9327200a98583ca18d77 - branch: master - specs: - simplecov (0.12.0) - docile (~> 1.1.0) - json (>= 1.8, < 3) - simplecov-html (~> 0.10.0) - GEM remote: https://rubygems.org/ specs: ansi (1.5.0) - builder (3.2.2) - byebug (9.0.6) - codecov (0.1.6) + builder (3.2.3) + codecov (0.1.9) json simplecov url - coderay (1.1.1) - diff-lcs (1.2.5) + diff-lcs (1.3) docile (1.1.5) - json (2.0.2) + json (2.0.3) metaclass (0.0.4) - method_source (0.8.2) - minitest (5.9.1) - minitest-reporters (1.1.12) + minitest (5.10.1) + minitest-reporters (1.1.14) ansi builder minitest (>= 5.0) ruby-progressbar mocha (1.2.1) metaclass (~> 0.0.1) - parallel (1.9.0) - parallel_tests (2.10.0) + parallel (1.10.0) + parallel_tests (2.13.0) parallel - pry (0.10.4) - coderay (~> 1.1.0) - method_source (~> 0.8.1) - slop (~> 3.4) - pry-byebug (3.4.0) - byebug (~> 9.0) - pry (~> 0.10) - rake (11.3.0) rspec (3.5.0) rspec-core (~> 3.5.0) rspec-expectations (~> 3.5.0) @@ -63,8 +41,11 @@ GEM rspec-wait (0.0.9) rspec (>= 3, < 4) ruby-progressbar (1.8.1) + simplecov (0.13.0) + docile (~> 1.1.0) + json (>= 1.8, < 3) + simplecov-html (~> 0.10.0) simplecov-html (0.10.0) - slop (3.6.0) url (0.3.2) PLATFORMS @@ -72,17 +53,14 @@ PLATFORMS DEPENDENCIES codecov - minitest (~> 5.9) + minitest minitest-reporters - mocha (~> 1.1) + mocha parallel_tests - pry - pry-byebug - rake - rspec (~> 3.5) + rspec rspec-its rspec-wait - simplecov (= 0.12.0)! + simplecov BUNDLED WITH - 1.13.6 + 1.13.7 diff --git a/Library/Homebrew/cask/Rakefile b/Library/Homebrew/cask/Rakefile deleted file mode 100644 index 39398aa19..000000000 --- a/Library/Homebrew/cask/Rakefile +++ /dev/null @@ -1,26 +0,0 @@ -require "rake/testtask" -require "rspec/core/rake_task" - -$LOAD_PATH.unshift(File.expand_path("#{ENV["HOMEBREW_REPOSITORY"]}/Library/Homebrew")) -$LOAD_PATH.unshift(File.expand_path("../lib", __FILE__)) - -namespace :test do - namespace :coverage do - desc "Upload coverage to Codecov" - task :upload do - require "simplecov" - require "codecov" - formatter = SimpleCov::Formatter::Codecov.new - formatter.format(SimpleCov::ResultMerger.merged_result) - end - end -end - -desc "Open a REPL for debugging and experimentation" -task :console do - require "pry" - require "pry-byebug" - require "hbc" - ARGV.clear - Hbc.pry -end diff --git a/Library/Homebrew/cask/cmd/brew-cask-tests.rb b/Library/Homebrew/cask/cmd/brew-cask-tests.rb index 43683a263..b27bc2fe7 100755 --- a/Library/Homebrew/cask/cmd/brew-cask-tests.rb +++ b/Library/Homebrew/cask/cmd/brew-cask-tests.rb @@ -10,8 +10,8 @@ def run_tests(executable, files, args = []) system "bundle", "exec", executable, *opts, "--", *args, "--", *files end -repo_root = Pathname.new(__FILE__).realpath.parent.parent -repo_root.cd do +cask_root = Pathname.new(__FILE__).realpath.parent.parent +cask_root.cd do ENV["HOMEBREW_NO_ANALYTICS_THIS_RUN"] = "1" ENV["HOMEBREW_NO_EMOJI"] = "1" ENV.delete("HOMEBREW_CASK_OPTS") @@ -21,37 +21,25 @@ repo_root.cd do system "bundle", "install" end - rspec = ARGV.flag?("--rspec") || !ARGV.flag?("--minitest") - minitest = ARGV.flag?("--minitest") || !ARGV.flag?("--rspec") - - p [:coverage, ARGV.flag?("--coverage"), ENV["CI"], ENV["TRAVIS"]] if ARGV.flag?("--coverage") ENV["HOMEBREW_TESTS_COVERAGE"] = "1" upload_coverage = ENV["CODECOV_TOKEN"] || ENV["TRAVIS"] end - failed = false - - if rspec - run_tests "parallel_rspec", Dir["spec/**/*_spec.rb"], %w[ - --color - --require spec_helper - --format progress - --format ParallelTests::RSpec::RuntimeLogger - --out tmp/parallel_runtime_rspec.log - ] - failed ||= !$CHILD_STATUS.success? - end + run_tests "parallel_rspec", Dir["spec/**/*_spec.rb"], %w[ + --color + --require spec_helper + --format progress + --format ParallelTests::RSpec::RuntimeLogger + --out tmp/parallel_runtime_rspec.log + ] - if minitest - run_tests "parallel_test", Dir["test/**/*_test.rb"] - failed ||= !$CHILD_STATUS.success? + unless $CHILD_STATUS.success? + Homebrew.failed = true end - Homebrew.failed = failed - if upload_coverage puts "Submitting Codecov coverage..." - system "bundle", "exec", "rake", "test:coverage:upload" + system "bundle", "exec", "spec/upload_coverage.rb" end end diff --git a/Library/Homebrew/cask/lib/hbc.rb b/Library/Homebrew/cask/lib/hbc.rb index 69b6e8f21..80f1f1da0 100644 --- a/Library/Homebrew/cask/lib/hbc.rb +++ b/Library/Homebrew/cask/lib/hbc.rb @@ -6,6 +6,7 @@ require "hbc/audit" require "hbc/auditor" require "hbc/cache" require "hbc/cask" +require "hbc/cask_loader" require "hbc/without_source" require "hbc/caskroom" require "hbc/checkable" @@ -46,7 +47,7 @@ module Hbc def self.init Cache.ensure_cache_exists - Cache.migrate_legacy_cache + Cache.delete_legacy_cache Caskroom.migrate_caskroom_from_repo_to_prefix Caskroom.ensure_caskroom_exists diff --git a/Library/Homebrew/cask/lib/hbc/artifact.rb b/Library/Homebrew/cask/lib/hbc/artifact.rb index 8b4babdf6..b155a125a 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact.rb @@ -27,41 +27,39 @@ module Hbc module Artifact # NOTE: order is important here, since we want to extract nested containers # before we handle any other artifacts - def self.artifacts - [ - PreflightBlock, - NestedContainer, - Installer, - App, - Suite, - Artifact, # generic 'artifact' stanza - Colorpicker, - Pkg, - Prefpane, - Qlplugin, - Dictionary, - Font, - Service, - StageOnly, - Binary, - InputMethod, - InternetPlugin, - AudioUnitPlugin, - VstPlugin, - Vst3Plugin, - ScreenSaver, - Uninstall, - PostflightBlock, - Zap, - ] - end + TYPES = [ + PreflightBlock, + NestedContainer, + Installer, + App, + Suite, + Artifact, # generic 'artifact' stanza + Colorpicker, + Pkg, + Prefpane, + Qlplugin, + Dictionary, + Font, + Service, + StageOnly, + Binary, + InputMethod, + InternetPlugin, + AudioUnitPlugin, + VstPlugin, + Vst3Plugin, + ScreenSaver, + Uninstall, + PostflightBlock, + Zap, + ].freeze - def self.for_cask(cask) + def self.for_cask(cask, command: SystemCommand, force: false) odebug "Determining which artifacts are present in Cask #{cask}" - artifacts.select do |artifact| - odebug "Checking for artifact class #{artifact}" - artifact.me?(cask) - end + + TYPES + .select { |klass| klass.me?(cask) } + .map { |klass| klass.new(cask, command: command, force: force) } end end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/base.rb b/Library/Homebrew/cask/lib/hbc/artifact/base.rb index b53c13f08..d925ff340 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/base.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/base.rb @@ -27,10 +27,6 @@ module Hbc attr_reader :force - def zap_phase - odebug "Nothing to do. The #{self.class.artifact_name} artifact has no zap phase." - end - # TODO: this sort of logic would make more sense in dsl.rb, or a # constructor called from dsl.rb, so long as that isn't slow. def self.read_script_arguments(arguments, stanza, default_arguments = {}, override_arguments = {}, key = nil) diff --git a/Library/Homebrew/cask/lib/hbc/artifact/installer.rb b/Library/Homebrew/cask/lib/hbc/artifact/installer.rb index b64b00fe3..55e8d38c0 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/installer.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/installer.rb @@ -3,16 +3,6 @@ require "hbc/artifact/base" module Hbc module Artifact class Installer < Base - # TODO: for backward compatibility, removeme - def install - install_phase - end - - # TODO: for backward compatibility, removeme - def uninstall - uninstall_phase - end - def install_phase @cask.artifacts[self.class.artifact_dsl_key].each do |artifact| if artifact.manual @@ -36,10 +26,6 @@ module Hbc end end end - - def uninstall_phase - odebug "Nothing to do. The #{self.class.artifact_dsl_key} artifact has no uninstall phase." - end end end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/nested_container.rb b/Library/Homebrew/cask/lib/hbc/artifact/nested_container.rb index 107640797..45f23fe37 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/nested_container.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/nested_container.rb @@ -7,10 +7,6 @@ module Hbc @cask.artifacts[:nested_container].each { |container| extract(container) } end - def uninstall_phase - # no need to take action; is removed after extraction - end - def extract(container_relative_path) source = @cask.staged_path.join(container_relative_path) container = Container.for_path(source, @command) diff --git a/Library/Homebrew/cask/lib/hbc/artifact/pkg.rb b/Library/Homebrew/cask/lib/hbc/artifact/pkg.rb index 0569d2a86..6d6362d46 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/pkg.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/pkg.rb @@ -36,10 +36,6 @@ module Hbc @cask.artifacts[:pkg].each { |pkg_description| run_installer(pkg_description) } end - def uninstall_phase - # Do nothing. Must be handled explicitly by a separate :uninstall stanza. - end - def run_installer(pkg_description) load_pkg_description pkg_description ohai "Running installer for #{@cask}; your password may be necessary." diff --git a/Library/Homebrew/cask/lib/hbc/artifact/stage_only.rb b/Library/Homebrew/cask/lib/hbc/artifact/stage_only.rb index 594c5bef9..1122c1d02 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/stage_only.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/stage_only.rb @@ -6,14 +6,6 @@ module Hbc def self.artifact_dsl_key :stage_only end - - def install_phase - # do nothing - end - - def uninstall_phase - # do nothing - end end end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/uninstall.rb b/Library/Homebrew/cask/lib/hbc/artifact/uninstall.rb index 8b5603064..5a3dc098d 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/uninstall.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/uninstall.rb @@ -3,6 +3,9 @@ require "hbc/artifact/uninstall_base" module Hbc module Artifact class Uninstall < UninstallBase + def uninstall_phase + dispatch_uninstall_directives + end end end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/uninstall_base.rb b/Library/Homebrew/cask/lib/hbc/artifact/uninstall_base.rb index ccb06a9ab..75d210931 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/uninstall_base.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/uninstall_base.rb @@ -34,6 +34,10 @@ module Hbc end end + def self.expand_glob(path_strings) + path_strings.flat_map(&Pathname.method(:glob)) + end + def self.remove_relative_path_strings(action, path_strings) relative = path_strings.map do |path_string| path_string if %r{/\.\.(?:/|\Z)}.match(path_string) || !%r{\A/}.match(path_string) @@ -54,15 +58,14 @@ module Hbc path_strings - undeletable end - def install_phase - odebug "Nothing to do. The uninstall artifact has no install phase." - end - - def uninstall_phase - dispatch_uninstall_directives + def self.prepare_path_strings(action, path_strings, expand_tilde) + path_strings = expand_path_strings(path_strings) if expand_tilde + path_strings = remove_relative_path_strings(action, path_strings) + path_strings = expand_glob(path_strings) + remove_undeletable_path_strings(action, path_strings) end - def dispatch_uninstall_directives(expand_tilde = true) + def dispatch_uninstall_directives(expand_tilde: true) directives_set = @cask.artifacts[stanza] ohai "Running #{stanza} process for #{@cask}; your password may be necessary" @@ -209,7 +212,15 @@ module Hbc ohai "Running uninstall script #{executable}" raise CaskInvalidError.new(@cask, "#{stanza} :#{directive_name} without :executable.") if executable.nil? executable_path = @cask.staged_path.join(executable) - @command.run("/bin/chmod", args: ["--", "+x", executable_path]) if File.exist?(executable_path) + + unless executable_path.exist? + message = "uninstall script #{executable} does not exist" + raise CaskError, "#{message}." unless force + opoo "#{message}, skipping." + return + end + + @command.run("/bin/chmod", args: ["--", "+x", executable_path]) @command.run(executable_path, script_arguments) sleep 1 end @@ -225,9 +236,7 @@ module Hbc def uninstall_delete(directives, expand_tilde = true) Array(directives[:delete]).concat(Array(directives[:trash])).flatten.each_slice(PATH_ARG_SLICE_SIZE) do |path_slice| ohai "Removing files: #{path_slice.utf8_inspect}" - path_slice = self.class.expand_path_strings(path_slice) if expand_tilde - path_slice = self.class.remove_relative_path_strings(:delete, path_slice) - path_slice = self.class.remove_undeletable_path_strings(:delete, path_slice) + path_slice = self.class.prepare_path_strings(:delete, path_slice, expand_tilde) @command.run!("/bin/rm", args: path_slice.unshift("-rf", "--"), sudo: true) end end @@ -238,11 +247,9 @@ module Hbc uninstall_delete(directives, expand_tilde) end - def uninstall_rmdir(directives, expand_tilde = true) - Array(directives[:rmdir]).flatten.each do |directory| - directory = self.class.expand_path_strings([directory]).first if expand_tilde - directory = self.class.remove_relative_path_strings(:rmdir, [directory]).first - directory = self.class.remove_undeletable_path_strings(:rmdir, [directory]).first + def uninstall_rmdir(directories, expand_tilde = true) + action = :rmdir + self.class.prepare_path_strings(action, Array(directories[action]).flatten, expand_tilde).each do |directory| next if directory.to_s.empty? ohai "Removing directory if empty: #{directory.to_s.utf8_inspect}" directory = Pathname.new(directory) diff --git a/Library/Homebrew/cask/lib/hbc/artifact/zap.rb b/Library/Homebrew/cask/lib/hbc/artifact/zap.rb index 503ea35c4..7793e5772 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/zap.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/zap.rb @@ -3,17 +3,8 @@ require "hbc/artifact/uninstall_base" module Hbc module Artifact class Zap < UninstallBase - def install_phase - odebug "Nothing to do. The zap artifact has no install phase." - end - - def uninstall_phase - odebug "Nothing to do. The zap artifact has no uninstall phase." - end - def zap_phase - expand_tilde = true - dispatch_uninstall_directives(expand_tilde) + dispatch_uninstall_directives(expand_tilde: true) end end end diff --git a/Library/Homebrew/cask/lib/hbc/audit.rb b/Library/Homebrew/cask/lib/hbc/audit.rb index 955ecdbb0..12cefb939 100644 --- a/Library/Homebrew/cask/lib/hbc/audit.rb +++ b/Library/Homebrew/cask/lib/hbc/audit.rb @@ -133,20 +133,19 @@ module Hbc def check_appcast_checkpoint_accuracy odebug "Verifying appcast checkpoint is accurate" - result = @command.run("/usr/bin/curl", args: ["--compressed", "--location", "--user-agent", URL::FAKE_USER_AGENT, cask.appcast], print_stderr: false) - if result.success? - processed_appcast_text = result.stdout.gsub(%r{<pubDate>[^<]*</pubDate>}, "") - # This step is necessary to replicate running `sed` from the command line - processed_appcast_text << "\n" unless processed_appcast_text.end_with?("\n") + result = cask.appcast.calculate_checkpoint + + actual_checkpoint = result[:checkpoint] + + if actual_checkpoint.nil? + add_warning "error retrieving appcast: #{result[:command_result].stderr}" + else expected = cask.appcast.checkpoint - actual = Digest::SHA2.hexdigest(processed_appcast_text) - add_warning <<-EOS.undent unless expected == actual + add_warning <<-EOS.undent unless expected == actual_checkpoint appcast checkpoint mismatch Expected: #{expected} - Actual: #{actual} + Actual: #{actual_checkpoint} EOS - else - add_warning "error retrieving appcast: #{result.stderr}" end end diff --git a/Library/Homebrew/cask/lib/hbc/cache.rb b/Library/Homebrew/cask/lib/hbc/cache.rb index e343da3fa..7b586528e 100644 --- a/Library/Homebrew/cask/lib/hbc/cache.rb +++ b/Library/Homebrew/cask/lib/hbc/cache.rb @@ -9,27 +9,10 @@ module Hbc Hbc.cache.mkpath end - def migrate_legacy_cache + def delete_legacy_cache return unless Hbc.legacy_cache.exist? - ohai "Migrating cached files to #{Hbc.cache}..." - Hbc.legacy_cache.children.select(&:symlink?).each do |symlink| - file = symlink.readlink - - new_name = file.basename - .sub(/\-((?:(\d|#{DSL::Version::DIVIDER_REGEX})*\-\2*)*[^\-]+)$/x, - '--\1') - - renamed_file = Hbc.cache.join(new_name) - - if file.exist? - puts "#{file} -> #{renamed_file}" - FileUtils.mv(file, renamed_file) - end - - FileUtils.rm(symlink) - end - + ohai "Deleting legacy cache at #{Hbc.legacy_cache}..." FileUtils.remove_entry_secure(Hbc.legacy_cache) end end diff --git a/Library/Homebrew/cask/lib/hbc/cask_loader.rb b/Library/Homebrew/cask/lib/hbc/cask_loader.rb index 3875b30df..3fe02d7e1 100644 --- a/Library/Homebrew/cask/lib/hbc/cask_loader.rb +++ b/Library/Homebrew/cask/lib/hbc/cask_loader.rb @@ -32,22 +32,12 @@ module Hbc end def cask(header_token, &block) - @klass = Cask - build_cask(header_token, &block) - end - - def test_cask(header_token, &block) - @klass = TestCask - build_cask(header_token, &block) - end - - def build_cask(header_token, &block) raise CaskTokenDoesNotMatchError.new(@token, header_token) unless @token == header_token if @path.nil? - @klass.new(@token, &block) + Cask.new(@token, &block) else - @klass.new(@token, sourcefile_path: @path, &block) + Cask.new(@token, sourcefile_path: @path, &block) end end end diff --git a/Library/Homebrew/cask/lib/hbc/caskroom.rb b/Library/Homebrew/cask/lib/hbc/caskroom.rb index 644728129..255e23888 100644 --- a/Library/Homebrew/cask/lib/hbc/caskroom.rb +++ b/Library/Homebrew/cask/lib/hbc/caskroom.rb @@ -21,9 +21,10 @@ module Hbc return if Hbc.caskroom.exist? ohai "Creating Caskroom at #{Hbc.caskroom}" - ohai "We'll set permissions properly so we won't need sudo in the future" sudo = !Hbc.caskroom.parent.writable? + ohai "We'll set permissions properly so we won't need sudo in the future" if sudo + SystemCommand.run("/bin/mkdir", args: ["-p", Hbc.caskroom], sudo: sudo) SystemCommand.run("/bin/chmod", args: ["g+rwx", Hbc.caskroom], sudo: sudo) SystemCommand.run("/usr/sbin/chown", args: [Utils.current_user, Hbc.caskroom], sudo: sudo) diff --git a/Library/Homebrew/cask/lib/hbc/cli.rb b/Library/Homebrew/cask/lib/hbc/cli.rb index 42c3982ba..8e178e373 100644 --- a/Library/Homebrew/cask/lib/hbc/cli.rb +++ b/Library/Homebrew/cask/lib/hbc/cli.rb @@ -23,6 +23,7 @@ require "hbc/cli/zap" require "hbc/cli/internal_use_base" require "hbc/cli/internal_audit_modified_casks" +require "hbc/cli/internal_appcast_checkpoint" require "hbc/cli/internal_checkurl" require "hbc/cli/internal_dump" require "hbc/cli/internal_help" @@ -36,6 +37,7 @@ module Hbc "-S" => "search", # verb starting with "-" is questionable "up" => "update", "instal" => "install", # gem does the same + "uninstal" => "uninstall", "rm" => "uninstall", "remove" => "uninstall", "abv" => "info", @@ -141,13 +143,17 @@ module Hbc end def self.process(arguments) + unless ENV["MACOS_VERSION"].nil? + MacOS.full_version = ENV["MACOS_VERSION"] + end + command_string, *rest = *arguments rest = process_options(rest) command = Hbc.help ? "help" : lookup_command(command_string) Hbc.default_tap.install unless Hbc.default_tap.installed? Hbc.init if should_init?(command) run_command(command, *rest) - rescue CaskError, CaskSha256MismatchError => e + rescue CaskError, CaskSha256MismatchError, ArgumentError => e msg = e.message msg << e.backtrace.join("\n") if Hbc.debug onoe msg diff --git a/Library/Homebrew/cask/lib/hbc/cli/doctor.rb b/Library/Homebrew/cask/lib/hbc/cli/doctor.rb index 84d8e1ebc..6b2f4caab 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/doctor.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/doctor.rb @@ -2,116 +2,39 @@ module Hbc class CLI class Doctor < Base def self.run - ohai "macOS Release:", render_with_none_as_error(MacOS.full_version) - ohai "Hardware Architecture:", render_with_none_as_error("#{Hardware::CPU.type}-#{Hardware::CPU.bits}") - ohai "Ruby Version:", render_with_none_as_error("#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}") - ohai "Ruby Path:", render_with_none_as_error(RbConfig.ruby) - # TODO: consider removing most Homebrew constants from doctor output - ohai "Homebrew Version:", render_with_none_as_error(homebrew_version) - ohai "Homebrew Executable Path:", render_with_none_as_error(HOMEBREW_BREW_FILE) - ohai "Homebrew Cellar Path:", render_with_none_as_error(homebrew_cellar) - ohai "Homebrew Repository Path:", render_with_none_as_error(HOMEBREW_REPOSITORY) - ohai "Homebrew Origin:", render_with_none_as_error(homebrew_origin) - ohai "Homebrew-Cask Version:", render_with_none_as_error(Hbc.full_version) - ohai "Homebrew-Cask Install Location:", render_install_location - ohai "Homebrew-Cask Staging Location:", render_staging_location(Hbc.caskroom) - ohai "Homebrew-Cask Cached Downloads:", render_cached_downloads - ohai "Homebrew-Cask Default Tap Path:", render_tap_paths(Hbc.default_tap.path) - ohai "Homebrew-Cask Alternate Cask Taps:", render_tap_paths(alt_taps) - ohai "Homebrew-Cask Default Tap Cask Count:", render_with_none_as_error(default_cask_count) - ohai "Contents of $LOAD_PATH:", render_load_path($LOAD_PATH) - ohai "Contents of $RUBYLIB Environment Variable:", render_env_var("RUBYLIB") - ohai "Contents of $RUBYOPT Environment Variable:", render_env_var("RUBYOPT") - ohai "Contents of $RUBYPATH Environment Variable:", render_env_var("RUBYPATH") - ohai "Contents of $RBENV_VERSION Environment Variable:", render_env_var("RBENV_VERSION") - ohai "Contents of $CHRUBY_VERSION Environment Variable:", render_env_var("CHRUBY_VERSION") - ohai "Contents of $GEM_HOME Environment Variable:", render_env_var("GEM_HOME") - ohai "Contents of $GEM_PATH Environment Variable:", render_env_var("GEM_PATH") - ohai "Contents of $BUNDLE_PATH Environment Variable:", render_env_var("BUNDLE_PATH") - ohai "Contents of $PATH Environment Variable:", render_env_var("PATH") - ohai "Contents of $SHELL Environment Variable:", render_env_var("SHELL") - ohai "Contents of Locale Environment Variables:", render_with_none(locale_variables) - end - - def self.alt_taps - Tap.select { |t| t.cask_dir && t != Hbc.default_tap } - .map(&:path) - end - - def self.default_cask_count - Hbc.default_tap.cask_files.count - rescue StandardError - "0 #{error_string "Error reading #{Hbc.default_tap.path}"}" - end - - def self.homebrew_origin - homebrew_origin = notfound_string - begin - Dir.chdir(HOMEBREW_REPOSITORY) do - homebrew_origin = SystemCommand.run("/usr/bin/git", - args: %w[config --get remote.origin.url], - print_stderr: false).stdout.strip - end - if homebrew_origin !~ /\S/ - homebrew_origin = "#{none_string} #{error_string}" - elsif homebrew_origin !~ %r{(mxcl|Homebrew)/(home)?brew(\.git)?\Z} - homebrew_origin.concat " #{error_string "warning: nonstandard origin"}" - end - rescue StandardError - homebrew_origin = error_string "Not Found - Error running git" - end - homebrew_origin - end - - def self.homebrew_cellar - homebrew_constants("cellar") - end - - def self.homebrew_version - homebrew_constants("version") - end - - def self.homebrew_taps - Tap::TAP_DIRECTORY - end - - def self.homebrew_constants(name) - @homebrew_constants ||= {} - return @homebrew_constants[name] if @homebrew_constants.key?(name) - @homebrew_constants[name] = notfound_string - begin - @homebrew_constants[name] = SystemCommand.run!(HOMEBREW_BREW_FILE, - args: ["--#{name}"], - print_stderr: false) - .stdout - .strip - if @homebrew_constants[name] !~ /\S/ - @homebrew_constants[name] = "#{none_string} #{error_string}" - end - path = Pathname.new(@homebrew_constants[name]) - @homebrew_constants[name] = path if path.exist? - rescue StandardError - @homebrew_constants[name] = error_string "Not Found - Error running brew" - end - @homebrew_constants[name] + ohai "Homebrew-Cask Version", Hbc.full_version + ohai "Homebrew-Cask Install Location", render_install_location + ohai "Homebrew-Cask Staging Location", render_staging_location(Hbc.caskroom) + ohai "Homebrew-Cask Cached Downloads", render_cached_downloads + ohai "Homebrew-Cask Taps:" + puts render_taps(Hbc.default_tap, *alt_taps) + ohai "Contents of $LOAD_PATH", render_load_path($LOAD_PATH) + ohai "Environment Variables" + + environment_variables = [ + "RUBYLIB", + "RUBYOPT", + "RUBYPATH", + "RBENV_VERSION", + "CHRUBY_VERSION", + "GEM_HOME", + "GEM_PATH", + "BUNDLE_PATH", + "PATH", + "SHELL", + ] + + (locale_variables + environment_variables).sort.each(&method(:render_env_var)) end def self.locale_variables - ENV.keys.grep(/^(?:LC_\S+|LANG|LANGUAGE)\Z/).collect { |v| %Q(#{v}="#{ENV[v]}") }.sort.join("\n") + ENV.keys.grep(/^(?:LC_\S+|LANG|LANGUAGE)\Z/).sort end def self.none_string "<NONE>" end - def self.legacy_tap_pattern - /phinze/ - end - - def self.notfound_string - Formatter.error("Not Found - Unknown Error") - end - def self.error_string(string = "Error") Formatter.error("(#{string})") end @@ -121,37 +44,42 @@ module Hbc none_string end - def self.render_with_none_as_error(string) - return string if !string.nil? && string.respond_to?(:to_s) && !string.to_s.empty? - "#{none_string} #{error_string}" + def self.alt_taps + Tap.select { |t| t.cask_dir && t != Hbc.default_tap } end - def self.render_tap_paths(paths) - paths = [paths] unless paths.respond_to?(:each) - paths.collect do |dir| - if dir.nil? || dir.to_s.empty? + def self.cask_count_for_tap(tap) + count = tap.cask_files.count + "#{count} #{count == 1 ? "cask" : "casks"}" + rescue StandardError + "0 #{error_string "error reading #{tap.path}"}" + end + + def self.render_taps(*taps) + taps.collect do |tap| + if tap.path.nil? || tap.path.to_s.empty? none_string - elsif dir.to_s.match(legacy_tap_pattern) - dir.to_s.concat(" #{error_string "Warning: legacy tap path"}") else - dir.to_s + "#{tap.path} (#{cask_count_for_tap(tap)})" end end end def self.render_env_var(var) - if ENV.key?(var) - %Q(#{var}="#{ENV[var]}") - else - none_string - end + return unless ENV.key?(var) + var = %Q(#{var}="#{ENV[var]}") + puts user_tilde(var) + end + + def self.user_tilde(path) + path.gsub(ENV["HOME"], "~") end # This could be done by calling into Homebrew, but the situation # where "doctor" is needed is precisely the situation where such # things are less dependable. def self.render_install_location - locations = Dir.glob(Pathname.new(homebrew_cellar).join("brew-cask", "*")).reverse + locations = Dir.glob(HOMEBREW_CELLAR.join("brew-cask", "*")).reverse if locations.empty? none_string else @@ -162,7 +90,7 @@ module Hbc end def self.render_staging_location(path) - path = Pathname.new(path) + path = Pathname.new(user_tilde(path.to_s)) if !path.exist? "#{path} #{error_string "error: path does not exist"}}" elsif !path.writable? @@ -173,19 +101,18 @@ module Hbc end def self.render_load_path(paths) + paths.map(&method(:user_tilde)) return "#{none_string} #{error_string}" if [*paths].empty? paths end def self.render_cached_downloads cleanup = CLI::Cleanup.default - files = cleanup.cache_files - count = files.count + count = cleanup.cache_files.count size = cleanup.disk_cleanup_size - size_msg = "#{number_readable(count)} files, #{disk_usage_readable(size)}" - warn_msg = error_string('warning: run "brew cask cleanup"') - size_msg << " #{warn_msg}" if count > 0 - [Hbc.cache, size_msg] + msg = user_tilde(Hbc.cache.to_s) + msg << " (#{number_readable(count)} files, #{disk_usage_readable(size)})" unless count.zero? + msg end def self.help diff --git a/Library/Homebrew/cask/lib/hbc/cli/fetch.rb b/Library/Homebrew/cask/lib/hbc/cli/fetch.rb index 9b3d5099c..fc928586f 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/fetch.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/fetch.rb @@ -15,6 +15,10 @@ module Hbc end end + def self.needs_init? + true + end + def self.help "downloads remote application files to local cache" end diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb new file mode 100644 index 000000000..790e917b2 --- /dev/null +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb @@ -0,0 +1,61 @@ +module Hbc + class CLI + class InternalAppcastCheckpoint < InternalUseBase + def self.run(*args) + calculate = args.include? "--calculate" + cask_tokens = cask_tokens_from(args) + raise CaskUnspecifiedError if cask_tokens.empty? + + if cask_tokens.all? { |t| t =~ %r{^https?://} && t !~ /\.rb$/ } + appcask_checkpoint_for_url(cask_tokens) + else + appcask_checkpoint(cask_tokens, calculate) + end + end + + def self.appcask_checkpoint_for_url(urls) + urls.each do |url| + appcast = DSL::Appcast.new(url) + puts appcast.calculate_checkpoint[:checkpoint] + end + end + + def self.appcask_checkpoint(cask_tokens, calculate) + count = 0 + + cask_tokens.each do |cask_token| + cask = Hbc.load(cask_token) + + if cask.appcast.nil? + opoo "Cask '#{cask}' is missing an `appcast` stanza." + else + if calculate + result = cask.appcast.calculate_checkpoint + + checkpoint = result[:checkpoint] + else + checkpoint = cask.appcast.checkpoint + end + + if checkpoint.nil? + onoe "Could not retrieve `appcast` checkpoint for cask '#{cask}': #{result[:command_result].stderr}" + else + puts cask_tokens.count > 1 ? "#{checkpoint} #{cask}": checkpoint + count += 1 + end + end + end + + count == cask_tokens.count + end + + def self.help + "prints or calculates a given Cask's or URL's appcast checkpoint" + end + + def self.needs_init? + true + end + end + end +end diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_dump.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_dump.rb index af1494e5f..ac1b20493 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/internal_dump.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_dump.rb @@ -27,7 +27,7 @@ module Hbc end def self.help - "Dump the given Cask in YAML format" + "dump the given Cask in YAML format" end end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_help.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_help.rb index 6c646cfd7..0908ee05e 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/internal_help.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_help.rb @@ -16,7 +16,7 @@ module Hbc end def self.help - "Print help strings for unstable internal-use commands" + "print help strings for unstable internal-use commands" end end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb index e5c04ee51..c54db8795 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb @@ -44,18 +44,20 @@ module Hbc :stage_only, :nested_container, :uninstall, - :postflight, - :uninstall_postflight, :preflight, + :postflight, + :uninstall_preflight, :uninstall_postflight, ] - def self.run(*arguments) - table = arguments.include? "--table" - quiet = arguments.include? "--quiet" - format = :to_yaml if arguments.include? "--yaml" - format = :inspect if arguments.include? "--inspect" - cask_tokens = arguments.reject { |arg| arg.chars.first == "-" } + def self.run(*args) + raise ArgumentError, "No stanza given." if args.empty? + + table = args.include? "--table" + quiet = args.include? "--quiet" + format = :to_yaml if args.include? "--yaml" + format = :inspect if args.include? "--inspect" + cask_tokens = cask_tokens_from(args) stanza = cask_tokens.shift.to_sym cask_tokens = Hbc.all_tokens if cask_tokens.empty? @@ -125,7 +127,7 @@ module Hbc end def self.help - "Extract and render a specific stanza for the given Casks" + "extract and render a specific stanza for the given Casks" end end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/list.rb b/Library/Homebrew/cask/lib/hbc/cli/list.rb index 4094b3d38..e100fbd83 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/list.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/list.rb @@ -55,7 +55,7 @@ module Hbc def self.list_artifacts(cask) Artifact.for_cask(cask).each do |artifact| - summary = artifact.new(cask).summary + summary = artifact.summary ohai summary[:english_description], summary[:contents] unless summary.empty? end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/style.rb b/Library/Homebrew/cask/lib/hbc/cli/style.rb index cdcc135b8..d3e44382d 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/style.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/style.rb @@ -23,12 +23,10 @@ module Hbc $CHILD_STATUS.success? end - RUBOCOP_CASK_VERSION = "~> 0.10.6".freeze - def install_rubocop Utils.capture_stderr do begin - Homebrew.install_gem_setup_path! "rubocop-cask", RUBOCOP_CASK_VERSION, "rubocop" + Homebrew.install_gem_setup_path! "rubocop-cask", HOMEBREW_RUBOCOP_CASK_VERSION, "rubocop" rescue SystemExit raise CaskError, Tty.strip_ansi($stderr.string).chomp.sub(/\AError: /, "") end diff --git a/Library/Homebrew/cask/lib/hbc/container.rb b/Library/Homebrew/cask/lib/hbc/container.rb index e31fbc8fb..fc7246f3d 100644 --- a/Library/Homebrew/cask/lib/hbc/container.rb +++ b/Library/Homebrew/cask/lib/hbc/container.rb @@ -16,7 +16,6 @@ require "hbc/container/tar" require "hbc/container/ttf" require "hbc/container/rar" require "hbc/container/xar" -require "hbc/container/xip" require "hbc/container/xz" require "hbc/container/zip" @@ -34,7 +33,6 @@ module Hbc Sit, Rar, Zip, - Xip, # needs to be before xar as this is a cpio inside a gzip inside a xar Xar, # need to be before tar as tar can also list xar Tar, # or compressed tar (bzip2/gzip/lzma/xz) Bzip2, # pure bzip2 diff --git a/Library/Homebrew/cask/lib/hbc/container/dmg.rb b/Library/Homebrew/cask/lib/hbc/container/dmg.rb index 987455ad7..815f8f010 100644 --- a/Library/Homebrew/cask/lib/hbc/container/dmg.rb +++ b/Library/Homebrew/cask/lib/hbc/container/dmg.rb @@ -43,11 +43,16 @@ module Hbc next unless mountpath.exist? begin - tries ||= 2 - @command.run("/usr/sbin/diskutil", - args: ["eject", mountpath], - print_stderr: false) - + tries ||= 3 + if tries > 1 + @command.run("/usr/sbin/diskutil", + args: ["eject", mountpath], + print_stderr: false) + else + @command.run("/usr/sbin/diskutil", + args: ["unmount", "force", mountpath], + print_stderr: false) + end raise CaskError, "Failed to eject #{mountpath}" if mountpath.exist? rescue CaskError => e raise e if (tries -= 1).zero? diff --git a/Library/Homebrew/cask/lib/hbc/container/xip.rb b/Library/Homebrew/cask/lib/hbc/container/xip.rb deleted file mode 100644 index 982402e4e..000000000 --- a/Library/Homebrew/cask/lib/hbc/container/xip.rb +++ /dev/null @@ -1,29 +0,0 @@ -require "tmpdir" - -module Hbc - class Container - class Xip < Base - def self.me?(criteria) - criteria.magic_number(/^xar!/n) && - IO.popen(["/usr/bin/xar", "-t", "-f", criteria.path.to_s], err: "/dev/null") { |io| io.read =~ /\AContent\nMetadata\n\Z/ } - end - - def extract - Dir.mktmpdir do |unpack_dir| - begin - ohai "Verifying signature for #{@path.basename}" - @command.run!("/usr/sbin/pkgutil", args: ["--check-signature", @path]) - rescue - raise "Signature check failed." - end - - @command.run!("/usr/bin/xar", args: ["-x", "-f", @path, "Content", "-C", unpack_dir]) - - Dir.chdir(@cask.staged_path) do - @command.run!("/usr/bin/cpio", args: ["--quiet", "-i", "-I", Pathname(unpack_dir).join("Content")]) - end - end - end - end - end -end diff --git a/Library/Homebrew/cask/lib/hbc/dsl.rb b/Library/Homebrew/cask/lib/hbc/dsl.rb index c62873665..4707ae76a 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl.rb @@ -270,14 +270,17 @@ module Hbc ORDINARY_ARTIFACT_TYPES.each do |type| define_method(type) do |*args| - if type == :stage_only && args != [true] - raise CaskInvalidError.new(token, "'stage_only' takes a single argument: true") - end - artifacts[type] << args - if artifacts.key?(:stage_only) && artifacts.keys.count > 1 && - !(artifacts.keys & ACTIVATABLE_ARTIFACT_TYPES).empty? - raise CaskInvalidError.new(token, "'stage_only' must be the only activatable artifact") + if type == :stage_only + if args != [true] + raise CaskInvalidError.new(token, "'stage_only' takes a single argument: true") + end + + unless (artifacts.keys & ACTIVATABLE_ARTIFACT_TYPES).empty? + raise CaskInvalidError.new(token, "'stage_only' must be the only activatable artifact") + end end + + artifacts[type].add(args) end end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb b/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb index 2f1245d3d..e27870622 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb @@ -1,3 +1,5 @@ +require "hbc/system_command" + module Hbc class DSL class Appcast @@ -9,6 +11,20 @@ module Hbc @checkpoint = @parameters[:checkpoint] end + def calculate_checkpoint + result = SystemCommand.run("/usr/bin/curl", args: ["--compressed", "--location", "--user-agent", URL::FAKE_USER_AGENT, @uri], print_stderr: false) + + checkpoint = if result.success? + processed_appcast_text = result.stdout.gsub(%r{<pubDate>[^<]*</pubDate>}m, "") + Digest::SHA2.hexdigest(processed_appcast_text) + end + + { + checkpoint: checkpoint, + command_result: result, + } + end + def to_yaml [@uri, @parameters].to_yaml end diff --git a/Library/Homebrew/cask/lib/hbc/installer.rb b/Library/Homebrew/cask/lib/hbc/installer.rb index 3875e1c8f..b86f3264d 100644 --- a/Library/Homebrew/cask/lib/hbc/installer.rb +++ b/Library/Homebrew/cask/lib/hbc/installer.rb @@ -133,22 +133,23 @@ module Hbc def install_artifacts already_installed_artifacts = [] - options = { command: @command, force: force } odebug "Installing artifacts" - artifacts = Artifact.for_cask(@cask) + artifacts = Artifact.for_cask(@cask, command: @command, force: force) odebug "#{artifacts.length} artifact/s defined", artifacts artifacts.each do |artifact| - odebug "Installing artifact of class #{artifact}" + next unless artifact.respond_to?(:install_phase) + odebug "Installing artifact of class #{artifact.class}" + artifact.install_phase already_installed_artifacts.unshift(artifact) - artifact.new(@cask, options).install_phase end rescue StandardError => e begin already_installed_artifacts.each do |artifact| - odebug "Reverting installation of artifact of class #{artifact}" - artifact.new(@cask, options).uninstall_phase + next unless artifact.respond_to?(:uninstall_phase) + odebug "Reverting installation of artifact of class #{artifact.class}" + artifact.uninstall_phase end ensure purge_versioned_files @@ -316,12 +317,18 @@ module Hbc def uninstall_artifacts odebug "Un-installing artifacts" - artifacts = Artifact.for_cask(@cask) + artifacts = Artifact.for_cask(@cask, command: @command, force: force) + + # Make sure the `uninstall` stanza is run first, as it + # may depend on other artifacts still being installed. + artifacts = artifacts.sort_by { |a| a.is_a?(Artifact::Uninstall) ? -1 : 1 } + odebug "#{artifacts.length} artifact/s defined", artifacts + artifacts.each do |artifact| - odebug "Un-installing artifact of class #{artifact}" - options = { command: @command, force: force } - artifact.new(@cask, options).uninstall_phase + next unless artifact.respond_to?(:uninstall_phase) + odebug "Un-installing artifact of class #{artifact.class}" + artifact.uninstall_phase end end diff --git a/Library/Homebrew/cask/lib/hbc/macos.rb b/Library/Homebrew/cask/lib/hbc/macos.rb index 5c1515d0c..d47e04fb2 100644 --- a/Library/Homebrew/cask/lib/hbc/macos.rb +++ b/Library/Homebrew/cask/lib/hbc/macos.rb @@ -181,6 +181,7 @@ module OS "/usr/include", "/usr/lib", "/usr/libexec", + "/usr/libexec/cups", "/usr/local", "/usr/local/Cellar", "/usr/local/Frameworks", diff --git a/Library/Homebrew/cask/lib/hbc/pkg.rb b/Library/Homebrew/cask/lib/hbc/pkg.rb index 2fb634f24..39252b48a 100644 --- a/Library/Homebrew/cask/lib/hbc/pkg.rb +++ b/Library/Homebrew/cask/lib/hbc/pkg.rb @@ -26,6 +26,7 @@ module Hbc _deepest_path_first(pkgutil_bom_dirs).each do |dir| next unless dir.exist? && !MacOS.undeletable?(dir) _with_full_permissions(dir) do + _delete_broken_file_dir(dir) && next _clean_broken_symlinks(dir) _clean_ds_store(dir) _rmdir(dir) @@ -97,6 +98,13 @@ module Hbc end end + # Some pkgs incorrectly report files (generally nibs) + # as directories; we remove these as files instead. + def _delete_broken_file_dir(path) + return unless path.file? && !path.symlink? + @command.run!("/bin/rm", args: ["-f", "--", path], sudo: true) + end + # Some pkgs leave broken symlinks hanging around; we clean them out before # attempting to rmdir to prevent extra cruft from lying around after # uninstall diff --git a/Library/Homebrew/cask/lib/hbc/staged.rb b/Library/Homebrew/cask/lib/hbc/staged.rb index dcc05ef5d..c1aa01b29 100644 --- a/Library/Homebrew/cask/lib/hbc/staged.rb +++ b/Library/Homebrew/cask/lib/hbc/staged.rb @@ -27,7 +27,7 @@ module Hbc full_paths = remove_nonexistent(paths) return if full_paths.empty? @command.run!("/bin/chmod", args: ["-R", "--", permissions_str] + full_paths, - sudo: true) + sudo: false) end def set_ownership(paths, user: current_user, group: "staff") diff --git a/Library/Homebrew/cask/spec/cask/accessibility_spec.rb b/Library/Homebrew/cask/spec/cask/accessibility_spec.rb new file mode 100644 index 000000000..71bebfa4b --- /dev/null +++ b/Library/Homebrew/cask/spec/cask/accessibility_spec.rb @@ -0,0 +1,82 @@ +require "spec_helper" + +# TODO: this test should be named after the corresponding class, once +# that class is abstracted from installer.rb. +describe "Accessibility Access" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-accessibility-access.rb") } + let(:fake_system_command) { class_double(Hbc::SystemCommand) } + let(:installer) { Hbc::Installer.new(cask, command: fake_system_command) } + + before(:each) 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 + + context "on MacOS 10.8 and below" do + let(:macos_version) { "10.8" } + + it "can enable accessibility access in macOS releases prior to Mavericks" do + expect(fake_system_command).to receive(:run!).with( + "/usr/bin/touch", + args: [Hbc.pre_mavericks_accessibility_dotfile], + sudo: true, + ) + + shutup do + installer.enable_accessibility_access + end + end + + it "warns about disabling accessibility access on old macOS releases" do + expect { + installer.disable_accessibility_access + }.to output(/Warning: Accessibility access cannot be disabled automatically on this version of macOS\./).to_stderr + end + end + + context "on MacOS 10.9" do + let(:macos_version) { "10.9" } + + it "can enable accessibility access" do + expect(fake_system_command).to receive(:run!).with( + "/usr/bin/sqlite3", + args: [Hbc.tcc_db, "INSERT OR REPLACE INTO access VALUES('kTCCServiceAccessibility','com.example.BasicCask',0,1,1,NULL);"], + sudo: true, + ) + + shutup do + installer.enable_accessibility_access + end + end + + it "can disable accessibility access" do + expect(fake_system_command).to receive(:run!).with( + "/usr/bin/sqlite3", + args: [Hbc.tcc_db, "DELETE FROM access WHERE client='com.example.BasicCask';"], + sudo: true, + ) + + shutup do + installer.disable_accessibility_access + end + end + end + + context "on MacOS 10.12 and above" do + let(:macos_version) { "10.12" } + + it "warns about enabling accessibility access on new macOS releases" do + expect { + expect { + installer.enable_accessibility_access + }.to output.to_stdout + }.to output(/Warning: Accessibility access cannot be enabled automatically on this version of macOS\./).to_stderr + end + + it "warns about disabling accessibility access on new macOS releases" do + expect { + installer.disable_accessibility_access + }.to output(/Warning: Accessibility access cannot be disabled automatically on this version of macOS\./).to_stderr + end + end +end diff --git a/Library/Homebrew/cask/test/cask/artifact/alt_target_test.rb b/Library/Homebrew/cask/spec/cask/artifact/alt_target_spec.rb index d1fe26eaa..9a57a9878 100644 --- a/Library/Homebrew/cask/test/cask/artifact/alt_target_test.rb +++ b/Library/Homebrew/cask/spec/cask/artifact/alt_target_spec.rb @@ -1,8 +1,8 @@ -require "test_helper" +require "spec_helper" describe Hbc::Artifact::App do describe "activate to alternate target" do - let(:cask) { Hbc.load("with-alt-target") } + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-alt-target.rb") } let(:install_phase) { -> { Hbc::Artifact::App.new(cask).install_phase } @@ -12,19 +12,19 @@ describe Hbc::Artifact::App do let(:target_path) { Hbc.appdir.join("AnotherName.app") } before do - TestHelper.install_without_artifacts(cask) + InstallHelper.install_without_artifacts(cask) end it "installs the given apps using the proper target directory" do - source_path.must_be :directory? - target_path.wont_be :exist? + expect(source_path).to be_a_directory + expect(target_path).not_to exist shutup do install_phase.call end - target_path.must_be :directory? - source_path.wont_be :exist? + expect(target_path).to be_a_directory + expect(source_path).not_to exist end describe "when app is in a subdirectory" do @@ -46,8 +46,8 @@ describe Hbc::Artifact::App do install_phase.call end - target_path.must_be :directory? - appsubdir.join("Caffeine.app").wont_be :exist? + expect(target_path).to be_a_directory + expect(appsubdir.join("Caffeine.app")).not_to exist end end @@ -59,23 +59,21 @@ describe Hbc::Artifact::App do install_phase.call end - target_path.must_be :directory? - source_path.wont_be :exist? + expect(target_path).to be_a_directory + expect(source_path).not_to exist - Hbc.appdir.join("Caffeine Deluxe.app").wont_be :exist? - cask.staged_path.join("Caffeine Deluxe.app").must_be :directory? + expect(Hbc.appdir.join("Caffeine Deluxe.app")).not_to exist + expect(cask.staged_path.join("Caffeine Deluxe.app")).to be_a_directory end it "avoids clobbering an existing app by moving over it" do target_path.mkpath - err = install_phase.must_raise(Hbc::CaskError) + expect(install_phase).to raise_error(Hbc::CaskError, "It seems there is already an App at '#{target_path}'.") - err.message.must_equal("It seems there is already an App at '#{target_path}'.") - - source_path.must_be :directory? - target_path.must_be :directory? - File.identical?(source_path, target_path).must_equal false + expect(source_path).to be_a_directory + expect(target_path).to be_a_directory + expect(File.identical?(source_path, target_path)).to be false end end end diff --git a/Library/Homebrew/cask/test/cask/artifact/app_test.rb b/Library/Homebrew/cask/spec/cask/artifact/app_spec.rb index 3eeeb729f..b3877f000 100644 --- a/Library/Homebrew/cask/test/cask/artifact/app_test.rb +++ b/Library/Homebrew/cask/spec/cask/artifact/app_spec.rb @@ -1,7 +1,7 @@ -require "test_helper" +require "spec_helper" describe Hbc::Artifact::App do - let(:cask) { Hbc.load("local-caffeine") } + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb") } let(:command) { Hbc::SystemCommand } let(:force) { false } let(:app) { Hbc::Artifact::App.new(cask, command: command, force: force) } @@ -12,8 +12,8 @@ describe Hbc::Artifact::App do let(:install_phase) { -> { app.install_phase } } let(:uninstall_phase) { -> { app.uninstall_phase } } - before do - TestHelper.install_without_artifacts(cask) + before(:each) do + InstallHelper.install_without_artifacts(cask) end describe "install_phase" do @@ -22,8 +22,8 @@ describe Hbc::Artifact::App do install_phase.call end - target_path.must_be :directory? - source_path.wont_be :exist? + expect(target_path).to be_a_directory + expect(source_path).not_to exist end describe "when app is in a subdirectory" do @@ -45,8 +45,8 @@ describe Hbc::Artifact::App do install_phase.call end - target_path.must_be :directory? - appsubdir.join("Caffeine.app").wont_be :exist? + expect(target_path).to be_a_directory + expect(appsubdir.join("Caffeine.app")).not_to exist end end @@ -58,36 +58,34 @@ describe Hbc::Artifact::App do install_phase.call end - target_path.must_be :directory? - source_path.wont_be :exist? + expect(target_path).to be_a_directory + expect(source_path).not_to exist - Hbc.appdir.join("Caffeine Deluxe.app").wont_be :exist? - cask.staged_path.join("Caffeine Deluxe.app").must_be :exist? + expect(Hbc.appdir.join("Caffeine Deluxe.app")).not_to exist + expect(cask.staged_path.join("Caffeine Deluxe.app")).to exist end describe "when the target already exists" do - before do + before(:each) do target_path.mkpath end it "avoids clobbering an existing app" do - err = install_phase.must_raise(Hbc::CaskError) + expect(install_phase).to raise_error(Hbc::CaskError, "It seems there is already an App at '#{target_path}'.") - err.message.must_equal("It seems there is already an App at '#{target_path}'.") - - source_path.must_be :directory? - target_path.must_be :directory? - File.identical?(source_path, target_path).must_equal false + expect(source_path).to be_a_directory + expect(target_path).to be_a_directory + expect(File.identical?(source_path, target_path)).to be false contents_path = target_path.join("Contents/Info.plist") - contents_path.wont_be :exist? + expect(contents_path).not_to exist end describe "given the force option" do let(:force) { true } - before do - Hbc::Utils.stubs(current_user: "fake_user") + before(:each) do + allow(Hbc::Utils).to receive(:current_user).and_return("fake_user") end describe "target is both writable and user-owned" do @@ -101,40 +99,31 @@ describe Hbc::Artifact::App do Warning: It seems there is already an App at '#{target_path}'; overwriting. EOS - install_phase.must_output(stdout, stderr) + expect { + expect(install_phase).to output(stdout).to_stdout + }.to output(stderr).to_stderr - source_path.wont_be :exist? - target_path.must_be :directory? + expect(source_path).not_to exist + expect(target_path).to be_a_directory contents_path = target_path.join("Contents/Info.plist") - contents_path.must_be :exist? + expect(contents_path).to exist end end describe "target is user-owned but contains read-only files" do - let(:command) { Hbc::FakeSystemCommand } - - let(:chmod_cmd) { - ["/bin/chmod", "-R", "--", "u+rwx", target_path] - } - - let(:chmod_n_cmd) { - ["/bin/chmod", "-R", "-N", target_path] - } - - let(:chflags_cmd) { - ["/usr/bin/chflags", "-R", "--", "000", target_path] - } - - before do + before(:each) do system "/usr/bin/touch", "--", "#{target_path}/foo" system "/bin/chmod", "--", "0555", target_path end it "overwrites the existing app" do - command.expect_and_pass_through(chflags_cmd) - command.expect_and_pass_through(chmod_cmd) - command.expect_and_pass_through(chmod_n_cmd) + expect(command).to receive(:run).with("/bin/chmod", args: ["-R", "--", "u+rwx", target_path], must_succeed: false) + .and_call_original + expect(command).to receive(:run).with("/bin/chmod", args: ["-R", "-N", target_path], must_succeed: false) + .and_call_original + expect(command).to receive(:run).with("/usr/bin/chflags", args: ["-R", "--", "000", target_path], must_succeed: false) + .and_call_original stdout = <<-EOS.undent ==> Removing App: '#{target_path}' @@ -145,16 +134,18 @@ describe Hbc::Artifact::App do Warning: It seems there is already an App at '#{target_path}'; overwriting. EOS - install_phase.must_output(stdout, stderr) + expect { + expect(install_phase).to output(stdout).to_stdout + }.to output(stderr).to_stderr - source_path.wont_be :exist? - target_path.must_be :directory? + expect(source_path).not_to exist + expect(target_path).to be_a_directory contents_path = target_path.join("Contents/Info.plist") - contents_path.must_be :exist? + expect(contents_path).to exist end - after do + after(:each) do system "/bin/chmod", "--", "0755", target_path end end @@ -164,18 +155,15 @@ describe Hbc::Artifact::App do describe "when the target is a broken symlink" do let(:deleted_path) { cask.staged_path.join("Deleted.app") } - before do + before(:each) do deleted_path.mkdir File.symlink(deleted_path, target_path) deleted_path.rmdir end it "leaves the target alone" do - err = install_phase.must_raise(Hbc::CaskError) - - err.message.must_equal("It seems there is already an App at '#{target_path}'.") - - File.symlink?(target_path).must_equal true + expect(install_phase).to raise_error(Hbc::CaskError, "It seems there is already an App at '#{target_path}'.") + expect(target_path).to be_a_symlink end describe "given the force option" do @@ -191,13 +179,15 @@ describe Hbc::Artifact::App do Warning: It seems there is already an App at '#{target_path}'; overwriting. EOS - install_phase.must_output(stdout, stderr) + expect { + expect(install_phase).to output(stdout).to_stdout + }.to output(stderr).to_stderr - source_path.wont_be :exist? - target_path.must_be :directory? + expect(source_path).not_to exist + expect(target_path).to be_a_directory contents_path = target_path.join("Contents/Info.plist") - contents_path.must_be :exist? + expect(contents_path).to exist end end end @@ -207,26 +197,23 @@ describe Hbc::Artifact::App do message = "It seems the App source is not there: '#{source_path}'" - error = install_phase.must_raise(Hbc::CaskError) - error.message.must_equal message + expect(install_phase).to raise_error(Hbc::CaskError, message) end end describe "uninstall_phase" do - before do + it "deletes managed apps" do shutup do install_phase.call end - end - it "deletes managed apps" do - target_path.must_be :exist? + expect(target_path).to exist shutup do uninstall_phase.call end - target_path.wont_be :exist? + expect(target_path).not_to exist end end @@ -235,25 +222,23 @@ describe Hbc::Artifact::App do let(:contents) { app.summary[:contents] } it "returns the correct english_description" do - description.must_equal "Apps" + expect(description).to eq("Apps") end describe "app is correctly installed" do - before do + it "returns the path to the app" do shutup do install_phase.call end - end - it "returns the path to the app" do - contents.must_equal ["#{target_path} (#{target_path.abv})"] + expect(contents).to eq(["#{target_path} (#{target_path.abv})"]) end end describe "app is missing" do it "returns a warning and the supposed path to the app" do - contents.size.must_equal 1 - contents[0].must_match(/.*Missing App.*: #{target_path}/) + expect(contents.size).to eq(1) + expect(contents[0]).to match(/.*Missing App.*: #{target_path}/) end end end diff --git a/Library/Homebrew/cask/spec/cask/artifact/binary_spec.rb b/Library/Homebrew/cask/spec/cask/artifact/binary_spec.rb index fbb117f67..c27dcc8f0 100644 --- a/Library/Homebrew/cask/spec/cask/artifact/binary_spec.rb +++ b/Library/Homebrew/cask/spec/cask/artifact/binary_spec.rb @@ -1,6 +1,6 @@ describe Hbc::Artifact::Binary do let(:cask) { - Hbc.load("with-binary").tap do |cask| + Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-binary.rb").tap do |cask| shutup do InstallHelper.install_without_artifacts(cask) end @@ -20,7 +20,8 @@ describe Hbc::Artifact::Binary do shutup do Hbc::Artifact::Binary.new(cask).install_phase end - expect(FileHelper.valid_alias?(expected_path)).to be true + expect(expected_path).to be_a_symlink + expect(expected_path.readlink).to exist end it "avoids clobbering an existing binary by linking over it" do @@ -69,7 +70,7 @@ describe Hbc::Artifact::Binary do context "binary is inside an app package" do let(:cask) { - Hbc.load("with-embedded-binary").tap do |cask| + Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-embedded-binary.rb").tap do |cask| shutup do InstallHelper.install_without_artifacts(cask) end @@ -82,7 +83,8 @@ describe Hbc::Artifact::Binary do Hbc::Artifact::Binary.new(cask).install_phase end - expect(FileHelper.valid_alias?(expected_path)).to be true + expect(expected_path).to be_a_symlink + expect(expected_path.readlink).to exist end end end diff --git a/Library/Homebrew/cask/spec/cask/artifact/generic_artifact_spec.rb b/Library/Homebrew/cask/spec/cask/artifact/generic_artifact_spec.rb new file mode 100644 index 000000000..7d9128c0e --- /dev/null +++ b/Library/Homebrew/cask/spec/cask/artifact/generic_artifact_spec.rb @@ -0,0 +1,47 @@ +require "spec_helper" + +describe Hbc::Artifact::Artifact do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-generic-artifact.rb") } + + let(:install_phase) { + -> { Hbc::Artifact::Artifact.new(cask).install_phase } + } + + let(:source_path) { cask.staged_path.join("Caffeine.app") } + let(:target_path) { Hbc.appdir.join("Caffeine.app") } + + before do + InstallHelper.install_without_artifacts(cask) + end + + describe "with no target" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-generic-artifact-no-target.rb") } + + it "fails to install with no target" do + expect(install_phase).to raise_error(Hbc::CaskInvalidError) + end + end + + it "moves the artifact to the proper directory" do + shutup do + install_phase.call + end + + expect(target_path).to be_a_directory + expect(source_path).not_to exist + end + + it "avoids clobbering an existing artifact" do + target_path.mkpath + + expect { + shutup do + install_phase.call + end + }.to raise_error(Hbc::CaskError) + + expect(source_path).to be_a_directory + expect(target_path).to be_a_directory + expect(File.identical?(source_path, target_path)).to be false + end +end diff --git a/Library/Homebrew/cask/spec/cask/artifact/nested_container_spec.rb b/Library/Homebrew/cask/spec/cask/artifact/nested_container_spec.rb new file mode 100644 index 000000000..31a1cb5eb --- /dev/null +++ b/Library/Homebrew/cask/spec/cask/artifact/nested_container_spec.rb @@ -0,0 +1,17 @@ +require "spec_helper" + +describe Hbc::Artifact::NestedContainer do + describe "install" do + it "extracts the specified paths as containers" do + cask = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/nested-app.rb").tap do |c| + InstallHelper.install_without_artifacts(c) + end + + shutup do + Hbc::Artifact::NestedContainer.new(cask).install_phase + end + + expect(cask.staged_path.join("MyNestedApp.app")).to be_a_directory + end + end +end diff --git a/Library/Homebrew/cask/spec/cask/artifact/pkg_spec.rb b/Library/Homebrew/cask/spec/cask/artifact/pkg_spec.rb new file mode 100644 index 000000000..93ef2ecdf --- /dev/null +++ b/Library/Homebrew/cask/spec/cask/artifact/pkg_spec.rb @@ -0,0 +1,71 @@ +require "spec_helper" + +describe Hbc::Artifact::Pkg do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-installable.rb") } + let(:fake_system_command) { class_double(Hbc::SystemCommand) } + + before(:each) do + shutup do + InstallHelper.install_without_artifacts(cask) + end + end + + describe "install_phase" do + it "runs the system installer on the specified pkgs" do + pkg = Hbc::Artifact::Pkg.new(cask, command: fake_system_command) + + expect(fake_system_command).to receive(:run!).with( + "/usr/sbin/installer", + args: ["-pkg", cask.staged_path.join("MyFancyPkg", "Fancy.pkg"), "-target", "/"], + sudo: true, + print_stdout: true, + ) + + shutup do + pkg.install_phase + end + end + end + + describe "choices" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-choices.rb") } + + it "passes the choice changes xml to the system installer" do + pkg = Hbc::Artifact::Pkg.new(cask, command: fake_system_command) + + file = double(path: Pathname.new("/tmp/choices.xml")) + + expect(file).to receive(:write).with(<<-EOS.undent) + <?xml version="1.0" encoding="UTF-8"?> + <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> + <plist version="1.0"> + <array> + \t<dict> + \t\t<key>attributeSetting</key> + \t\t<integer>1</integer> + \t\t<key>choiceAttribute</key> + \t\t<string>selected</string> + \t\t<key>choiceIdentifier</key> + \t\t<string>choice1</string> + \t</dict> + </array> + </plist> + EOS + + expect(file).to receive(:close) + expect(file).to receive(:unlink) + expect(Tempfile).to receive(:open).and_yield(file) + + expect(fake_system_command).to receive(:run!).with( + "/usr/sbin/installer", + args: ["-pkg", cask.staged_path.join("MyFancyPkg", "Fancy.pkg"), "-target", "/", "-applyChoiceChangesXML", cask.staged_path.join("/tmp/choices.xml")], + sudo: true, + print_stdout: true, + ) + + shutup do + pkg.install_phase + end + end + end +end diff --git a/Library/Homebrew/cask/test/cask/artifact/postflight_block_test.rb b/Library/Homebrew/cask/spec/cask/artifact/postflight_block_spec.rb index 47dcdd905..6f58afb2a 100644 --- a/Library/Homebrew/cask/test/cask/artifact/postflight_block_test.rb +++ b/Library/Homebrew/cask/spec/cask/artifact/postflight_block_spec.rb @@ -1,9 +1,9 @@ -require "test_helper" +require "spec_helper" describe Hbc::Artifact::PostflightBlock do describe "install_phase" do it "calls the specified block after installing, passing a Cask mini-dsl" do - called = false + called = false yielded_arg = nil cask = Hbc::Cask.new("with-postflight") do @@ -13,16 +13,16 @@ describe Hbc::Artifact::PostflightBlock do end end - Hbc::Artifact::PostflightBlock.new(cask).install_phase + described_class.new(cask).install_phase - called.must_equal true - yielded_arg.must_be_kind_of Hbc::DSL::Postflight + expect(called).to be true + expect(yielded_arg).to be_kind_of(Hbc::DSL::Postflight) end end describe "uninstall_phase" do it "calls the specified block after uninstalling, passing a Cask mini-dsl" do - called = false + called = false yielded_arg = nil cask = Hbc::Cask.new("with-uninstall-postflight") do @@ -32,10 +32,10 @@ describe Hbc::Artifact::PostflightBlock do end end - Hbc::Artifact::PostflightBlock.new(cask).uninstall_phase + described_class.new(cask).uninstall_phase - called.must_equal true - yielded_arg.must_be_kind_of Hbc::DSL::UninstallPostflight + expect(called).to be true + expect(yielded_arg).to be_kind_of(Hbc::DSL::UninstallPostflight) end end end diff --git a/Library/Homebrew/cask/test/cask/artifact/preflight_block_test.rb b/Library/Homebrew/cask/spec/cask/artifact/preflight_block_spec.rb index 440b1db3a..ac5313bca 100644 --- a/Library/Homebrew/cask/test/cask/artifact/preflight_block_test.rb +++ b/Library/Homebrew/cask/spec/cask/artifact/preflight_block_spec.rb @@ -1,9 +1,9 @@ -require "test_helper" +require "spec_helper" describe Hbc::Artifact::PreflightBlock do describe "install_phase" do it "calls the specified block before installing, passing a Cask mini-dsl" do - called = false + called = false yielded_arg = nil cask = Hbc::Cask.new("with-preflight") do @@ -13,16 +13,16 @@ describe Hbc::Artifact::PreflightBlock do end end - Hbc::Artifact::PreflightBlock.new(cask).install_phase + described_class.new(cask).install_phase - called.must_equal true - yielded_arg.must_be_kind_of Hbc::DSL::Preflight + expect(called).to be true + expect(yielded_arg).to be_kind_of Hbc::DSL::Preflight end end describe "uninstall_phase" do it "calls the specified block before uninstalling, passing a Cask mini-dsl" do - called = false + called = false yielded_arg = nil cask = Hbc::Cask.new("with-uninstall-preflight") do @@ -32,10 +32,10 @@ describe Hbc::Artifact::PreflightBlock do end end - Hbc::Artifact::PreflightBlock.new(cask).uninstall_phase + described_class.new(cask).uninstall_phase - called.must_equal true - yielded_arg.must_be_kind_of Hbc::DSL::UninstallPreflight + expect(called).to be true + expect(yielded_arg).to be_kind_of Hbc::DSL::UninstallPreflight end end end diff --git a/Library/Homebrew/cask/spec/cask/artifact/suite_spec.rb b/Library/Homebrew/cask/spec/cask/artifact/suite_spec.rb new file mode 100644 index 000000000..79ca0546c --- /dev/null +++ b/Library/Homebrew/cask/spec/cask/artifact/suite_spec.rb @@ -0,0 +1,49 @@ +require "spec_helper" + +describe Hbc::Artifact::Suite do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-suite.rb") } + + let(:install_phase) { -> { Hbc::Artifact::Suite.new(cask).install_phase } } + + let(:target_path) { Hbc.appdir.join("Caffeine") } + let(:source_path) { cask.staged_path.join("Caffeine") } + + before(:each) do + InstallHelper.install_without_artifacts(cask) + end + + it "moves the suite to the proper directory" do + skip("flaky test") # FIXME + + shutup do + install_phase.call + end + + expect(target_path).to be_a_directory + expect(target_path).to be_a_symlink + expect(target_path.readlink).to exist + expect(source_path).not_to exist + end + + it "creates a suite containing the expected app" do + shutup do + install_phase.call + end + + expect(target_path.join("Caffeine.app")).to exist + end + + it "avoids clobbering an existing suite by moving over it" do + target_path.mkpath + + expect { + shutup do + install_phase.call + end + }.to raise_error(Hbc::CaskError) + + expect(source_path).to be_a_directory + expect(target_path).to be_a_directory + expect(File.identical?(source_path, target_path)).to be false + end +end diff --git a/Library/Homebrew/cask/spec/cask/artifact/two_apps_correct_spec.rb b/Library/Homebrew/cask/spec/cask/artifact/two_apps_correct_spec.rb new file mode 100644 index 000000000..7fa44dbce --- /dev/null +++ b/Library/Homebrew/cask/spec/cask/artifact/two_apps_correct_spec.rb @@ -0,0 +1,93 @@ +require "spec_helper" + +describe Hbc::Artifact::App do + describe "multiple apps" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-two-apps-correct.rb") } + + let(:install_phase) { + -> { Hbc::Artifact::App.new(cask).install_phase } + } + + let(:source_path_mini) { cask.staged_path.join("Caffeine Mini.app") } + let(:target_path_mini) { Hbc.appdir.join("Caffeine Mini.app") } + + let(:source_path_pro) { cask.staged_path.join("Caffeine Pro.app") } + let(:target_path_pro) { Hbc.appdir.join("Caffeine Pro.app") } + + before(:each) do + InstallHelper.install_without_artifacts(cask) + end + + it "installs both apps using the proper target directory" do + shutup do + install_phase.call + end + + expect(target_path_mini).to be_a_directory + expect(source_path_mini).not_to exist + + expect(target_path_pro).to be_a_directory + expect(source_path_pro).not_to exist + end + + describe "when apps are in a subdirectory" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-two-apps-subdir.rb") } + + it "installs both apps using the proper target directory" do + shutup do + install_phase.call + end + + expect(target_path_mini).to be_a_directory + expect(source_path_mini).not_to exist + + expect(target_path_pro).to be_a_directory + expect(source_path_pro).not_to exist + end + end + + it "only uses apps when they are specified" do + FileUtils.cp_r source_path_mini, source_path_mini.sub("Caffeine Mini.app", "Caffeine Deluxe.app") + + shutup do + install_phase.call + end + + expect(target_path_mini).to be_a_directory + expect(source_path_mini).not_to exist + + expect(Hbc.appdir.join("Caffeine Deluxe.app")).not_to exist + expect(cask.staged_path.join("Caffeine Deluxe.app")).to exist + end + + describe "avoids clobbering an existing app" do + it "when the first app of two already exists" do + target_path_mini.mkpath + + expect { + expect(install_phase).to output(<<-EOS.undent).to_stdout + ==> Moving App 'Caffeine Pro.app' to '#{target_path_pro}' + EOS + }.to raise_error(Hbc::CaskError, "It seems there is already an App at '#{target_path_mini}'.") + + expect(source_path_mini).to be_a_directory + expect(target_path_mini).to be_a_directory + expect(File.identical?(source_path_mini, target_path_mini)).to be false + end + + it "when the second app of two already exists" do + target_path_pro.mkpath + + expect { + expect(install_phase).to output(<<-EOS.undent).to_stdout + ==> Moving App 'Caffeine Mini.app' to '#{target_path_mini}' + EOS + }.to raise_error(Hbc::CaskError, "It seems there is already an App at '#{target_path_pro}'.") + + expect(source_path_pro).to be_a_directory + expect(target_path_pro).to be_a_directory + expect(File.identical?(source_path_pro, target_path_pro)).to be false + end + end + end +end diff --git a/Library/Homebrew/cask/spec/cask/artifact/two_apps_incorrect_spec.rb b/Library/Homebrew/cask/spec/cask/artifact/two_apps_incorrect_spec.rb new file mode 100644 index 000000000..0aa38d910 --- /dev/null +++ b/Library/Homebrew/cask/spec/cask/artifact/two_apps_incorrect_spec.rb @@ -0,0 +1,11 @@ +require "spec_helper" + +describe Hbc::Artifact::App do + # FIXME: Doesn't actually raise because the `app` stanza is not evaluated on load. + # it "must raise" do + # lambda { + # Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-two-apps-incorrect.rb") + # }.must_raise + # # TODO: later give the user a nice exception for this case and check for it here + # end +end diff --git a/Library/Homebrew/cask/spec/cask/artifact/uninstall_no_zap_spec.rb b/Library/Homebrew/cask/spec/cask/artifact/uninstall_no_zap_spec.rb new file mode 100644 index 000000000..3150b50be --- /dev/null +++ b/Library/Homebrew/cask/spec/cask/artifact/uninstall_no_zap_spec.rb @@ -0,0 +1,21 @@ +require "spec_helper" + +describe Hbc::Artifact::Zap do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-installable.rb") } + + let(:zap_artifact) { + Hbc::Artifact::Zap.new(cask) + } + + before do + shutup do + InstallHelper.install_without_artifacts(cask) + end + end + + describe "#uninstall_phase" do + subject { zap_artifact } + + it { is_expected.not_to respond_to(:uninstall_phase) } + end +end diff --git a/Library/Homebrew/cask/test/cask/artifact/uninstall_test.rb b/Library/Homebrew/cask/spec/cask/artifact/uninstall_spec.rb index b09d39833..e3595621d 100644 --- a/Library/Homebrew/cask/test/cask/artifact/uninstall_test.rb +++ b/Library/Homebrew/cask/spec/cask/artifact/uninstall_spec.rb @@ -1,43 +1,37 @@ -require "test_helper" +require "spec_helper" describe Hbc::Artifact::Uninstall do - let(:cask) { Hbc.load("with-installable") } + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-installable.rb") } let(:uninstall_artifact) { Hbc::Artifact::Uninstall.new(cask, command: Hbc::FakeSystemCommand) } - before do + let(:absolute_path) { Pathname.new("#{TEST_TMPDIR}/absolute_path") } + let(:path_with_tilde) { Pathname.new("#{TEST_TMPDIR}/path_with_tilde") } + let(:glob_path1) { Pathname.new("#{TEST_TMPDIR}/glob_path1") } + let(:glob_path2) { Pathname.new("#{TEST_TMPDIR}/glob_path2") } + + before(:each) do + FileUtils.touch(absolute_path) + FileUtils.touch(path_with_tilde) + FileUtils.touch(glob_path1) + FileUtils.touch(glob_path2) + ENV["HOME"] = TEST_TMPDIR shutup do - TestHelper.install_without_artifacts(cask) - end - end - - describe "install_phase" do - it "does nothing, because the install_phase method is a no-op" do - shutup do - uninstall_artifact.install_phase - end - end - end - - describe "zap_phase" do - it "does nothing, because the zap_phase method is a no-op" do - shutup do - uninstall_artifact.zap_phase - end + InstallHelper.install_without_artifacts(cask) end end describe "uninstall_phase" do - subject do + subject { shutup do uninstall_artifact.uninstall_phase end - end + } - describe "when using launchctl" do - let(:cask) { Hbc.load("with-uninstall-launchctl") } + context "when using launchctl" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-uninstall-launchctl.rb") } let(:launchctl_list_cmd) { %w[/bin/launchctl list my.fancy.package.service] } let(:launchctl_remove_cmd) { %w[/bin/launchctl remove my.fancy.package.service] } let(:unknown_response) { "launchctl list returned unknown response\n" } @@ -56,16 +50,16 @@ describe Hbc::Artifact::Uninstall do EOS } - describe "when launchctl job is owned by user" do + context "when launchctl job is owned by user" do it "can uninstall" do Hbc::FakeSystemCommand.stubs_command( launchctl_list_cmd, - service_info + service_info, ) Hbc::FakeSystemCommand.stubs_command( sudo(launchctl_list_cmd), - unknown_response + unknown_response, ) Hbc::FakeSystemCommand.expects_command(launchctl_remove_cmd) @@ -74,16 +68,16 @@ describe Hbc::Artifact::Uninstall do end end - describe "when launchctl job is owned by system" do + context "when launchctl job is owned by system" do it "can uninstall" do Hbc::FakeSystemCommand.stubs_command( launchctl_list_cmd, - unknown_response + unknown_response, ) Hbc::FakeSystemCommand.stubs_command( sudo(launchctl_list_cmd), - service_info + service_info, ) Hbc::FakeSystemCommand.expects_command(sudo(launchctl_remove_cmd)) @@ -93,8 +87,8 @@ describe Hbc::Artifact::Uninstall do end end - describe "when using pkgutil" do - let(:cask) { Hbc.load("with-uninstall-pkgutil") } + context "when using pkgutil" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-uninstall-pkgutil.rb") } let(:main_pkg_id) { "my.fancy.package.main" } let(:agent_pkg_id) { "my.fancy.package.agent" } let(:main_files) { @@ -141,7 +135,7 @@ describe Hbc::Artifact::Uninstall do it "can uninstall" do Hbc::FakeSystemCommand.stubs_command( %w[/usr/sbin/pkgutil --pkgs=my.fancy.package.*], - "#{main_pkg_id}\n#{agent_pkg_id}" + "#{main_pkg_id}\n#{agent_pkg_id}", ) [ @@ -150,28 +144,28 @@ describe Hbc::Artifact::Uninstall do ].each do |pkg_id, pkg_files, pkg_dirs| Hbc::FakeSystemCommand.stubs_command( %W[/usr/sbin/pkgutil --only-files --files #{pkg_id}], - pkg_files.join("\n") + pkg_files.join("\n"), ) Hbc::FakeSystemCommand.stubs_command( %W[/usr/sbin/pkgutil --only-dirs --files #{pkg_id}], - pkg_dirs.join("\n") + pkg_dirs.join("\n"), ) Hbc::FakeSystemCommand.stubs_command( %W[/usr/sbin/pkgutil --files #{pkg_id}], - (pkg_files + pkg_dirs).join("\n") + (pkg_files + pkg_dirs).join("\n"), ) Hbc::FakeSystemCommand.stubs_command( %W[/usr/sbin/pkgutil --pkg-info-plist #{pkg_id}], - pkg_info_plist + pkg_info_plist, ) Hbc::FakeSystemCommand.expects_command(sudo(%W[/usr/sbin/pkgutil --forget #{pkg_id}])) Hbc::FakeSystemCommand.expects_command( - sudo(%w[/bin/rm -f --] + pkg_files.map { |path| Pathname("/tmp/#{path}") }) + sudo(%w[/bin/rm -f --] + pkg_files.map { |path| Pathname("/tmp/#{path}") }), ) end @@ -179,8 +173,8 @@ describe Hbc::Artifact::Uninstall do end end - describe "when using kext" do - let(:cask) { Hbc.load("with-uninstall-kext") } + context "when using kext" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-uninstall-kext.rb") } let(:kext_id) { "my.fancy.package.kernelextension" } it "can uninstall" do @@ -189,7 +183,7 @@ describe Hbc::Artifact::Uninstall do ) Hbc::FakeSystemCommand.expects_command( - sudo(%W[/sbin/kextunload -b #{kext_id}]) + sudo(%W[/sbin/kextunload -b #{kext_id}]), ) Hbc::FakeSystemCommand.expects_command( @@ -197,15 +191,15 @@ describe Hbc::Artifact::Uninstall do ) Hbc::FakeSystemCommand.expects_command( - sudo(["/bin/rm", "-rf", "/Library/Extensions/FancyPackage.kext"]) + sudo(["/bin/rm", "-rf", "/Library/Extensions/FancyPackage.kext"]), ) subject end end - describe "when using quit" do - let(:cask) { Hbc.load("with-uninstall-quit") } + context "when using quit" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-uninstall-quit.rb") } let(:bundle_id) { "my.fancy.package.app" } let(:quit_application_script) { %Q(tell application id "#{bundle_id}" to quit) @@ -217,15 +211,15 @@ describe Hbc::Artifact::Uninstall do ) Hbc::FakeSystemCommand.stubs_command( - %w[/bin/launchctl list] + %w[/bin/launchctl list], ) subject end end - describe "when using signal" do - let(:cask) { Hbc.load("with-uninstall-signal") } + context "when using signal" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-uninstall-signal.rb") } let(:bundle_id) { "my.fancy.package.app" } let(:signals) { %w[TERM KILL] } let(:unix_pids) { [12_345, 67_890] } @@ -236,95 +230,107 @@ describe Hbc::Artifact::Uninstall do ) signals.each do |signal| - Process.expects(:kill).with(signal, *unix_pids) + expect(Process).to receive(:kill).with(signal, *unix_pids) end subject end end - describe "when using delete" do - let(:cask) { Hbc.load("with-uninstall-delete") } + context "when using delete" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-uninstall-delete.rb") } it "can uninstall" do Hbc::FakeSystemCommand.expects_command( sudo(%w[/bin/rm -rf --], - Pathname.new("/permissible/absolute/path"), - Pathname.new("~/permissible/path/with/tilde").expand_path) + absolute_path, + path_with_tilde, + glob_path1, + glob_path2), ) subject end end - describe "when using trash" do - let(:cask) { Hbc.load("with-uninstall-trash") } + context "when using trash" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-uninstall-trash.rb") } it "can uninstall" do Hbc::FakeSystemCommand.expects_command( sudo(%w[/bin/rm -rf --], - Pathname.new("/permissible/absolute/path"), - Pathname.new("~/permissible/path/with/tilde").expand_path) + absolute_path, + path_with_tilde, + glob_path1, + glob_path2), ) subject end end - describe "when using rmdir" do - let(:cask) { Hbc.load("with-uninstall-rmdir") } - let(:dir_pathname) { Pathname.new("#{TEST_FIXTURE_DIR}/cask/empty_directory") } + context "when using rmdir" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-uninstall-rmdir.rb") } + let(:empty_directory_path) { Pathname.new("#{TEST_TMPDIR}/empty_directory_path") } + + before(:each) do + empty_directory_path.mkdir + end + + after(:each) do + empty_directory_path.rmdir + end it "can uninstall" do Hbc::FakeSystemCommand.expects_command( - sudo(%w[/bin/rm -f --], dir_pathname.join(".DS_Store")) + sudo(%w[/bin/rm -f --], empty_directory_path/".DS_Store"), ) Hbc::FakeSystemCommand.expects_command( - sudo(%w[/bin/rmdir --], dir_pathname) + sudo(%w[/bin/rmdir --], empty_directory_path), ) subject end end - describe "when using script" do - let(:cask) { Hbc.load("with-uninstall-script") } + context "when using script" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-uninstall-script.rb") } let(:script_pathname) { cask.staged_path.join("MyFancyPkg", "FancyUninstaller.tool") } it "can uninstall" do Hbc::FakeSystemCommand.expects_command(%w[/bin/chmod -- +x] + [script_pathname]) Hbc::FakeSystemCommand.expects_command( - sudo(cask.staged_path.join("MyFancyPkg", "FancyUninstaller.tool"), "--please") + sudo(cask.staged_path.join("MyFancyPkg", "FancyUninstaller.tool"), "--please"), ) subject end end - describe "when using early_script" do - let(:cask) { Hbc.load("with-uninstall-early-script") } + context "when using early_script" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-uninstall-early-script.rb") } let(:script_pathname) { cask.staged_path.join("MyFancyPkg", "FancyUninstaller.tool") } it "can uninstall" do Hbc::FakeSystemCommand.expects_command(%w[/bin/chmod -- +x] + [script_pathname]) Hbc::FakeSystemCommand.expects_command( - sudo(cask.staged_path.join("MyFancyPkg", "FancyUninstaller.tool"), "--please") + sudo(cask.staged_path.join("MyFancyPkg", "FancyUninstaller.tool"), "--please"), ) subject end end - describe "when using login_item" do - let(:cask) { Hbc.load("with-uninstall-login-item") } + context "when using login_item" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-uninstall-login-item.rb") } it "can uninstall" do Hbc::FakeSystemCommand.expects_command( ["/usr/bin/osascript", "-e", 'tell application "System Events" to delete every login ' \ - 'item whose name is "Fancy"'] + 'item whose name is "Fancy"'], ) subject diff --git a/Library/Homebrew/cask/test/cask/artifact/zap_test.rb b/Library/Homebrew/cask/spec/cask/artifact/zap_spec.rb index b65b0bf5c..c49cebbb8 100644 --- a/Library/Homebrew/cask/test/cask/artifact/zap_test.rb +++ b/Library/Homebrew/cask/spec/cask/artifact/zap_spec.rb @@ -1,44 +1,38 @@ -require "test_helper" +require "spec_helper" # TODO: test that zap removes an alternate version of the same Cask describe Hbc::Artifact::Zap do - let(:cask) { Hbc.load("with-installable") } + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-installable.rb") } let(:zap_artifact) { Hbc::Artifact::Zap.new(cask, command: Hbc::FakeSystemCommand) } - before do + let(:absolute_path) { Pathname.new("#{TEST_TMPDIR}/absolute_path") } + let(:path_with_tilde) { Pathname.new("#{TEST_TMPDIR}/path_with_tilde") } + let(:glob_path1) { Pathname.new("#{TEST_TMPDIR}/glob_path1") } + let(:glob_path2) { Pathname.new("#{TEST_TMPDIR}/glob_path2") } + + before(:each) do + FileUtils.touch(absolute_path) + FileUtils.touch(path_with_tilde) + FileUtils.touch(glob_path1) + FileUtils.touch(glob_path2) + ENV["HOME"] = TEST_TMPDIR shutup do - TestHelper.install_without_artifacts(cask) + InstallHelper.install_without_artifacts(cask) end end - describe "install_phase" do - it "does nothing, because the install_phase method is a no-op" do - shutup do - zap_artifact.install_phase - end - end - end - - describe "uninstall_phase" do - it "does nothing, because the uninstall_phase method is a no-op" do - shutup do - zap_artifact.uninstall_phase - end - end - end - - describe "zap_phase" do - subject do + describe "#zap_phase" do + subject { shutup do zap_artifact.zap_phase end - end + } - describe "when using launchctl" do - let(:cask) { Hbc.load("with-zap-launchctl") } + context "when using launchctl" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-zap-launchctl.rb") } let(:launchctl_list_cmd) { %w[/bin/launchctl list my.fancy.package.service] } let(:launchctl_remove_cmd) { %w[/bin/launchctl remove my.fancy.package.service] } let(:unknown_response) { "launchctl list returned unknown response\n" } @@ -57,16 +51,16 @@ describe Hbc::Artifact::Zap do EOS } - describe "when launchctl job is owned by user" do + context "when launchctl job is owned by user" do it "can zap" do Hbc::FakeSystemCommand.stubs_command( launchctl_list_cmd, - service_info + service_info, ) Hbc::FakeSystemCommand.stubs_command( sudo(launchctl_list_cmd), - unknown_response + unknown_response, ) Hbc::FakeSystemCommand.expects_command(launchctl_remove_cmd) @@ -79,12 +73,12 @@ describe Hbc::Artifact::Zap do it "can zap" do Hbc::FakeSystemCommand.stubs_command( launchctl_list_cmd, - unknown_response + unknown_response, ) Hbc::FakeSystemCommand.stubs_command( sudo(launchctl_list_cmd), - service_info + service_info, ) Hbc::FakeSystemCommand.expects_command(sudo(launchctl_remove_cmd)) @@ -94,8 +88,8 @@ describe Hbc::Artifact::Zap do end end - describe "when using pkgutil" do - let(:cask) { Hbc.load("with-zap-pkgutil") } + context "when using pkgutil" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-zap-pkgutil.rb") } let(:main_pkg_id) { "my.fancy.package.main" } let(:agent_pkg_id) { "my.fancy.package.agent" } let(:main_files) { @@ -142,7 +136,7 @@ describe Hbc::Artifact::Zap do it "can zap" do Hbc::FakeSystemCommand.stubs_command( %w[/usr/sbin/pkgutil --pkgs=my.fancy.package.*], - "#{main_pkg_id}\n#{agent_pkg_id}" + "#{main_pkg_id}\n#{agent_pkg_id}", ) [ @@ -151,28 +145,28 @@ describe Hbc::Artifact::Zap do ].each do |pkg_id, pkg_files, pkg_dirs| Hbc::FakeSystemCommand.stubs_command( %W[/usr/sbin/pkgutil --only-files --files #{pkg_id}], - pkg_files.join("\n") + pkg_files.join("\n"), ) Hbc::FakeSystemCommand.stubs_command( %W[/usr/sbin/pkgutil --only-dirs --files #{pkg_id}], - pkg_dirs.join("\n") + pkg_dirs.join("\n"), ) Hbc::FakeSystemCommand.stubs_command( %W[/usr/sbin/pkgutil --files #{pkg_id}], - (pkg_files + pkg_dirs).join("\n") + (pkg_files + pkg_dirs).join("\n"), ) Hbc::FakeSystemCommand.stubs_command( %W[/usr/sbin/pkgutil --pkg-info-plist #{pkg_id}], - pkg_info_plist + pkg_info_plist, ) Hbc::FakeSystemCommand.expects_command(sudo(%W[/usr/sbin/pkgutil --forget #{pkg_id}])) Hbc::FakeSystemCommand.expects_command( - sudo(%w[/bin/rm -f --] + pkg_files.map { |path| Pathname("/tmp/#{path}") }) + sudo(%w[/bin/rm -f --] + pkg_files.map { |path| Pathname("/tmp/#{path}") }), ) end @@ -180,8 +174,8 @@ describe Hbc::Artifact::Zap do end end - describe "when using kext" do - let(:cask) { Hbc.load("with-zap-kext") } + context "when using kext" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-zap-kext.rb") } let(:kext_id) { "my.fancy.package.kernelextension" } it "can zap" do @@ -190,7 +184,7 @@ describe Hbc::Artifact::Zap do ) Hbc::FakeSystemCommand.expects_command( - sudo(%W[/sbin/kextunload -b #{kext_id}]) + sudo(%W[/sbin/kextunload -b #{kext_id}]), ) Hbc::FakeSystemCommand.expects_command( @@ -198,15 +192,15 @@ describe Hbc::Artifact::Zap do ) Hbc::FakeSystemCommand.expects_command( - sudo(["/bin/rm", "-rf", "/Library/Extensions/FancyPackage.kext"]) + sudo(["/bin/rm", "-rf", "/Library/Extensions/FancyPackage.kext"]), ) subject end end - describe "when using quit" do - let(:cask) { Hbc.load("with-zap-quit") } + context "when using quit" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-zap-quit.rb") } let(:bundle_id) { "my.fancy.package.app" } let(:quit_application_script) { %Q(tell application id "#{bundle_id}" to quit) @@ -218,15 +212,15 @@ describe Hbc::Artifact::Zap do ) Hbc::FakeSystemCommand.stubs_command( - %w[/bin/launchctl list] + %w[/bin/launchctl list], ) subject end end - describe "when using signal" do - let(:cask) { Hbc.load("with-zap-signal") } + context "when using signal" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-zap-signal.rb") } let(:bundle_id) { "my.fancy.package.app" } let(:signals) { %w[TERM KILL] } let(:unix_pids) { [12_345, 67_890] } @@ -237,95 +231,107 @@ describe Hbc::Artifact::Zap do ) signals.each do |signal| - Process.expects(:kill).with(signal, *unix_pids) + expect(Process).to receive(:kill).with(signal, *unix_pids) end subject end end - describe "when using delete" do - let(:cask) { Hbc.load("with-zap-delete") } + context "when using delete" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-zap-delete.rb") } it "can zap" do Hbc::FakeSystemCommand.expects_command( sudo(%w[/bin/rm -rf --], - Pathname.new("/permissible/absolute/path"), - Pathname.new("~/permissible/path/with/tilde").expand_path) + absolute_path, + path_with_tilde, + glob_path1, + glob_path2), ) subject end end - describe "when using trash" do - let(:cask) { Hbc.load("with-zap-trash") } + context "when using trash" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-zap-trash.rb") } it "can zap" do Hbc::FakeSystemCommand.expects_command( sudo(%w[/bin/rm -rf --], - Pathname.new("/permissible/absolute/path"), - Pathname.new("~/permissible/path/with/tilde").expand_path) + absolute_path, + path_with_tilde, + glob_path1, + glob_path2), ) subject end end - describe "when using rmdir" do - let(:cask) { Hbc.load("with-zap-rmdir") } - let(:dir_pathname) { Pathname.new("#{TEST_FIXTURE_DIR}/cask/empty_directory") } + context "when using rmdir" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-zap-rmdir.rb") } + let(:empty_directory_path) { Pathname.new("#{TEST_TMPDIR}/empty_directory_path") } + + before(:each) do + empty_directory_path.mkdir + end + + after(:each) do + empty_directory_path.rmdir + end it "can zap" do Hbc::FakeSystemCommand.expects_command( - sudo(%w[/bin/rm -f --], dir_pathname.join(".DS_Store")) + sudo(%w[/bin/rm -f --], empty_directory_path/".DS_Store"), ) Hbc::FakeSystemCommand.expects_command( - sudo(%w[/bin/rmdir --], dir_pathname) + sudo(%w[/bin/rmdir --], empty_directory_path), ) subject end end - describe "when using script" do - let(:cask) { Hbc.load("with-zap-script") } + context "when using script" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-zap-script.rb") } let(:script_pathname) { cask.staged_path.join("MyFancyPkg", "FancyUninstaller.tool") } it "can zap" do Hbc::FakeSystemCommand.expects_command(%w[/bin/chmod -- +x] + [script_pathname]) Hbc::FakeSystemCommand.expects_command( - sudo(cask.staged_path.join("MyFancyPkg", "FancyUninstaller.tool"), "--please") + sudo(cask.staged_path.join("MyFancyPkg", "FancyUninstaller.tool"), "--please"), ) subject end end - describe "when using early_script" do - let(:cask) { Hbc.load("with-zap-early-script") } + context "when using early_script" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-zap-early-script.rb") } let(:script_pathname) { cask.staged_path.join("MyFancyPkg", "FancyUninstaller.tool") } it "can zap" do Hbc::FakeSystemCommand.expects_command(%w[/bin/chmod -- +x] + [script_pathname]) Hbc::FakeSystemCommand.expects_command( - sudo(cask.staged_path.join("MyFancyPkg", "FancyUninstaller.tool"), "--please") + sudo(cask.staged_path.join("MyFancyPkg", "FancyUninstaller.tool"), "--please"), ) subject end end - describe "when using login_item" do - let(:cask) { Hbc.load("with-zap-login-item") } + context "when using login_item" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-zap-login-item.rb") } it "can zap" do Hbc::FakeSystemCommand.expects_command( ["/usr/bin/osascript", "-e", 'tell application "System Events" to delete every login ' \ - 'item whose name is "Fancy"'] + 'item whose name is "Fancy"'], ) subject diff --git a/Library/Homebrew/cask/spec/cask/audit_spec.rb b/Library/Homebrew/cask/spec/cask/audit_spec.rb index c12063a1d..9eb9f0136 100644 --- a/Library/Homebrew/cask/spec/cask/audit_spec.rb +++ b/Library/Homebrew/cask/spec/cask/audit_spec.rb @@ -1,6 +1,5 @@ describe Hbc::Audit do include AuditMatchers - include Sha256Helper let(:cask) { instance_double(Hbc::Cask) } let(:download) { false } @@ -162,7 +161,7 @@ describe Hbc::Audit do before do allow(audit).to receive(:check_appcast_http_code) - allow(fake_system_command).to receive(:run).and_return(fake_curl_result) + allow(Hbc::SystemCommand).to receive(:run).and_return(fake_curl_result) allow(fake_curl_result).to receive(:success?).and_return(success) end @@ -178,7 +177,7 @@ describe Hbc::Audit do end context "when appcast checkpoint is out of date" do - let(:actual_checkpoint) { random_sha256 } + let(:actual_checkpoint) { "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" } it { is_expected.to warn_with(mismatch_msg) } it { should_not warn_with(curl_error_msg) } end diff --git a/Library/Homebrew/cask/spec/cask/cask_spec.rb b/Library/Homebrew/cask/spec/cask/cask_spec.rb index d470c6ec3..32f3d8258 100644 --- a/Library/Homebrew/cask/spec/cask/cask_spec.rb +++ b/Library/Homebrew/cask/spec/cask/cask_spec.rb @@ -20,4 +20,73 @@ describe Hbc::Cask do end end end + + describe "load" do + let(:hbc_relative_tap_path) { "../../Taps/caskroom/homebrew-cask" } + + it "returns an instance of the Cask for the given token" do + c = Hbc.load("adium") + expect(c).to be_kind_of(Hbc::Cask) + expect(c.token).to eq("adium") + end + + it "returns an instance of the Cask from a specific file location" do + location = File.expand_path(hbc_relative_tap_path + "/Casks/dia.rb") + c = Hbc.load(location) + expect(c).to be_kind_of(Hbc::Cask) + expect(c.token).to eq("dia") + end + + it "returns an instance of the Cask from a url" do + url = "file://" + File.expand_path(hbc_relative_tap_path + "/Casks/dia.rb") + c = shutup do + Hbc.load(url) + end + expect(c).to be_kind_of(Hbc::Cask) + expect(c.token).to eq("dia") + end + + it "raises an error when failing to download a Cask from a url" do + expect { + url = "file://" + File.expand_path(hbc_relative_tap_path + "/Casks/notacask.rb") + shutup do + Hbc.load(url) + end + }.to raise_error(Hbc::CaskUnavailableError) + end + + it "returns an instance of the Cask from a relative file location" do + c = Hbc.load(hbc_relative_tap_path + "/Casks/bbedit.rb") + expect(c).to be_kind_of(Hbc::Cask) + expect(c.token).to eq("bbedit") + end + + it "uses exact match when loading by token" do + expect(Hbc.load("test-opera").token).to eq("test-opera") + expect(Hbc.load("test-opera-mail").token).to eq("test-opera-mail") + end + + it "raises an error when attempting to load a Cask that doesn't exist" do + expect { + Hbc.load("notacask") + }.to raise_error(Hbc::CaskUnavailableError) + end + end + + describe "all_tokens" do + it "returns a token for every Cask" do + all_cask_tokens = Hbc.all_tokens + expect(all_cask_tokens.count).to be > 20 + all_cask_tokens.each { |token| expect(token).to be_kind_of(String) } + end + end + + describe "metadata" do + it "proposes a versioned metadata directory name for each instance" do + cask_token = "adium" + c = Hbc.load(cask_token) + metadata_path = Hbc.caskroom.join(cask_token, ".metadata", c.version) + expect(c.metadata_versioned_container_path.to_s).to eq(metadata_path.to_s) + end + end end diff --git a/Library/Homebrew/cask/spec/cask/cli/audit_spec.rb b/Library/Homebrew/cask/spec/cask/cli/audit_spec.rb new file mode 100644 index 000000000..b520a88df --- /dev/null +++ b/Library/Homebrew/cask/spec/cask/cli/audit_spec.rb @@ -0,0 +1,61 @@ +require "spec_helper" + +describe Hbc::CLI::Audit do + let(:auditor) { double } + let(:cask) { double } + + describe "selection of Casks to audit" do + it "audits all Casks if no tokens are given" do + allow(Hbc).to receive(:all).and_return([cask, cask]) + + expect(auditor).to receive(:audit).twice + + run_audit([], auditor) + end + + it "audits specified Casks if tokens are given" do + cask_token = "nice-app" + expect(Hbc).to receive(:load).with(cask_token).and_return(cask) + + expect(auditor).to receive(:audit).with(cask, audit_download: false, check_token_conflicts: false) + + run_audit([cask_token], auditor) + end + end + + describe "rules for downloading a Cask" do + it "does not download the Cask per default" do + allow(Hbc).to receive(:load).and_return(cask) + expect(auditor).to receive(:audit).with(cask, audit_download: false, check_token_conflicts: false) + + run_audit(["casktoken"], auditor) + end + + it "download a Cask if --download flag is set" do + allow(Hbc).to receive(:load).and_return(cask) + expect(auditor).to receive(:audit).with(cask, audit_download: true, check_token_conflicts: false) + + run_audit(["casktoken", "--download"], auditor) + end + end + + describe "rules for checking token conflicts" do + it "does not check for token conflicts per default" do + allow(Hbc).to receive(:load).and_return(cask) + expect(auditor).to receive(:audit).with(cask, audit_download: false, check_token_conflicts: false) + + run_audit(["casktoken"], auditor) + end + + it "checks for token conflicts if --token-conflicts flag is set" do + allow(Hbc).to receive(:load).and_return(cask) + expect(auditor).to receive(:audit).with(cask, audit_download: false, check_token_conflicts: true) + + run_audit(["casktoken", "--token-conflicts"], auditor) + end + end + + def run_audit(args, auditor) + Hbc::CLI::Audit.new(args, auditor).run + end +end diff --git a/Library/Homebrew/cask/test/cask/cli/cat_test.rb b/Library/Homebrew/cask/spec/cask/cli/cat_spec.rb index df49efda0..7517c1b5c 100644 --- a/Library/Homebrew/cask/test/cask/cli/cat_test.rb +++ b/Library/Homebrew/cask/spec/cask/cli/cat_spec.rb @@ -1,10 +1,10 @@ -require "test_helper" +require "spec_helper" describe Hbc::CLI::Cat do describe "given a basic Cask" do - before do - @expected_output = <<-EOS.undent - test_cask 'basic-cask' do + let(:expected_output) { + <<-EOS.undent + cask 'basic-cask' do version '1.2.3' sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' @@ -14,46 +14,46 @@ describe Hbc::CLI::Cat do app 'TestCask.app' end EOS - end + } it "displays the Cask file content about the specified Cask" do - lambda { + expect { Hbc::CLI::Cat.run("basic-cask") - }.must_output(@expected_output) + }.to output(expected_output).to_stdout end it "throws away additional Cask arguments and uses the first" do - lambda { + expect { Hbc::CLI::Cat.run("basic-cask", "local-caffeine") - }.must_output(@expected_output) + }.to output(expected_output).to_stdout end it "throws away stray options" do - lambda { + expect { Hbc::CLI::Cat.run("--notavalidoption", "basic-cask") - }.must_output(@expected_output) + }.to output(expected_output).to_stdout end end it "raises an exception when the Cask does not exist" do - lambda { + expect { Hbc::CLI::Cat.run("notacask") - }.must_raise Hbc::CaskUnavailableError + }.to raise_error(Hbc::CaskUnavailableError) end describe "when no Cask is specified" do it "raises an exception" do - lambda { + expect { Hbc::CLI::Cat.run - }.must_raise Hbc::CaskUnspecifiedError + }.to raise_error(Hbc::CaskUnspecifiedError) end end describe "when no Cask is specified, but an invalid option" do it "raises an exception" do - lambda { + expect { Hbc::CLI::Cat.run("--notavalidoption") - }.must_raise Hbc::CaskUnspecifiedError + }.to raise_error(Hbc::CaskUnspecifiedError) end end end diff --git a/Library/Homebrew/cask/test/cask/cli/create_test.rb b/Library/Homebrew/cask/spec/cask/cli/create_spec.rb index f09c91e8e..e3d484d87 100644 --- a/Library/Homebrew/cask/test/cask/cli/create_test.rb +++ b/Library/Homebrew/cask/spec/cask/cli/create_spec.rb @@ -1,4 +1,4 @@ -require "test_helper" +require "spec_helper" # monkeypatch for testing module Hbc @@ -20,11 +20,11 @@ module Hbc end describe Hbc::CLI::Create do - before do + before(:each) do Hbc::CLI::Create.reset! end - after do + after(:each) do %w[new-cask additional-cask another-cask yet-another-cask local-caff].each do |cask| path = Hbc.path(cask) path.delete if path.exist? @@ -33,7 +33,7 @@ describe Hbc::CLI::Create do it "opens the editor for the specified Cask" do Hbc::CLI::Create.run("new-cask") - Hbc::CLI::Create.editor_commands.must_equal [ + expect(Hbc::CLI::Create.editor_commands).to eq [ [Hbc.path("new-cask")], ] end @@ -41,7 +41,7 @@ describe Hbc::CLI::Create do it "drops a template down for the specified Cask" do Hbc::CLI::Create.run("new-cask") template = File.read(Hbc.path("new-cask")) - template.must_equal <<-EOS.undent + expect(template).to eq <<-EOS.undent cask 'new-cask' do version '' sha256 '' @@ -57,44 +57,44 @@ describe Hbc::CLI::Create do it "throws away additional Cask arguments and uses the first" do Hbc::CLI::Create.run("additional-cask", "another-cask") - Hbc::CLI::Create.editor_commands.must_equal [ + expect(Hbc::CLI::Create.editor_commands).to eq [ [Hbc.path("additional-cask")], ] end it "throws away stray options" do Hbc::CLI::Create.run("--notavalidoption", "yet-another-cask") - Hbc::CLI::Create.editor_commands.must_equal [ + expect(Hbc::CLI::Create.editor_commands).to eq [ [Hbc.path("yet-another-cask")], ] end it "raises an exception when the Cask already exists" do - lambda { + expect { Hbc::CLI::Create.run("basic-cask") - }.must_raise Hbc::CaskAlreadyCreatedError + }.to raise_error(Hbc::CaskAlreadyCreatedError) end it "allows creating Casks that are substrings of existing Casks" do Hbc::CLI::Create.run("local-caff") - Hbc::CLI::Create.editor_commands.must_equal [ + expect(Hbc::CLI::Create.editor_commands).to eq [ [Hbc.path("local-caff")], ] end describe "when no Cask is specified" do it "raises an exception" do - lambda { + expect { Hbc::CLI::Create.run - }.must_raise Hbc::CaskUnspecifiedError + }.to raise_error(Hbc::CaskUnspecifiedError) end end describe "when no Cask is specified, but an invalid option" do it "raises an exception" do - lambda { + expect { Hbc::CLI::Create.run("--notavalidoption") - }.must_raise Hbc::CaskUnspecifiedError + }.to raise_error(Hbc::CaskUnspecifiedError) end end end diff --git a/Library/Homebrew/cask/spec/cask/cli/doctor_spec.rb b/Library/Homebrew/cask/spec/cask/cli/doctor_spec.rb index 38f8b50ac..ff1cf5706 100644 --- a/Library/Homebrew/cask/spec/cask/cli/doctor_spec.rb +++ b/Library/Homebrew/cask/spec/cask/cli/doctor_spec.rb @@ -4,7 +4,7 @@ describe Hbc::CLI::Doctor do it "displays some nice info about the environment" do expect { Hbc::CLI::Doctor.run - }.to output(/\A==> macOS Release:/).to_stdout + }.to output(/\A==> Homebrew-Cask Version/).to_stdout end it "raises an exception when arguments are given" do diff --git a/Library/Homebrew/cask/test/cask/cli/edit_test.rb b/Library/Homebrew/cask/spec/cask/cli/edit_spec.rb index 6eb2289c0..5ddf27a48 100644 --- a/Library/Homebrew/cask/test/cask/cli/edit_test.rb +++ b/Library/Homebrew/cask/spec/cask/cli/edit_spec.rb @@ -1,4 +1,4 @@ -require "test_helper" +require "spec_helper" # monkeypatch for testing module Hbc @@ -20,43 +20,43 @@ module Hbc end describe Hbc::CLI::Edit do - before do + before(:each) do Hbc::CLI::Edit.reset! end it "opens the editor for the specified Cask" do - Hbc::CLI::Edit.run("alfred") - Hbc::CLI::Edit.editor_commands.must_equal [ - [Hbc.path("alfred")], + Hbc::CLI::Edit.run("local-caffeine") + expect(Hbc::CLI::Edit.editor_commands).to eq [ + [Hbc.path("local-caffeine")], ] end it "throws away additional arguments and uses the first" do - Hbc::CLI::Edit.run("adium", "alfred") - Hbc::CLI::Edit.editor_commands.must_equal [ - [Hbc.path("adium")], + Hbc::CLI::Edit.run("local-caffeine", "local-transmission") + expect(Hbc::CLI::Edit.editor_commands).to eq [ + [Hbc.path("local-caffeine")], ] end it "raises an exception when the Cask doesnt exist" do - lambda { + expect { Hbc::CLI::Edit.run("notacask") - }.must_raise Hbc::CaskUnavailableError + }.to raise_error(Hbc::CaskUnavailableError) end describe "when no Cask is specified" do it "raises an exception" do - lambda { + expect { Hbc::CLI::Edit.run - }.must_raise Hbc::CaskUnspecifiedError + }.to raise_error(Hbc::CaskUnspecifiedError) end end describe "when no Cask is specified, but an invalid option" do it "raises an exception" do - lambda { + expect { Hbc::CLI::Edit.run("--notavalidoption") - }.must_raise Hbc::CaskUnspecifiedError + }.to raise_error(Hbc::CaskUnspecifiedError) end end end diff --git a/Library/Homebrew/cask/test/cask/cli/fetch_test.rb b/Library/Homebrew/cask/spec/cask/cli/fetch_spec.rb index 70c25646d..bb8133453 100644 --- a/Library/Homebrew/cask/test/cask/cli/fetch_test.rb +++ b/Library/Homebrew/cask/spec/cask/cli/fetch_spec.rb @@ -1,20 +1,20 @@ -require "test_helper" +require "spec_helper" describe Hbc::CLI::Fetch do let(:local_transmission) { - Hbc.load("local-transmission") + Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb") } let(:local_caffeine) { - Hbc.load("local-caffeine") + Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb") } it "allows download the installer of a Cask" do shutup do Hbc::CLI::Fetch.run("local-transmission", "local-caffeine") end - Hbc::CurlDownloadStrategy.new(local_transmission).cached_location.must_be :exist? - Hbc::CurlDownloadStrategy.new(local_caffeine).cached_location.must_be :exist? + expect(Hbc::CurlDownloadStrategy.new(local_transmission).cached_location).to exist + expect(Hbc::CurlDownloadStrategy.new(local_caffeine).cached_location).to exist end it "prevents double fetch (without nuking existing installation)" do @@ -30,7 +30,7 @@ describe Hbc::CLI::Fetch do end new_ctime = File.stat(download_stategy.cached_location).ctime - old_ctime.to_i.must_equal new_ctime.to_i + expect(old_ctime.to_i).to eq(new_ctime.to_i) end it "allows double fetch with --force" do @@ -48,31 +48,30 @@ describe Hbc::CLI::Fetch do download_stategy = Hbc::CurlDownloadStrategy.new(local_transmission) new_ctime = File.stat(download_stategy.cached_location).ctime - # new_ctime.to_i.must_be :>, old_ctime.to_i - new_ctime.to_i.must_be :>, old_ctime.to_i + expect(new_ctime.to_i).to be > old_ctime.to_i end it "properly handles Casks that are not present" do - lambda { + expect { shutup do Hbc::CLI::Fetch.run("notacask") end - }.must_raise Hbc::CaskUnavailableError + }.to raise_error(Hbc::CaskUnavailableError) end describe "when no Cask is specified" do it "raises an exception" do - lambda { + expect { Hbc::CLI::Fetch.run - }.must_raise Hbc::CaskUnspecifiedError + }.to raise_error(Hbc::CaskUnspecifiedError) end end describe "when no Cask is specified, but an invalid option" do it "raises an exception" do - lambda { + expect { Hbc::CLI::Fetch.run("--notavalidoption") - }.must_raise Hbc::CaskUnspecifiedError + }.to raise_error(Hbc::CaskUnspecifiedError) end end end diff --git a/Library/Homebrew/cask/test/cask/cli/home_test.rb b/Library/Homebrew/cask/spec/cask/cli/home_spec.rb index 67bcb024a..a2b49b433 100644 --- a/Library/Homebrew/cask/test/cask/cli/home_test.rb +++ b/Library/Homebrew/cask/spec/cask/cli/home_spec.rb @@ -1,4 +1,4 @@ -require "test_helper" +require "spec_helper" # monkeypatch for testing module Hbc @@ -25,23 +25,23 @@ describe Hbc::CLI::Home do end it "opens the homepage for the specified Cask" do - Hbc::CLI::Home.run("alfred") - Hbc::CLI::Home.system_commands.must_equal [ - ["/usr/bin/open", "--", "https://www.alfredapp.com/"], + Hbc::CLI::Home.run("local-caffeine") + expect(Hbc::CLI::Home.system_commands).to eq [ + ["/usr/bin/open", "--", "http://example.com/local-caffeine"], ] end it "works for multiple Casks" do - Hbc::CLI::Home.run("alfred", "adium") - Hbc::CLI::Home.system_commands.must_equal [ - ["/usr/bin/open", "--", "https://www.alfredapp.com/"], - ["/usr/bin/open", "--", "https://www.adium.im/"], + Hbc::CLI::Home.run("local-caffeine", "local-transmission") + expect(Hbc::CLI::Home.system_commands).to eq [ + ["/usr/bin/open", "--", "http://example.com/local-caffeine"], + ["/usr/bin/open", "--", "http://example.com/local-transmission"], ] end it "opens the project page when no Cask is specified" do Hbc::CLI::Home.run - Hbc::CLI::Home.system_commands.must_equal [ + expect(Hbc::CLI::Home.system_commands).to eq [ ["/usr/bin/open", "--", "http://caskroom.io/"], ] end diff --git a/Library/Homebrew/cask/test/cask/cli/info_test.rb b/Library/Homebrew/cask/spec/cask/cli/info_spec.rb index 767a594e8..6977f81c3 100644 --- a/Library/Homebrew/cask/test/cask/cli/info_test.rb +++ b/Library/Homebrew/cask/spec/cask/cli/info_spec.rb @@ -1,14 +1,14 @@ -require "test_helper" +require "spec_helper" describe Hbc::CLI::Info do it "displays some nice info about the specified Cask" do - lambda { + expect { Hbc::CLI::Info.run("local-caffeine") - }.must_output <<-EOS.undent + }.to output(<<-EOS.undent).to_stdout local-caffeine: 1.2.3 http://example.com/local-caffeine Not installed - From: https://github.com/caskroom/homebrew-test/blob/master/Casks/local-caffeine.rb + From: https://github.com/caskroom/homebrew-spec/blob/master/Casks/local-caffeine.rb ==> Name None ==> Artifacts @@ -17,12 +17,12 @@ describe Hbc::CLI::Info do end describe "given multiple Casks" do - before do - @expected_output = <<-EOS.undent + let(:expected_output) { + <<-EOS.undent local-caffeine: 1.2.3 http://example.com/local-caffeine Not installed - From: https://github.com/caskroom/homebrew-test/blob/master/Casks/local-caffeine.rb + From: https://github.com/caskroom/homebrew-spec/blob/master/Casks/local-caffeine.rb ==> Name None ==> Artifacts @@ -30,35 +30,35 @@ describe Hbc::CLI::Info do local-transmission: 2.61 http://example.com/local-transmission Not installed - From: https://github.com/caskroom/homebrew-test/blob/master/Casks/local-transmission.rb + From: https://github.com/caskroom/homebrew-spec/blob/master/Casks/local-transmission.rb ==> Name None ==> Artifacts Transmission.app (app) EOS - end + } it "displays the info" do - lambda { + expect { Hbc::CLI::Info.run("local-caffeine", "local-transmission") - }.must_output(@expected_output) + }.to output(expected_output).to_stdout end it "throws away stray options" do - lambda { + expect { Hbc::CLI::Info.run("--notavalidoption", "local-caffeine", "local-transmission") - }.must_output(@expected_output) + }.to output(expected_output).to_stdout end end it "should print caveats if the Cask provided one" do - lambda { + expect { Hbc::CLI::Info.run("with-caveats") - }.must_output <<-EOS.undent + }.to output(<<-EOS.undent).to_stdout with-caveats: 1.2.3 http://example.com/local-caffeine Not installed - From: https://github.com/caskroom/homebrew-test/blob/master/Casks/with-caveats.rb + From: https://github.com/caskroom/homebrew-spec/blob/master/Casks/with-caveats.rb ==> Name None ==> Artifacts @@ -78,13 +78,13 @@ describe Hbc::CLI::Info do end it 'should not print "Caveats" section divider if the caveats block has no output' do - lambda { + expect { Hbc::CLI::Info.run("with-conditional-caveats") - }.must_output <<-EOS.undent + }.to output(<<-EOS.undent).to_stdout with-conditional-caveats: 1.2.3 http://example.com/local-caffeine Not installed - From: https://github.com/caskroom/homebrew-test/blob/master/Casks/with-conditional-caveats.rb + From: https://github.com/caskroom/homebrew-spec/blob/master/Casks/with-conditional-caveats.rb ==> Name None ==> Artifacts @@ -94,17 +94,17 @@ describe Hbc::CLI::Info do describe "when no Cask is specified" do it "raises an exception" do - lambda { + expect { Hbc::CLI::Info.run - }.must_raise Hbc::CaskUnspecifiedError + }.to raise_error(Hbc::CaskUnspecifiedError) end end describe "when no Cask is specified, but an invalid option" do it "raises an exception" do - lambda { + expect { Hbc::CLI::Info.run("--notavalidoption") - }.must_raise Hbc::CaskUnspecifiedError + }.to raise_error(Hbc::CaskUnspecifiedError) end end end diff --git a/Library/Homebrew/cask/test/cask/cli/install_test.rb b/Library/Homebrew/cask/spec/cask/cli/install_spec.rb index eef3f2e5b..07aa78aa3 100644 --- a/Library/Homebrew/cask/test/cask/cli/install_test.rb +++ b/Library/Homebrew/cask/spec/cask/cli/install_spec.rb @@ -1,4 +1,4 @@ -require "test_helper" +require "spec_helper" describe Hbc::CLI::Install do it "allows staging and activation of multiple Casks at once" do @@ -6,10 +6,10 @@ describe Hbc::CLI::Install do Hbc::CLI::Install.run("local-transmission", "local-caffeine") end - Hbc.load("local-transmission").must_be :installed? - Hbc.appdir.join("Transmission.app").must_be :directory? - Hbc.load("local-caffeine").must_be :installed? - Hbc.appdir.join("Caffeine.app").must_be :directory? + expect(Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb")).to be_installed + expect(Hbc.appdir.join("Transmission.app")).to be_a_directory + expect(Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb")).to be_installed + expect(Hbc.appdir.join("Caffeine.app")).to be_a_directory end it "skips double install (without nuking existing installation)" do @@ -19,7 +19,7 @@ describe Hbc::CLI::Install do shutup do Hbc::CLI::Install.run("local-transmission") end - Hbc.load("local-transmission").must_be :installed? + expect(Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb")).to be_installed end it "prints a warning message on double install" do @@ -27,9 +27,9 @@ describe Hbc::CLI::Install do Hbc::CLI::Install.run("local-transmission") end - lambda { + expect { Hbc::CLI::Install.run("local-transmission", "") - }.must_output nil, /Warning: A Cask for local-transmission is already installed./ + }.to output(/Warning: A Cask for local-transmission is already installed./).to_stderr end it "allows double install with --force" do @@ -37,54 +37,56 @@ describe Hbc::CLI::Install do Hbc::CLI::Install.run("local-transmission") end - lambda { - Hbc::CLI::Install.run("local-transmission", "--force") - }.must_output(/local-transmission was successfully installed!/) + expect { + expect { + Hbc::CLI::Install.run("local-transmission", "--force") + }.to output(/It seems there is already an App at.*overwriting\./).to_stderr + }.to output(/local-transmission was successfully installed!/).to_stdout end it "skips dependencies with --skip-cask-deps" do shutup do Hbc::CLI::Install.run("with-depends-on-cask-multiple", "--skip-cask-deps") end - Hbc.load("with-depends-on-cask-multiple").must_be :installed? - Hbc.load("local-caffeine").wont_be :installed? - Hbc.load("local-transmission").wont_be :installed? + expect(Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-depends-on-cask-multiple.rb")).to be_installed + expect(Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb")).not_to be_installed + expect(Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb")).not_to be_installed end it "properly handles Casks that are not present" do - lambda { + expect { shutup do Hbc::CLI::Install.run("notacask") end - }.must_raise Hbc::CaskError + }.to raise_error(Hbc::CaskError) end it "returns a suggestion for a misspelled Cask" do - lambda { + expect { begin Hbc::CLI::Install.run("googlechrome") rescue Hbc::CaskError nil end - }.must_output(nil, /No available Cask for googlechrome\. Did you mean:\ngoogle-chrome/) + }.to output(/No available Cask for googlechrome\. Did you mean:\ngoogle-chrome/).to_stderr end it "returns multiple suggestions for a Cask fragment" do - lambda { + expect { begin Hbc::CLI::Install.run("google") rescue Hbc::CaskError nil end - }.must_output(nil, /No available Cask for google\. Did you mean one of:\ngoogle/) + }.to output(/No available Cask for google\. Did you mean one of:\ngoogle/).to_stderr end describe "when no Cask is specified" do with_options = lambda do |options| it "raises an exception" do - lambda { + expect { Hbc::CLI::Install.run(*options) - }.must_raise Hbc::CaskUnspecifiedError + }.to raise_error(Hbc::CaskUnspecifiedError) end end diff --git a/Library/Homebrew/cask/test/cask/cli/list_test.rb b/Library/Homebrew/cask/spec/cask/cli/list_spec.rb index 4220ea510..49c06c521 100644 --- a/Library/Homebrew/cask/test/cask/cli/list_test.rb +++ b/Library/Homebrew/cask/spec/cask/cli/list_spec.rb @@ -1,16 +1,16 @@ -require "test_helper" +require "spec_helper" describe Hbc::CLI::List do it "lists the installed Casks in a pretty fashion" do casks = %w[local-caffeine local-transmission].map { |c| Hbc.load(c) } casks.each do |c| - TestHelper.install_with_caskfile(c) + InstallHelper.install_with_caskfile(c) end - lambda { + expect { Hbc::CLI::List.run - }.must_output <<-EOS.undent + }.to output(<<-EOS.undent).to_stdout local-caffeine local-transmission EOS @@ -18,7 +18,7 @@ describe Hbc::CLI::List do describe "lists versions" do let(:casks) { ["local-caffeine", "local-transmission"] } - let(:output) { + let(:expected_output) { <<-EOS.undent local-caffeine 1.2.3 local-transmission 2.61 @@ -26,19 +26,19 @@ describe Hbc::CLI::List do } before(:each) do - casks.map(&Hbc.method(:load)).each(&TestHelper.method(:install_with_caskfile)) + casks.map(&Hbc.method(:load)).each(&InstallHelper.method(:install_with_caskfile)) end it "of all installed Casks" do - lambda { + expect { Hbc::CLI::List.run("--versions") - }.must_output(output) + }.to output(expected_output).to_stdout end it "of given Casks" do - lambda { + expect { Hbc::CLI::List.run("--versions", "local-caffeine", "local-transmission") - }.must_output(output) + }.to output(expected_output).to_stdout end end @@ -50,34 +50,30 @@ describe Hbc::CLI::List do staged_path.mkpath end - after do - caskroom_path.rmtree - end - it "lists installed Casks without backing ruby files (due to renames or otherwise)" do - lambda { + expect { Hbc::CLI::List.run - }.must_output <<-EOS.undent + }.to output(<<-EOS.undent).to_stdout ive-been-renamed (!) EOS end end describe "given a set of installed Casks" do - let(:caffeine) { Hbc.load("local-caffeine") } - let(:transmission) { Hbc.load("local-transmission") } + let(:caffeine) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb") } + let(:transmission) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb") } let(:casks) { [caffeine, transmission] } it "lists the installed files for those Casks" do - casks.each(&TestHelper.method(:install_without_artifacts_with_caskfile)) + casks.each(&InstallHelper.method(:install_without_artifacts_with_caskfile)) shutup do Hbc::Artifact::App.new(transmission).install_phase end - lambda { + expect { Hbc::CLI::List.run("local-transmission", "local-caffeine") - }.must_output <<-EOS.undent + }.to output(<<-EOS.undent).to_stdout ==> Apps #{Hbc.appdir.join("Transmission.app")} (#{Hbc.appdir.join("Transmission.app").abv}) ==> Apps diff --git a/Library/Homebrew/cask/test/cask/cli/options_test.rb b/Library/Homebrew/cask/spec/cask/cli/options_spec.rb index d49e7827b..a4381213a 100644 --- a/Library/Homebrew/cask/test/cask/cli/options_test.rb +++ b/Library/Homebrew/cask/spec/cask/cli/options_spec.rb @@ -1,10 +1,10 @@ -require "test_helper" +require "spec_helper" describe Hbc::CLI do it "supports setting the appdir" do Hbc::CLI.process_options %w[help --appdir=/some/path/foo] - Hbc.appdir.must_equal Pathname("/some/path/foo") + expect(Hbc.appdir).to eq(Pathname.new("/some/path/foo")) end it "supports setting the appdir from ENV" do @@ -12,13 +12,13 @@ describe Hbc::CLI do Hbc::CLI.process_options %w[help] - Hbc.appdir.must_equal Pathname("/some/path/bar") + expect(Hbc.appdir).to eq(Pathname.new("/some/path/bar")) end it "supports setting the prefpanedir" do Hbc::CLI.process_options %w[help --prefpanedir=/some/path/foo] - Hbc.prefpanedir.must_equal Pathname("/some/path/foo") + expect(Hbc.prefpanedir).to eq(Pathname.new("/some/path/foo")) end it "supports setting the prefpanedir from ENV" do @@ -26,13 +26,13 @@ describe Hbc::CLI do Hbc::CLI.process_options %w[help] - Hbc.prefpanedir.must_equal Pathname("/some/path/bar") + expect(Hbc.prefpanedir).to eq(Pathname.new("/some/path/bar")) end it "supports setting the qlplugindir" do Hbc::CLI.process_options %w[help --qlplugindir=/some/path/foo] - Hbc.qlplugindir.must_equal Pathname("/some/path/foo") + expect(Hbc.qlplugindir).to eq(Pathname.new("/some/path/foo")) end it "supports setting the qlplugindir from ENV" do @@ -40,13 +40,13 @@ describe Hbc::CLI do Hbc::CLI.process_options %w[help] - Hbc.qlplugindir.must_equal Pathname("/some/path/bar") + expect(Hbc.qlplugindir).to eq(Pathname.new("/some/path/bar")) end it "supports setting the colorpickerdir" do Hbc::CLI.process_options %w[help --colorpickerdir=/some/path/foo] - Hbc.colorpickerdir.must_equal Pathname("/some/path/foo") + expect(Hbc.colorpickerdir).to eq(Pathname.new("/some/path/foo")) end it "supports setting the colorpickerdir from ENV" do @@ -54,13 +54,13 @@ describe Hbc::CLI do Hbc::CLI.process_options %w[help] - Hbc.colorpickerdir.must_equal Pathname("/some/path/bar") + expect(Hbc.colorpickerdir).to eq(Pathname.new("/some/path/bar")) end it "supports setting the dictionarydir" do Hbc::CLI.process_options %w[help --dictionarydir=/some/path/foo] - Hbc.dictionarydir.must_equal Pathname("/some/path/foo") + expect(Hbc.dictionarydir).to eq(Pathname.new("/some/path/foo")) end it "supports setting the dictionarydir from ENV" do @@ -68,13 +68,13 @@ describe Hbc::CLI do Hbc::CLI.process_options %w[help] - Hbc.dictionarydir.must_equal Pathname("/some/path/bar") + expect(Hbc.dictionarydir).to eq(Pathname.new("/some/path/bar")) end it "supports setting the fontdir" do Hbc::CLI.process_options %w[help --fontdir=/some/path/foo] - Hbc.fontdir.must_equal Pathname("/some/path/foo") + expect(Hbc.fontdir).to eq(Pathname.new("/some/path/foo")) end it "supports setting the fontdir from ENV" do @@ -82,13 +82,13 @@ describe Hbc::CLI do Hbc::CLI.process_options %w[help] - Hbc.fontdir.must_equal Pathname("/some/path/bar") + expect(Hbc.fontdir).to eq(Pathname.new("/some/path/bar")) end it "supports setting the servicedir" do Hbc::CLI.process_options %w[help --servicedir=/some/path/foo] - Hbc.servicedir.must_equal Pathname("/some/path/foo") + expect(Hbc.servicedir).to eq(Pathname.new("/some/path/foo")) end it "supports setting the servicedir from ENV" do @@ -96,36 +96,36 @@ describe Hbc::CLI do Hbc::CLI.process_options %w[help] - Hbc.servicedir.must_equal Pathname("/some/path/bar") + expect(Hbc.servicedir).to eq(Pathname.new("/some/path/bar")) end it "allows additional options to be passed through" do rest = Hbc::CLI.process_options %w[edit foo --create --appdir=/some/path/qux] - Hbc.appdir.must_equal Pathname("/some/path/qux") - rest.must_equal %w[edit foo --create] + expect(Hbc.appdir).to eq(Pathname.new("/some/path/qux")) + expect(rest).to eq(%w[edit foo --create]) end describe "when a mandatory argument is missing" do it "shows a user-friendly error message" do - lambda { + expect { Hbc::CLI.process_options %w[install -f] - }.must_raise Hbc::CaskError + }.to raise_error(Hbc::CaskError) end end describe "given an ambiguous option" do it "shows a user-friendly error message" do - lambda { + expect { Hbc::CLI.process_options %w[edit -c] - }.must_raise Hbc::CaskError + }.to raise_error(Hbc::CaskError) end end describe "--debug" do it "sets the Cask debug method to true" do Hbc::CLI.process_options %w[help --debug] - Hbc.debug.must_equal true + expect(Hbc.debug).to be true Hbc.debug = false end end @@ -133,12 +133,8 @@ describe Hbc::CLI do describe "--help" do it "sets the Cask help method to true" do Hbc::CLI.process_options %w[foo --help] - Hbc.help.must_equal true + expect(Hbc.help).to be true Hbc.help = false end end - - after do - ENV["HOMEBREW_CASK_OPTS"] = nil - end end diff --git a/Library/Homebrew/cask/spec/cask/cli/reinstall_spec.rb b/Library/Homebrew/cask/spec/cask/cli/reinstall_spec.rb new file mode 100644 index 000000000..df83c53e2 --- /dev/null +++ b/Library/Homebrew/cask/spec/cask/cli/reinstall_spec.rb @@ -0,0 +1,24 @@ +require "spec_helper" + +describe Hbc::CLI::Reinstall do + it "allows reinstalling a Cask" do + shutup do + Hbc::CLI::Install.run("local-transmission") + end + expect(Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb")).to be_installed + + shutup do + Hbc::CLI::Reinstall.run("local-transmission") + end + expect(Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb")).to be_installed + end + + it "allows reinstalling a non installed Cask" do + expect(Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb")).not_to be_installed + + shutup do + Hbc::CLI::Reinstall.run("local-transmission") + end + expect(Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb")).to be_installed + end +end diff --git a/Library/Homebrew/cask/spec/cask/cli/search_spec.rb b/Library/Homebrew/cask/spec/cask/cli/search_spec.rb new file mode 100644 index 000000000..fe669dd3e --- /dev/null +++ b/Library/Homebrew/cask/spec/cask/cli/search_spec.rb @@ -0,0 +1,61 @@ +require "spec_helper" + +describe Hbc::CLI::Search do + it "lists the available Casks that match the search term" do + expect { + Hbc::CLI::Search.run("photoshop") + }.to output(<<-EOS.undent).to_stdout + ==> Partial matches + adobe-photoshop-cc + adobe-photoshop-lightroom + EOS + end + + it "shows that there are no Casks matching a search term that did not result in anything" do + expect { + Hbc::CLI::Search.run("foo-bar-baz") + }.to output("No Cask found for \"foo-bar-baz\".\n").to_stdout + end + + it "lists all available Casks with no search term" do + expect { + Hbc::CLI::Search.run + }.to output(/google-chrome/).to_stdout + end + + it "ignores hyphens in search terms" do + expect { + Hbc::CLI::Search.run("goo-gle-chrome") + }.to output(/google-chrome/).to_stdout + end + + it "ignores hyphens in Cask tokens" do + expect { + Hbc::CLI::Search.run("googlechrome") + }.to output(/google-chrome/).to_stdout + end + + it "accepts multiple arguments" do + expect { + Hbc::CLI::Search.run("google chrome") + }.to output(/google-chrome/).to_stdout + end + + it "accepts a regexp argument" do + expect { + Hbc::CLI::Search.run("/^google-c[a-z]rome$/") + }.to output("==> Regexp matches\ngoogle-chrome\n").to_stdout + end + + it "Returns both exact and partial matches" do + expect { + Hbc::CLI::Search.run("mnemosyne") + }.to output(/^==> Exact match\nmnemosyne\n==> Partial matches\nsubclassed-mnemosyne/).to_stdout + end + + it "does not search the Tap name" do + expect { + Hbc::CLI::Search.run("caskroom") + }.to output(/^No Cask found for "caskroom"\.\n/).to_stdout + end +end diff --git a/Library/Homebrew/cask/spec/cask/cli/style_spec.rb b/Library/Homebrew/cask/spec/cask/cli/style_spec.rb index b0d34576a..106bfbb44 100644 --- a/Library/Homebrew/cask/spec/cask/cli/style_spec.rb +++ b/Library/Homebrew/cask/spec/cask/cli/style_spec.rb @@ -1,4 +1,6 @@ require "English" +require "open3" +require "rubygems" describe Hbc::CLI::Style do let(:args) { [] } @@ -77,6 +79,20 @@ describe Hbc::CLI::Style do expect { subject }.to raise_error(Hbc::CaskError) end end + + context "version" do + it "matches `HOMEBREW_RUBOCOP_VERSION`" do + stdout, status = Open3.capture2("gem", "dependency", "rubocop-cask", "--version", HOMEBREW_RUBOCOP_CASK_VERSION, "--pipe", "--remote") + + expect(status).to be_a_success + + requirement = Gem::Requirement.new(stdout.scan(/rubocop --version '(.*)'/).flatten.first) + version = Gem::Version.new(HOMEBREW_RUBOCOP_VERSION) + + expect(requirement).not_to be_none + expect(requirement).to be_satisfied_by(version) + end + end end describe "#cask_paths" do diff --git a/Library/Homebrew/cask/test/cask/cli/uninstall_test.rb b/Library/Homebrew/cask/spec/cask/cli/uninstall_spec.rb index 0368ad87c..a1b47e823 100644 --- a/Library/Homebrew/cask/test/cask/cli/uninstall_test.rb +++ b/Library/Homebrew/cask/spec/cask/cli/uninstall_spec.rb @@ -1,44 +1,91 @@ -require "test_helper" +require "spec_helper" describe Hbc::CLI::Uninstall do it "shows an error when a bad Cask is provided" do - lambda { + expect { Hbc::CLI::Uninstall.run("notacask") - }.must_raise Hbc::CaskUnavailableError + }.to raise_error(Hbc::CaskUnavailableError) end it "shows an error when a Cask is provided that's not installed" do - lambda { + expect { Hbc::CLI::Uninstall.run("anvil") - }.must_raise Hbc::CaskNotInstalledError + }.to raise_error(Hbc::CaskNotInstalledError) end it "tries anyway on a non-present Cask when --force is given" do - lambda do + expect { Hbc::CLI::Uninstall.run("anvil", "--force") - end # wont_raise + }.not_to raise_error end it "can uninstall and unlink multiple Casks at once" do - caffeine = Hbc.load("local-caffeine") - transmission = Hbc.load("local-transmission") + caffeine = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb") + transmission = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb") shutup do Hbc::Installer.new(caffeine).install Hbc::Installer.new(transmission).install end - caffeine.must_be :installed? - transmission.must_be :installed? + expect(caffeine).to be_installed + expect(transmission).to be_installed shutup do Hbc::CLI::Uninstall.run("local-caffeine", "local-transmission") end - caffeine.wont_be :installed? - Hbc.appdir.join("Transmission.app").wont_be :exist? - transmission.wont_be :installed? - Hbc.appdir.join("Caffeine.app").wont_be :exist? + expect(caffeine).not_to be_installed + expect(Hbc.appdir.join("Transmission.app")).not_to exist + expect(transmission).not_to be_installed + expect(Hbc.appdir.join("Caffeine.app")).not_to exist + end + + it "calls `uninstall` before removing artifacts" do + cask = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-uninstall-script-app.rb") + + shutup do + Hbc::Installer.new(cask).install + end + + expect(cask).to be_installed + + expect { + shutup do + Hbc::CLI::Uninstall.run("with-uninstall-script-app") + end + }.not_to raise_error + + expect(cask).not_to be_installed + expect(Hbc.appdir.join("MyFancyApp.app")).not_to exist + end + + it "can uninstall Casks when the uninstall script is missing, but only when using `--force`" do + cask = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-uninstall-script-app.rb") + + shutup do + Hbc::Installer.new(cask).install + end + + expect(cask).to be_installed + + Hbc.appdir.join("MyFancyApp.app").rmtree + + expect { + shutup do + Hbc::CLI::Uninstall.run("with-uninstall-script-app") + end + }.to raise_error(Hbc::CaskError, /does not exist/) + + expect(cask).to be_installed + + expect { + shutup do + Hbc::CLI::Uninstall.run("with-uninstall-script-app", "--force") + end + }.not_to raise_error + + expect(cask).not_to be_installed end describe "when multiple versions of a cask are installed" do @@ -67,34 +114,29 @@ describe Hbc::CLI::Uninstall do end end - after(:each) do - caskroom_path.rmtree if caskroom_path.exist? - end - it "uninstalls one version at a time" do shutup do Hbc::CLI::Uninstall.run("versioned-cask") end - caskroom_path.join(first_installed_version).must_be :exist? - caskroom_path.join(last_installed_version).wont_be :exist? - caskroom_path.must_be :exist? + expect(caskroom_path.join(first_installed_version)).to exist + expect(caskroom_path.join(last_installed_version)).not_to exist + expect(caskroom_path).to exist shutup do Hbc::CLI::Uninstall.run("versioned-cask") end - caskroom_path.join(first_installed_version).wont_be :exist? - caskroom_path.wont_be :exist? + expect(caskroom_path.join(first_installed_version)).not_to exist + expect(caskroom_path).not_to exist end it "displays a message when versions remain installed" do - out, err = capture_io do - Hbc::CLI::Uninstall.run("versioned-cask") - end - - out.must_match(/#{token} #{first_installed_version} is still installed./) - err.must_be :empty? + expect { + expect { + Hbc::CLI::Uninstall.run("versioned-cask") + }.not_to output.to_stderr + }.to output(/#{token} #{first_installed_version} is still installed./).to_stdout end end @@ -121,34 +163,29 @@ describe Hbc::CLI::Uninstall do EOS end - after do - app.rmtree if app.exist? - caskroom_path.rmtree if caskroom_path.exist? - end - it "can still uninstall those Casks" do shutup do Hbc::CLI::Uninstall.run("ive-been-renamed") end - app.wont_be :exist? - caskroom_path.wont_be :exist? + expect(app).not_to exist + expect(caskroom_path).not_to exist end end describe "when no Cask is specified" do it "raises an exception" do - lambda { + expect { Hbc::CLI::Uninstall.run - }.must_raise Hbc::CaskUnspecifiedError + }.to raise_error(Hbc::CaskUnspecifiedError) end end describe "when no Cask is specified, but an invalid option" do it "raises an exception" do - lambda { + expect { Hbc::CLI::Uninstall.run("--notavalidoption") - }.must_raise Hbc::CaskUnspecifiedError + }.to raise_error(Hbc::CaskUnspecifiedError) end end end diff --git a/Library/Homebrew/cask/spec/cask/cli/version_spec.rb b/Library/Homebrew/cask/spec/cask/cli/version_spec.rb new file mode 100644 index 000000000..e6fcf4850 --- /dev/null +++ b/Library/Homebrew/cask/spec/cask/cli/version_spec.rb @@ -0,0 +1,11 @@ +require "spec_helper" + +describe "brew cask --version" do + it "respects the --version argument" do + expect { + expect { + Hbc::CLI::NullCommand.new("--version").run + }.not_to output.to_stderr + }.to output(Hbc.full_version).to_stdout + end +end diff --git a/Library/Homebrew/cask/test/cask/cli/zap_test.rb b/Library/Homebrew/cask/spec/cask/cli/zap_spec.rb index a9e862b11..d26114567 100644 --- a/Library/Homebrew/cask/test/cask/cli/zap_test.rb +++ b/Library/Homebrew/cask/spec/cask/cli/zap_spec.rb @@ -1,33 +1,33 @@ -require "test_helper" +require "spec_helper" describe Hbc::CLI::Zap do it "shows an error when a bad Cask is provided" do - lambda { + expect { Hbc::CLI::Zap.run("notacask") - }.must_raise Hbc::CaskUnavailableError + }.to raise_error(Hbc::CaskUnavailableError) end it "can zap and unlink multiple Casks at once" do - caffeine = Hbc.load("local-caffeine") - transmission = Hbc.load("local-transmission") + caffeine = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb") + transmission = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb") shutup do Hbc::Installer.new(caffeine).install Hbc::Installer.new(transmission).install end - caffeine.must_be :installed? - transmission.must_be :installed? + expect(caffeine).to be_installed + expect(transmission).to be_installed shutup do Hbc::CLI::Zap.run("--notavalidoption", "local-caffeine", "local-transmission") end - caffeine.wont_be :installed? - Hbc.appdir.join("Transmission.app").wont_be :symlink? - transmission.wont_be :installed? - Hbc.appdir.join("Caffeine.app").wont_be :symlink? + expect(caffeine).not_to be_installed + expect(Hbc.appdir.join("Caffeine.app")).not_to be_a_symlink + expect(transmission).not_to be_installed + expect(Hbc.appdir.join("Transmission.app")).not_to be_a_symlink end # TODO: Explicit test that both zap and uninstall directives get dispatched. @@ -59,17 +59,17 @@ describe Hbc::CLI::Zap do describe "when no Cask is specified" do it "raises an exception" do - lambda { + expect { Hbc::CLI::Zap.run - }.must_raise Hbc::CaskUnspecifiedError + }.to raise_error(Hbc::CaskUnspecifiedError) end end describe "when no Cask is specified, but an invalid option" do it "raises an exception" do - lambda { + expect { Hbc::CLI::Zap.run("--notavalidoption") - }.must_raise Hbc::CaskUnspecifiedError + }.to raise_error(Hbc::CaskUnspecifiedError) end end end diff --git a/Library/Homebrew/cask/spec/cask/cli_spec.rb b/Library/Homebrew/cask/spec/cask/cli_spec.rb index 9964275f1..6b2313a41 100644 --- a/Library/Homebrew/cask/spec/cask/cli_spec.rb +++ b/Library/Homebrew/cask/spec/cask/cli_spec.rb @@ -39,17 +39,17 @@ describe Hbc::CLI do end it "respects the env variable when choosing what appdir to create" do - with_environment "HOMEBREW_CASK_OPTS" => "--appdir=/custom/appdir" do - expect(Hbc).to receive(:appdir=).with(Pathname("/custom/appdir")) - described_class.process("noop") - end + allow(ENV).to receive(:[]) + allow(ENV).to receive(:[]).with("HOMEBREW_CASK_OPTS").and_return("--appdir=/custom/appdir") + expect(Hbc).to receive(:appdir=).with(Pathname.new("/custom/appdir")) + described_class.process("noop") end it "respects the env variable when choosing a non-default Caskroom location" do - with_environment "HOMEBREW_CASK_OPTS" => "--caskroom=/custom/caskdir" do - expect(Hbc).to receive(:caskroom=).with(Pathname("/custom/caskdir")) - described_class.process("noop") - end + allow(ENV).to receive(:[]) + allow(ENV).to receive(:[]).with("HOMEBREW_CASK_OPTS").and_return("--caskroom=/custom/caskdir") + expect(Hbc).to receive(:caskroom=).with(Pathname.new("/custom/caskdir")) + described_class.process("noop") end it "exits with a status of 1 when something goes wrong" do diff --git a/Library/Homebrew/cask/test/cask/container/dmg_test.rb b/Library/Homebrew/cask/spec/cask/container/dmg_spec.rb index 2c33b88b6..cf35b7545 100644 --- a/Library/Homebrew/cask/test/cask/container/dmg_test.rb +++ b/Library/Homebrew/cask/spec/cask/container/dmg_spec.rb @@ -1,19 +1,19 @@ -require "test_helper" +require "spec_helper" describe Hbc::Container::Dmg do - describe "mount!" do + describe "#mount!" do it "does not store nil mounts for dmgs with extra data" do - transmission = Hbc.load("local-transmission") + transmission = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb") dmg = Hbc::Container::Dmg.new( transmission, Pathname(transmission.url.path), - Hbc::SystemCommand + Hbc::SystemCommand, ) begin dmg.mount! - dmg.mounts.wont_include nil + expect(dmg.mounts).not_to include nil ensure dmg.eject! end diff --git a/Library/Homebrew/cask/test/cask/container/naked_test.rb b/Library/Homebrew/cask/spec/cask/container/naked_spec.rb index d40c16de5..ee4102eca 100644 --- a/Library/Homebrew/cask/test/cask/container/naked_test.rb +++ b/Library/Homebrew/cask/spec/cask/container/naked_spec.rb @@ -1,4 +1,4 @@ -require "test_helper" +require "spec_helper" describe Hbc::Container::Naked do it "saves files with spaces in them from uris with encoded spaces" do @@ -13,8 +13,13 @@ describe Hbc::Container::Naked do Hbc::FakeSystemCommand.stubs_command(expected_command) container = Hbc::Container::Naked.new(cask, path, Hbc::FakeSystemCommand) - container.extract - Hbc::FakeSystemCommand.system_calls[expected_command].must_equal 1 + expect { + shutup do + container.extract + end + }.not_to raise_error + + expect(Hbc::FakeSystemCommand.system_calls[expected_command]).to eq(1) end end diff --git a/Library/Homebrew/cask/spec/cask/depends_on_spec.rb b/Library/Homebrew/cask/spec/cask/depends_on_spec.rb new file mode 100644 index 000000000..078a2bce7 --- /dev/null +++ b/Library/Homebrew/cask/spec/cask/depends_on_spec.rb @@ -0,0 +1,92 @@ +require "spec_helper" + +# TODO: this test should be named after the corresponding class, once +# that class is abstracted from installer.rb +describe "Satisfy Dependencies and Requirements" do + subject { + lambda do + shutup do + Hbc::Installer.new(cask).install + end + end + } + + describe "depends_on cask" do + context "when depends_on cask is cyclic" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-depends-on-cask-cyclic.rb") } + it { is_expected.to raise_error(Hbc::CaskCyclicCaskDependencyError) } + end + + context do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-depends-on-cask.rb") } + let(:dependency) { Hbc.load(cask.depends_on.cask.first) } + + it "installs the dependency of a Cask and the Cask itself" do + expect(subject).not_to raise_error + expect(cask).to be_installed + expect(dependency).to be_installed + end + end + end + + describe "depends_on macos" do + context "given an array" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-depends-on-macos-array.rb") } + it { is_expected.not_to raise_error } + end + + context "given a comparisson" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-depends-on-macos-comparison.rb") } + it { is_expected.not_to raise_error } + end + + context "given a string" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-depends-on-macos-string.rb") } + it { is_expected.not_to raise_error } + end + + context "given a symbol" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-depends-on-macos-symbol.rb") } + it { is_expected.not_to raise_error } + end + + context "when not satisfied" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-depends-on-macos-failure.rb") } + it { is_expected.to raise_error(Hbc::CaskError) } + end + end + + describe "depends_on arch" do + context "when satisfied" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-depends-on-arch.rb") } + it { is_expected.not_to raise_error } + end + end + + describe "depends_on x11" do + before(:each) do + allow(MacOS::X11).to receive(:installed?).and_return(x11_installed) + end + + context "when satisfied" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-depends-on-x11.rb") } + let(:x11_installed) { true } + + it { is_expected.not_to raise_error } + end + + context "when not satisfied" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-depends-on-x11.rb") } + let(:x11_installed) { false } + + it { is_expected.to raise_error(Hbc::CaskX11DependencyError) } + end + + context "when depends_on x11: false" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-depends-on-x11-false.rb") } + let(:x11_installed) { false } + + it { is_expected.not_to raise_error } + end + end +end diff --git a/Library/Homebrew/cask/spec/cask/download_strategy_spec.rb b/Library/Homebrew/cask/spec/cask/download_strategy_spec.rb index d6c28bbd1..900ceb3e2 100644 --- a/Library/Homebrew/cask/spec/cask/download_strategy_spec.rb +++ b/Library/Homebrew/cask/spec/cask/download_strategy_spec.rb @@ -176,7 +176,7 @@ describe "download strategies" do expect(downloader).to have_received(:fetch_repo).with( downloader.cached_location, - cask.url.to_s + cask.url.to_s, ) end @@ -196,7 +196,7 @@ describe "download strategies" do "config:miscellany:use-commit-times=yes", cask.url.to_s, downloader.cached_location, - ]) + ]), ) end @@ -226,7 +226,7 @@ describe "download strategies" do "--non-interactive", cask.url.to_s, downloader.cached_location, - ]) + ]), ) end end @@ -257,7 +257,7 @@ describe "download strategies" do downloader.cached_location, "-r", "10", - ]) + ]), ) end end @@ -283,7 +283,7 @@ describe "download strategies" do downloader.tarball_path, "--", ".", - ]) + ]), ) end end diff --git a/Library/Homebrew/cask/test/cask/dsl/caveats_test.rb b/Library/Homebrew/cask/spec/cask/dsl/caveats_spec.rb index d0c7eef34..777491d66 100644 --- a/Library/Homebrew/cask/test/cask/dsl/caveats_test.rb +++ b/Library/Homebrew/cask/spec/cask/dsl/caveats_spec.rb @@ -1,7 +1,7 @@ -require "test_helper" +require "spec_helper" describe Hbc::DSL::Caveats do - let(:cask) { Hbc.load("basic-cask") } + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/basic-cask.rb") } let(:dsl) { Hbc::DSL::Caveats.new(cask) } it_behaves_like Hbc::DSL::Base diff --git a/Library/Homebrew/cask/test/cask/dsl/postflight_test.rb b/Library/Homebrew/cask/spec/cask/dsl/postflight_spec.rb index c5e80b6d0..116a7c8a8 100644 --- a/Library/Homebrew/cask/test/cask/dsl/postflight_test.rb +++ b/Library/Homebrew/cask/spec/cask/dsl/postflight_spec.rb @@ -1,7 +1,7 @@ -require "test_helper" +require "spec_helper" describe Hbc::DSL::Postflight do - let(:cask) { Hbc.load("basic-cask") } + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/basic-cask.rb") } let(:dsl) { Hbc::DSL::Postflight.new(cask, Hbc::FakeSystemCommand) } it_behaves_like Hbc::DSL::Base diff --git a/Library/Homebrew/cask/test/cask/dsl/preflight_test.rb b/Library/Homebrew/cask/spec/cask/dsl/preflight_spec.rb index 1c49a62ad..90d2634db 100644 --- a/Library/Homebrew/cask/test/cask/dsl/preflight_test.rb +++ b/Library/Homebrew/cask/spec/cask/dsl/preflight_spec.rb @@ -1,7 +1,7 @@ -require "test_helper" +require "spec_helper" describe Hbc::DSL::Preflight do - let(:cask) { Hbc.load("basic-cask") } + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/basic-cask.rb") } let(:dsl) { Hbc::DSL::Preflight.new(cask, Hbc::FakeSystemCommand) } it_behaves_like Hbc::DSL::Base diff --git a/Library/Homebrew/cask/test/cask/dsl/uninstall_postflight_test.rb b/Library/Homebrew/cask/spec/cask/dsl/uninstall_postflight_spec.rb index c704706ad..4b7dd7557 100644 --- a/Library/Homebrew/cask/test/cask/dsl/uninstall_postflight_test.rb +++ b/Library/Homebrew/cask/spec/cask/dsl/uninstall_postflight_spec.rb @@ -1,7 +1,7 @@ -require "test_helper" +require "spec_helper" describe Hbc::DSL::UninstallPostflight do - let(:cask) { Hbc.load("basic-cask") } + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/basic-cask.rb") } let(:dsl) { Hbc::DSL::UninstallPostflight.new(cask, Hbc::FakeSystemCommand) } it_behaves_like Hbc::DSL::Base diff --git a/Library/Homebrew/cask/test/cask/dsl/uninstall_preflight_test.rb b/Library/Homebrew/cask/spec/cask/dsl/uninstall_preflight_spec.rb index f6ab36b60..a4930e99e 100644 --- a/Library/Homebrew/cask/test/cask/dsl/uninstall_preflight_test.rb +++ b/Library/Homebrew/cask/spec/cask/dsl/uninstall_preflight_spec.rb @@ -1,7 +1,7 @@ -require "test_helper" +require "spec_helper" describe Hbc::DSL::UninstallPreflight do - let(:cask) { Hbc.load("basic-cask") } + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/basic-cask.rb") } let(:dsl) { Hbc::DSL::UninstallPreflight.new(cask, Hbc::FakeSystemCommand) } it_behaves_like Hbc::DSL::Base diff --git a/Library/Homebrew/cask/spec/cask/dsl_spec.rb b/Library/Homebrew/cask/spec/cask/dsl_spec.rb new file mode 100644 index 000000000..99525cc20 --- /dev/null +++ b/Library/Homebrew/cask/spec/cask/dsl_spec.rb @@ -0,0 +1,548 @@ +require "spec_helper" + +describe Hbc::DSL do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/#{token}.rb") } + let(:token) { "basic-cask" } + + context "stanzas" do + it "lets you set url, homepage, and version" do + expect(cask.url.to_s).to eq("http://example.com/TestCask.dmg") + expect(cask.homepage).to eq("http://example.com/") + expect(cask.version.to_s).to eq("1.2.3") + end + end + + describe "when a Cask includes an unknown method" do + let(:attempt_unknown_method) { + lambda do + Hbc::Cask.new("unexpected-method-cask") do + future_feature :not_yet_on_your_machine + end + end + } + + it "prints a warning that it has encountered an unexpected method" do + expected = Regexp.compile(<<-EOS.undent.lines.map(&:chomp).join("")) + (?m) + Warning: + .* + Unexpected method 'future_feature' called on Cask unexpected-method-cask\\. + .* + https://github.com/caskroom/homebrew-cask/blob/master/doc/reporting_bugs/pre_bug_report.md + .* + https://github.com/caskroom/homebrew-cask#reporting-bugs + EOS + + expect { + expect(attempt_unknown_method).not_to output.to_stdout + }.to output(expected).to_stderr + end + + it "will simply warn, not throw an exception" do + expect { + shutup do + attempt_unknown_method.call + end + }.not_to raise_error + end + end + + 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 + end + + context "when token does not match the file name" do + let(:token) { "invalid/invalid-header-token-mismatch" } + + it "raises an error" do + expect { + cask + }.to raise_error(Hbc::CaskTokenDoesNotMatchError, /Bad header line:.*does not match file name/) + end + end + + context "when it contains no DSL version" do + let(:token) { "no-dsl-version" } + + it "does not require a DSL version in the header" do + expect(cask.token).to eq("no-dsl-version") + expect(cask.url.to_s).to eq("http://example.com/TestCask.dmg") + expect(cask.homepage).to eq("http://example.com/") + expect(cask.version.to_s).to eq("1.2.3") + end + end + + context "when it contains a deprecated DSL version" do + let(:token) { "with-dsl-version" } + + it "may use deprecated DSL version hash syntax" do + allow(ENV).to receive(:[]).with("HOMEBREW_DEVELOPER").and_return(nil) + + shutup do + expect(cask.token).to eq("with-dsl-version") + expect(cask.url.to_s).to eq("http://example.com/TestCask.dmg") + expect(cask.homepage).to eq("http://example.com/") + expect(cask.version.to_s).to eq("1.2.3") + end + end + end + end + + describe "name stanza" do + it "lets you set the full name via a name stanza" do + cask = Hbc::Cask.new("name-cask") do + name "Proper Name" + end + + expect(cask.name).to eq([ + "Proper Name", + ]) + end + + it "Accepts an array value to the name stanza" do + cask = Hbc::Cask.new("array-name-cask") do + name ["Proper Name", "Alternate Name"] + end + + expect(cask.name).to eq([ + "Proper Name", + "Alternate Name", + ]) + end + + it "Accepts multiple name stanzas" do + cask = Hbc::Cask.new("multi-name-cask") do + name "Proper Name" + name "Alternate Name" + end + + expect(cask.name).to eq([ + "Proper Name", + "Alternate Name", + ]) + end + end + + describe "sha256 stanza" do + it "lets you set checksum via sha256" do + cask = Hbc::Cask.new("checksum-cask") do + sha256 "imasha2" + end + + expect(cask.sha256).to eq("imasha2") + end + end + + describe "language stanza" do + it "allows multilingual casks" do + cask = lambda do + Hbc::Cask.new("cask-with-apps") do + language "zh" do + sha256 "abc123" + "zh-CN" + end + + language "en-US", default: true do + sha256 "xyz789" + "en-US" + end + + url "https://example.org/#{language}.zip" + end + end + + allow(MacOS).to receive(:languages).and_return(["zh"]) + expect(cask.call.language).to eq("zh-CN") + expect(cask.call.sha256).to eq("abc123") + expect(cask.call.url.to_s).to eq("https://example.org/zh-CN.zip") + + allow(MacOS).to receive(:languages).and_return(["zh-XX"]) + expect(cask.call.language).to eq("zh-CN") + expect(cask.call.sha256).to eq("abc123") + expect(cask.call.url.to_s).to eq("https://example.org/zh-CN.zip") + + allow(MacOS).to receive(:languages).and_return(["en"]) + expect(cask.call.language).to eq("en-US") + expect(cask.call.sha256).to eq("xyz789") + expect(cask.call.url.to_s).to eq("https://example.org/en-US.zip") + + allow(MacOS).to receive(:languages).and_return(["xx-XX"]) + expect(cask.call.language).to eq("en-US") + expect(cask.call.sha256).to eq("xyz789") + expect(cask.call.url.to_s).to eq("https://example.org/en-US.zip") + + allow(MacOS).to receive(:languages).and_return(["xx-XX", "zh", "en"]) + expect(cask.call.language).to eq("zh-CN") + expect(cask.call.sha256).to eq("abc123") + expect(cask.call.url.to_s).to eq("https://example.org/zh-CN.zip") + + allow(MacOS).to receive(:languages).and_return(["xx-XX", "en-US", "zh"]) + expect(cask.call.language).to eq("en-US") + expect(cask.call.sha256).to eq("xyz789") + expect(cask.call.url.to_s).to eq("https://example.org/en-US.zip") + end + end + + describe "app stanza" do + it "allows you to specify app stanzas" do + cask = Hbc::Cask.new("cask-with-apps") do + app "Foo.app" + app "Bar.app" + end + + expect(Array(cask.artifacts[:app])).to eq([["Foo.app"], ["Bar.app"]]) + end + + it "allow app stanzas to be empty" do + cask = Hbc::Cask.new("cask-with-no-apps") + expect(Array(cask.artifacts[:app])).to eq([]) + end + end + + describe "caveats stanza" do + it "allows caveats to be specified via a method define" do + cask = Hbc::Cask.new("plain-cask") + + expect(cask.caveats).to be_empty + + cask = Hbc::Cask.new("cask-with-caveats") do + def caveats; <<-EOS.undent + When you install this Cask, you probably want to know this. + EOS + end + end + + expect(cask.caveats).to eq("When you install this Cask, you probably want to know this.\n") + end + end + + describe "pkg stanza" do + it "allows installable pkgs to be specified" do + cask = Hbc::Cask.new("cask-with-pkgs") do + pkg "Foo.pkg" + pkg "Bar.pkg" + end + + expect(Array(cask.artifacts[:pkg])).to eq([["Foo.pkg"], ["Bar.pkg"]]) + end + end + + describe "url stanza" do + let(:token) { "invalid/invalid-two-url" } + + it "prevents defining multiple urls" do + expect { cask }.to raise_error(Hbc::CaskInvalidError, /'url' stanza may only appear once/) + end + end + + describe "homepage stanza" do + let(:token) { "invalid/invalid-two-homepage" } + + it "prevents defining multiple homepages" do + expect { cask }.to raise_error(Hbc::CaskInvalidError, /'homepage' stanza may only appear once/) + end + end + + 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 + end + + describe "appcast stanza" do + let(:token) { "with-appcast" } + + it "allows appcasts to be specified" do + expect(cask.appcast.to_s).to match(/^http/) + end + + context "when multiple appcasts are defined" do + let(:token) { "invalid/invalid-appcast-multiple" } + + it "raises an error" do + expect { cask }.to raise_error(Hbc::CaskInvalidError, /'appcast' stanza may only appear once/) + end + end + + context "when appcast URL is invalid" do + let(:token) { "invalid/invalid-appcast-url" } + + it "refuses to load" do + expect { cask }.to raise_error(Hbc::CaskInvalidError) + end + end + end + + describe "GPG stanza" do + context "valid" do + let(:token) { "with-gpg" } + + it "is allowed to be specified" do + expect(cask.gpg.to_s).to match(/\S/) + end + end + + 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 + end + + context "specifying mmultiple times" do + let(:token) { "invalid/invalid-gpg-multiple-stanzas" } + + it "is not allowed" do + expect { cask }.to raise_error(Hbc::CaskInvalidError, /'gpg' stanza may only appear once/) + end + end + + context "missing GPG key parameters" do + let(:token) { "invalid/invalid-gpg-missing-key" } + + it "refuses to load" do + expect { cask }.to raise_error(Hbc::CaskInvalidError, /'gpg' stanza must include exactly one/) + end + end + + context "conflicting GPG key parameters" do + let(:token) { "invalid/invalid-gpg-conflicting-keys" } + + it "refuses to load" do + expect { cask }.to raise_error(Hbc::CaskInvalidError, /'gpg' stanza must include exactly one/) + end + end + + context "invalid GPG signature URLs" do + let(:token) { "invalid/invalid-gpg-signature-url" } + + it "refuses to load" do + expect { cask }.to raise_error(Hbc::CaskInvalidError) + end + end + + context "invalid GPG key URLs" do + let(:token) { "invalid/invalid-gpg-key-url" } + + it "refuses to load" do + expect { cask }.to raise_error(Hbc::CaskInvalidError) + end + end + + context "invalid GPG key IDs" do + let(:token) { "invalid/invalid-gpg-key-id" } + + it "refuses to load" do + expect { cask }.to raise_error(Hbc::CaskInvalidError) + end + end + + context "GPG parameter is unknown" do + let(:token) { "invalid/invalid-gpg-parameter" } + + it "refuses to load" do + expect { cask }.to raise_error(Hbc::CaskInvalidError) + end + end + end + + describe "depends_on stanza" do + let(:token) { "invalid/invalid-depends-on-key" } + + it "refuses to load with an invalid depends_on key" do + expect { cask }.to raise_error(Hbc::CaskInvalidError) + end + end + + describe "depends_on formula" do + context "with one Formula" do + let(:token) { "with-depends-on-formula" } + + it "allows depends_on formula to be specified" do + expect(cask.depends_on.formula).not_to be nil + end + end + + context "with multiple Formulae" do + let(:token) { "with-depends-on-formula-multiple" } + + it "allows multiple depends_on formula to be specified" do + expect(cask.depends_on.formula).not_to be nil + end + end + end + + 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 + end + + context "specifying multiple" do + let(:token) { "with-depends-on-cask-multiple" } + + it "is allowed" do + expect(cask.depends_on.cask).not_to be nil + end + end + end + + describe "depends_on macos" do + context "valid" do + let(:token) { "with-depends-on-macos-string" } + + it "allows depends_on macos to be specified" do + expect(cask.depends_on.macos).not_to be nil + end + end + + context "invalid depends_on macos value" do + let(:token) { "invalid/invalid-depends-on-macos-bad-release" } + + it "refuses to load" do + expect { cask }.to raise_error(Hbc::CaskInvalidError) + end + end + + context "conflicting depends_on macos forms" do + let(:token) { "invalid/invalid-depends-on-macos-conflicting-forms" } + + it "refuses to load" do + expect { cask }.to raise_error(Hbc::CaskInvalidError) + end + end + end + + describe "depends_on arch" do + context "valid" do + let(:token) { "with-depends-on-arch" } + + it "is allowed to be specified" do + expect(cask.depends_on.arch).not_to be nil + end + end + + context "invalid depends_on arch value" do + let(:token) { "invalid/invalid-depends-on-arch-value" } + + it "refuses to load" do + expect { cask }.to raise_error(Hbc::CaskInvalidError) + end + end + end + + describe "depends_on x11" do + context "valid" do + let(:token) { "with-depends-on-x11" } + + it "is allowed to be specified" do + expect(cask.depends_on.x11).not_to be nil + end + end + + context "invalid depends_on x11 value" do + let(:token) { "invalid/invalid-depends-on-x11-value" } + + it "refuses to load" do + expect { cask }.to raise_error(Hbc::CaskInvalidError) + end + end + end + + describe "conflicts_with stanza" do + context "valid" do + let(:token) { "with-conflicts-with" } + + it "allows conflicts_with stanza to be specified" do + expect(cask.conflicts_with.formula).not_to be nil + end + end + + context "invalid conflicts_with key" do + let(:token) { "invalid/invalid-conflicts-with-key" } + + it "refuses to load invalid conflicts_with key" do + expect { cask }.to raise_error(Hbc::CaskInvalidError) + end + end + end + + describe "installer stanza" do + context "script" do + let(:token) { "with-installer-script" } + + it "allows installer script to be specified" do + expect(cask.artifacts[:installer].first.script[:executable]).to eq("/usr/bin/true") + expect(cask.artifacts[:installer].first.script[:args]).to eq(["--flag"]) + expect(cask.artifacts[:installer].to_a[1].script[:executable]).to eq("/usr/bin/false") + expect(cask.artifacts[:installer].to_a[1].script[:args]).to eq(["--flag"]) + end + end + + context "manual" do + let(:token) { "with-installer-manual" } + + it "allows installer manual to be specified" do + expect(cask.artifacts[:installer].first.manual).to eq("Caffeine.app") + end + end + end + + describe "stage_only stanza" do + context "when there is no other activatable artifact" do + let(:token) { "stage-only" } + + it "allows stage_only stanza to be specified" do + expect(cask.artifacts[:stage_only].first).to eq([true]) + end + end + + context "when there is are activatable artifacts" do + let(:token) { "invalid/invalid-stage-only-conflict" } + + it "prevents specifying stage_only" do + expect { cask }.to raise_error(Hbc::CaskInvalidError, /'stage_only' must be the only activatable artifact/) + end + end + end + + describe "auto_updates stanza" do + let(:token) { "auto-updates" } + + it "allows auto_updates stanza to be specified" do + expect(cask.auto_updates).to be true + end + end + + describe "appdir" do + context "interpolation of the appdir in stanzas" do + let(:token) { "appdir-interpolation" } + + it "is allowed" do + expect(cask.artifacts[:binary].first).to eq(["#{Hbc.appdir}/some/path"]) + end + end + + it "does not include a trailing slash" do + begin + original_appdir = Hbc.appdir + Hbc.appdir = "#{original_appdir}/" + + cask = Hbc::Cask.new("appdir-trailing-slash") do + binary "#{appdir}/some/path" + end + + expect(cask.artifacts[:binary].first).to eq(["#{original_appdir}/some/path"]) + ensure + Hbc.appdir = original_appdir + end + end + end +end diff --git a/Library/Homebrew/cask/spec/cask/installer_spec.rb b/Library/Homebrew/cask/spec/cask/installer_spec.rb new file mode 100644 index 000000000..c0148c387 --- /dev/null +++ b/Library/Homebrew/cask/spec/cask/installer_spec.rb @@ -0,0 +1,398 @@ +require "spec_helper" + +describe Hbc::Installer do + describe "install" do + let(:empty_depends_on_stub) { + double(formula: [], cask: [], macos: nil, arch: nil, x11: nil) + } + + it "downloads and installs a nice fresh Cask" do + caffeine = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb") + + shutup do + Hbc::Installer.new(caffeine).install + end + + expect(Hbc.caskroom.join("local-caffeine", caffeine.version)).to be_a_directory + expect(Hbc.appdir.join("Caffeine.app")).to be_a_directory + end + + it "works with dmg-based Casks" do + asset = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/container-dmg.rb") + + shutup do + Hbc::Installer.new(asset).install + end + + expect(Hbc.caskroom.join("container-dmg", asset.version)).to be_a_directory + expect(Hbc.appdir.join("container")).to be_a_file + end + + it "works with tar-gz-based Casks" do + asset = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/container-tar-gz.rb") + + shutup do + Hbc::Installer.new(asset).install + end + + expect(Hbc.caskroom.join("container-tar-gz", asset.version)).to be_a_directory + expect(Hbc.appdir.join("container")).to be_a_file + end + + it "works with cab-based Casks" do + skip("cabextract not installed") if which("cabextract").nil? + asset = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/container-cab.rb") + + allow(asset).to receive(:depends_on).and_return(empty_depends_on_stub) + + shutup do + Hbc::Installer.new(asset).install + end + + expect(Hbc.caskroom.join("container-cab", asset.version)).to be_a_directory + expect(Hbc.appdir.join("container")).to be_a_file + end + + it "works with Adobe AIR-based Casks" do + skip("Adobe AIR not installed") unless Hbc::Container::Air.installer_exist? + asset = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/container-air.rb") + + shutup do + Hbc::Installer.new(asset).install + end + + expect(Hbc.caskroom.join("container-air", asset.version)).to be_a_directory + expect(Hbc.appdir.join("container.app")).to be_a_directory + end + + it "works with 7z-based Casks" do + skip("unar not installed") if which("unar").nil? + asset = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/container-7z.rb") + + allow(asset).to receive(:depends_on).and_return(empty_depends_on_stub) + shutup do + Hbc::Installer.new(asset).install + end + + expect(Hbc.caskroom.join("container-7z", asset.version)).to be_a_directory + expect(Hbc.appdir.join("container")).to be_a_file + end + + it "works with xar-based Casks" do + asset = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/container-xar.rb") + + shutup do + Hbc::Installer.new(asset).install + end + + expect(Hbc.caskroom.join("container-xar", asset.version)).to be_a_directory + expect(Hbc.appdir.join("container")).to be_a_file + end + + it "works with Stuffit-based Casks" do + skip("unar not installed") if which("unar").nil? + asset = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/container-sit.rb") + + allow(asset).to receive(:depends_on).and_return(empty_depends_on_stub) + shutup do + Hbc::Installer.new(asset).install + end + + expect(Hbc.caskroom.join("container-sit", asset.version)).to be_a_directory + expect(Hbc.appdir.join("container")).to be_a_file + end + + it "works with RAR-based Casks" do + skip("unar not installed") if which("unar").nil? + asset = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/container-rar.rb") + + allow(asset).to receive(:depends_on).and_return(empty_depends_on_stub) + shutup do + Hbc::Installer.new(asset).install + end + + expect(Hbc.caskroom.join("container-rar", asset.version)).to be_a_directory + expect(Hbc.appdir.join("container")).to be_a_file + end + + it "works with pure bzip2-based Casks" do + asset = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/container-bzip2.rb") + + shutup do + Hbc::Installer.new(asset).install + end + + expect(Hbc.caskroom.join("container-bzip2", asset.version)).to be_a_directory + expect(Hbc.appdir.join("container-bzip2--#{asset.version}")).to be_a_file + end + + it "works with pure gzip-based Casks" do + asset = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/container-gzip.rb") + + shutup do + Hbc::Installer.new(asset).install + end + + expect(Hbc.caskroom.join("container-gzip", asset.version)).to be_a_directory + expect(Hbc.appdir.join("container")).to be_a_file + end + + it "works with pure xz-based Casks" do + skip("unxz not installed") if which("unxz").nil? + asset = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/container-xz.rb") + + allow(asset).to receive(:depends_on).and_return(empty_depends_on_stub) + shutup do + Hbc::Installer.new(asset).install + end + + expect(Hbc.caskroom.join("container-xz", asset.version)).to be_a_directory + expect(Hbc.appdir.join("container-xz--#{asset.version}")).to be_a_file + end + + it "works with lzma-based Casks" do + skip("unlzma not installed") if which("unlzma").nil? + asset = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/container-lzma.rb") + + allow(asset).to receive(:depends_on).and_return(empty_depends_on_stub) + shutup do + Hbc::Installer.new(asset).install + end + + expect(Hbc.caskroom.join("container-lzma", asset.version)).to be_a_directory + expect(Hbc.appdir.join("container-lzma--#{asset.version}")).to be_a_file + end + + it "blows up on a bad checksum" do + bad_checksum = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/bad-checksum.rb") + expect { + shutup do + Hbc::Installer.new(bad_checksum).install + end + }.to raise_error(Hbc::CaskSha256MismatchError) + end + + it "blows up on a missing checksum" do + missing_checksum = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/missing-checksum.rb") + expect { + shutup do + Hbc::Installer.new(missing_checksum).install + end + }.to raise_error(Hbc::CaskSha256MissingError) + end + + it "installs fine if sha256 :no_check is used" do + no_checksum = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/no-checksum.rb") + + shutup do + Hbc::Installer.new(no_checksum).install + end + + expect(no_checksum).to be_installed + end + + it "fails to install if sha256 :no_check is used with --require-sha" do + no_checksum = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/no-checksum.rb") + expect { + Hbc::Installer.new(no_checksum, require_sha: true).install + }.to raise_error(Hbc::CaskNoShasumError) + end + + it "installs fine if sha256 :no_check is used with --require-sha and --force" do + no_checksum = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/no-checksum.rb") + + shutup do + Hbc::Installer.new(no_checksum, require_sha: true, force: true).install + end + + expect(no_checksum).to be_installed + end + + it "prints caveats if they're present" do + with_caveats = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-caveats.rb") + + expect { + Hbc::Installer.new(with_caveats).install + }.to output(/Here are some things you might want to know/).to_stdout + + expect(with_caveats).to be_installed + end + + it "prints installer :manual instructions when present" do + with_installer_manual = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-installer-manual.rb") + + expect { + Hbc::Installer.new(with_installer_manual).install + }.to output(/To complete the installation of Cask with-installer-manual, you must also\nrun the installer at\n\n '#{with_installer_manual.staged_path.join('Caffeine.app')}'/).to_stdout + + expect(with_installer_manual).to be_installed + end + + it "does not extract __MACOSX directories from zips" do + with_macosx_dir = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-macosx-dir.rb") + + shutup do + Hbc::Installer.new(with_macosx_dir).install + end + + expect(with_macosx_dir.staged_path.join("__MACOSX")).not_to be_a_directory + end + + it "installer method raises an exception when already-installed Casks which auto-update are attempted" do + with_auto_updates = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/auto-updates.rb") + + expect(with_auto_updates).not_to be_installed + + installer = Hbc::Installer.new(with_auto_updates) + + shutup do + installer.install + end + + expect { + installer.install + }.to raise_error(Hbc::CaskAlreadyInstalledAutoUpdatesError) + end + + it "allows already-installed Casks which auto-update to be installed if force is provided" do + with_auto_updates = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/auto-updates.rb") + + expect(with_auto_updates).not_to be_installed + + shutup do + Hbc::Installer.new(with_auto_updates).install + end + + expect { + shutup do + Hbc::Installer.new(with_auto_updates, force: true).install + end + }.not_to raise_error + end + + # unlike the CLI, the internal interface throws exception on double-install + it "installer method raises an exception when already-installed Casks are attempted" do + transmission = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb") + + expect(transmission).not_to be_installed + + installer = Hbc::Installer.new(transmission) + + shutup do + installer.install + end + + expect { + installer.install + }.to raise_error(Hbc::CaskAlreadyInstalledError) + end + + it "allows already-installed Casks to be installed if force is provided" do + transmission = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb") + + expect(transmission).not_to be_installed + + shutup do + Hbc::Installer.new(transmission).install + end + + shutup do + Hbc::Installer.new(transmission, force: true).install + end # wont_raise + end + + it "works naked-pkg-based Casks" do + naked_pkg = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/container-pkg.rb") + + shutup do + Hbc::Installer.new(naked_pkg).install + end + + expect(Hbc.caskroom.join("container-pkg", naked_pkg.version, "container.pkg")).to be_a_file + end + + it "works properly with an overridden container :type" do + naked_executable = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/naked-executable.rb") + + shutup do + Hbc::Installer.new(naked_executable).install + end + + expect(Hbc.caskroom.join("naked-executable", naked_executable.version, "naked_executable")).to be_a_file + end + + it "works fine with a nested container" do + nested_app = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/nested-app.rb") + + shutup do + Hbc::Installer.new(nested_app).install + end + + expect(Hbc.appdir.join("MyNestedApp.app")).to be_a_directory + end + + it "generates and finds a timestamped metadata directory for an installed Cask" do + caffeine = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb") + + shutup do + Hbc::Installer.new(caffeine).install + end + + m_path = caffeine.metadata_path(:now, true) + expect(caffeine.metadata_path(:now, false)).to eq(m_path) + expect(caffeine.metadata_path(:latest)).to eq(m_path) + end + + it "generates and finds a metadata subdirectory for an installed Cask" do + caffeine = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb") + + shutup do + Hbc::Installer.new(caffeine).install + end + + subdir_name = "Casks" + m_subdir = caffeine.metadata_subdir(subdir_name, :now, true) + expect(caffeine.metadata_subdir(subdir_name, :now, false)).to eq(m_subdir) + expect(caffeine.metadata_subdir(subdir_name, :latest)).to eq(m_subdir) + end + end + + describe "uninstall" do + it "fully uninstalls a Cask" do + caffeine = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb") + installer = Hbc::Installer.new(caffeine) + + shutup do + installer.install + installer.uninstall + end + + expect(Hbc.caskroom.join("local-caffeine", caffeine.version, "Caffeine.app")).not_to be_a_directory + expect(Hbc.caskroom.join("local-caffeine", caffeine.version)).not_to be_a_directory + expect(Hbc.caskroom.join("local-caffeine")).not_to be_a_directory + end + + it "uninstalls all versions if force is set" do + caffeine = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb") + mutated_version = caffeine.version + ".1" + + shutup do + Hbc::Installer.new(caffeine).install + end + + expect(Hbc.caskroom.join("local-caffeine", caffeine.version)).to be_a_directory + expect(Hbc.caskroom.join("local-caffeine", mutated_version)).not_to be_a_directory + FileUtils.mv(Hbc.caskroom.join("local-caffeine", caffeine.version), Hbc.caskroom.join("local-caffeine", mutated_version)) + expect(Hbc.caskroom.join("local-caffeine", caffeine.version)).not_to be_a_directory + expect(Hbc.caskroom.join("local-caffeine", mutated_version)).to be_a_directory + + shutup do + Hbc::Installer.new(caffeine, force: true).uninstall + end + + expect(Hbc.caskroom.join("local-caffeine", caffeine.version)).not_to be_a_directory + expect(Hbc.caskroom.join("local-caffeine", mutated_version)).not_to be_a_directory + expect(Hbc.caskroom.join("local-caffeine")).not_to be_a_directory + end + end +end diff --git a/Library/Homebrew/cask/spec/cask/macos_spec.rb b/Library/Homebrew/cask/spec/cask/macos_spec.rb index a1ebb0a9e..f931e1104 100644 --- a/Library/Homebrew/cask/spec/cask/macos_spec.rb +++ b/Library/Homebrew/cask/spec/cask/macos_spec.rb @@ -1,67 +1,67 @@ describe MacOS do it "says '/' is undeletable" do expect(MacOS).to be_undeletable( - "/" + "/", ) expect(MacOS).to be_undeletable( - "/." + "/.", ) expect(MacOS).to be_undeletable( - "/usr/local/Library/Taps/../../../.." + "/usr/local/Library/Taps/../../../..", ) end it "says '/Applications' is undeletable" do expect(MacOS).to be_undeletable( - "/Applications" + "/Applications", ) expect(MacOS).to be_undeletable( - "/Applications/" + "/Applications/", ) expect(MacOS).to be_undeletable( - "/Applications/." + "/Applications/.", ) expect(MacOS).to be_undeletable( - "/Applications/Mail.app/.." + "/Applications/Mail.app/..", ) end it "says the home directory is undeletable" do expect(MacOS).to be_undeletable( - Dir.home + Dir.home, ) expect(MacOS).to be_undeletable( - "#{Dir.home}/" + "#{Dir.home}/", ) expect(MacOS).to be_undeletable( - "#{Dir.home}/Documents/.." + "#{Dir.home}/Documents/..", ) end it "says the user library directory is undeletable" do expect(MacOS).to be_undeletable( - "#{Dir.home}/Library" + "#{Dir.home}/Library", ) expect(MacOS).to be_undeletable( - "#{Dir.home}/Library/" + "#{Dir.home}/Library/", ) expect(MacOS).to be_undeletable( - "#{Dir.home}/Library/." + "#{Dir.home}/Library/.", ) expect(MacOS).to be_undeletable( - "#{Dir.home}/Library/Preferences/.." + "#{Dir.home}/Library/Preferences/..", ) end it "says '/Applications/.app' is deletable" do expect(MacOS).not_to be_undeletable( - "/Applications/.app" + "/Applications/.app", ) end it "says '/Applications/SnakeOil Professional.app' is deletable" do expect(MacOS).not_to be_undeletable( - "/Applications/SnakeOil Professional.app" + "/Applications/SnakeOil Professional.app", ) end end diff --git a/Library/Homebrew/cask/spec/cask/pkg_spec.rb b/Library/Homebrew/cask/spec/cask/pkg_spec.rb new file mode 100644 index 000000000..6610b0e48 --- /dev/null +++ b/Library/Homebrew/cask/spec/cask/pkg_spec.rb @@ -0,0 +1,114 @@ +require "spec_helper" + +describe Hbc::Pkg do + describe "uninstall" do + let(:fake_system_command) { Hbc::NeverSudoSystemCommand } + let(:empty_response) { double(stdout: "") } + let(:pkg) { described_class.new("my.fake.pkg", fake_system_command) } + + it "removes files and dirs referenced by the pkg" do + some_files = Array.new(3) { Pathname.new(Tempfile.new("testfile").path) } + allow(pkg).to receive(:pkgutil_bom_files).and_return(some_files) + + some_specials = Array.new(3) { Pathname.new(Tempfile.new("testfile").path) } + allow(pkg).to receive(:pkgutil_bom_specials).and_return(some_specials) + + some_dirs = Array.new(3) { Pathname.new(Dir.mktmpdir) } + allow(pkg).to receive(:pkgutil_bom_dirs).and_return(some_dirs) + + allow(pkg).to receive(:forget) + + pkg.uninstall + + some_files.each do |file| + expect(file).not_to exist + end + + some_dirs.each do |dir| + expect(dir).not_to exist + end + end + + context "pkgutil" do + let(:fake_system_command) { class_double(Hbc::SystemCommand) } + + it "forgets the pkg" do + allow(fake_system_command).to receive(:run!).with( + "/usr/sbin/pkgutil", + args: ["--only-files", "--files", "my.fake.pkg"], + ).and_return(empty_response) + + allow(fake_system_command).to receive(:run!).with( + "/usr/sbin/pkgutil", + args: ["--only-dirs", "--files", "my.fake.pkg"], + ).and_return(empty_response) + + allow(fake_system_command).to receive(:run!).with( + "/usr/sbin/pkgutil", + args: ["--files", "my.fake.pkg"], + ).and_return(empty_response) + + expect(fake_system_command).to receive(:run!).with( + "/usr/sbin/pkgutil", + args: ["--forget", "my.fake.pkg"], + sudo: true, + ) + + pkg.uninstall + end + end + + it "removes broken symlinks" do + fake_dir = Pathname.new(Dir.mktmpdir) + fake_file = fake_dir.join("ima_file").tap { |path| FileUtils.touch(path) } + + intact_symlink = fake_dir.join("intact_symlink").tap { |path| path.make_symlink(fake_file) } + broken_symlink = fake_dir.join("broken_symlink").tap { |path| path.make_symlink("im_nota_file") } + + allow(pkg).to receive(:pkgutil_bom_specials).and_return([]) + allow(pkg).to receive(:pkgutil_bom_files).and_return([]) + allow(pkg).to receive(:pkgutil_bom_dirs).and_return([fake_dir]) + allow(pkg).to receive(:forget) + + pkg.uninstall + + expect(intact_symlink).to exist + expect(broken_symlink).not_to exist + expect(fake_dir).to exist + end + + it "removes files incorrectly reportes as directories" do + fake_dir = Pathname.new(Dir.mktmpdir) + fake_file = fake_dir.join("ima_file_pretending_to_be_a_dir").tap { |path| FileUtils.touch(path) } + + allow(pkg).to receive(:pkgutil_bom_specials).and_return([]) + allow(pkg).to receive(:pkgutil_bom_files).and_return([]) + allow(pkg).to receive(:pkgutil_bom_dirs).and_return([fake_file, fake_dir]) + allow(pkg).to receive(:forget) + + pkg.uninstall + + expect(fake_file).not_to exist + expect(fake_dir).not_to exist + end + + it "snags permissions on ornery dirs, but returns them afterwards" do + fake_dir = Pathname.new(Dir.mktmpdir) + fake_file = fake_dir.join("ima_installed_file").tap { |path| FileUtils.touch(path) } + fake_dir.chmod(0000) + + allow(pkg).to receive(:pkgutil_bom_specials).and_return([]) + allow(pkg).to receive(:pkgutil_bom_files).and_return([fake_file]) + allow(pkg).to receive(:pkgutil_bom_dirs).and_return([fake_dir]) + allow(pkg).to receive(:forget) + + shutup do + pkg.uninstall + end + + expect(fake_dir).to be_a_directory + expect(fake_file).not_to be_a_file + expect((fake_dir.stat.mode % 01000).to_s(8)).to eq("0") + end + end +end diff --git a/Library/Homebrew/cask/spec/cask/scopes_spec.rb b/Library/Homebrew/cask/spec/cask/scopes_spec.rb index 12c1a697f..e6e507da8 100644 --- a/Library/Homebrew/cask/spec/cask/scopes_spec.rb +++ b/Library/Homebrew/cask/spec/cask/scopes_spec.rb @@ -1,39 +1,31 @@ describe Hbc::Scopes do describe "installed" do - let(:fake_caskroom) { Pathname(Dir.mktmpdir) } - - before do - allow(Hbc).to receive(:caskroom) { fake_caskroom } - end - - after do - fake_caskroom.rmtree - end - it "returns a list installed Casks by loading Casks for all the dirs that exist in the caskroom" do allow(Hbc).to receive(:load) { |token| "loaded-#{token}" } - fake_caskroom.join("cask-bar").mkdir - fake_caskroom.join("cask-foo").mkdir + Hbc.caskroom.join("cask-bar").mkpath + Hbc.caskroom.join("cask-foo").mkpath installed_casks = Hbc.installed expect(Hbc).to have_received(:load).with("cask-bar") expect(Hbc).to have_received(:load).with("cask-foo") - expect(installed_casks).to eq(%w[ - loaded-cask-bar - loaded-cask-foo - ]) + expect(installed_casks).to eq( + %w[ + loaded-cask-bar + loaded-cask-foo + ], + ) end it "optimizes performance by resolving to a fully qualified path before calling Hbc.load" do - fake_tapped_cask_dir = Pathname(Dir.mktmpdir).join("Casks") + fake_tapped_cask_dir = Pathname.new(Dir.mktmpdir).join("Casks") absolute_path_to_cask = fake_tapped_cask_dir.join("some-cask.rb") allow(Hbc).to receive(:load) allow(Hbc).to receive(:all_tapped_cask_dirs) { [fake_tapped_cask_dir] } - fake_caskroom.join("some-cask").mkdir + Hbc.caskroom.join("some-cask").mkdir fake_tapped_cask_dir.mkdir FileUtils.touch(absolute_path_to_cask) diff --git a/Library/Homebrew/cask/test/cask/staged_test.rb b/Library/Homebrew/cask/spec/cask/staged_spec.rb index fe3bf2339..10f1cbb47 100644 --- a/Library/Homebrew/cask/test/cask/staged_test.rb +++ b/Library/Homebrew/cask/spec/cask/staged_spec.rb @@ -1,18 +1,18 @@ -require "test_helper" +require "spec_helper" # TODO: this test should be named after the corresponding class, once # that class is abstracted from installer.rb. It makes little sense # to be invoking bundle_identifier off of the installer instance. describe "Operations on staged Casks" do describe "bundle ID" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb") } + let(:installer) { Hbc::Installer.new(cask) } it "fetches the bundle ID from a staged cask" do - transmission_cask = Hbc.load("local-transmission") - tr_installer = Hbc::Installer.new(transmission_cask) - shutup do - tr_installer.install + installer.install end - tr_installer.bundle_identifier.must_equal("org.m0k.transmission") + + expect(installer.bundle_identifier).to eq("org.m0k.transmission") end end end diff --git a/Library/Homebrew/cask/spec/cask/url_checker_spec.rb b/Library/Homebrew/cask/spec/cask/url_checker_spec.rb new file mode 100644 index 000000000..8d2161586 --- /dev/null +++ b/Library/Homebrew/cask/spec/cask/url_checker_spec.rb @@ -0,0 +1,44 @@ +require "spec_helper" + +describe Hbc::UrlChecker do + describe "request processing" do + let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/basic-cask.rb") } + let(:checker) { Hbc::UrlChecker.new(cask) } + + before(:each) do + allow(Hbc::Fetcher).to receive(:head).and_return(response) + checker.run + end + + context "with an empty response" do + let(:response) { "" } + + it "adds an error" do + expect(checker.errors).to include("timeout while requesting #{cask.url}") + end + end + + context "with a valid http response" do + let(:response) { + <<-EOS.undent + HTTP/1.1 200 OK + Content-Type: application/x-apple-diskimage + ETag: "b4208f3e84967be4b078ecaa03fba941" + Content-Length: 23726161 + Last-Modified: Sun, 12 Aug 2012 21:17:21 GMT + EOS + } + + it "properly populates the response code and headers" do + expect(checker.errors).to be_empty + expect(checker.response_status).to eq("HTTP/1.1 200 OK") + expect(checker.headers).to eq( + "Content-Type" => "application/x-apple-diskimage", + "ETag" => '"b4208f3e84967be4b078ecaa03fba941"', + "Content-Length" => "23726161", + "Last-Modified" => "Sun, 12 Aug 2012 21:17:21 GMT", + ) + end + end + end +end diff --git a/Library/Homebrew/cask/spec/cask/verify/checksum_spec.rb b/Library/Homebrew/cask/spec/cask/verify/checksum_spec.rb index a379dafb9..d803c566d 100644 --- a/Library/Homebrew/cask/spec/cask/verify/checksum_spec.rb +++ b/Library/Homebrew/cask/spec/cask/verify/checksum_spec.rb @@ -1,6 +1,4 @@ describe Hbc::Verify::Checksum do - include Sha256Helper - let(:cask) { double("cask") } let(:downloaded_path) { double("downloaded_path") } let(:verification) { described_class.new(cask, downloaded_path) } @@ -35,7 +33,7 @@ describe Hbc::Verify::Checksum do end context "sha256 is a valid shasum" do - let(:sha256) { random_sha256 } + let(:sha256) { "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" } it { is_expected.to be true } end @@ -44,7 +42,7 @@ describe Hbc::Verify::Checksum do describe "#verify" do subject { verification.verify } - let(:computed) { random_sha256 } + let(:computed) { "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" } before do allow(verification).to receive(:computed).and_return(computed) @@ -67,7 +65,7 @@ describe Hbc::Verify::Checksum do end context "sha256 does not match computed" do - let(:sha256) { random_sha256 } + let(:sha256) { "d3adb33fd3adb33fd3adb33fd3adb33fd3adb33fd3adb33fd3adb33fd3adb33f" } it "raises an error" do expect { subject }.to raise_error(Hbc::CaskSha256MismatchError) diff --git a/Library/Homebrew/cask/spec/formatter_spec.rb b/Library/Homebrew/cask/spec/formatter_spec.rb index ad4c441cb..e8bd34416 100644 --- a/Library/Homebrew/cask/spec/formatter_spec.rb +++ b/Library/Homebrew/cask/spec/formatter_spec.rb @@ -21,7 +21,7 @@ describe Formatter do "aa\n" \ "bbb\n" \ "ccc\n" \ - "dd\n" + "dd\n", ) end @@ -32,7 +32,7 @@ describe Formatter do expect(subject).to eq( "aa ccc\n" \ - "bbb dd\n" + "bbb dd\n", ) end @@ -41,7 +41,7 @@ describe Formatter do allow(Tty).to receive(:width).and_return(20) expect(subject).to eq( - "aa bbb ccc dd\n" + "aa bbb ccc dd\n", ) end end diff --git a/Library/Homebrew/cask/spec/plist/parser_spec.rb b/Library/Homebrew/cask/spec/plist/parser_spec.rb new file mode 100644 index 000000000..a71b7ea2e --- /dev/null +++ b/Library/Homebrew/cask/spec/plist/parser_spec.rb @@ -0,0 +1,75 @@ +require "spec_helper" + +describe Plist do + subject { described_class.parse_xml(input) } + + describe "::parse_xml" do + context "given a hdiutil output as input" do + let(:input) { + <<-EOS.undent + <?xml version="1.0" encoding="UTF-8"?> + <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> + <plist version="1.0"> + <dict> + <key>system-entities</key> + <array> + <dict> + <key>content-hint</key> + <string>Apple_partition_map</string> + <key>dev-entry</key> + <string>/dev/disk3s1</string> + <key>potentially-mountable</key> + <false/> + <key>unmapped-content-hint</key> + <string>Apple_partition_map</string> + </dict> + <dict> + <key>content-hint</key> + <string>Apple_partition_scheme</string> + <key>dev-entry</key> + <string>/dev/disk3</string> + <key>potentially-mountable</key> + <false/> + <key>unmapped-content-hint</key> + <string>Apple_partition_scheme</string> + </dict> + <dict> + <key>content-hint</key> + <string>Apple_HFS</string> + <key>dev-entry</key> + <string>/dev/disk3s2</string> + <key>mount-point</key> + <string>/private/tmp/dmg.BhfS2g</string> + <key>potentially-mountable</key> + <true/> + <key>unmapped-content-hint</key> + <string>Apple_HFS</string> + <key>volume-kind</key> + <string>hfs</string> + </dict> + </array> + </dict> + </plist> + EOS + } + + it "successfully parses it" do + expect(subject.keys).to eq(["system-entities"]) + expect(subject["system-entities"].length).to eq(3) + expect(subject["system-entities"].map { |e| e["dev-entry"] }).to eq( + %w[ + /dev/disk3s1 + /dev/disk3 + /dev/disk3s2 + ], + ) + end + end + + context "given an empty input" do + let(:input) { "" } + + it { is_expected.to be_nil } + end + end +end diff --git a/Library/Homebrew/cask/spec/spec_helper.rb b/Library/Homebrew/cask/spec/spec_helper.rb index 458fe00f4..ea6a87f41 100644 --- a/Library/Homebrew/cask/spec/spec_helper.rb +++ b/Library/Homebrew/cask/spec/spec_helper.rb @@ -15,17 +15,12 @@ require "global" # add Homebrew-Cask to load path $LOAD_PATH.push(HOMEBREW_LIBRARY_PATH.join("cask", "lib").to_s) -require "test/support/helper/env" require "test/support/helper/shutup" -Pathname.glob(HOMEBREW_LIBRARY_PATH.join("cask", "spec", "support", "*.rb")).each(&method(:require)) +Pathname.glob(HOMEBREW_LIBRARY_PATH.join("cask", "spec", "support", "**", "*.rb")).each(&method(:require)) require "hbc" -module Hbc - class TestCask < Cask; end -end - # create and override default directories Hbc.appdir = Pathname.new(TEST_TMPDIR).join("Applications").tap(&:mkpath) Hbc.cache.mkpath @@ -33,11 +28,42 @@ Hbc.caskroom = Hbc.default_caskroom.tap(&:mkpath) Hbc.default_tap = Tap.fetch("caskroom", "spec").tap do |tap| # link test casks FileUtils.mkdir_p tap.path.dirname - FileUtils.ln_s Pathname.new(__FILE__).dirname.join("support"), tap.path + FileUtils.ln_s TEST_FIXTURE_DIR.join("cask"), tap.path end +# pretend that the caskroom/cask Tap is installed +FileUtils.ln_s Pathname.new(ENV["HOMEBREW_LIBRARY"]).join("Taps", "caskroom", "homebrew-cask"), Tap.fetch("caskroom", "cask").path + +HOMEBREW_CASK_DIRS = [ + :appdir, + :caskroom, + :prefpanedir, + :qlplugindir, + :servicedir, + :binarydir, +].freeze + RSpec.configure do |config| config.order = :random - config.include(Test::Helper::Env) config.include(Test::Helper::Shutup) + config.around(:each) do |example| + begin + @__dirs = HOMEBREW_CASK_DIRS.map { |dir| + Pathname.new(TEST_TMPDIR).join(dir.to_s).tap { |path| + path.mkpath + Hbc.public_send("#{dir}=", path) + } + } + + @__argv = ARGV.dup + @__env = ENV.to_hash # dup doesn't work on ENV + + example.run + ensure + ARGV.replace(@__argv) + ENV.replace(@__env) + + FileUtils.rm_rf @__dirs.map(&:children) + end + end end diff --git a/Library/Homebrew/cask/spec/support/Casks/generic-artifact-no-target.rb b/Library/Homebrew/cask/spec/support/Casks/generic-artifact-no-target.rb deleted file mode 100644 index f7657dbb5..000000000 --- a/Library/Homebrew/cask/spec/support/Casks/generic-artifact-no-target.rb +++ /dev/null @@ -1,3 +0,0 @@ -test_cask 'generic-artifact-no-target' do - artifact 'Caffeine.app' -end diff --git a/Library/Homebrew/cask/test/support/fake_system_command.rb b/Library/Homebrew/cask/spec/support/fake_system_command.rb index 97efd0761..b9390d482 100644 --- a/Library/Homebrew/cask/test/support/fake_system_command.rb +++ b/Library/Homebrew/cask/spec/support/fake_system_command.rb @@ -1,3 +1,7 @@ +def sudo(*args) + %w[/usr/bin/sudo -E --] + args.flatten +end + module Hbc class FakeSystemCommand def self.responses @@ -42,6 +46,7 @@ module Hbc def self.run(command_string, options = {}) command = Hbc::SystemCommand.new(command_string, options).command + puts command unless responses.key?(command) raise("no response faked for #{command.inspect}, faked responses are: #{responses.inspect}") end @@ -61,17 +66,12 @@ module Hbc end end -module FakeSystemCommandHooks - def after_teardown - super - Hbc::FakeSystemCommand.verify_expectations! - ensure - Hbc::FakeSystemCommand.clear - end -end - -module MiniTest - class Spec - include FakeSystemCommandHooks +RSpec.configure do |config| + config.after(:each) do + begin + Hbc::FakeSystemCommand.verify_expectations! + ensure + Hbc::FakeSystemCommand.clear + end end end diff --git a/Library/Homebrew/cask/spec/support/file_helper.rb b/Library/Homebrew/cask/spec/support/file_helper.rb deleted file mode 100644 index abe7b2618..000000000 --- a/Library/Homebrew/cask/spec/support/file_helper.rb +++ /dev/null @@ -1,8 +0,0 @@ -module FileHelper - module_function - - def valid_alias?(candidate) - return false unless candidate.symlink? - candidate.readlink.exist? - end -end diff --git a/Library/Homebrew/cask/spec/support/install_helper.rb b/Library/Homebrew/cask/spec/support/install_helper.rb index c8023c66b..d91b9ea57 100644 --- a/Library/Homebrew/cask/spec/support/install_helper.rb +++ b/Library/Homebrew/cask/spec/support/install_helper.rb @@ -1,10 +1,42 @@ module InstallHelper - class << self - def install_without_artifacts(cask) - Hbc::Installer.new(cask).tap do |i| + module_function + + require "test/support/helper/shutup" + extend Test::Helper::Shutup + + def self.install_without_artifacts(cask) + Hbc::Installer.new(cask).tap do |i| + shutup do i.download i.extract_primary_container end end end + + def self.install_without_artifacts_with_caskfile(cask) + Hbc::Installer.new(cask).tap do |i| + shutup do + i.download + i.extract_primary_container + i.save_caskfile + end + end + end + + def install_without_artifacts(cask) + Hbc::Installer.new(cask).tap do |i| + shutup do + i.download + i.extract_primary_container + end + end + end + + def install_with_caskfile(cask) + Hbc::Installer.new(cask).tap do |i| + shutup do + i.save_caskfile + end + end + end end diff --git a/Library/Homebrew/cask/spec/support/kernel_at_exit_hacks.rb b/Library/Homebrew/cask/spec/support/kernel_at_exit_hacks.rb deleted file mode 100644 index b5c84869b..000000000 --- a/Library/Homebrew/cask/spec/support/kernel_at_exit_hacks.rb +++ /dev/null @@ -1,13 +0,0 @@ -module Kernel - alias real_at_exit at_exit - - def at_exit(&block) - real_at_exit(&block) unless ENV["DISABLE_AT_EXIT"] - end - - def with_disabled_at_exit - ENV["DISABLE_AT_EXIT"] = "1" - yield - ENV.delete("DISABLE_AT_EXIT") - end -end diff --git a/Library/Homebrew/cask/test/support/never_sudo_system_command.rb b/Library/Homebrew/cask/spec/support/never_sudo_system_command.rb index 8a370df44..eb8b677f2 100644 --- a/Library/Homebrew/cask/test/support/never_sudo_system_command.rb +++ b/Library/Homebrew/cask/spec/support/never_sudo_system_command.rb @@ -1,3 +1,5 @@ +require "hbc/system_command" + module Hbc class NeverSudoSystemCommand < SystemCommand def self.run(command, options = {}) diff --git a/Library/Homebrew/cask/spec/support/sha256_helper.rb b/Library/Homebrew/cask/spec/support/sha256_helper.rb deleted file mode 100644 index 14f2a2519..000000000 --- a/Library/Homebrew/cask/spec/support/sha256_helper.rb +++ /dev/null @@ -1,8 +0,0 @@ -require"digest" - -module Sha256Helper - def random_sha256 - seed = "--#{rand(10_000)}--#{Time.now}--" - Digest::SHA2.hexdigest(seed) - end -end diff --git a/Library/Homebrew/cask/spec/support/shared_examples/dsl_base.rb b/Library/Homebrew/cask/spec/support/shared_examples/dsl_base.rb new file mode 100644 index 000000000..400ff40f6 --- /dev/null +++ b/Library/Homebrew/cask/spec/support/shared_examples/dsl_base.rb @@ -0,0 +1,23 @@ +require "hbc/dsl/base" + +shared_examples Hbc::DSL::Base do + it "supports the token method" do + expect(dsl.token).to eq(cask.token) + end + + it "supports the version method" do + expect(dsl.version).to eq(cask.version) + end + + it "supports the caskroom_path method" do + expect(dsl.caskroom_path).to eq(cask.caskroom_path) + end + + it "supports the staged_path method" do + expect(dsl.staged_path).to eq(cask.staged_path) + end + + it "supports the appdir method" do + expect(dsl.appdir).to eq(cask.appdir) + end +end diff --git a/Library/Homebrew/cask/spec/support/shared_examples/staged.rb b/Library/Homebrew/cask/spec/support/shared_examples/staged.rb new file mode 100644 index 000000000..d815ef7a0 --- /dev/null +++ b/Library/Homebrew/cask/spec/support/shared_examples/staged.rb @@ -0,0 +1,143 @@ +require "spec_helper" + +require "hbc/staged" + +shared_examples Hbc::Staged do + let(:fake_pathname_exists) { + fake_pathname = Pathname.new("/path/to/file/that/exists") + allow(fake_pathname).to receive(:exist?).and_return(true) + allow(fake_pathname).to receive(:expand_path).and_return(fake_pathname) + fake_pathname + } + + let(:fake_pathname_does_not_exist) { + fake_pathname = Pathname.new("/path/to/file/that/does/not/exist") + allow(fake_pathname).to receive(:exist?).and_return(false) + allow(fake_pathname).to receive(:expand_path).and_return(fake_pathname) + fake_pathname + } + + it "can run system commands with list-form arguments" do + Hbc::FakeSystemCommand.expects_command( + ["echo", "homebrew-cask", "rocks!"], + ) + + shutup do + staged.system_command("echo", args: ["homebrew-cask", "rocks!"]) + end + end + + it "can get the Info.plist file for the primary app" do + expect(staged.info_plist_file.to_s).to include Hbc.appdir.join("TestCask.app/Contents/Info.plist") + end + + it "can execute commands on the Info.plist file" do + allow(staged).to receive(:bundle_identifier).and_return("com.example.BasicCask") + + Hbc::FakeSystemCommand.expects_command( + ["/usr/libexec/PlistBuddy", "-c", "Print CFBundleIdentifier", staged.info_plist_file], + ) + + shutup do + staged.plist_exec("Print CFBundleIdentifier") + end + end + + it "can set a key in the Info.plist file" do + allow(staged).to receive(:bundle_identifier).and_return("com.example.BasicCask") + + Hbc::FakeSystemCommand.expects_command( + ["/usr/libexec/PlistBuddy", "-c", "Set :JVMOptions:JVMVersion 1.6+", staged.info_plist_file], + ) + + shutup do + staged.plist_set(":JVMOptions:JVMVersion", "1.6+") + end + end + + it "can set the permissions of a file" do + fake_pathname = fake_pathname_exists + allow(staged).to receive(:Pathname).and_return(fake_pathname) + + Hbc::FakeSystemCommand.expects_command( + ["/bin/chmod", "-R", "--", "777", fake_pathname], + ) + + shutup do + staged.set_permissions(fake_pathname.to_s, "777") + end + end + + it "can set the permissions of multiple files" do + fake_pathname = fake_pathname_exists + allow(staged).to receive(:Pathname).and_return(fake_pathname) + + Hbc::FakeSystemCommand.expects_command( + ["/bin/chmod", "-R", "--", "777", fake_pathname, fake_pathname], + ) + + shutup do + staged.set_permissions([fake_pathname.to_s, fake_pathname.to_s], "777") + end + end + + it "cannot set the permissions of a file that does not exist" do + fake_pathname = fake_pathname_does_not_exist + allow(staged).to receive(:Pathname).and_return(fake_pathname) + staged.set_permissions(fake_pathname.to_s, "777") + end + + it "can set the ownership of a file" do + fake_pathname = fake_pathname_exists + + allow(staged).to receive(:current_user).and_return("fake_user") + allow(staged).to receive(:Pathname).and_return(fake_pathname) + + Hbc::FakeSystemCommand.expects_command( + ["/usr/bin/sudo", "-E", "--", "/usr/sbin/chown", "-R", "--", "fake_user:staff", fake_pathname], + ) + + shutup do + staged.set_ownership(fake_pathname.to_s) + end + end + + it "can set the ownership of multiple files" do + fake_pathname = fake_pathname_exists + + allow(staged).to receive(:current_user).and_return("fake_user") + allow(staged).to receive(:Pathname).and_return(fake_pathname) + + Hbc::FakeSystemCommand.expects_command( + ["/usr/bin/sudo", "-E", "--", "/usr/sbin/chown", "-R", "--", "fake_user:staff", fake_pathname, fake_pathname], + ) + + shutup do + staged.set_ownership([fake_pathname.to_s, fake_pathname.to_s]) + end + end + + it "can set the ownership of a file with a different user and group" do + fake_pathname = fake_pathname_exists + + allow(staged).to receive(:Pathname).and_return(fake_pathname) + + Hbc::FakeSystemCommand.expects_command( + ["/usr/bin/sudo", "-E", "--", "/usr/sbin/chown", "-R", "--", "other_user:other_group", fake_pathname], + ) + + shutup do + staged.set_ownership(fake_pathname.to_s, user: "other_user", group: "other_group") + end + end + + it "cannot set the ownership of a file that does not exist" do + allow(staged).to receive(:current_user).and_return("fake_user") + fake_pathname = fake_pathname_does_not_exist + allow(staged).to receive(:Pathname).and_return(fake_pathname) + + shutup do + staged.set_ownership(fake_pathname.to_s) + end + end +end diff --git a/Library/Homebrew/cask/spec/upload_coverage.rb b/Library/Homebrew/cask/spec/upload_coverage.rb new file mode 100755 index 000000000..06d38157d --- /dev/null +++ b/Library/Homebrew/cask/spec/upload_coverage.rb @@ -0,0 +1,6 @@ +#!/usr/bin/env ruby +require "simplecov" +require "codecov" + +formatter = SimpleCov::Formatter::Codecov.new +formatter.format SimpleCov::ResultMerger.merged_result diff --git a/Library/Homebrew/cask/test/README.md b/Library/Homebrew/cask/test/README.md deleted file mode 100644 index 4b73af8c4..000000000 --- a/Library/Homebrew/cask/test/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Naming - -Only files matching `*_test.rb` will be executed as tests. diff --git a/Library/Homebrew/cask/test/cask/accessibility_test.rb b/Library/Homebrew/cask/test/cask/accessibility_test.rb deleted file mode 100644 index 7c6484dd4..000000000 --- a/Library/Homebrew/cask/test/cask/accessibility_test.rb +++ /dev/null @@ -1,77 +0,0 @@ -require "test_helper" - -# TODO: this test should be named after the corresponding class, once -# that class is abstracted from installer.rb. -describe "Accessibility Access" do - let(:cask) { Hbc.load("with-accessibility-access") } - let(:with_fake_command) { { command: Hbc::FakeSystemCommand } } - let(:installer) { Hbc::Installer.new(cask, with_fake_command) } - - describe "install" do - it "can enable accessibility access" do - MacOS.stub :version, MacOS::Version.new("10.9") do - installer.stub :bundle_identifier, "com.example.BasicCask" do - Hbc::FakeSystemCommand.expects_command( - ["/usr/bin/sudo", "-E", "--", "/usr/bin/sqlite3", Hbc.tcc_db, "INSERT OR REPLACE INTO access VALUES('kTCCServiceAccessibility','com.example.BasicCask',0,1,1,NULL);"] - ) - shutup do - installer.enable_accessibility_access - end - end - end - end - - it "can enable accessibility access in macOS releases prior to Mavericks" do - MacOS.stub :version, MacOS::Version.new("10.8") do - Hbc::FakeSystemCommand.expects_command( - ["/usr/bin/sudo", "-E", "--", "/usr/bin/touch", Hbc.pre_mavericks_accessibility_dotfile] - ) - shutup do - installer.enable_accessibility_access - end - end - end - - it "warns about enabling accessibility access on new macOS releases" do - MacOS.stub :version, MacOS::Version.new("10.12") do - installer.stub :bundle_identifier, "com.example.BasicCask" do - capture_io { installer.enable_accessibility_access }[1] - .must_match("Warning: Accessibility access cannot be enabled automatically on this version of macOS.") - end - end - end - end - - describe "uninstall" do - it "can disable accessibility access" do - MacOS.stub :version, MacOS::Version.new("10.9") do - installer.stub :bundle_identifier, "com.example.BasicCask" do - Hbc::FakeSystemCommand.expects_command( - ["/usr/bin/sudo", "-E", "--", "/usr/bin/sqlite3", Hbc.tcc_db, "DELETE FROM access WHERE client='com.example.BasicCask';"] - ) - shutup do - installer.disable_accessibility_access - end - end - end - end - - it "warns about disabling accessibility access on old macOS releases" do - MacOS.stub :version, MacOS::Version.new("10.8") do - installer.stub :bundle_identifier, "com.example.BasicCask" do - capture_io { installer.disable_accessibility_access }[1] - .must_match("Warning: Accessibility access cannot be disabled automatically on this version of macOS.") - end - end - end - - it "warns about disabling accessibility access on new macOS releases" do - MacOS.stub :version, MacOS::Version.new("10.12") do - installer.stub :bundle_identifier, "com.example.BasicCask" do - capture_io { installer.disable_accessibility_access }[1] - .must_match("Warning: Accessibility access cannot be disabled automatically on this version of macOS.") - end - end - end - end -end diff --git a/Library/Homebrew/cask/test/cask/artifact/generic_artifact_test.rb b/Library/Homebrew/cask/test/cask/artifact/generic_artifact_test.rb deleted file mode 100644 index 42740cd44..000000000 --- a/Library/Homebrew/cask/test/cask/artifact/generic_artifact_test.rb +++ /dev/null @@ -1,47 +0,0 @@ -require "test_helper" - -describe Hbc::Artifact::Artifact do - let(:cask) { Hbc.load("with-generic-artifact") } - - let(:install_phase) { - -> { Hbc::Artifact::Artifact.new(cask).install_phase } - } - - let(:source_path) { cask.staged_path.join("Caffeine.app") } - let(:target_path) { Hbc.appdir.join("Caffeine.app") } - - before do - TestHelper.install_without_artifacts(cask) - end - - describe "with no target" do - let(:cask) { Hbc.load("with-generic-artifact-no-target") } - - it "fails to install with no target" do - install_phase.must_raise Hbc::CaskInvalidError - end - end - - it "moves the artifact to the proper directory" do - shutup do - install_phase.call - end - - target_path.must_be :directory? - source_path.wont_be :exist? - end - - it "avoids clobbering an existing artifact" do - target_path.mkpath - - assert_raises Hbc::CaskError do - shutup do - install_phase.call - end - end - - source_path.must_be :directory? - target_path.must_be :directory? - File.identical?(source_path, target_path).must_equal false - end -end diff --git a/Library/Homebrew/cask/test/cask/artifact/nested_container_test.rb b/Library/Homebrew/cask/test/cask/artifact/nested_container_test.rb deleted file mode 100644 index b771ba345..000000000 --- a/Library/Homebrew/cask/test/cask/artifact/nested_container_test.rb +++ /dev/null @@ -1,17 +0,0 @@ -require "test_helper" - -describe Hbc::Artifact::NestedContainer do - describe "install" do - it "extracts the specified paths as containers" do - cask = Hbc.load("nested-app").tap do |c| - TestHelper.install_without_artifacts(c) - end - - shutup do - Hbc::Artifact::NestedContainer.new(cask).install_phase - end - - cask.staged_path.join("MyNestedApp.app").must_be :directory? - end - end -end diff --git a/Library/Homebrew/cask/test/cask/artifact/pkg_test.rb b/Library/Homebrew/cask/test/cask/artifact/pkg_test.rb deleted file mode 100644 index 3ed427763..000000000 --- a/Library/Homebrew/cask/test/cask/artifact/pkg_test.rb +++ /dev/null @@ -1,74 +0,0 @@ -require "test_helper" - -describe Hbc::Artifact::Pkg do - before do - @cask = Hbc.load("with-installable") - shutup do - TestHelper.install_without_artifacts(@cask) - end - end - - describe "install_phase" do - it "runs the system installer on the specified pkgs" do - pkg = Hbc::Artifact::Pkg.new(@cask, - command: Hbc::FakeSystemCommand) - - Hbc::FakeSystemCommand.expects_command(["/usr/bin/sudo", "-E", "--", "/usr/sbin/installer", "-pkg", @cask.staged_path.join("MyFancyPkg", "Fancy.pkg"), "-target", "/"]) - - shutup do - pkg.install_phase - end - end - end - - describe "uninstall_phase" do - it "does nothing, because the uninstall_phase method is a no-op" do - pkg = Hbc::Artifact::Pkg.new(@cask, - command: Hbc::FakeSystemCommand) - shutup do - pkg.uninstall_phase - end - end - end - - describe "choices" do - before do - @cask = Hbc.load("with-choices") - shutup do - TestHelper.install_without_artifacts(@cask) - end - end - - it "passes the choice changes xml to the system installer" do - pkg = Hbc::Artifact::Pkg.new(@cask, command: Hbc::FakeSystemCommand) - - file = mock - file.expects(:write).with <<-EOS.undent - <?xml version="1.0" encoding="UTF-8"?> - <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> - <plist version="1.0"> - <array> - \t<dict> - \t\t<key>attributeSetting</key> - \t\t<integer>1</integer> - \t\t<key>choiceAttribute</key> - \t\t<string>selected</string> - \t\t<key>choiceIdentifier</key> - \t\t<string>choice1</string> - \t</dict> - </array> - </plist> - EOS - file.stubs path: Pathname.new("/tmp/choices.xml") - file.expects(:close) - file.expects(:unlink) - Tempfile.expects(:open).yields file - - Hbc::FakeSystemCommand.expects_command(["/usr/bin/sudo", "-E", "--", "/usr/sbin/installer", "-pkg", @cask.staged_path.join("MyFancyPkg", "Fancy.pkg"), "-target", "/", "-applyChoiceChangesXML", @cask.staged_path.join("/tmp/choices.xml")]) - - shutup do - pkg.install_phase - end - end - end -end diff --git a/Library/Homebrew/cask/test/cask/artifact/suite_test.rb b/Library/Homebrew/cask/test/cask/artifact/suite_test.rb deleted file mode 100644 index b2949950e..000000000 --- a/Library/Homebrew/cask/test/cask/artifact/suite_test.rb +++ /dev/null @@ -1,46 +0,0 @@ -require "test_helper" - -describe Hbc::Artifact::Suite do - let(:cask) { Hbc.load("with-suite") } - - let(:install_phase) { -> { Hbc::Artifact::Suite.new(cask).install_phase } } - - let(:target_path) { Hbc.appdir.join("Caffeine") } - let(:source_path) { cask.staged_path.join("Caffeine") } - - before do - TestHelper.install_without_artifacts(cask) - end - - it "moves the suite to the proper directory" do - shutup do - install_phase.call - end - - target_path.must_be :directory? - TestHelper.valid_alias?(target_path).must_equal false - source_path.wont_be :exist? - end - - it "creates a suite containing the expected app" do - shutup do - install_phase.call - end - - target_path.join("Caffeine.app").must_be :exist? - end - - it "avoids clobbering an existing suite by moving over it" do - target_path.mkpath - - assert_raises Hbc::CaskError do - shutup do - install_phase.call - end - end - - source_path.must_be :directory? - target_path.must_be :directory? - File.identical?(source_path, target_path).must_equal false - end -end diff --git a/Library/Homebrew/cask/test/cask/artifact/two_apps_correct_test.rb b/Library/Homebrew/cask/test/cask/artifact/two_apps_correct_test.rb deleted file mode 100644 index c699d247f..000000000 --- a/Library/Homebrew/cask/test/cask/artifact/two_apps_correct_test.rb +++ /dev/null @@ -1,97 +0,0 @@ -require "test_helper" - -describe Hbc::Artifact::App do - describe "multiple apps" do - let(:cask) { Hbc.load("with-two-apps-correct") } - - let(:install_phase) { - -> { Hbc::Artifact::App.new(cask).install_phase } - } - - let(:source_path_mini) { cask.staged_path.join("Caffeine Mini.app") } - let(:target_path_mini) { Hbc.appdir.join("Caffeine Mini.app") } - - let(:source_path_pro) { cask.staged_path.join("Caffeine Pro.app") } - let(:target_path_pro) { Hbc.appdir.join("Caffeine Pro.app") } - - before do - TestHelper.install_without_artifacts(cask) - end - - it "installs both apps using the proper target directory" do - shutup do - install_phase.call - end - - target_path_mini.must_be :directory? - source_path_mini.wont_be :exist? - - target_path_pro.must_be :directory? - source_path_pro.wont_be :exist? - end - - describe "when apps are in a subdirectory" do - let(:cask) { Hbc.load("with-two-apps-subdir") } - - it "installs both apps using the proper target directory" do - shutup do - install_phase.call - end - - target_path_mini.must_be :directory? - source_path_mini.wont_be :exist? - - target_path_pro.must_be :directory? - source_path_pro.wont_be :exist? - end - end - - it "only uses apps when they are specified" do - FileUtils.cp_r source_path_mini, source_path_mini.sub("Caffeine Mini.app", "Caffeine Deluxe.app") - - shutup do - install_phase.call - end - - target_path_mini.must_be :directory? - source_path_mini.wont_be :exist? - - Hbc.appdir.join("Caffeine Deluxe.app").wont_be :exist? - cask.staged_path.join("Caffeine Deluxe.app").must_be :exist? - end - - describe "avoids clobbering an existing app" do - it "when the first app of two already exists" do - target_path_mini.mkpath - - err = assert_raises Hbc::CaskError do - install_phase.must_output <<-EOS.undent - ==> Moving App 'Caffeine Pro.app' to '#{target_path_pro}' - EOS - end - - err.message.must_equal("It seems there is already an App at '#{target_path_mini}'.") - - source_path_mini.must_be :directory? - target_path_mini.must_be :directory? - File.identical?(source_path_mini, target_path_mini).must_equal false - end - - it "when the second app of two already exists" do - target_path_pro.mkpath - - err = assert_raises Hbc::CaskError do - install_phase.must_output <<-EOS.undent - ==> Moving App 'Caffeine Mini.app' to '#{target_path_mini}' - EOS - end - - err.message.must_equal("It seems there is already an App at '#{target_path_pro}'.") - - source_path_pro.must_be :directory? - target_path_pro.must_be :directory? - File.identical?(source_path_pro, target_path_pro).must_equal false - end - end - end -end diff --git a/Library/Homebrew/cask/test/cask/artifact/two_apps_incorrect_test.rb b/Library/Homebrew/cask/test/cask/artifact/two_apps_incorrect_test.rb deleted file mode 100644 index a89a94fba..000000000 --- a/Library/Homebrew/cask/test/cask/artifact/two_apps_incorrect_test.rb +++ /dev/null @@ -1,14 +0,0 @@ -require "test_helper" - -describe Hbc::Artifact::App do - it "must raise" do - exception_raised = begin - Hbc.load("two-apps-incorrect") - false - rescue - true - end - # TODO: later give the user a nice exception for this case and check for it here - assert exception_raised - end -end diff --git a/Library/Homebrew/cask/test/cask/cli/audit_test.rb b/Library/Homebrew/cask/test/cask/cli/audit_test.rb deleted file mode 100644 index 89a7d140a..000000000 --- a/Library/Homebrew/cask/test/cask/cli/audit_test.rb +++ /dev/null @@ -1,64 +0,0 @@ -require "test_helper" - -describe Hbc::CLI::Audit do - let(:auditor) { mock } - let(:cask) { mock } - - describe "selection of Casks to audit" do - it "audits all Casks if no tokens are given" do - Hbc.stub :all, [cask, cask] do - auditor.expects(:audit).times(2) - - run_audit([], auditor) - end - end - - it "audits specified Casks if tokens are given" do - cask_token = "nice-app" - Hbc.expects(:load).with(cask_token).returns(cask) - auditor.expects(:audit).with(cask, audit_download: false, check_token_conflicts: false) - - run_audit([cask_token], auditor) - end - end - - describe "rules for downloading a Cask" do - it "does not download the Cask per default" do - Hbc.stub :load, cask do - auditor.expects(:audit).with(cask, audit_download: false, check_token_conflicts: false) - - run_audit(["casktoken"], auditor) - end - end - - it "download a Cask if --download flag is set" do - Hbc.stub :load, cask do - auditor.expects(:audit).with(cask, audit_download: true, check_token_conflicts: false) - - run_audit(["casktoken", "--download"], auditor) - end - end - end - - describe "rules for checking token conflicts" do - it "does not check for token conflicts per default" do - Hbc.stub :load, cask do - auditor.expects(:audit).with(cask, audit_download: false, check_token_conflicts: false) - - run_audit(["casktoken"], auditor) - end - end - - it "checks for token conflicts if --token-conflicts flag is set" do - Hbc.stub :load, cask do - auditor.expects(:audit).with(cask, audit_download: false, check_token_conflicts: true) - - run_audit(["casktoken", "--token-conflicts"], auditor) - end - end - end - - def run_audit(args, auditor) - Hbc::CLI::Audit.new(args, auditor).run - end -end diff --git a/Library/Homebrew/cask/test/cask/cli/reinstall_test.rb b/Library/Homebrew/cask/test/cask/cli/reinstall_test.rb deleted file mode 100644 index 02cdeb763..000000000 --- a/Library/Homebrew/cask/test/cask/cli/reinstall_test.rb +++ /dev/null @@ -1,24 +0,0 @@ -require "test_helper" - -describe Hbc::CLI::Reinstall do - it "allows reinstalling a Cask" do - shutup do - Hbc::CLI::Install.run("local-transmission") - end - Hbc.load("local-transmission").must_be :installed? - - shutup do - Hbc::CLI::Reinstall.run("local-transmission") - end - Hbc.load("local-transmission").must_be :installed? - end - - it "allows reinstalling a non installed Cask" do - Hbc.load("local-transmission").wont_be :installed? - - shutup do - Hbc::CLI::Reinstall.run("local-transmission") - end - Hbc.load("local-transmission").must_be :installed? - end -end diff --git a/Library/Homebrew/cask/test/cask/cli/search_test.rb b/Library/Homebrew/cask/test/cask/cli/search_test.rb deleted file mode 100644 index 6eb6badb9..000000000 --- a/Library/Homebrew/cask/test/cask/cli/search_test.rb +++ /dev/null @@ -1,59 +0,0 @@ -require "test_helper" - -describe Hbc::CLI::Search do - it "lists the available Casks that match the search term" do - lambda { - Hbc::CLI::Search.run("photoshop") - }.must_output <<-EOS.undent - ==> Partial matches - adobe-photoshop-cc - adobe-photoshop-lightroom - EOS - end - - it "shows that there are no Casks matching a search term that did not result in anything" do - lambda { - Hbc::CLI::Search.run("foo-bar-baz") - }.must_output("No Cask found for \"foo-bar-baz\".\n") - end - - it "lists all available Casks with no search term" do - out = capture_io { Hbc::CLI::Search.run }[0] - out.must_match(/google-chrome/) - out.length.must_be :>, 1000 - end - - it "ignores hyphens in search terms" do - out = capture_io { Hbc::CLI::Search.run("goo-gle-chrome") }[0] - out.must_match(/google-chrome/) - out.length.must_be :<, 100 - end - - it "ignores hyphens in Cask tokens" do - out = capture_io { Hbc::CLI::Search.run("googlechrome") }[0] - out.must_match(/google-chrome/) - out.length.must_be :<, 100 - end - - it "accepts multiple arguments" do - out = capture_io { Hbc::CLI::Search.run("google chrome") }[0] - out.must_match(/google-chrome/) - out.length.must_be :<, 100 - end - - it "accepts a regexp argument" do - lambda { - Hbc::CLI::Search.run("/^google-c[a-z]rome$/") - }.must_output "==> Regexp matches\ngoogle-chrome\n" - end - - it "Returns both exact and partial matches" do - out = capture_io { Hbc::CLI::Search.run("mnemosyne") }[0] - out.must_match(/^==> Exact match\nmnemosyne\n==> Partial matches\nsubclassed-mnemosyne/) - end - - it "does not search the Tap name" do - out = capture_io { Hbc::CLI::Search.run("caskroom") }[0] - out.must_match(/^No Cask found for "caskroom"\.\n/) - end -end diff --git a/Library/Homebrew/cask/test/cask/cli/version_test.rb b/Library/Homebrew/cask/test/cask/cli/version_test.rb deleted file mode 100644 index 60e6d22ae..000000000 --- a/Library/Homebrew/cask/test/cask/cli/version_test.rb +++ /dev/null @@ -1,9 +0,0 @@ -require "test_helper" - -describe "brew cask --version" do - it "respects the --version argument" do - lambda { - Hbc::CLI::NullCommand.new("--version").run - }.must_output Hbc.full_version - end -end diff --git a/Library/Homebrew/cask/test/cask/depends_on_test.rb b/Library/Homebrew/cask/test/cask/depends_on_test.rb deleted file mode 100644 index 4516dad37..000000000 --- a/Library/Homebrew/cask/test/cask/depends_on_test.rb +++ /dev/null @@ -1,113 +0,0 @@ -require "test_helper" - -# TODO: this test should be named after the corresponding class, once -# that class is abstracted from installer.rb -describe "Satisfy Dependencies and Requirements" do - # TODO: test that depends_on formula invokes Homebrew - # - # describe "depends_on formula" do - # it "" do - # end - # end - # - - describe "depends_on cask" do - it "raises an exception when depends_on cask is cyclic" do - dep_cask = Hbc.load("with-depends-on-cask-cyclic") - lambda { - shutup do - Hbc::Installer.new(dep_cask).install - end - }.must_raise(Hbc::CaskCyclicCaskDependencyError) - end - - it "installs the dependency of a Cask and the Cask itself" do - csk = Hbc.load("with-depends-on-cask") - dependency = Hbc.load(csk.depends_on.cask.first) - shutup do - Hbc::Installer.new(csk).install - end - - csk.must_be :installed? - dependency.must_be :installed? - end - end - - describe "depends_on macos" do - it "understands depends_on macos: <array>" do - macos_cask = Hbc.load("with-depends-on-macos-array") - shutup do - Hbc::Installer.new(macos_cask).install - end - end - - it "understands depends_on macos: <comparison>" do - macos_cask = Hbc.load("with-depends-on-macos-comparison") - shutup do - Hbc::Installer.new(macos_cask).install - end - end - - it "understands depends_on macos: <string>" do - macos_cask = Hbc.load("with-depends-on-macos-string") - shutup do - Hbc::Installer.new(macos_cask).install - end - end - - it "understands depends_on macos: <symbol>" do - macos_cask = Hbc.load("with-depends-on-macos-symbol") - shutup do - Hbc::Installer.new(macos_cask).install - end - end - - it "raises an exception when depends_on macos is not satisfied" do - macos_cask = Hbc.load("with-depends-on-macos-failure") - lambda { - shutup do - Hbc::Installer.new(macos_cask).install - end - }.must_raise(Hbc::CaskError) - end - end - - describe "depends_on arch" do - it "succeeds when depends_on arch is satisfied" do - arch_cask = Hbc.load("with-depends-on-arch") - shutup do - Hbc::Installer.new(arch_cask).install - end - end - end - - describe "depends_on x11" do - it "succeeds when depends_on x11 is satisfied" do - x11_cask = Hbc.load("with-depends-on-x11") - MacOS::X11.stubs(:installed?).returns(true) - shutup do - Hbc::Installer.new(x11_cask).install - end - end - - it "raises an exception when depends_on x11 is not satisfied" do - x11_cask = Hbc.load("with-depends-on-x11") - MacOS::X11.stubs(:installed?).returns(false) - lambda { - shutup do - Hbc::Installer.new(x11_cask).install - end - }.must_raise(Hbc::CaskX11DependencyError) - end - - it "never raises when depends_on x11: false" do - x11_cask = Hbc.load("with-depends-on-x11-false") - MacOS::X11.stubs(:installed?).returns(false) - lambda do - shutup do - Hbc::Installer.new(x11_cask).install - end - end # won't raise - end - end -end diff --git a/Library/Homebrew/cask/test/cask/dsl_test.rb b/Library/Homebrew/cask/test/cask/dsl_test.rb deleted file mode 100644 index 96d24a1a1..000000000 --- a/Library/Homebrew/cask/test/cask/dsl_test.rb +++ /dev/null @@ -1,475 +0,0 @@ -require "test_helper" - -describe Hbc::DSL do - it "lets you set url, homepage, and version" do - test_cask = Hbc.load("basic-cask") - test_cask.url.to_s.must_equal "http://example.com/TestCask.dmg" - test_cask.homepage.must_equal "http://example.com/" - test_cask.version.to_s.must_equal "1.2.3" - end - - describe "when a Cask includes an unknown method" do - attempt_unknown_method = nil - - before do - attempt_unknown_method = lambda do - Hbc::Cask.new("unexpected-method-cask") do - future_feature :not_yet_on_your_machine - end - end - end - - it "prints a warning that it has encountered an unexpected method" do - expected = Regexp.compile(<<-EOS.undent.lines.map(&:chomp).join("")) - (?m) - Warning: - .* - Unexpected method 'future_feature' called on Cask unexpected-method-cask\\. - .* - https://github.com/caskroom/homebrew-cask/blob/master/doc/reporting_bugs/pre_bug_report.md - .* - https://github.com/caskroom/homebrew-cask#reporting-bugs - EOS - - attempt_unknown_method.must_output nil, expected - end - - it "will simply warn, not throw an exception" do - begin - shutup do - attempt_unknown_method.call - end - rescue StandardError => e - flunk("Wanted unexpected method to simply warn, but got exception #{e}") - end - end - end - - describe "header line" do - it "requires a valid header format" do - lambda { - Hbc.load("invalid/invalid-header-format") - }.must_raise(SyntaxError) - end - - it "requires the header token to match the file name" do - err = lambda { - Hbc.load("invalid/invalid-header-token-mismatch") - }.must_raise(Hbc::CaskTokenDoesNotMatchError) - err.message.must_include "Bad header line:" - err.message.must_include "does not match file name" - end - - it "does not require a DSL version in the header" do - test_cask = Hbc.load("no-dsl-version") - test_cask.token.must_equal "no-dsl-version" - test_cask.url.to_s.must_equal "http://example.com/TestCask.dmg" - test_cask.homepage.must_equal "http://example.com/" - test_cask.version.to_s.must_equal "1.2.3" - end - - it "may use deprecated DSL version hash syntax" do - with_environment "HOMEBREW_DEVELOPER" => nil do - shutup do - test_cask = Hbc.load("with-dsl-version") - test_cask.token.must_equal "with-dsl-version" - test_cask.url.to_s.must_equal "http://example.com/TestCask.dmg" - test_cask.homepage.must_equal "http://example.com/" - test_cask.version.to_s.must_equal "1.2.3" - end - end - end - end - - describe "name stanza" do - it "lets you set the full name via a name stanza" do - cask = Hbc::Cask.new("name-cask") do - name "Proper Name" - end - - cask.name.must_equal [ - "Proper Name", - ] - end - - it "Accepts an array value to the name stanza" do - cask = Hbc::Cask.new("array-name-cask") do - name ["Proper Name", "Alternate Name"] - end - - cask.name.must_equal [ - "Proper Name", - "Alternate Name", - ] - end - - it "Accepts multiple name stanzas" do - cask = Hbc::Cask.new("multi-name-cask") do - name "Proper Name" - name "Alternate Name" - end - - cask.name.must_equal [ - "Proper Name", - "Alternate Name", - ] - end - end - - describe "sha256 stanza" do - it "lets you set checksum via sha256" do - cask = Hbc::Cask.new("checksum-cask") do - sha256 "imasha2" - end - - cask.sha256.must_equal "imasha2" - end - end - - describe "language stanza" do - it "allows multilingual casks" do - cask = lambda do - Hbc::Cask.new("cask-with-apps") do - language "zh" do - sha256 "abc123" - "zh-CN" - end - - language "en-US", default: true do - sha256 "xyz789" - "en-US" - end - - url "https://example.org/#{language}.zip" - end - end - - MacOS.stub :languages, ["zh"] do - cask.call.language.must_equal "zh-CN" - cask.call.sha256.must_equal "abc123" - cask.call.url.to_s.must_equal "https://example.org/zh-CN.zip" - end - - MacOS.stub :languages, ["zh-XX"] do - cask.call.language.must_equal "zh-CN" - cask.call.sha256.must_equal "abc123" - cask.call.url.to_s.must_equal "https://example.org/zh-CN.zip" - end - - MacOS.stub :languages, ["en"] do - cask.call.language.must_equal "en-US" - cask.call.sha256.must_equal "xyz789" - cask.call.url.to_s.must_equal "https://example.org/en-US.zip" - end - - MacOS.stub :languages, ["xx-XX"] do - cask.call.language.must_equal "en-US" - cask.call.sha256.must_equal "xyz789" - cask.call.url.to_s.must_equal "https://example.org/en-US.zip" - end - - MacOS.stub :languages, ["xx-XX", "zh", "en"] do - cask.call.language.must_equal "zh-CN" - cask.call.sha256.must_equal "abc123" - cask.call.url.to_s.must_equal "https://example.org/zh-CN.zip" - end - - MacOS.stub :languages, ["xx-XX", "en-US", "zh"] do - cask.call.language.must_equal "en-US" - cask.call.sha256.must_equal "xyz789" - cask.call.url.to_s.must_equal "https://example.org/en-US.zip" - end - end - end - - describe "app stanza" do - it "allows you to specify app stanzas" do - cask = Hbc::Cask.new("cask-with-apps") do - app "Foo.app" - app "Bar.app" - end - - Array(cask.artifacts[:app]).must_equal [["Foo.app"], ["Bar.app"]] - end - - it "allow app stanzas to be empty" do - cask = Hbc::Cask.new("cask-with-no-apps") - Array(cask.artifacts[:app]).must_equal %w[] - end - end - - describe "caveats stanza" do - it "allows caveats to be specified via a method define" do - cask = Hbc::Cask.new("plain-cask") - - cask.caveats.must_be :empty? - - cask = Hbc::Cask.new("cask-with-caveats") do - def caveats; <<-EOS.undent - When you install this Cask, you probably want to know this. - EOS - end - end - - cask.caveats.must_equal "When you install this Cask, you probably want to know this.\n" - end - end - - describe "pkg stanza" do - it "allows installable pkgs to be specified" do - cask = Hbc::Cask.new("cask-with-pkgs") do - pkg "Foo.pkg" - pkg "Bar.pkg" - end - - Array(cask.artifacts[:pkg]).must_equal [["Foo.pkg"], ["Bar.pkg"]] - end - end - - describe "url stanza" do - it "prevents defining multiple urls" do - err = lambda { - Hbc.load("invalid/invalid-two-url") - }.must_raise(Hbc::CaskInvalidError) - err.message.must_include "'url' stanza may only appear once" - end - end - - describe "homepage stanza" do - it "prevents defining multiple homepages" do - err = lambda { - Hbc.load("invalid/invalid-two-homepage") - }.must_raise(Hbc::CaskInvalidError) - err.message.must_include "'homepage' stanza may only appear once" - end - end - - describe "version stanza" do - it "prevents defining multiple versions" do - err = lambda { - Hbc.load("invalid/invalid-two-version") - }.must_raise(Hbc::CaskInvalidError) - err.message.must_include "'version' stanza may only appear once" - end - end - - describe "appcast stanza" do - it "allows appcasts to be specified" do - cask = Hbc.load("with-appcast") - cask.appcast.to_s.must_match(/^http/) - end - - it "prevents defining multiple appcasts" do - err = lambda { - Hbc.load("invalid/invalid-appcast-multiple") - }.must_raise(Hbc::CaskInvalidError) - err.message.must_include "'appcast' stanza may only appear once" - end - - it "refuses to load invalid appcast URLs" do - lambda { - Hbc.load("invalid/invalid-appcast-url") - }.must_raise(Hbc::CaskInvalidError) - end - end - - describe "gpg stanza" do - it "allows gpg stanza to be specified" do - cask = Hbc.load("with-gpg") - cask.gpg.to_s.must_match(/\S/) - end - - it "allows gpg stanza to be specified with :key_url" do - cask = Hbc.load("with-gpg-key-url") - cask.gpg.to_s.must_match(/\S/) - end - - it "prevents specifying gpg stanza multiple times" do - err = lambda { - Hbc.load("invalid/invalid-gpg-multiple-stanzas") - }.must_raise(Hbc::CaskInvalidError) - err.message.must_include "'gpg' stanza may only appear once" - end - - it "prevents missing gpg key parameters" do - err = lambda { - Hbc.load("invalid/invalid-gpg-missing-key") - }.must_raise(Hbc::CaskInvalidError) - err.message.must_include "'gpg' stanza must include exactly one" - end - - it "prevents conflicting gpg key parameters" do - err = lambda { - Hbc.load("invalid/invalid-gpg-conflicting-keys") - }.must_raise(Hbc::CaskInvalidError) - err.message.must_include "'gpg' stanza must include exactly one" - end - - it "refuses to load invalid gpg signature URLs" do - lambda { - Hbc.load("invalid/invalid-gpg-signature-url") - }.must_raise(Hbc::CaskInvalidError) - end - - it "refuses to load invalid gpg key URLs" do - lambda { - Hbc.load("invalid/invalid-gpg-key-url") - }.must_raise(Hbc::CaskInvalidError) - end - - it "refuses to load invalid gpg key IDs" do - lambda { - Hbc.load("invalid/invalid-gpg-key-id") - }.must_raise(Hbc::CaskInvalidError) - end - - it "refuses to load if gpg parameter is unknown" do - lambda { - Hbc.load("invalid/invalid-gpg-parameter") - }.must_raise(Hbc::CaskInvalidError) - end - end - - describe "depends_on stanza" do - it "refuses to load with an invalid depends_on key" do - lambda { - Hbc.load("invalid/invalid-depends-on-key") - }.must_raise(Hbc::CaskInvalidError) - end - end - - describe "depends_on formula" do - it "allows depends_on formula to be specified" do - cask = Hbc.load("with-depends-on-formula") - cask.depends_on.formula.wont_be_nil - end - - it "allows multiple depends_on formula to be specified" do - cask = Hbc.load("with-depends-on-formula-multiple") - cask.depends_on.formula.wont_be_nil - end - end - - describe "depends_on cask" do - it "allows depends_on cask to be specified" do - cask = Hbc.load("with-depends-on-cask") - cask.depends_on.cask.wont_be_nil - end - - it "allows multiple depends_on cask to be specified" do - cask = Hbc.load("with-depends-on-cask-multiple") - cask.depends_on.cask.wont_be_nil - end - end - - describe "depends_on macos" do - it "allows depends_on macos to be specified" do - cask = Hbc.load("with-depends-on-macos-string") - cask.depends_on.macos.wont_be_nil - end - it "refuses to load with an invalid depends_on macos value" do - lambda { - Hbc.load("invalid/invalid-depends-on-macos-bad-release") - }.must_raise(Hbc::CaskInvalidError) - end - it "refuses to load with conflicting depends_on macos forms" do - lambda { - Hbc.load("invalid/invalid-depends-on-macos-conflicting-forms") - }.must_raise(Hbc::CaskInvalidError) - end - end - - describe "depends_on arch" do - it "allows depends_on arch to be specified" do - cask = Hbc.load("with-depends-on-arch") - cask.depends_on.arch.wont_be_nil - end - it "refuses to load with an invalid depends_on arch value" do - lambda { - Hbc.load("invalid/invalid-depends-on-arch-value") - }.must_raise(Hbc::CaskInvalidError) - end - end - - describe "depends_on x11" do - it "allows depends_on x11 to be specified" do - cask = Hbc.load("with-depends-on-x11") - cask.depends_on.x11.wont_be_nil - end - it "refuses to load with an invalid depends_on x11 value" do - lambda { - Hbc.load("invalid/invalid-depends-on-x11-value") - }.must_raise(Hbc::CaskInvalidError) - end - end - - describe "conflicts_with stanza" do - it "allows conflicts_with stanza to be specified" do - cask = Hbc.load("with-conflicts-with") - cask.conflicts_with.formula.wont_be_nil - end - - it "refuses to load invalid conflicts_with key" do - lambda { - Hbc.load("invalid/invalid-conflicts-with-key") - }.must_raise(Hbc::CaskInvalidError) - end - end - - describe "installer stanza" do - it "allows installer script to be specified" do - cask = Hbc.load("with-installer-script") - cask.artifacts[:installer].first.script[:executable].must_equal "/usr/bin/true" - cask.artifacts[:installer].first.script[:args].must_equal ["--flag"] - cask.artifacts[:installer].to_a[1].script[:executable].must_equal "/usr/bin/false" - cask.artifacts[:installer].to_a[1].script[:args].must_equal ["--flag"] - end - it "allows installer manual to be specified" do - cask = Hbc.load("with-installer-manual") - cask.artifacts[:installer].first.manual.must_equal "Caffeine.app" - end - end - - describe "stage_only stanza" do - it "allows stage_only stanza to be specified" do - cask = Hbc.load("stage-only") - cask.artifacts[:stage_only].first.must_equal [true] - end - - it "prevents specifying stage_only with other activatables" do - err = lambda { - Hbc.load("invalid/invalid-stage-only-conflict") - }.must_raise(Hbc::CaskInvalidError) - err.message.must_include "'stage_only' must be the only activatable artifact" - end - end - - describe "auto_updates stanza" do - it "allows auto_updates stanza to be specified" do - cask = Hbc.load("auto-updates") - cask.auto_updates.must_equal true - end - end - - describe "appdir" do - it "allows interpolation of the appdir value in stanzas" do - cask = Hbc.load("appdir-interpolation") - cask.artifacts[:binary].first.must_equal ["#{Hbc.appdir}/some/path"] - end - - it "does not include a trailing slash" do - original_appdir = Hbc.appdir - Hbc.appdir = "#{original_appdir}/" - - begin - cask = Hbc::Cask.new("appdir-trailing-slash") do - binary "#{appdir}/some/path" - end - - cask.artifacts[:binary].first.must_equal ["#{original_appdir}/some/path"] - ensure - Hbc.appdir = original_appdir - end - end - end -end diff --git a/Library/Homebrew/cask/test/cask/installer_test.rb b/Library/Homebrew/cask/test/cask/installer_test.rb deleted file mode 100644 index d76411ae6..000000000 --- a/Library/Homebrew/cask/test/cask/installer_test.rb +++ /dev/null @@ -1,422 +0,0 @@ -require "test_helper" - -describe Hbc::Installer do - describe "install" do - let(:empty_depends_on_stub) { - stub(formula: [], cask: [], macos: nil, arch: nil, x11: nil) - } - - it "downloads and installs a nice fresh Cask" do - caffeine = Hbc.load("local-caffeine") - - shutup do - Hbc::Installer.new(caffeine).install - end - - dest_path = Hbc.caskroom.join("local-caffeine", caffeine.version) - dest_path.must_be :directory? - application = Hbc.appdir.join("Caffeine.app") - application.must_be :directory? - end - - it "works with dmg-based Casks" do - asset = Hbc.load("container-dmg") - - shutup do - Hbc::Installer.new(asset).install - end - - dest_path = Hbc.caskroom.join("container-dmg", asset.version) - dest_path.must_be :directory? - file = Hbc.appdir.join("container") - file.must_be :file? - end - - it "works with tar-gz-based Casks" do - asset = Hbc.load("container-tar-gz") - - shutup do - Hbc::Installer.new(asset).install - end - - dest_path = Hbc.caskroom.join("container-tar-gz", asset.version) - dest_path.must_be :directory? - application = Hbc.appdir.join("container") - application.must_be :file? - end - - it "works with cab-based Casks" do - skip("cabextract not installed") if which("cabextract").nil? - asset = Hbc.load("container-cab") - - asset.stub :depends_on, empty_depends_on_stub do - shutup do - Hbc::Installer.new(asset).install - end - end - - dest_path = Hbc.caskroom.join("container-cab", asset.version) - dest_path.must_be :directory? - application = Hbc.appdir.join("container") - application.must_be :file? - end - - it "works with Adobe AIR-based Casks" do - skip("Adobe AIR not installed") unless Hbc::Container::Air.installer_exist? - asset = Hbc.load("container-air") - - shutup do - Hbc::Installer.new(asset).install - end - - dest_path = Hbc.caskroom.join("container-air", asset.version) - dest_path.must_be :directory? - application = Hbc.appdir.join("container.app") - application.must_be :directory? - end - - it "works with 7z-based Casks" do - skip("unar not installed") if which("unar").nil? - asset = Hbc.load("container-7z") - - asset.stub :depends_on, empty_depends_on_stub do - shutup do - Hbc::Installer.new(asset).install - end - end - - dest_path = Hbc.caskroom.join("container-7z", asset.version) - dest_path.must_be :directory? - file = Hbc.appdir.join("container") - file.must_be :file? - end - - it "works with xar-based Casks" do - asset = Hbc.load("container-xar") - - shutup do - Hbc::Installer.new(asset).install - end - - dest_path = Hbc.caskroom.join("container-xar", asset.version) - dest_path.must_be :directory? - file = Hbc.appdir.join("container") - file.must_be :file? - end - - it "works with Stuffit-based Casks" do - skip("unar not installed") if which("unar").nil? - asset = Hbc.load("container-sit") - - asset.stub :depends_on, empty_depends_on_stub do - shutup do - Hbc::Installer.new(asset).install - end - end - - dest_path = Hbc.caskroom.join("container-sit", asset.version) - dest_path.must_be :directory? - application = Hbc.appdir.join("container") - application.must_be :file? - end - - it "works with RAR-based Casks" do - skip("unar not installed") if which("unar").nil? - asset = Hbc.load("container-rar") - - asset.stub :depends_on, empty_depends_on_stub do - shutup do - Hbc::Installer.new(asset).install - end - end - - dest_path = Hbc.caskroom.join("container-rar", asset.version) - dest_path.must_be :directory? - application = Hbc.appdir.join("container") - application.must_be :file? - end - - it "works with pure bzip2-based Casks" do - asset = Hbc.load("container-bzip2") - - shutup do - Hbc::Installer.new(asset).install - end - - dest_path = Hbc.caskroom.join("container-bzip2", asset.version) - dest_path.must_be :directory? - file = Hbc.appdir.join("container-bzip2--#{asset.version}") - file.must_be :file? - end - - it "works with pure gzip-based Casks" do - asset = Hbc.load("container-gzip") - - shutup do - Hbc::Installer.new(asset).install - end - - dest_path = Hbc.caskroom.join("container-gzip", asset.version) - dest_path.must_be :directory? - file = Hbc.appdir.join("container") - file.must_be :file? - end - - it "works with pure xz-based Casks" do - skip("unxz not installed") if which("unxz").nil? - asset = Hbc.load("container-xz") - - asset.stub :depends_on, empty_depends_on_stub do - shutup do - Hbc::Installer.new(asset).install - end - end - - dest_path = Hbc.caskroom.join("container-xz", asset.version) - dest_path.must_be :directory? - file = Hbc.appdir.join("container-xz--#{asset.version}") - file.must_be :file? - end - - it "works with lzma-based Casks" do - skip("unlzma not installed") if which("unlzma").nil? - asset = Hbc.load("container-lzma") - - asset.stub :depends_on, empty_depends_on_stub do - shutup do - Hbc::Installer.new(asset).install - end - end - - dest_path = Hbc.caskroom.join("container-lzma", asset.version) - dest_path.must_be :directory? - file = Hbc.appdir.join("container-lzma--#{asset.version}") - file.must_be :file? - end - - it "blows up on a bad checksum" do - bad_checksum = Hbc.load("bad-checksum") - lambda { - shutup do - Hbc::Installer.new(bad_checksum).install - end - }.must_raise(Hbc::CaskSha256MismatchError) - end - - it "blows up on a missing checksum" do - missing_checksum = Hbc.load("missing-checksum") - lambda { - shutup do - Hbc::Installer.new(missing_checksum).install - end - }.must_raise(Hbc::CaskSha256MissingError) - end - - it "installs fine if sha256 :no_check is used" do - no_checksum = Hbc.load("no-checksum") - - shutup do - Hbc::Installer.new(no_checksum).install - end - - no_checksum.must_be :installed? - end - - it "fails to install if sha256 :no_check is used with --require-sha" do - no_checksum = Hbc.load("no-checksum") - lambda { - Hbc::Installer.new(no_checksum, require_sha: true).install - }.must_raise(Hbc::CaskNoShasumError) - end - - it "installs fine if sha256 :no_check is used with --require-sha and --force" do - no_checksum = Hbc.load("no-checksum") - - shutup do - Hbc::Installer.new(no_checksum, require_sha: true, force: true).install - end - - no_checksum.must_be :installed? - end - - it "prints caveats if they're present" do - with_caveats = Hbc.load("with-caveats") - lambda { - Hbc::Installer.new(with_caveats).install - }.must_output(/Here are some things you might want to know/) - with_caveats.must_be :installed? - end - - it "prints installer :manual instructions when present" do - with_installer_manual = Hbc.load("with-installer-manual") - lambda { - Hbc::Installer.new(with_installer_manual).install - }.must_output(/To complete the installation of Cask with-installer-manual, you must also\nrun the installer at\n\n '#{with_installer_manual.staged_path.join('Caffeine.app')}'/) - with_installer_manual.must_be :installed? - end - - it "does not extract __MACOSX directories from zips" do - with_macosx_dir = Hbc.load("with-macosx-dir") - - shutup do - Hbc::Installer.new(with_macosx_dir).install - end - - with_macosx_dir.staged_path.join("__MACOSX").wont_be :directory? - end - - it "installer method raises an exception when already-installed Casks which auto-update are attempted" do - auto_updates = Hbc.load("auto-updates") - auto_updates.installed?.must_equal false - installer = Hbc::Installer.new(auto_updates) - - shutup do - installer.install - end - - lambda { - installer.install - }.must_raise(Hbc::CaskAlreadyInstalledAutoUpdatesError) - end - - it "allows already-installed Casks which auto-update to be installed if force is provided" do - auto_updates = Hbc.load("auto-updates") - auto_updates.installed?.must_equal false - - shutup do - Hbc::Installer.new(auto_updates).install - end - - shutup do - Hbc::Installer.new(auto_updates, force: true).install - end # wont_raise - end - - # unlike the CLI, the internal interface throws exception on double-install - it "installer method raises an exception when already-installed Casks are attempted" do - transmission = Hbc.load("local-transmission") - transmission.installed?.must_equal false - installer = Hbc::Installer.new(transmission) - - shutup do - installer.install - end - - lambda { - installer.install - }.must_raise(Hbc::CaskAlreadyInstalledError) - end - - it "allows already-installed Casks to be installed if force is provided" do - transmission = Hbc.load("local-transmission") - transmission.installed?.must_equal false - - shutup do - Hbc::Installer.new(transmission).install - end - - shutup do - Hbc::Installer.new(transmission, force: true).install - end # wont_raise - end - - it "works naked-pkg-based Casks" do - naked_pkg = Hbc.load("container-pkg") - - shutup do - Hbc::Installer.new(naked_pkg).install - end - - dest_path = Hbc.caskroom.join("container-pkg", naked_pkg.version) - pkg = dest_path.join("container.pkg") - pkg.must_be :file? - end - - it "works properly with an overridden container :type" do - naked_executable = Hbc.load("naked-executable") - - shutup do - Hbc::Installer.new(naked_executable).install - end - - dest_path = Hbc.caskroom.join("naked-executable", naked_executable.version) - executable = dest_path.join("naked_executable") - executable.must_be :file? - end - - it "works fine with a nested container" do - nested_app = Hbc.load("nested-app") - - shutup do - Hbc::Installer.new(nested_app).install - end - - dest_path = Hbc.appdir.join("MyNestedApp.app") - dest_path.must_be :directory? - end - - it "generates and finds a timestamped metadata directory for an installed Cask" do - caffeine = Hbc.load("local-caffeine") - - shutup do - Hbc::Installer.new(caffeine).install - end - - m_path = caffeine.metadata_path(:now, true) - caffeine.metadata_path(:now, false).must_equal(m_path) - caffeine.metadata_path(:latest).must_equal(m_path) - end - - it "generates and finds a metadata subdirectory for an installed Cask" do - caffeine = Hbc.load("local-caffeine") - - shutup do - Hbc::Installer.new(caffeine).install - end - - subdir_name = "Casks" - m_subdir = caffeine.metadata_subdir(subdir_name, :now, true) - caffeine.metadata_subdir(subdir_name, :now, false).must_equal(m_subdir) - caffeine.metadata_subdir(subdir_name, :latest).must_equal(m_subdir) - end - end - - describe "uninstall" do - it "fully uninstalls a Cask" do - caffeine = Hbc.load("local-caffeine") - installer = Hbc::Installer.new(caffeine) - - shutup do - installer.install - installer.uninstall - end - - Hbc.caskroom.join("local-caffeine", caffeine.version, "Caffeine.app").wont_be :directory? - Hbc.caskroom.join("local-caffeine", caffeine.version).wont_be :directory? - Hbc.caskroom.join("local-caffeine").wont_be :directory? - end - - it "uninstalls all versions if force is set" do - caffeine = Hbc.load("local-caffeine") - mutated_version = caffeine.version + ".1" - - shutup do - Hbc::Installer.new(caffeine).install - end - - Hbc.caskroom.join("local-caffeine", caffeine.version).must_be :directory? - Hbc.caskroom.join("local-caffeine", mutated_version).wont_be :directory? - FileUtils.mv(Hbc.caskroom.join("local-caffeine", caffeine.version), Hbc.caskroom.join("local-caffeine", mutated_version)) - Hbc.caskroom.join("local-caffeine", caffeine.version).wont_be :directory? - Hbc.caskroom.join("local-caffeine", mutated_version).must_be :directory? - - shutup do - Hbc::Installer.new(caffeine, force: true).uninstall - end - - Hbc.caskroom.join("local-caffeine", caffeine.version).wont_be :directory? - Hbc.caskroom.join("local-caffeine", mutated_version).wont_be :directory? - Hbc.caskroom.join("local-caffeine").wont_be :directory? - end - end -end diff --git a/Library/Homebrew/cask/test/cask/pkg_test.rb b/Library/Homebrew/cask/test/cask/pkg_test.rb deleted file mode 100644 index 85a42356e..000000000 --- a/Library/Homebrew/cask/test/cask/pkg_test.rb +++ /dev/null @@ -1,94 +0,0 @@ -require "test_helper" - -describe Hbc::Pkg do - describe "uninstall" do - it "removes files and dirs referenced by the pkg" do - pkg = Hbc::Pkg.new("my.fake.pkg", Hbc::NeverSudoSystemCommand) - - some_files = Array.new(3) { Pathname(Tempfile.new("testfile").path) } - pkg.stubs(:pkgutil_bom_files).returns some_files - - some_specials = Array.new(3) { Pathname(Tempfile.new("testfile").path) } - pkg.stubs(:pkgutil_bom_specials).returns some_specials - - some_dirs = Array.new(3) { Pathname(Dir.mktmpdir) } - pkg.stubs(:pkgutil_bom_dirs).returns some_dirs - - pkg.stubs(:forget) - - pkg.uninstall - - some_files.each do |file| - file.wont_be :exist? - end - - some_dirs.each do |dir| - dir.wont_be :exist? - end - end - - it "forgets the pkg" do - pkg = Hbc::Pkg.new("my.fake.pkg", Hbc::FakeSystemCommand) - - Hbc::FakeSystemCommand.stubs_command( - ["/usr/sbin/pkgutil", "--only-files", "--files", "my.fake.pkg"] - ) - Hbc::FakeSystemCommand.stubs_command( - ["/usr/sbin/pkgutil", "--only-dirs", "--files", "my.fake.pkg"] - ) - Hbc::FakeSystemCommand.stubs_command( - ["/usr/sbin/pkgutil", "--files", "my.fake.pkg"] - ) - - Hbc::FakeSystemCommand.expects_command( - ["/usr/bin/sudo", "-E", "--", "/usr/sbin/pkgutil", "--forget", "my.fake.pkg"] - ) - - pkg.uninstall - end - - it "cleans broken symlinks, but leaves AOK symlinks" do - pkg = Hbc::Pkg.new("my.fake.pkg", Hbc::NeverSudoSystemCommand) - - fake_dir = Pathname(Dir.mktmpdir) - fake_file = fake_dir.join("ima_file").tap { |path| FileUtils.touch(path) } - - intact_symlink = fake_dir.join("intact_symlink").tap { |path| path.make_symlink(fake_file) } - broken_symlink = fake_dir.join("broken_symlink").tap { |path| path.make_symlink("im_nota_file") } - - pkg.stubs(:pkgutil_bom_specials).returns([]) - pkg.stubs(:pkgutil_bom_files).returns([]) - pkg.stubs(:pkgutil_bom_dirs).returns([fake_dir]) - pkg.stubs(:forget) - - pkg.uninstall - - intact_symlink.must_be :exist? - broken_symlink.wont_be :exist? - fake_dir.must_be :exist? - end - - it "snags permissions on ornery dirs, but returns them afterwords" do - pkg = Hbc::Pkg.new("my.fake.pkg", Hbc::NeverSudoSystemCommand) - - fake_dir = Pathname(Dir.mktmpdir) - - fake_file = fake_dir.join("ima_installed_file").tap { |path| FileUtils.touch(path) } - - fake_dir.chmod(0000) - - pkg.stubs(:pkgutil_bom_specials).returns([]) - pkg.stubs(:pkgutil_bom_files).returns([fake_file]) - pkg.stubs(:pkgutil_bom_dirs).returns([fake_dir]) - pkg.stubs(:forget) - - shutup do - pkg.uninstall - end - - fake_dir.must_be :directory? - fake_file.wont_be :file? - (fake_dir.stat.mode % 01000).to_s(8).must_equal "0" - end - end -end diff --git a/Library/Homebrew/cask/test/cask/url_checker_test.rb b/Library/Homebrew/cask/test/cask/url_checker_test.rb deleted file mode 100644 index 199182bf2..000000000 --- a/Library/Homebrew/cask/test/cask/url_checker_test.rb +++ /dev/null @@ -1,51 +0,0 @@ -require "test_helper" - -describe Hbc::UrlChecker do - describe "request processing" do - let(:cask) { Hbc.load("basic-cask") } - let(:checker) { Hbc::UrlChecker.new(cask) } - let(:with_stubbed_fetcher) { - lambda { |&block| - Hbc::Fetcher.stub(:head, response) do - checker.run - instance_eval(&block) - end - } - } - - describe "with an empty response" do - let(:response) { "" } - - it "adds an error" do - with_stubbed_fetcher.call do - expect(checker.errors).must_include("timeout while requesting #{cask.url}") - end - end - end - - describe "with a valid http response" do - let(:response) { - <<-EOS.undent - HTTP/1.1 200 OK - Content-Type: application/x-apple-diskimage - ETag: "b4208f3e84967be4b078ecaa03fba941" - Content-Length: 23726161 - Last-Modified: Sun, 12 Aug 2012 21:17:21 GMT - EOS - } - - it "properly populates the response code and headers" do - with_stubbed_fetcher.call do - expect(checker.errors).must_be_empty - expect(checker.response_status).must_equal("HTTP/1.1 200 OK") - expect(checker.headers).must_equal( - "Content-Type" => "application/x-apple-diskimage", - "ETag" => '"b4208f3e84967be4b078ecaa03fba941"', - "Content-Length" => "23726161", - "Last-Modified" => "Sun, 12 Aug 2012 21:17:21 GMT" - ) - end - end - end - end -end diff --git a/Library/Homebrew/cask/test/cask_test.rb b/Library/Homebrew/cask/test/cask_test.rb deleted file mode 100644 index 64fc21965..000000000 --- a/Library/Homebrew/cask/test/cask_test.rb +++ /dev/null @@ -1,71 +0,0 @@ -require "test_helper" - -describe "Cask" do - hbc_relative_tap_path = "../../Taps/caskroom/homebrew-cask" - describe "load" do - it "returns an instance of the Cask for the given token" do - c = Hbc.load("adium") - c.must_be_kind_of(Hbc::Cask) - c.token.must_equal("adium") - end - - it "returns an instance of the Cask from a specific file location" do - location = File.expand_path(hbc_relative_tap_path + "/Casks/dia.rb") - c = Hbc.load(location) - c.must_be_kind_of(Hbc::Cask) - c.token.must_equal("dia") - end - - it "returns an instance of the Cask from a url" do - url = "file://" + File.expand_path(hbc_relative_tap_path + "/Casks/dia.rb") - c = shutup do - Hbc.load(url) - end - c.must_be_kind_of(Hbc::Cask) - c.token.must_equal("dia") - end - - it "raises an error when failing to download a Cask from a url" do - lambda { - url = "file://" + File.expand_path(hbc_relative_tap_path + "/Casks/notacask.rb") - shutup do - Hbc.load(url) - end - }.must_raise(Hbc::CaskUnavailableError) - end - - it "returns an instance of the Cask from a relative file location" do - c = Hbc.load(hbc_relative_tap_path + "/Casks/bbedit.rb") - c.must_be_kind_of(Hbc::Cask) - c.token.must_equal("bbedit") - end - - it "uses exact match when loading by token" do - Hbc.load("test-opera").token.must_equal("test-opera") - Hbc.load("test-opera-mail").token.must_equal("test-opera-mail") - end - - it "raises an error when attempting to load a Cask that doesn't exist" do - lambda { - Hbc.load("notacask") - }.must_raise(Hbc::CaskUnavailableError) - end - end - - describe "all_tokens" do - it "returns a token for every Cask" do - all_cask_tokens = Hbc.all_tokens - all_cask_tokens.count.must_be :>, 20 - all_cask_tokens.each { |token| token.must_be_kind_of String } - end - end - - describe "metadata" do - it "proposes a versioned metadata directory name for each instance" do - cask_token = "adium" - c = Hbc.load(cask_token) - metadata_path = Hbc.caskroom.join(cask_token, ".metadata", c.version) - c.metadata_versioned_container_path.to_s.must_equal(metadata_path.to_s) - end - end -end diff --git a/Library/Homebrew/cask/test/plist/parser_test.rb b/Library/Homebrew/cask/test/plist/parser_test.rb deleted file mode 100644 index 7f844e377..000000000 --- a/Library/Homebrew/cask/test/plist/parser_test.rb +++ /dev/null @@ -1,65 +0,0 @@ -require "test_helper" - -describe Plist do - it "parses some hdiutil output okay" do - hdiutil_output = <<-EOS.undent - <?xml version="1.0" encoding="UTF-8"?> - <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> - <plist version="1.0"> - <dict> - <key>system-entities</key> - <array> - <dict> - <key>content-hint</key> - <string>Apple_partition_map</string> - <key>dev-entry</key> - <string>/dev/disk3s1</string> - <key>potentially-mountable</key> - <false/> - <key>unmapped-content-hint</key> - <string>Apple_partition_map</string> - </dict> - <dict> - <key>content-hint</key> - <string>Apple_partition_scheme</string> - <key>dev-entry</key> - <string>/dev/disk3</string> - <key>potentially-mountable</key> - <false/> - <key>unmapped-content-hint</key> - <string>Apple_partition_scheme</string> - </dict> - <dict> - <key>content-hint</key> - <string>Apple_HFS</string> - <key>dev-entry</key> - <string>/dev/disk3s2</string> - <key>mount-point</key> - <string>/private/tmp/dmg.BhfS2g</string> - <key>potentially-mountable</key> - <true/> - <key>unmapped-content-hint</key> - <string>Apple_HFS</string> - <key>volume-kind</key> - <string>hfs</string> - </dict> - </array> - </dict> - </plist> - EOS - - parsed = Plist.parse_xml(hdiutil_output) - - parsed.keys.must_equal ["system-entities"] - parsed["system-entities"].length.must_equal 3 - parsed["system-entities"].map { |e| e["dev-entry"] }.must_equal %w[ - /dev/disk3s1 - /dev/disk3 - /dev/disk3s2 - ] - end - - it "does not choke on empty input" do - Plist.parse_xml("").must_equal {} - end -end diff --git a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-header-token-mismatch.rb b/Library/Homebrew/cask/test/support/Casks/invalid/invalid-header-token-mismatch.rb deleted file mode 100644 index 2b8ad5619..000000000 --- a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-header-token-mismatch.rb +++ /dev/null @@ -1,9 +0,0 @@ -test_cask 'invalid-header-token-mismatch-this-text-does-not-belong' do - version '1.2.3' - sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' - - url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip" - homepage 'http://example.com/local-caffeine' - - app 'Caffeine.app' -end diff --git a/Library/Homebrew/cask/test/support/Casks/with-uninstall-rmdir.rb b/Library/Homebrew/cask/test/support/Casks/with-uninstall-rmdir.rb deleted file mode 100644 index 88142ea71..000000000 --- a/Library/Homebrew/cask/test/support/Casks/with-uninstall-rmdir.rb +++ /dev/null @@ -1,11 +0,0 @@ -test_cask 'with-uninstall-rmdir' do - version '1.2.3' - sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' - - url "file://#{TEST_FIXTURE_DIR}/cask/MyFancyPkg.zip" - homepage 'http://example.com/fancy-pkg' - - pkg 'MyFancyPkg/Fancy.pkg' - - uninstall rmdir: "#{TEST_FIXTURE_DIR}/cask/empty_directory" -end diff --git a/Library/Homebrew/cask/test/support/Casks/with-zap-rmdir.rb b/Library/Homebrew/cask/test/support/Casks/with-zap-rmdir.rb deleted file mode 100644 index eac02ad0e..000000000 --- a/Library/Homebrew/cask/test/support/Casks/with-zap-rmdir.rb +++ /dev/null @@ -1,11 +0,0 @@ -test_cask 'with-zap-rmdir' do - version '1.2.3' - sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' - - url "file://#{TEST_FIXTURE_DIR}/cask/MyFancyPkg.zip" - homepage 'http://example.com/fancy-pkg' - - pkg 'MyFancyPkg/Fancy.pkg' - - zap rmdir: "#{TEST_FIXTURE_DIR}/cask/empty_directory" -end diff --git a/Library/Homebrew/cask/test/support/cleanup.rb b/Library/Homebrew/cask/test/support/cleanup.rb deleted file mode 100644 index c31a74be2..000000000 --- a/Library/Homebrew/cask/test/support/cleanup.rb +++ /dev/null @@ -1,10 +0,0 @@ -module MiniTest - class Spec - def after_teardown - super - Hbc.installed.each do |cask| - Hbc::Installer.new(cask).purge_versioned_files - end - end - end -end diff --git a/Library/Homebrew/cask/test/support/fake_dirs.rb b/Library/Homebrew/cask/test/support/fake_dirs.rb deleted file mode 100644 index ea7acc685..000000000 --- a/Library/Homebrew/cask/test/support/fake_dirs.rb +++ /dev/null @@ -1,31 +0,0 @@ -# wire in a set of fake link dirs per-test -module FakeDirHooks - DIRS = [:appdir, :qlplugindir, :binarydir].freeze - - def before_setup - super - - @canned_dirs = {} - - DIRS.each do |dir_name| - dir = HOMEBREW_PREFIX.join("#{dir_name}-#{Time.now.to_i}-#{rand(1024)}") - dir.mkpath - Hbc.send("#{dir_name}=", dir) - @canned_dirs[:dir_name] = dir - end - end - - def after_teardown - super - - @canned_dirs.each_value do |dir| - dir.rmtree if dir.exist? - end - end -end - -module MiniTest - class Spec - include FakeDirHooks - end -end diff --git a/Library/Homebrew/cask/test/support/shared_examples.rb b/Library/Homebrew/cask/test/support/shared_examples.rb deleted file mode 100644 index 594ca81c1..000000000 --- a/Library/Homebrew/cask/test/support/shared_examples.rb +++ /dev/null @@ -1,25 +0,0 @@ -# Adapted from https://gist.github.com/jodosha/1560208 -MiniTest::Spec.class_eval do - def self.shared_examples - @shared_examples ||= {} - end -end - -module MiniTest - class Spec - module SharedExamples - def shared_examples_for(desc, &block) - MiniTest::Spec.shared_examples[desc] = block - end - - def it_behaves_like(desc, *args, &block) - instance_exec(*args, &MiniTest::Spec.shared_examples[desc]) - instance_eval(&block) if block_given? - end - end - end -end - -Object.class_eval do - include(MiniTest::Spec::SharedExamples) -end diff --git a/Library/Homebrew/cask/test/support/shared_examples/dsl_base.rb b/Library/Homebrew/cask/test/support/shared_examples/dsl_base.rb deleted file mode 100644 index 28115bb4b..000000000 --- a/Library/Homebrew/cask/test/support/shared_examples/dsl_base.rb +++ /dev/null @@ -1,23 +0,0 @@ -require "test_helper" - -shared_examples_for Hbc::DSL::Base do - it "supports the token method" do - dsl.token.must_equal cask.token - end - - it "supports the version method" do - dsl.version.must_equal cask.version - end - - it "supports the caskroom_path method" do - dsl.caskroom_path.must_equal cask.caskroom_path - end - - it "supports the staged_path method" do - dsl.staged_path.must_equal cask.staged_path - end - - it "supports the appdir method" do - dsl.appdir.must_equal cask.appdir - end -end diff --git a/Library/Homebrew/cask/test/support/shared_examples/staged.rb b/Library/Homebrew/cask/test/support/shared_examples/staged.rb deleted file mode 100644 index ef4ff0341..000000000 --- a/Library/Homebrew/cask/test/support/shared_examples/staged.rb +++ /dev/null @@ -1,109 +0,0 @@ -require "test_helper" - -shared_examples_for Hbc::Staged do - let(:fake_pathname_exists) { - fake_pathname = Pathname("/path/to/file/that/exists") - fake_pathname.stubs(exist?: true, expand_path: fake_pathname) - fake_pathname - } - - let(:fake_pathname_does_not_exist) { - fake_pathname = Pathname("/path/to/file/that/does/not/exist") - fake_pathname.stubs(exist?: false, expand_path: fake_pathname) - fake_pathname - } - - it "can run system commands with list-form arguments" do - Hbc::FakeSystemCommand.expects_command( - ["echo", "homebrew-cask", "rocks!"] - ) - staged.system_command("echo", args: ["homebrew-cask", "rocks!"]) - end - - it "can get the Info.plist file for the primary app" do - staged.info_plist_file.to_s.must_include Hbc.appdir.join("TestCask.app/Contents/Info.plist") - end - - it "can execute commands on the Info.plist file" do - staged.stubs(bundle_identifier: "com.example.BasicCask") - - Hbc::FakeSystemCommand.expects_command( - ["/usr/libexec/PlistBuddy", "-c", "Print CFBundleIdentifier", staged.info_plist_file] - ) - staged.plist_exec("Print CFBundleIdentifier") - end - - it "can set a key in the Info.plist file" do - staged.stubs(bundle_identifier: "com.example.BasicCask") - - Hbc::FakeSystemCommand.expects_command( - ["/usr/libexec/PlistBuddy", "-c", "Set :JVMOptions:JVMVersion 1.6+", staged.info_plist_file] - ) - staged.plist_set(":JVMOptions:JVMVersion", "1.6+") - end - - it "can set the permissions of a file" do - fake_pathname = fake_pathname_exists - staged.stubs(Pathname: fake_pathname) - - Hbc::FakeSystemCommand.expects_command( - ["/usr/bin/sudo", "-E", "--", "/bin/chmod", "-R", "--", "777", fake_pathname] - ) - staged.set_permissions(fake_pathname.to_s, "777") - end - - it "can set the permissions of multiple files" do - fake_pathname = fake_pathname_exists - staged.stubs(:Pathname).returns(fake_pathname) - - Hbc::FakeSystemCommand.expects_command( - ["/usr/bin/sudo", "-E", "--", "/bin/chmod", "-R", "--", "777", fake_pathname, fake_pathname] - ) - staged.set_permissions([fake_pathname.to_s, fake_pathname.to_s], "777") - end - - it "cannot set the permissions of a file that does not exist" do - fake_pathname = fake_pathname_does_not_exist - staged.stubs(Pathname: fake_pathname) - staged.set_permissions(fake_pathname.to_s, "777") - end - - it "can set the ownership of a file" do - staged.stubs(current_user: "fake_user") - fake_pathname = fake_pathname_exists - staged.stubs(Pathname: fake_pathname) - - Hbc::FakeSystemCommand.expects_command( - ["/usr/bin/sudo", "-E", "--", "/usr/sbin/chown", "-R", "--", "fake_user:staff", fake_pathname] - ) - staged.set_ownership(fake_pathname.to_s) - end - - it "can set the ownership of multiple files" do - staged.stubs(current_user: "fake_user") - fake_pathname = fake_pathname_exists - staged.stubs(Pathname: fake_pathname) - - Hbc::FakeSystemCommand.expects_command( - ["/usr/bin/sudo", "-E", "--", "/usr/sbin/chown", "-R", "--", "fake_user:staff", fake_pathname, fake_pathname] - ) - staged.set_ownership([fake_pathname.to_s, fake_pathname.to_s]) - end - - it "can set the ownership of a file with a different user and group" do - fake_pathname = fake_pathname_exists - staged.stubs(Pathname: fake_pathname) - - Hbc::FakeSystemCommand.expects_command( - ["/usr/bin/sudo", "-E", "--", "/usr/sbin/chown", "-R", "--", "other_user:other_group", fake_pathname] - ) - staged.set_ownership(fake_pathname.to_s, user: "other_user", group: "other_group") - end - - it "cannot set the ownership of a file that does not exist" do - staged.stubs(current_user: "fake_user") - fake_pathname = fake_pathname_does_not_exist - staged.stubs(Pathname: fake_pathname) - staged.set_ownership(fake_pathname.to_s) - end -end diff --git a/Library/Homebrew/cask/test/syntax_test.rb b/Library/Homebrew/cask/test/syntax_test.rb deleted file mode 100644 index 0ea832bde..000000000 --- a/Library/Homebrew/cask/test/syntax_test.rb +++ /dev/null @@ -1,17 +0,0 @@ -require "test_helper" - -describe "Syntax check" do - project_root = Pathname.new(File.expand_path("#{File.dirname(__FILE__)}/../")) - backend_files = Dir[project_root.join("**", "*.rb")].reject { |f| f.match %r{/vendor/|/Casks/} } - interpreter = RUBY_PATH - flags = %w[-c] - flags.unshift "--disable-all" - backend_files.each do |file| - it "#{file} is valid Ruby" do - args = flags + ["--", file] - shutup do - raise SyntaxError, "#{file} failed syntax check" unless system(interpreter, *args) - end - end - end -end diff --git a/Library/Homebrew/cask/test/test_helper.rb b/Library/Homebrew/cask/test/test_helper.rb deleted file mode 100644 index 275ede304..000000000 --- a/Library/Homebrew/cask/test/test_helper.rb +++ /dev/null @@ -1,110 +0,0 @@ -require "bundler" -require "bundler/setup" -require "pathname" - -require "simplecov" if ENV["HOMEBREW_TESTS_COVERAGE"] - -# add Homebrew to load path -$LOAD_PATH.unshift(File.expand_path("#{ENV["HOMEBREW_REPOSITORY"]}/Library/Homebrew")) -$LOAD_PATH.unshift(File.expand_path("#{ENV["HOMEBREW_REPOSITORY"]}/Library/Homebrew/test/support/lib")) - -require "global" - -# add Homebrew-Cask to load path -$LOAD_PATH.push(HOMEBREW_LIBRARY_PATH.join("cask", "lib").to_s) - -require "test/support/helper/env" -require "test/support/helper/shutup" -include Test::Helper::Env -include Test::Helper::Shutup - -def sudo(*args) - %w[/usr/bin/sudo -E --] + args.flatten -end - -# must be called after testing_env so at_exit hooks are in proper order -require "minitest/autorun" -require "minitest/reporters" -Minitest::Reporters.use! Minitest::Reporters::DefaultReporter.new(color: true) - -require "parallel_tests/test/runtime_logger" - -# Force mocha to patch MiniTest since we have both loaded thanks to homebrew's testing_env -require "mocha/api" -require "mocha/integration/mini_test" -Mocha::Integration::MiniTest.activate - -# our baby -require "hbc" - -module Hbc - class TestCask < Cask; end -end - -# create and override default directories -Hbc.appdir = Pathname.new(TEST_TMPDIR).join("Applications").tap(&:mkpath) -Hbc.cache.mkpath -Hbc.caskroom = Hbc.default_caskroom.tap(&:mkpath) -Hbc.default_tap = Tap.fetch("caskroom", "test").tap do |tap| - # link test casks - FileUtils.mkdir_p tap.path.dirname - FileUtils.ln_s Pathname.new(__FILE__).dirname.join("support"), tap.path -end - -# pretend that the caskroom/cask Tap is installed -FileUtils.ln_s Pathname.new(ENV["HOMEBREW_LIBRARY"]).join("Taps", "caskroom", "homebrew-cask"), Tap.fetch("caskroom", "cask").path - -class TestHelper - # helpers for test Casks to reference local files easily - def self.local_binary_path(name) - File.expand_path(File.join(File.dirname(__FILE__), "support", "binaries", name)) - end - - def self.local_binary_url(name) - "file://" + local_binary_path(name) - end - - def self.valid_alias?(candidate) - return false unless candidate.symlink? - candidate.readlink.exist? - end - - def self.install_without_artifacts(cask) - Hbc::Installer.new(cask).tap do |i| - shutup do - i.download - i.extract_primary_container - end - end - end - - def self.install_with_caskfile(cask) - Hbc::Installer.new(cask).tap do |i| - shutup do - i.save_caskfile - end - end - end - - def self.install_without_artifacts_with_caskfile(cask) - Hbc::Installer.new(cask).tap do |i| - shutup do - i.download - i.extract_primary_container - i.save_caskfile - end - end - end -end - -# Extend MiniTest API with support for RSpec-style shared examples -require "support/shared_examples" -require "support/shared_examples/dsl_base.rb" -require "support/shared_examples/staged.rb" - -require "support/fake_dirs" -require "support/fake_system_command" -require "support/cleanup" -require "support/never_sudo_system_command" -require "tmpdir" -require "tempfile" diff --git a/Library/Homebrew/caveats.rb b/Library/Homebrew/caveats.rb index d1dda9d4c..f5543cf49 100644 --- a/Library/Homebrew/caveats.rb +++ b/Library/Homebrew/caveats.rb @@ -47,21 +47,24 @@ class Caveats return unless f.keg_only? s = "This formula is keg-only, which means it was not symlinked into #{HOMEBREW_PREFIX}." - s << "\n\n#{f.keg_only_reason}" - if f.lib.directory? || f.include.directory? - s << - <<-EOS.undent_________________________________________________________72 - - - Generally there are no consequences of this for you. If you build your - own software and it requires this formula, you'll need to add to your - build variables: + s << "\n\n#{f.keg_only_reason}\n" + if f.bin.directory? || f.sbin.directory? + s << "\nIf you need to have this software first in your PATH run:\n" + if f.bin.directory? + s << " #{Utils::Shell.prepend_path_in_shell_profile(f.opt_bin.to_s)}\n" + end + if f.sbin.directory? + s << " #{Utils::Shell.prepend_path_in_shell_profile(f.opt_sbin.to_s)}\n" + end + end - EOS + if f.lib.directory? || f.include.directory? + s << "\nFor compilers to find this software you may need to set:\n" s << " LDFLAGS: -L#{f.opt_lib}\n" if f.lib.directory? s << " CPPFLAGS: -I#{f.opt_include}\n" if f.include.directory? - - if which("pkg-config") + if which("pkg-config") && + ((f.lib/"pkgconfig").directory? || (f.share/"pkgconfig").directory?) + s << "For pkg-config to find this software you may need to set:\n" s << " PKG_CONFIG_PATH: #{f.opt_lib}/pkgconfig\n" if (f.lib/"pkgconfig").directory? s << " PKG_CONFIG_PATH: #{f.opt_share}/pkgconfig\n" if (f.share/"pkgconfig").directory? end diff --git a/Library/Homebrew/cmd/--prefix.rb b/Library/Homebrew/cmd/--prefix.rb index f6e7d2ee2..956ab0403 100644 --- a/Library/Homebrew/cmd/--prefix.rb +++ b/Library/Homebrew/cmd/--prefix.rb @@ -11,7 +11,9 @@ module Homebrew if ARGV.named.empty? puts HOMEBREW_PREFIX else - puts ARGV.resolved_formulae.map(&:installed_prefix) + puts ARGV.resolved_formulae.map { |f| + f.opt_prefix.exist? ? f.opt_prefix : f.installed_prefix + } end end end diff --git a/Library/Homebrew/cmd/cleanup.rb b/Library/Homebrew/cmd/cleanup.rb index 5b46e0872..126309579 100644 --- a/Library/Homebrew/cmd/cleanup.rb +++ b/Library/Homebrew/cmd/cleanup.rb @@ -7,7 +7,7 @@ #: If `--dry-run` or `-n` is passed, show what would be removed, but do not #: actually remove anything. #: -#: If `-s` is passed, scrubs the cache, removing downloads for even the latest +#: If `-s` is passed, scrub the cache, removing downloads for even the latest #: versions of formulae. Note downloads for any installed formulae will still not be #: deleted. If you want to delete those too: `rm -rf $(brew --cache)` diff --git a/Library/Homebrew/cmd/deps.rb b/Library/Homebrew/cmd/deps.rb index 205cbe172..f80bdfb0d 100644 --- a/Library/Homebrew/cmd/deps.rb +++ b/Library/Homebrew/cmd/deps.rb @@ -50,7 +50,7 @@ module Homebrew tree?: ARGV.include?("--tree"), all?: ARGV.include?("--all"), topo_order?: ARGV.include?("-n"), - union?: ARGV.include?("--union") + union?: ARGV.include?("--union"), ) if mode.installed? && mode.tree? diff --git a/Library/Homebrew/cmd/desc.rb b/Library/Homebrew/cmd/desc.rb index 3ef02288b..53291602e 100644 --- a/Library/Homebrew/cmd/desc.rb +++ b/Library/Homebrew/cmd/desc.rb @@ -1,11 +1,10 @@ #: * `desc` <formula>: #: Display <formula>'s name and one-line description. #: -#: * `desc` [`-s`|`-n`|`-d`] <pattern>: +#: * `desc` [`-s`|`-n`|`-d`] (<text>|`/`<text>`/`): #: Search both name and description (`-s`), just the names (`-n`), or just the -#: descriptions (`-d`) for `<pattern>`. `<pattern>` is by default interpreted -#: as a literal string; if flanked by slashes, it is instead interpreted as a -#: regular expression. Formula descriptions are cached; the cache is created on +#: descriptions (`-d`) for <text>. If <text> is flanked by slashes, it is interpreted +#: as a regular expression. Formula descriptions are cached; the cache is created on #: the first search, making that search slower than subsequent ones. require "descriptions" diff --git a/Library/Homebrew/cmd/info.rb b/Library/Homebrew/cmd/info.rb index 1850ae003..b06d99466 100644 --- a/Library/Homebrew/cmd/info.rb +++ b/Library/Homebrew/cmd/info.rb @@ -4,7 +4,7 @@ #: * `info` `--github` <formula>: #: Open a browser to the GitHub History page for formula <formula>. #: -#: To view formula history locally: `brew log -p <formula>`. +#: To view formula history locally: `brew log -p <formula>` #: #: * `info` `--json=`<version> (`--all`|`--installed`|<formulae>): #: Print a JSON representation of <formulae>. Currently the only accepted value @@ -13,7 +13,7 @@ #: Pass `--all` to get information on all formulae, or `--installed` to get #: information on all installed formulae. #: -#: See the docs for examples of using the JSON: +#: See the docs for examples of using the JSON output: #: <http://docs.brew.sh/Querying-Brew.html> require "blacklist" diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb index fbfe46e71..5a3aeb7b3 100644 --- a/Library/Homebrew/cmd/install.rb +++ b/Library/Homebrew/cmd/install.rb @@ -184,6 +184,14 @@ module Homebrew # FormulaInstaller will handle this case. formulae << f end + + # Even if we don't install this formula mark it as no longer just + # installed as a dependency. + next unless f.opt_prefix.directory? + keg = Keg.new(f.opt_prefix.resolved_path) + tab = Tab.for_keg(keg) + tab.installed_on_request = true + tab.write end perform_preinstall_checks diff --git a/Library/Homebrew/cmd/irb.rb b/Library/Homebrew/cmd/irb.rb index d162e3f4a..5561845e7 100644 --- a/Library/Homebrew/cmd/irb.rb +++ b/Library/Homebrew/cmd/irb.rb @@ -12,6 +12,7 @@ class Symbol Formulary.factory(to_s, *args) end end + class String def f(*args) Formulary.factory(self, *args) diff --git a/Library/Homebrew/cmd/log.rb b/Library/Homebrew/cmd/log.rb index 81f972b02..22a3ee11d 100644 --- a/Library/Homebrew/cmd/log.rb +++ b/Library/Homebrew/cmd/log.rb @@ -26,7 +26,7 @@ module Homebrew EOS end args = ARGV.options_only - args += ["--", path] unless path.nil? + args += ["--follow", "--", path] unless path.nil? exec "git", "log", *args end end diff --git a/Library/Homebrew/cmd/outdated.rb b/Library/Homebrew/cmd/outdated.rb index 9ed7a0f79..a18f4e399 100644 --- a/Library/Homebrew/cmd/outdated.rb +++ b/Library/Homebrew/cmd/outdated.rb @@ -1,4 +1,4 @@ -#: * `outdated` [`--quiet`|`--verbose`|`--json=v1`] [`--fetch-HEAD`]: +#: * `outdated` [`--quiet`|`--verbose`|`--json=`<version>] [`--fetch-HEAD`]: #: Show formulae that have an updated version available. #: #: By default, version information is displayed in interactive shells, and diff --git a/Library/Homebrew/cmd/readall.rb b/Library/Homebrew/cmd/readall.rb index 7c1a085c9..3591e0c09 100644 --- a/Library/Homebrew/cmd/readall.rb +++ b/Library/Homebrew/cmd/readall.rb @@ -4,7 +4,7 @@ #: #: This can be useful for debugging issues across all formulae #: when making significant changes to `formula.rb`, -#: or to determine if any current formulae have Ruby issues +#: or to determine if any current formulae have Ruby issues. require "readall" diff --git a/Library/Homebrew/cmd/reinstall.rb b/Library/Homebrew/cmd/reinstall.rb index 2eb2840a5..586405909 100644 --- a/Library/Homebrew/cmd/reinstall.rb +++ b/Library/Homebrew/cmd/reinstall.rb @@ -25,19 +25,21 @@ module Homebrew backup keg end - options = BuildOptions.new(Options.create(ARGV.flags_only), f.options).used_options + build_options = BuildOptions.new(Options.create(ARGV.flags_only), f.options) + options = build_options.used_options options |= f.build.used_options options &= f.options fi = FormulaInstaller.new(f) - fi.options = options - fi.build_bottle = ARGV.build_bottle? || (!f.bottled? && f.build.build_bottle?) - fi.build_from_source = ARGV.build_from_source? || ARGV.build_all_from_source? - fi.force_bottle = ARGV.force_bottle? - fi.interactive = ARGV.interactive? - fi.git = ARGV.git? - fi.verbose = ARGV.verbose? - fi.debug = ARGV.debug? + fi.options = options + fi.invalid_option_names = build_options.invalid_option_names + fi.build_bottle = ARGV.build_bottle? || (!f.bottled? && f.build.build_bottle?) + fi.build_from_source = ARGV.build_from_source? || ARGV.build_all_from_source? + fi.force_bottle = ARGV.force_bottle? + fi.interactive = ARGV.interactive? + fi.git = ARGV.git? + fi.verbose = ARGV.verbose? + fi.debug = ARGV.debug? fi.prelude oh1 "Reinstalling #{f.full_name} #{options.to_a.join " "}" diff --git a/Library/Homebrew/cmd/search.rb b/Library/Homebrew/cmd/search.rb index d69164eb9..e834a00b5 100644 --- a/Library/Homebrew/cmd/search.rb +++ b/Library/Homebrew/cmd/search.rb @@ -2,7 +2,7 @@ #: Display all locally available formulae for brewing (including tapped ones). #: No online search is performed if called without arguments. #: -#: * `search` [`--desc`] <text>|`/`<text>`/`: +#: * `search` [`--desc`] (<text>|`/`<text>`/`): #: Perform a substring search of formula names for <text>. If <text> is #: surrounded with slashes, then it is interpreted as a regular expression. #: The search for <text> is extended online to some popular taps. diff --git a/Library/Homebrew/cmd/style.rb b/Library/Homebrew/cmd/style.rb index 9befcf9ac..3d12561c1 100644 --- a/Library/Homebrew/cmd/style.rb +++ b/Library/Homebrew/cmd/style.rb @@ -47,7 +47,7 @@ module Homebrew def check_style_impl(files, output_type, options = {}) fix = options[:fix] - Homebrew.install_gem_setup_path! "rubocop", "0.45.0" + Homebrew.install_gem_setup_path! "rubocop", HOMEBREW_RUBOCOP_VERSION args = %w[ --force-exclusion diff --git a/Library/Homebrew/cmd/tap-info.rb b/Library/Homebrew/cmd/tap-info.rb index b46de30c1..225b70097 100644 --- a/Library/Homebrew/cmd/tap-info.rb +++ b/Library/Homebrew/cmd/tap-info.rb @@ -12,7 +12,7 @@ #: #: Pass `--installed` to get information on installed taps. #: -#: See the docs for examples of using the JSON: +#: See the docs for examples of using the JSON output: #: <http://docs.brew.sh/Querying-Brew.html> require "tap" diff --git a/Library/Homebrew/cmd/unlink.rb b/Library/Homebrew/cmd/unlink.rb index a105f9c56..3f858b2c4 100644 --- a/Library/Homebrew/cmd/unlink.rb +++ b/Library/Homebrew/cmd/unlink.rb @@ -1,7 +1,7 @@ #: * `unlink` [`--dry-run`] <formula>: #: Remove symlinks for <formula> from the Homebrew prefix. This can be useful #: for temporarily disabling a formula: -#: `brew unlink foo && commands && brew link foo`. +#: `brew unlink <formula> && <commands> && brew link <formula>` #: #: If `--dry-run` or `-n` is passed, Homebrew will list all files which would #: be unlinked, but will not actually unlink or delete any files. diff --git a/Library/Homebrew/cmd/unpack.rb b/Library/Homebrew/cmd/unpack.rb index 4e6584e70..60d796d9f 100644 --- a/Library/Homebrew/cmd/unpack.rb +++ b/Library/Homebrew/cmd/unpack.rb @@ -1,7 +1,7 @@ #: * `unpack` [`--git`|`--patch`] [`--destdir=`<path>] <formulae>: #: Unpack the source files for <formulae> into subdirectories of the current #: working directory. If `--destdir=`<path> is given, the subdirectories will -#: be created in the directory named by `<path>` instead. +#: be created in the directory named by <path> instead. #: #: If `--patch` is passed, patches for <formulae> will be applied to the #: unpacked source. diff --git a/Library/Homebrew/cmd/update-report.rb b/Library/Homebrew/cmd/update-report.rb index dcf2891d9..7cc1ce264 100644 --- a/Library/Homebrew/cmd/update-report.rb +++ b/Library/Homebrew/cmd/update-report.rb @@ -475,12 +475,18 @@ class Reporter if new_tap_name == "caskroom/cask" if new_tap.installed? && (HOMEBREW_PREFIX/"Caskroom").directory? ohai "#{name} has been moved to Homebrew-Cask." - ohai "brew uninstall --force #{name}" - system HOMEBREW_BREW_FILE, "uninstall", "--force", name + ohai "brew unlink #{name}" + system HOMEBREW_BREW_FILE, "unlink", name ohai "brew prune" system HOMEBREW_BREW_FILE, "prune" ohai "brew cask install #{new_name}" system HOMEBREW_BREW_FILE, "cask", "install", new_name + ohai <<-EOS.undent + #{name} has been moved to Homebrew-Cask. + The existing keg has been unlinked. + Please uninstall the formula when convenient by running: + brew uninstall --force #{name} + EOS else ohai "#{name} has been moved to Homebrew-Cask.", <<-EOS.undent To uninstall the formula and install the cask run: diff --git a/Library/Homebrew/cmd/update-reset.sh b/Library/Homebrew/cmd/update-reset.sh index 32daffc96..3a9e1caa9 100644 --- a/Library/Homebrew/cmd/update-reset.sh +++ b/Library/Homebrew/cmd/update-reset.sh @@ -37,7 +37,7 @@ EOS echo echo "==> Resetting $DIR..." - git checkout -B master origin/master + git checkout --force -B master origin/master echo done } diff --git a/Library/Homebrew/cmd/update.sh b/Library/Homebrew/cmd/update.sh index 678622230..c5e618403 100644 --- a/Library/Homebrew/cmd/update.sh +++ b/Library/Homebrew/cmd/update.sh @@ -1,6 +1,6 @@ #: * `update` [`--merge`] [`--force`]: #: Fetch the newest version of Homebrew and all formulae from GitHub using -#: `git`(1). +#: `git`(1) and perform any necessary migrations. #: #: If `--merge` is specified then `git merge` is used to include updates #: (rather than `git rebase`). diff --git a/Library/Homebrew/cmd/upgrade.rb b/Library/Homebrew/cmd/upgrade.rb index 5b49a9f65..ce892f85c 100644 --- a/Library/Homebrew/cmd/upgrade.rb +++ b/Library/Homebrew/cmd/upgrade.rb @@ -94,14 +94,24 @@ module Homebrew .select(&:directory?) .map { |k| Keg.new(k.resolved_path) } + if f.opt_prefix.directory? + keg = Keg.new(f.opt_prefix.resolved_path) + tab = Tab.for_keg(keg) + end + fi = FormulaInstaller.new(f) - fi.options = f.build.used_options - fi.options &= f.options - fi.build_bottle = ARGV.build_bottle? || (!f.bottled? && f.build.build_bottle?) - fi.build_from_source = ARGV.build_from_source? || ARGV.build_all_from_source? - fi.verbose = ARGV.verbose? - fi.quieter = ARGV.quieter? - fi.debug = ARGV.debug? + fi.options = f.build.used_options + fi.options &= f.options + fi.build_bottle = ARGV.build_bottle? || (!f.bottled? && f.build.build_bottle?) + fi.build_from_source = ARGV.build_from_source? || ARGV.build_all_from_source? + fi.verbose = ARGV.verbose? + fi.quieter = ARGV.quieter? + fi.debug = ARGV.debug? + fi.installed_on_request = !ARGV.named.empty? + if tab + fi.installed_as_dependency = tab.installed_as_dependency + fi.installed_on_request ||= tab.installed_on_request + end fi.prelude oh1 "Upgrading #{f.full_specified_name} #{fi.options.to_a.join " "}" diff --git a/Library/Homebrew/cmd/uses.rb b/Library/Homebrew/cmd/uses.rb index fb11a31a7..b1122c90a 100644 --- a/Library/Homebrew/cmd/uses.rb +++ b/Library/Homebrew/cmd/uses.rb @@ -12,8 +12,8 @@ #: `--include-build`. Similarly, pass `--include-optional` to include `:optional` #: dependencies. To skip `:recommended` type dependencies, pass `--skip-recommended`. #: -#: By default, `uses` shows usages of `formula` by stable builds. To find -#: cases where `formula` is used by development or HEAD build, pass +#: By default, `uses` shows usages of <formulae> by stable builds. To find +#: cases where <formulae> is used by development or HEAD build, pass #: `--devel` or `--HEAD`. require "formula" @@ -57,16 +57,36 @@ module Homebrew 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 + + dep_formulae = deps.map do |dep| + begin + dep.to_formula + rescue + end + end.compact + + reqs_by_formula = ([f] + dep_formulae).flat_map do |formula| + formula.requirements.map { |req| [formula, req] } end - reqs = f.recursive_requirements do |dependent, req| + + reqs_by_formula.reject! do |dependent, req| if req.recommended? - Requirement.prune if ignores.include?("recommended?") || dependent.build.without?(req) + ignores.include?("recommended?") || dependent.build.without?(req) elsif req.optional? - Requirement.prune if !includes.include?("optional?") && !dependent.build.with?(req) + !includes.include?("optional?") && !dependent.build.with?(req) elsif req.build? - Requirement.prune unless includes.include?("build?") + !includes.include?("build?") end end + + reqs = reqs_by_formula.map(&:last) else deps = f.deps.reject do |dep| ignores.any? { |ignore| dep.send(ignore) } && !includes.any? { |include| dep.send(include) } diff --git a/Library/Homebrew/compat/hbc/cask_loader.rb b/Library/Homebrew/compat/hbc/cask_loader.rb index e7f3a4aac..a7c84e3ce 100644 --- a/Library/Homebrew/compat/hbc/cask_loader.rb +++ b/Library/Homebrew/compat/hbc/cask_loader.rb @@ -1,7 +1,7 @@ module CaskLoaderCompatibilityLayer private - def build_cask(header_token, &block) + def cask(header_token, &block) if header_token.is_a?(Hash) && header_token.key?(:v1) odeprecated %q("cask :v1 => 'token'"), %q("cask 'token'") header_token = header_token[:v1] diff --git a/Library/Homebrew/compilers.rb b/Library/Homebrew/compilers.rb index 628e71e9b..36e50a177 100644 --- a/Library/Homebrew/compilers.rb +++ b/Library/Homebrew/compilers.rb @@ -75,6 +75,17 @@ class CompilerFailure create(gcc: "4.5"), create(gcc: "4.6"), ], + cxx14: [ + create(:clang) { build 600 }, + create(:gcc_4_0), + create(:gcc_4_2), + create(gcc: "4.3"), + create(gcc: "4.4"), + create(gcc: "4.5"), + create(gcc: "4.6"), + create(gcc: "4.7"), + create(gcc: "4.8"), + ], openmp: [ create(:clang), ], diff --git a/Library/Homebrew/config.rb b/Library/Homebrew/config.rb index 38d7c8043..30b7bc6c9 100644 --- a/Library/Homebrew/config.rb +++ b/Library/Homebrew/config.rb @@ -2,6 +2,8 @@ unless ENV["HOMEBREW_BREW_FILE"] raise "HOMEBREW_BREW_FILE was not exported! Please call bin/brew directly!" end +require "constants" + # Path to `bin/brew` main executable in HOMEBREW_PREFIX HOMEBREW_BREW_FILE = Pathname.new(ENV["HOMEBREW_BREW_FILE"]) diff --git a/Library/Homebrew/constants.rb b/Library/Homebrew/constants.rb new file mode 100644 index 000000000..660cad7a3 --- /dev/null +++ b/Library/Homebrew/constants.rb @@ -0,0 +1,3 @@ +# RuboCop version used for `brew style` and `brew cask style` +HOMEBREW_RUBOCOP_VERSION = "0.47.1".freeze +HOMEBREW_RUBOCOP_CASK_VERSION = "~> 0.11.0".freeze # has to be updated when RuboCop version changes diff --git a/Library/Homebrew/dependency.rb b/Library/Homebrew/dependency.rb index 253ba4bee..4a452440a 100644 --- a/Library/Homebrew/dependency.rb +++ b/Library/Homebrew/dependency.rb @@ -175,7 +175,7 @@ class TapDependency < Dependency attr_reader :tap def initialize(name, tags = [], env_proc = DEFAULT_ENV_PROC, option_names = [name.split("/").last]) - @tap = name.rpartition("/").first + @tap = Tap.fetch(name.rpartition("/").first) super(name, tags, env_proc, option_names) end diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index 88d9a535c..35d590b69 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -1,4 +1,4 @@ -#: * `audit` [`--strict`] [`--online`] [`--new-formula`] [`--display-cop-names`] [`--display-filename`] [<formulae>]: +#: * `audit` [`--strict`] [`--fix`] [`--online`] [`--new-formula`] [`--display-cop-names`] [`--display-filename`] [<formulae>]: #: Check <formulae> for Homebrew coding style violations. This should be #: run before submitting a new formula. #: @@ -7,6 +7,9 @@ #: If `--strict` is passed, additional checks are run, including RuboCop #: style checks. #: +#: If `--fix` is passed, style violations will be +#: automatically fixed using RuboCop's `--auto-correct` feature. +#: #: If `--online` is passed, additional slower checks that require a network #: connection are run. #: @@ -36,6 +39,7 @@ require "cmd/search" require "cmd/style" require "date" require "blacklist" +require "digest" module Homebrew module_function @@ -62,8 +66,9 @@ module Homebrew end if strict + options = { fix: ARGV.flag?("--fix"), realpath: true } # Check style in a single batch run up front for performance - style_results = check_style_json(files, realpath: true) + style_results = check_style_json(files, options) end ff.each do |f| @@ -169,31 +174,64 @@ class FormulaAuditor @specs = %w[stable devel head].map { |s| formula.send(s) }.compact end - def url_status_code(url, range: false, user_agent: :default) - # The system Curl is too old and unreliable with HTTPS homepages on - # Yosemite and below. - return "200" unless DevelopmentTools.curl_handles_most_https_homepages? + def self.check_http_content(url, user_agents: [:default]) + return unless url.start_with? "http" - extra_args = [ - "--connect-timeout", "15", - "--output", "/dev/null", - "--write-out", "%{http_code}" - ] - extra_args << "--range" << "0-0" if range - extra_args << url + details = nil + user_agent = nil + user_agents.each do |ua| + details = http_content_headers_and_checksum(url, user_agent: ua) + user_agent = ua + break if details[:status].to_s.start_with?("2") + end + + return "The URL #{url} is not reachable" unless details[:status] + unless details[:status].start_with? "2" + return "The URL #{url} is not reachable (HTTP status code #{details[:status]})" + end + + return unless url.start_with? "http:" + + secure_url = url.sub "http", "https" + secure_details = + http_content_headers_and_checksum(secure_url, user_agent: user_agent) + + if !details[:status].to_s.start_with?("2") || + !secure_details[:status].to_s.start_with?("2") + return + end + + etag_match = details[:etag] && + details[:etag] == secure_details[:etag] + content_length_match = + details[:content_length] && + details[:content_length] == secure_details[:content_length] + file_match = details[:file_hash] == secure_details[:file_hash] + + return if !etag_match && !content_length_match && !file_match + "The URL #{url} could use HTTPS rather than HTTP" + end + def self.http_content_headers_and_checksum(url, user_agent: :default) args = curl_args( - extra_args: extra_args, + extra_args: ["--connect-timeout", "15", "--include", url], show_output: true, - user_agent: user_agent + user_agent: user_agent, ) - retries = 3 - status_code = nil - retries.times do - status_code = Open3.popen3(*args) { |_, stdout, _, _| stdout.read } - break if status_code.start_with? "20" + output = Open3.popen3(*args) { |_, stdout, _, _| stdout.read } + + status_code = :unknown + while status_code == :unknown || status_code.to_s.start_with?("3") + headers, _, output = output.partition("\r\n\r\n") + status_code = headers[%r{HTTP\/.* (\d+)}, 1] end - status_code + + { + status: status_code, + etag: headers[%r{ETag: ([wW]\/)?"(([^"]|\\")*)"}, 2], + content_length: headers[/Content-Length: (\d+)/, 1], + file_hash: Digest::SHA256.digest(output), + } end def audit_style @@ -291,6 +329,27 @@ class FormulaAuditor problem "File should end with a newline" unless text.trailing_newline? + versioned_formulae = Dir[formula.path.to_s.gsub(/\.rb$/, "@*.rb")] + needs_versioned_alias = !versioned_formulae.empty? && + formula.tap && + formula.aliases.grep(/.@\d/).empty? + if needs_versioned_alias + _, last_alias_version = File.basename(versioned_formulae.sort.reverse.first) + .gsub(/\.rb$/, "") + .split("@") + major, minor, = formula.version.to_s.split(".") + alias_name = if last_alias_version.split(".").length == 1 + "#{formula.name}@#{major}" + else + "#{formula.name}@#{major}.#{minor}" + end + problem <<-EOS.undent + Formula has other versions so create an alias: + cd #{formula.tap.alias_dir} + ln -s #{formula.path.to_s.gsub(formula.tap.path, "..")} #{alias_name} + EOS + end + return unless @strict present = audit_components @@ -406,7 +465,8 @@ class FormulaAuditor problem "Dependency '#{dep.name}' was renamed; use new name '#{dep_f.name}'." end - if @@aliases.include?(dep.name) + if @@aliases.include?(dep.name) && + (core_formula? || !dep_f.versioned_formula?) problem "Dependency '#{dep.name}' is an alias; use the canonical name '#{dep.to_formula.full_name}'." end @@ -459,6 +519,14 @@ class FormulaAuditor end def audit_conflicts + if formula.conflicts.any? && formula.versioned_formula? + problem <<-EOS + Versioned formulae should not use `conflicts_with`. + Use `keg_only :versioned_formula` instead. + EOS + return + end + formula.conflicts.each do |c| begin Formulary.factory(c.name) @@ -481,6 +549,10 @@ class FormulaAuditor next unless @strict + if o.name == "universal" && !Formula["wine"].recursive_dependencies.map(&:name).include?(formula.name) + problem "macOS has been 64-bit only since 10.6 so universal options are deprecated." + end + if o.name !~ /with(out)?-/ && o.name != "c++11" && o.name != "universal" problem "Options should begin with with/without. Migrate '--#{o.name}' with `deprecated_option`." end @@ -493,7 +565,7 @@ class FormulaAuditor return unless @new_formula return if formula.deprecated_options.empty? - return if formula.name.include?("@") + return if formula.versioned_formula? problem "New formulae should not use `deprecated_option`." end @@ -569,10 +641,16 @@ class FormulaAuditor # People will run into mixed content sometimes, but we should enforce and then add # exemptions as they are discovered. Treat mixed content on homepages as a bug. # Justify each exemptions with a code comment so we can keep track here. - if homepage =~ %r{^http://[^/]*github\.io/} + case homepage + when %r{^http://[^/]*\.github\.io/}, + %r{^http://[^/]*\.sourceforge\.io/} problem "Please use https:// for #{homepage}" end + if homepage =~ %r{^http://([^/]*)\.(sf|sourceforge)\.net(/|$)} + problem "#{homepage} should be `https://#{$1}.sourceforge.io/`" + end + # There's an auto-redirect here, but this mistake is incredibly common too. # Only applies to the homepage and subdomains for now, not the FTP URLs. if homepage =~ %r{^http://((?:build|cloud|developer|download|extensions|git|glade|help|library|live|nagios|news|people|projects|rt|static|wiki|www)\.)?gnome\.org} @@ -597,9 +675,13 @@ class FormulaAuditor return unless @online - status_code = url_status_code(homepage, user_agent: :browser) - return if status_code.start_with? "20" - problem "The homepage #{homepage} is not reachable (HTTP status code #{status_code})" + # The system Curl is too old and unreliable with HTTPS homepages on + # Yosemite and below. + return unless DevelopmentTools.curl_handles_most_https_homepages? + if http_content_problem = FormulaAuditor.check_http_content(homepage, + user_agents: [:browser, :default]) + problem http_content_problem + end end def audit_bottle_spec @@ -649,11 +731,11 @@ class FormulaAuditor %w[Stable Devel HEAD].each do |name| next unless spec = formula.send(name.downcase) - ra = ResourceAuditor.new(spec).audit + ra = ResourceAuditor.new(spec, online: @online, strict: @strict).audit problems.concat ra.problems.map { |problem| "#{name}: #{problem}" } spec.resources.each_value do |resource| - ra = ResourceAuditor.new(resource).audit + ra = ResourceAuditor.new(resource, online: @online, strict: @strict).audit problems.concat ra.problems.map { |problem| "#{name} resource #{resource.name.inspect}: #{problem}" } @@ -680,6 +762,7 @@ class FormulaAuditor unstable_whitelist = %w[ aalib 1.4rc5 + angolmois 2.0.0alpha2 automysqlbackup 3.0-rc6 aview 1.3.0rc1 distcc 3.2rc1 @@ -687,6 +770,8 @@ class FormulaAuditor ftgl 2.1.3-rc5 hidapi 0.8.0-rc1 libcaca 0.99b19 + nethack4 4.3.0-beta2 + opensyobon 1.0rc2 premake 4.4-beta5 pwnat 0.3-beta pxz 4.999.9 @@ -839,7 +924,7 @@ class FormulaAuditor end end - if text =~ /xcodebuild[ (]["'*]/ && !text.include?("SYMROOT=") + if text =~ /xcodebuild[ (]*["'*]*/ && !text.include?("SYMROOT=") problem 'xcodebuild should be passed an explicit "SYMROOT"' end @@ -1200,7 +1285,7 @@ class ResourceAuditor attr_reader :problems attr_reader :version, :checksum, :using, :specs, :url, :mirrors, :name - def initialize(resource) + def initialize(resource, options = {}) @name = resource.name @version = resource.version @checksum = resource.checksum @@ -1208,6 +1293,8 @@ class ResourceAuditor @mirrors = resource.mirrors @using = resource.using @specs = resource.specs + @online = options[:online] + @strict = options[:strict] @problems = [] end @@ -1332,6 +1419,7 @@ class ResourceAuditor %r{^http://(?:[^/]*\.)?bintray\.com/}, %r{^http://tools\.ietf\.org/}, %r{^http://launchpad\.net/}, + %r{^http://github\.com/}, %r{^http://bitbucket\.org/}, %r{^http://anonscm\.debian\.org/}, %r{^http://cpan\.metacpan\.org/}, @@ -1463,6 +1551,26 @@ class ResourceAuditor next unless u =~ %r{https?://(?:central|repo\d+)\.maven\.org/maven2/(.+)$} problem "#{u} should be `https://search.maven.org/remotecontent?filepath=#{$1}`" end + + return unless @online + urls.each do |url| + next if !@strict && mirrors.include?(url) + + strategy = DownloadStrategyDetector.detect(url, using) + if strategy <= CurlDownloadStrategy && !url.start_with?("file") + if http_content_problem = FormulaAuditor.check_http_content(url) + problem http_content_problem + end + elsif strategy <= GitDownloadStrategy + unless Utils.git_remote_exists url + problem "The URL #{url} is not a valid git URL" + end + elsif strategy <= SubversionDownloadStrategy + unless Utils.svn_remote_exists url + problem "The URL #{url} is not a valid svn URL" + end + end + end end def problem(text) diff --git a/Library/Homebrew/dev-cmd/boneyard-formula-pr.rb b/Library/Homebrew/dev-cmd/boneyard-formula-pr.rb index 3066d2ee6..7531ef9cf 100644 --- a/Library/Homebrew/dev-cmd/boneyard-formula-pr.rb +++ b/Library/Homebrew/dev-cmd/boneyard-formula-pr.rb @@ -1,5 +1,5 @@ #: @hide_from_man_page -#: * `boneyard-formula-pr` [`--dry-run`] [`--local`] [`--reason=<reason>`] <formula-name> : +#: * `boneyard-formula-pr` [`--dry-run`] [`--local`] [`--reason=<reason>`] <formula> : #: Creates a pull request to boneyard a formula. #: #: If `--dry-run` is passed, print what would be done rather than doing it. diff --git a/Library/Homebrew/dev-cmd/bottle.rb b/Library/Homebrew/dev-cmd/bottle.rb index 9618cf412..91bdcba93 100644 --- a/Library/Homebrew/dev-cmd/bottle.rb +++ b/Library/Homebrew/dev-cmd/bottle.rb @@ -1,6 +1,5 @@ -#: * `bottle` [`--verbose`] [`--no-rebuild`] [`--keep-old`] [`--skip-relocation`] [`--root-url=<root_url>`] [`--force-core-tap`]: +#: * `bottle` [`--verbose`] [`--no-rebuild`] [`--keep-old`] [`--skip-relocation`] [`--root-url=`<URL>] [`--force-core-tap`]: #: * `bottle` `--merge` [`--no-commit`] [`--keep-old`] [`--write`]: -#: #: Generate a bottle (binary package) from a formula installed with #: `--build-bottle`. @@ -435,6 +434,7 @@ module Homebrew else string = s.sub!( /( + (\ {2}\#[^\n]*\n)* # comments \ {2}( # two spaces at the beginning (url|head)\ ['"][\S\ ]+['"] # url or head with a string ( @@ -442,7 +442,7 @@ module Homebrew (\n^\ {3}[\S\ ]+$)* # options can be in multiple lines )?| (homepage|desc|sha1|sha256|version|mirror)\ ['"][\S\ ]+['"]| # specs with a string - rebuild\ \d+ # rebuild with a number + revision\ \d+ # revision with a number )\n+ # multiple empty lines )+ /mx, '\0' + output + "\n" diff --git a/Library/Homebrew/dev-cmd/bump-formula-pr.rb b/Library/Homebrew/dev-cmd/bump-formula-pr.rb index 68bf32d0b..6c7b7d5b5 100644 --- a/Library/Homebrew/dev-cmd/bump-formula-pr.rb +++ b/Library/Homebrew/dev-cmd/bump-formula-pr.rb @@ -1,8 +1,7 @@ -#: * `bump-formula-pr` [`--devel`] [`--dry-run`] [`--audit`|`--strict`] [`--message=`<message>] `--url=`<url> `--sha256=`<sha-256> <formula>: -#: * `bump-formula-pr` [`--devel`] [`--dry-run`] [`--audit`|`--strict`] [`--message=`<message>] `--tag=`<tag> `--revision=`<revision> <formula>: -#: Creates a pull request to update the formula with a new url or a new tag. +#: * `bump-formula-pr` [`--devel`] [`--dry-run` [`--write`]] [`--audit`|`--strict`] [`--mirror=`<URL>] [`--version=`<version>] [`--message=`<message>] (`--url=`<URL> `--sha256=`<sha-256>|`--tag=`<tag> `--revision=`<revision>) <formula>: +#: Creates a pull request to update the formula with a new URL or a new tag. #: -#: If a <url> is specified, the <sha-256> checksum of the new download must +#: If a <URL> is specified, the <sha-256> checksum of the new download must #: also be specified. A best effort to determine the <sha-256> and <formula> #: name will be made if either or both values are not supplied by the user. #: @@ -21,17 +20,17 @@ #: #: If `--strict` is passed, run `brew audit --strict` before opening the PR. #: -#: If `--mirror=`<url> is passed, use the value as a mirror url. +#: If `--mirror=`<URL> is passed, use the value as a mirror URL. #: #: If `--version=`<version> is passed, use the value to override the value -#: parsed from the url or tag. Note that `--version=0` can be used to delete +#: parsed from the URL or tag. Note that `--version=0` can be used to delete #: an existing `version` override from a formula if it has become redundant. #: #: If `--message=`<message> is passed, append <message> to the default PR #: message. #: #: Note that this command cannot be used to transition a formula from a -#: url-and-sha256 style specification into a tag-and-revision style +#: URL-and-sha256 style specification into a tag-and-revision style #: specification, nor vice versa. It must use whichever style specification #: the preexisting formula already uses. @@ -78,8 +77,44 @@ module Homebrew end end + def fetch_pull_requests(formula) + GitHub.issues_for_formula(formula.name, tap: formula.tap).select do |pr| + pr["html_url"].include?("/pull/") && + /(^|\s)#{Regexp.quote(formula.name)}(:|\s|$)/i =~ pr["title"] + end + rescue GitHub::RateLimitExceededError => e + opoo e.message + [] + end + + def check_for_duplicate_pull_requests(formula) + pull_requests = fetch_pull_requests(formula) + return unless pull_requests && !pull_requests.empty? + duplicates_message = <<-EOS.undent + These open pull requests may be duplicates: + #{pull_requests.map { |pr| "#{pr["title"]} #{pr["html_url"]}" }.join("\n")} + EOS + error_message = "Duplicate PRs should not be opened. Use --force to override this error." + if ARGV.force? && !ARGV.flag?("--quiet") + opoo duplicates_message + elsif !ARGV.force? && ARGV.flag?("--quiet") + odie error_message + elsif !ARGV.force? + odie <<-EOS.undent + #{duplicates_message.chomp} + #{error_message} + EOS + end + end + def bump_formula_pr formula = ARGV.formulae.first + + if formula + check_for_duplicate_pull_requests(formula) + checked_for_duplicates = true + end + new_url = ARGV.value("url") if new_url && !formula is_devel = ARGV.include?("--devel") @@ -101,6 +136,8 @@ module Homebrew end odie "No formula found!" unless formula + check_for_duplicate_pull_requests(formula) unless checked_for_duplicates + requested_spec, formula_spec = if ARGV.include?("--devel") devel_message = " (devel)" [:devel, formula.devel] diff --git a/Library/Homebrew/dev-cmd/create.rb b/Library/Homebrew/dev-cmd/create.rb index 07dd1b322..9c58dc71a 100644 --- a/Library/Homebrew/dev-cmd/create.rb +++ b/Library/Homebrew/dev-cmd/create.rb @@ -3,8 +3,7 @@ #: Homebrew will attempt to automatically derive the formula name #: and version, but if it fails, you'll have to make your own template. The `wget` #: formula serves as a simple example. For the complete API have a look at -#: -#: <http://www.rubydoc.info/github/Homebrew/brew/master/Formula> +#: <http://www.rubydoc.info/github/Homebrew/brew/master/Formula>. #: #: If `--autotools` is passed, create a basic template for an Autotools-style build. #: If `--cmake` is passed, create a basic template for a CMake-style build. @@ -142,12 +141,10 @@ class FormulaCreator def generate! raise "#{path} already exists" if path.exist? - if version.nil? + if version.nil? || version.null? opoo "Version cannot be determined from URL." puts "You'll need to add an explicit 'version' to the formula." - end - - if fetch? && version + elsif fetch? r = Resource.new r.url(url) r.version(version) diff --git a/Library/Homebrew/dev-cmd/formula.rb b/Library/Homebrew/dev-cmd/formula.rb new file mode 100644 index 000000000..67d11edce --- /dev/null +++ b/Library/Homebrew/dev-cmd/formula.rb @@ -0,0 +1,13 @@ +#: * `formula` <formula>: +#: Display the path where <formula> is located. + +require "formula" + +module Homebrew + module_function + + def formula + raise FormulaUnspecifiedError if ARGV.named.empty? + ARGV.resolved_formulae.each { |f| puts f.path } + end +end diff --git a/Library/Homebrew/dev-cmd/linkage.rb b/Library/Homebrew/dev-cmd/linkage.rb index 44e0f224e..e4da827f2 100644 --- a/Library/Homebrew/dev-cmd/linkage.rb +++ b/Library/Homebrew/dev-cmd/linkage.rb @@ -1,4 +1,4 @@ -#: * `linkage` [`--test`] [`--reverse`] <formula-name>: +#: * `linkage` [`--test`] [`--reverse`] <formula>: #: Checks the library links of an installed formula. #: #: Only works on installed formulae. An error is raised if it is run on diff --git a/Library/Homebrew/dev-cmd/man.rb b/Library/Homebrew/dev-cmd/man.rb index 64c970453..581db38ca 100644 --- a/Library/Homebrew/dev-cmd/man.rb +++ b/Library/Homebrew/dev-cmd/man.rb @@ -23,10 +23,10 @@ module Homebrew if ARGV.flag? "--link" odie "`brew man --link` is now done automatically by `brew update`." - else - regenerate_man_pages end + regenerate_man_pages + if system "git", "-C", HOMEBREW_REPOSITORY, "diff", "--quiet", "docs/brew.1.html", "manpages" puts "No changes to manpage output detected." elsif ARGV.include?("--fail-if-changed") diff --git a/Library/Homebrew/dev-cmd/mirror.rb b/Library/Homebrew/dev-cmd/mirror.rb index bd5868726..10811493c 100644 --- a/Library/Homebrew/dev-cmd/mirror.rb +++ b/Library/Homebrew/dev-cmd/mirror.rb @@ -1,5 +1,5 @@ #: @hide_from_man_page -#: * `mirror` [`--test`] <formula-name> [<formula-name> ...]: +#: * `mirror` [`--test`] <formulae>: #: Reuploads the stable URL for a formula to Bintray to use it as a mirror. module Homebrew diff --git a/Library/Homebrew/dev-cmd/pull.rb b/Library/Homebrew/dev-cmd/pull.rb index f7006baaa..98a62e578 100644 --- a/Library/Homebrew/dev-cmd/pull.rb +++ b/Library/Homebrew/dev-cmd/pull.rb @@ -1,33 +1,42 @@ -#: `pull` [`--bottle`] [`--bump`] [`--clean`] [`--ignore-whitespace`] [`--resolve`] [`--branch-okay`] [`--no-pbcopy`] [`--no-publish`] <patch-source> [<patch-source>] -#: +#: * `pull` [`--bottle`] [`--bump`] [`--clean`] [`--ignore-whitespace`] [`--resolve`] [`--branch-okay`] [`--no-pbcopy`] [`--no-publish`] <patch-source> [<patch-source>]: #: Gets a patch from a GitHub commit or pull request and applies it to Homebrew. #: Optionally, installs the formulae changed by the patch. #: #: Each <patch-source> may be one of: -#: * The ID number of a PR (Pull Request) in the homebrew/core GitHub +#: +#: ~ The ID number of a PR (pull request) in the homebrew/core GitHub #: repository -#: * The URL of a PR on GitHub, using either the web page or API URL +#: +#: ~ The URL of a PR on GitHub, using either the web page or API URL #: formats. In this form, the PR may be on Homebrew/brew, #: Homebrew/homebrew-core or any tap. -#: * The URL of a commit on GitHub -#: * A "http://bot.brew.sh/job/..." string specifying a testing job ID #: -#: If `--bottle` was passed, handle bottles, pulling the bottle-update -#: commit and publishing files on Bintray. -#: If `--bump` was passed, for one-formula PRs, automatically reword -#: commit message to our preferred format. -#: If `--clean` was passed, do not rewrite or otherwise modify the -#: commits found in the pulled PR. -#: If `--ignore-whitespace` was passed, silently ignore whitespace -#: discrepancies when applying diffs. -#: If `--resolve` was passed, when a patch fails to apply, leave in -#: progress and allow user to -#: resolve, instead of aborting. -#: If `--branch-okay` was passed, do not warn if pulling to a branch -#: besides master (useful for testing). -#: If `--no-pbcopy` was passed, do not copy anything to the system -# clipboard. -#: If `--no-publish` was passed, do not publish bottles to Bintray. +#: ~ The URL of a commit on GitHub +#: +#: ~ A "http://bot.brew.sh/job/..." string specifying a testing job ID +#: +#: If `--bottle` is passed, handle bottles, pulling the bottle-update +#: commit and publishing files on Bintray. +#: +#: If `--bump` is passed, for one-formula PRs, automatically reword +#: commit message to our preferred format. +#: +#: If `--clean` is passed, do not rewrite or otherwise modify the +#: commits found in the pulled PR. +#: +#: If `--ignore-whitespace` is passed, silently ignore whitespace +#: discrepancies when applying diffs. +#: +#: If `--resolve` is passed, when a patch fails to apply, leave in +#: progress and allow user to resolve, instead of aborting. +#: +#: If `--branch-okay` is passed, do not warn if pulling to a branch +#: besides master (useful for testing). +#: +#: If `--no-pbcopy` is passed, do not copy anything to the system +#: clipboard. +#: +#: If `--no-publish` is passed, do not publish bottles to Bintray. require "net/http" require "net/https" @@ -248,7 +257,6 @@ module Homebrew changed_formulae_names.each do |name| f = Formula[name] next if f.bottle_unneeded? || f.bottle_disabled? - ohai "Publishing on Bintray: #{f.name} #{f.pkg_version}" publish_bottle_file_on_bintray(f, bintray_creds) published << f.full_name end @@ -377,7 +385,7 @@ module Homebrew subject_strs << "remove stable" formula_name_str += ":" # just for cosmetics else - subject_strs << formula.version.to_s + subject_strs << new[:stable] end end if old[:devel] != new[:devel] @@ -388,7 +396,7 @@ module Homebrew formula_name_str += ":" # just for cosmetics end else - subject_strs << "#{formula.devel.version} (devel)" + subject_strs << "#{new[:devel]} (devel)" end end subject = subject_strs.empty? ? nil : "#{formula_name_str} #{subject_strs.join(", ")}" @@ -408,7 +416,12 @@ module Homebrew if info.nil? raise "Failed publishing bottle: failed reading formula info for #{f.full_name}" end + unless info.bottle_info_any + opoo "No bottle defined in formula #{package}" + return + end version = info.pkg_version + ohai "Publishing on Bintray: #{package} #{version}" curl "-w", '\n', "--silent", "--fail", "-u#{creds[:user]}:#{creds[:key]}", "-X", "POST", "-H", "Content-Type: application/json", diff --git a/Library/Homebrew/dev-cmd/release-notes.rb b/Library/Homebrew/dev-cmd/release-notes.rb index 919243764..eb398fcfb 100644 --- a/Library/Homebrew/dev-cmd/release-notes.rb +++ b/Library/Homebrew/dev-cmd/release-notes.rb @@ -1,7 +1,7 @@ -#: * `release-notes` [<previous_tag>] [<end_ref>]: +#: * `release-notes` [`--markdown`] [<previous_tag>] [<end_ref>]: #: Output the merged pull requests on Homebrew/brew between two Git refs. -#: If no `previous_tag` is provided it defaults to the newest tag. -#: If no `end_ref` is provided it defaults to `origin/master`. +#: If no <previous_tag> is provided it defaults to the newest tag. +#: If no <end_ref> is provided it defaults to `origin/master`. #: #: If `--markdown` is passed, output as a Markdown list. diff --git a/Library/Homebrew/dev-cmd/tests.rb b/Library/Homebrew/dev-cmd/tests.rb index b4f3c2d40..0c8621a01 100644 --- a/Library/Homebrew/dev-cmd/tests.rb +++ b/Library/Homebrew/dev-cmd/tests.rb @@ -1,4 +1,4 @@ -#: * `tests` [`-v`] [`--coverage`] [`--generic`] [`--no-compat`] [`--only=`<test_script/test_method>] [`--seed` <seed>] [`--trace`] [`--online`] [`--official-cmd-taps`]: +#: * `tests` [`-v`] [`--coverage`] [`--generic`] [`--no-compat`] [`--only=`<test_script>`:`<test_method>] [`--seed` <seed>] [`--trace`] [`--online`] [`--official-cmd-taps`]: #: Run Homebrew's unit and integration tests. require "fileutils" @@ -7,10 +7,21 @@ require "tap" module Homebrew module_function + def run_tests(executable, files, args = []) + opts = [] + opts << "--serialize-stdout" if ENV["CI"] + + system "bundle", "exec", executable, *opts, "--", *args, "--", *files + + return if $?.success? + Homebrew.failed = true + end + def tests HOMEBREW_LIBRARY_PATH.cd do ENV.delete "HOMEBREW_VERBOSE" ENV.delete "VERBOSE" + ENV.delete("HOMEBREW_CASK_OPTS") ENV["HOMEBREW_NO_ANALYTICS_THIS_RUN"] = "1" ENV["HOMEBREW_DEVELOPER"] = "1" ENV["TESTOPTS"] = "-v" if ARGV.verbose? @@ -34,6 +45,7 @@ module Homebrew %w[AUTHOR COMMITTER].each do |role| ENV["GIT_#{role}_NAME"] = "brew tests" ENV["GIT_#{role}_EMAIL"] = "brew-tests@localhost" + ENV["GIT_#{role}_DATE"] = "Sun Jan 22 19:59:13 2017 +0000" end Homebrew.install_gem_setup_path! "bundler" @@ -44,27 +56,35 @@ module Homebrew # Make it easier to reproduce test runs. ENV["SEED"] = ARGV.next if ARGV.include? "--seed" - files = Dir.glob("test/**/*_test.rb") - .reject { |p| !OS.mac? && p.start_with?("test/os/mac/") } - .reject { |p| p.start_with?("test/vendor/bundle/") } - - opts = [] - opts << "--serialize-stdout" if ENV["CI"] + files = Dir.glob("test/**/*_{spec,test}.rb") + .reject { |p| !OS.mac? && p =~ %r{^test/(os/mac|cask)(/.*|_(test|spec)\.rb)$} } - args = [] - args << "--trace" if ARGV.include? "--trace" + test_args = [] + test_args << "--trace" if ARGV.include? "--trace" if ARGV.value("only") test_name, test_method = ARGV.value("only").split(":", 2) - files = Dir.glob("test/{#{test_name},#{test_name}/**/*}_test.rb") - args << "--name=test_#{test_method}" if test_method + files = Dir.glob("test/{#{test_name},#{test_name}/**/*}_{spec,test}.rb") + test_args << "--name=test_#{test_method}" if test_method end - args += ARGV.named.select { |v| v[/^TEST(OPTS)?=/] } + test_files = files.select { |p| p.end_with?("_test.rb") } + spec_files = files.select { |p| p.end_with?("_spec.rb") } + + test_args += ARGV.named.select { |v| v[/^TEST(OPTS)?=/] } + run_tests "parallel_test", test_files, test_args - system "bundle", "exec", "parallel_test", *opts, "--", *args, "--", *files + spec_args = [ + "--color", + "-I", HOMEBREW_LIBRARY_PATH/"test", + "--require", "spec_helper", + "--format", "progress", + "--format", "ParallelTests::RSpec::RuntimeLogger", + "--out", "tmp/parallel_runtime_rspec.log" + ] + spec_args << "--tag" << "~needs_macos" unless OS.mac? - Homebrew.failed = !$?.success? + run_tests "parallel_rspec", spec_files, spec_args if (fs_leak_log = HOMEBREW_LIBRARY_PATH/"tmp/fs_leak.log").file? fs_leak_log_content = fs_leak_log.read diff --git a/Library/Homebrew/dev-cmd/update-test.rb b/Library/Homebrew/dev-cmd/update-test.rb index 3b8dc11f9..9704426dd 100644 --- a/Library/Homebrew/dev-cmd/update-test.rb +++ b/Library/Homebrew/dev-cmd/update-test.rb @@ -1,14 +1,14 @@ -#: * `update-test` [`--commit=<commit>`] [`--before=<date>`] [`--keep-tmp`]: +#: * `update-test` [`--commit=`<commit>] [`--before=`<date>] [`--keep-tmp`]: #: Runs a test of `brew update` with a new repository clone. #: #: If no arguments are passed, use `origin/master` as the start commit. #: -#: If `--commit=<commit>` is passed, use `<commit>` as the start commit. +#: If `--commit=`<commit> is passed, use <commit> as the start commit. #: -#: If `--before=<date>` is passed, use the commit at `<date>` as the +#: If `--before=`<date> is passed, use the commit at <date> as the #: start commit. #: -#: If `--to-tag` is passed, set HOMEBREW_UPDATE_TO_TAG to test updating +#: If `--to-tag` is passed, set `HOMEBREW_UPDATE_TO_TAG` to test updating #: between tags. #: #: If `--keep-tmp` is passed, retain the temporary directory containing diff --git a/Library/Homebrew/emoji.rb b/Library/Homebrew/emoji.rb index 8c58ca895..43fa781e6 100644 --- a/Library/Homebrew/emoji.rb +++ b/Library/Homebrew/emoji.rb @@ -1,17 +1,7 @@ module Emoji class << self - def tick - # necessary for 1.8.7 unicode handling since many installs are on 1.8.7 - @tick ||= ["2714".hex].pack("U*") - end - - def cross - # necessary for 1.8.7 unicode handling since many installs are on 1.8.7 - @cross ||= ["2718".hex].pack("U*") - end - def install_badge - ENV["HOMEBREW_INSTALL_BADGE"] || "\xf0\x9f\x8d\xba" + ENV["HOMEBREW_INSTALL_BADGE"] || "🍺" end def enabled? diff --git a/Library/Homebrew/exceptions.rb b/Library/Homebrew/exceptions.rb index c5d888d64..77da4489e 100644 --- a/Library/Homebrew/exceptions.rb +++ b/Library/Homebrew/exceptions.rb @@ -131,6 +131,19 @@ class FormulaClassUnavailableError < FormulaUnavailableError end end +class FormulaUnreadableError < FormulaUnavailableError + attr_reader :formula_error + + def initialize(name, error) + super(name) + @formula_error = error + end + + def to_s + "#{name}: " + formula_error.to_s + end +end + class TapFormulaAmbiguityError < RuntimeError attr_reader :name, :paths, :formulae diff --git a/Library/Homebrew/extend/ARGV.rb b/Library/Homebrew/extend/ARGV.rb index 767ddc6e3..0825b13a7 100644 --- a/Library/Homebrew/extend/ARGV.rb +++ b/Library/Homebrew/extend/ARGV.rb @@ -16,11 +16,13 @@ module HomebrewArgvExtension --build-bottle --force-bottle --verbose + --force -i -v -d -g -s + -f ].freeze end diff --git a/Library/Homebrew/extend/ENV/shared.rb b/Library/Homebrew/extend/ENV/shared.rb index a93c1ee1f..3b07e0a71 100644 --- a/Library/Homebrew/extend/ENV/shared.rb +++ b/Library/Homebrew/extend/ENV/shared.rb @@ -17,7 +17,7 @@ module SharedEnvExtension FC_FLAG_VARS = %w[FCFLAGS FFLAGS].freeze # @private SANITIZED_VARS = %w[ - CDPATH GREP_OPTIONS CLICOLOR_FORCE + CDPATH CLICOLOR_FORCE CPATH C_INCLUDE_PATH CPLUS_INCLUDE_PATH OBJC_INCLUDE_PATH CC CXX OBJC OBJCXX CPP MAKE LD LDSHARED CFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS LDFLAGS CPPFLAGS @@ -269,7 +269,7 @@ module SharedEnvExtension # @private def gcc_version_formula(name) version = name[GNU_GCC_REGEXP, 1] - gcc_version_name = "gcc#{version.delete(".")}" + gcc_version_name = "gcc@#{version}" gcc = Formulary.factory("gcc") if gcc.version_suffix == version @@ -286,7 +286,6 @@ module SharedEnvExtension rescue FormulaUnavailableError => e raise <<-EOS.undent Homebrew GCC requested, but formula #{e.name} not found! - You may need to: brew tap homebrew/versions EOS end diff --git a/Library/Homebrew/extend/ENV/super.rb b/Library/Homebrew/extend/ENV/super.rb index 39ddb6681..1a5f420f6 100644 --- a/Library/Homebrew/extend/ENV/super.rb +++ b/Library/Homebrew/extend/ENV/super.rb @@ -277,7 +277,7 @@ module Superenv return unless Hardware::CPU.is_32_bit? self["HOMEBREW_OPTFLAGS"] = self["HOMEBREW_OPTFLAGS"].sub( /-march=\S*/, - "-Xarch_#{Hardware::CPU.arch_32_bit} \\0" + "-Xarch_#{Hardware::CPU.arch_32_bit} \\0", ) end diff --git a/Library/Homebrew/extend/fileutils.rb b/Library/Homebrew/extend/fileutils.rb index 4f20d36a3..287a1408f 100644 --- a/Library/Homebrew/extend/fileutils.rb +++ b/Library/Homebrew/extend/fileutils.rb @@ -3,7 +3,7 @@ require "tmpdir" require "etc" # Homebrew extends Ruby's `FileUtils` to make our code more readable. -# @see http://ruby-doc.org/stdlib-1.8.7/libdoc/fileutils/rdoc/FileUtils.html Ruby's FileUtils API +# @see http://ruby-doc.org/stdlib-2.0.0/libdoc/fileutils/rdoc/FileUtils.html Ruby's FileUtils API module FileUtils # Create a temporary directory then yield. When the block returns, # recursively delete the temporary directory. Passing opts[:retain] diff --git a/Library/Homebrew/extend/os/linux/requirements/java_requirement.rb b/Library/Homebrew/extend/os/linux/requirements/java_requirement.rb new file mode 100644 index 000000000..7816f6b6f --- /dev/null +++ b/Library/Homebrew/extend/os/linux/requirements/java_requirement.rb @@ -0,0 +1,16 @@ +require "language/java" + +class JavaRequirement < Requirement + default_formula "jdk" + + env do + env_java_common + env_oracle_jdk + end + + private + + def oracle_java_os + :linux + end +end diff --git a/Library/Homebrew/extend/os/mac/diagnostic.rb b/Library/Homebrew/extend/os/mac/diagnostic.rb index 6d30cd294..c7dabde2b 100644 --- a/Library/Homebrew/extend/os/mac/diagnostic.rb +++ b/Library/Homebrew/extend/os/mac/diagnostic.rb @@ -53,7 +53,10 @@ module Homebrew return unless MacOS::Xcode.installed? return unless MacOS::Xcode.outdated? - # Travis CI images are going to end up outdated so don't complain. + # Travis CI images are going to end up outdated so don't complain when + # `brew test-bot` runs `brew doctor` in the CI for the Homebrew/brew + # repository. This only needs to support whatever CI provider + # Homebrew/brew is currently using. return if ENV["TRAVIS"] message = <<-EOS.undent diff --git a/Library/Homebrew/extend/os/mac/hardware/cpu.rb b/Library/Homebrew/extend/os/mac/hardware/cpu.rb index 0695d4a5b..f759895c7 100644 --- a/Library/Homebrew/extend/os/mac/hardware/cpu.rb +++ b/Library/Homebrew/extend/os/mac/hardware/cpu.rb @@ -111,7 +111,7 @@ module Hardware @features ||= sysctl_n( "machdep.cpu.features", "machdep.cpu.extfeatures", - "machdep.cpu.leaf7_features" + "machdep.cpu.leaf7_features", ).split(" ").map { |s| s.downcase.to_sym } end diff --git a/Library/Homebrew/extend/os/mac/keg_relocate.rb b/Library/Homebrew/extend/os/mac/keg_relocate.rb index f44a97b31..476e5da4a 100644 --- a/Library/Homebrew/extend/os/mac/keg_relocate.rb +++ b/Library/Homebrew/extend/os/mac/keg_relocate.rb @@ -78,13 +78,19 @@ class Keg end end + def filename_contains_metavariable?(fn) + fn =~ /^@(loader_|executable_|r)path/ + end + def each_install_name_for(file, &block) dylibs = file.dynamically_linked_libraries - dylibs.reject! { |fn| fn =~ /^@(loader_|executable_|r)path/ } + dylibs.reject! { |fn| filename_contains_metavariable?(fn) } dylibs.each(&block) end def dylib_id_for(file) + return file.dylib_id if filename_contains_metavariable?(file.dylib_id) + # The new dylib ID should have the same basename as the old dylib ID, not # the basename of the file itself. basename = File.basename(file.dylib_id) diff --git a/Library/Homebrew/extend/os/mac/requirements/java_requirement.rb b/Library/Homebrew/extend/os/mac/requirements/java_requirement.rb new file mode 100644 index 000000000..5f989bb56 --- /dev/null +++ b/Library/Homebrew/extend/os/mac/requirements/java_requirement.rb @@ -0,0 +1,35 @@ +class JavaRequirement < Requirement + cask "java" + + env do + env_java_common + env_oracle_jdk || env_apple + end + + private + + def possible_javas + javas = [] + javas << Pathname.new(ENV["JAVA_HOME"])/"bin/java" if ENV["JAVA_HOME"] + javas << java_home_cmd + javas << which("java") + javas + end + + def java_home_cmd + return nil unless File.executable?("/usr/libexec/java_home") + args = %w[--failfast] + args << "--version" << @version.to_s if @version + java_home = Utils.popen_read("/usr/libexec/java_home", *args).chomp + return nil unless $?.success? + Pathname.new(java_home)/"bin/java" + end + + def env_apple + ENV.append_to_cflags "-I/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers/" + end + + def oracle_java_os + :darwin + end +end diff --git a/Library/Homebrew/extend/os/requirements/java_requirement.rb b/Library/Homebrew/extend/os/requirements/java_requirement.rb new file mode 100644 index 000000000..b512ada47 --- /dev/null +++ b/Library/Homebrew/extend/os/requirements/java_requirement.rb @@ -0,0 +1,7 @@ +require "requirements/java_requirement" + +if OS.mac? + require "extend/os/mac/requirements/java_requirement" +elsif OS.linux? + require "extend/os/linux/requirements/java_requirement" +end diff --git a/Library/Homebrew/extend/pathname.rb b/Library/Homebrew/extend/pathname.rb index cfb028704..9f6861a9a 100644 --- a/Library/Homebrew/extend/pathname.rb +++ b/Library/Homebrew/extend/pathname.rb @@ -335,7 +335,7 @@ class Pathname alias to_str to_s unless method_defined?(:to_str) def cd - Dir.chdir(self) { yield } + Dir.chdir(self) { yield self } end def subdirs diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index 91a3e8150..443619206 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -382,6 +382,11 @@ class Formula PkgVersion.new(version, revision) end + # If this is a `@`-versioned formula. + def versioned_formula? + name.include?("@") + end + # A named Resource for the currently active {SoftwareSpec}. # Additional downloads can be defined as {#resource}s. # {Resource#stage} will create a temporary directory and yield to a block. @@ -1021,7 +1026,9 @@ class Formula @prefix_returns_versioned_prefix = false end - # Tell the user about any caveats regarding this package. + # Tell the user about any Homebrew-specific caveats or locations regarding + # this package. These should not contain setup instructions that would apply + # to installation through a different package manager on a different OS. # @return [String] # <pre>def caveats # <<-EOS.undent @@ -1519,10 +1526,15 @@ class Formula # Returns a list of Dependency objects that are required at runtime. # @private def runtime_dependencies - recursive_dependencies do |_dependent, dependency| + runtime_dependencies = recursive_dependencies do |_, dependency| Dependency.prune if dependency.build? Dependency.prune if !dependency.required? && build.without?(dependency) end + runtime_requirement_deps = recursive_requirements do |_, requirement| + Requirement.prune if requirement.build? + Requirement.prune if !requirement.required? && build.without?(requirement) + end.map(&:to_dependency).compact + runtime_dependencies + runtime_requirement_deps end # Returns a list of formulae depended on by this formula that aren't @@ -1619,6 +1631,8 @@ class Formula "built_as_bottle" => tab.built_as_bottle, "poured_from_bottle" => tab.poured_from_bottle, "runtime_dependencies" => tab.runtime_dependencies, + "installed_as_dependency" => tab.installed_as_dependency, + "installed_on_request" => tab.installed_on_request, } end @@ -1831,7 +1845,16 @@ class Formula eligible_kegs = if head? && (head_prefix = latest_head_prefix) installed_kegs - [Keg.new(head_prefix)] else - installed_kegs.select { |k| pkg_version > k.version } + installed_kegs.select do |keg| + tab = Tab.for_keg(keg) + if version_scheme > tab.version_scheme + true + elsif version_scheme == tab.version_scheme + pkg_version > keg.version + else + false + end + end end unless eligible_kegs.empty? @@ -2012,7 +2035,7 @@ class Formula # @!attribute [w] url # The URL used to download the source for the {#stable} version of the formula. # We prefer `https` for security and proxy reasons. - # Optionally specify the download strategy with `:using => ...` + # If not inferrable, specify the download strategy with `:using => ...` # `:git`, `:hg`, `:svn`, `:bzr`, `:cvs`, # `:curl` (normal file download. Will also extract.) # `:nounzip` (without extracting) @@ -2020,7 +2043,10 @@ class Formula # `S3DownloadStrategy` (download from S3 using signed request) # # <pre>url "https://packed.sources.and.we.prefer.https.example.com/archive-1.2.3.tar.bz2"</pre> - # <pre>url "https://some.dont.provide.archives.example.com", :using => :git, :tag => "1.2.3", :revision => "db8e4de5b2d6653f66aea53094624468caad15d2"</pre> + # <pre>url "https://some.dont.provide.archives.example.com", + # :using => :git, + # :tag => "1.2.3", + # :revision => "db8e4de5b2d6653f66aea53094624468caad15d2"</pre> def url(val, specs = {}) stable.url(val, specs) end diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb index 115d38c45..1f91ad5c4 100644 --- a/Library/Homebrew/formula_installer.rb +++ b/Library/Homebrew/formula_installer.rb @@ -32,6 +32,7 @@ class FormulaInstaller attr_reader :formula attr_accessor :options, :build_bottle, :invalid_option_names + attr_accessor :installed_as_dependency, :installed_on_request mode_attr_accessor :show_summary_heading, :show_header mode_attr_accessor :build_from_source, :force_bottle mode_attr_accessor :ignore_deps, :only_deps, :interactive, :git @@ -50,6 +51,8 @@ class FormulaInstaller @verbose = false @quieter = false @debug = false + @installed_as_dependency = false + @installed_on_request = true @options = Options.new @invalid_option_names = [] @requirement_messages = [] @@ -148,6 +151,28 @@ class FormulaInstaller recursive_deps = formula.recursive_dependencies recursive_formulae = recursive_deps.map(&:to_formula) + recursive_dependencies = [] + recursive_formulae.each do |dep| + dep_recursive_dependencies = dep.recursive_dependencies.map(&:to_s) + if dep_recursive_dependencies.include?(formula.name) + recursive_dependencies << "#{formula.full_name} depends on #{dep.full_name}" + recursive_dependencies << "#{dep.full_name} depends on #{formula.full_name}" + end + end + + unless recursive_dependencies.empty? + raise CannotInstallFormulaError, <<-EOS.undent + #{formula.full_name} contains a recursive dependency on itself: + #{recursive_dependencies.join("\n ")} + EOS + end + + if recursive_formulae.flat_map(&:recursive_dependencies).map(&:to_s).include?(formula.name) + raise CannotInstallFormulaError, <<-EOS.undent + #{formula.full_name} contains a recursive dependency on itself! + EOS + end + if ENV["HOMEBREW_CHECK_RECURSIVE_VERSION_DEPENDENCIES"] version_hash = {} version_conflicts = Set.new @@ -168,12 +193,14 @@ class FormulaInstaller end end - unlinked_deps = recursive_formulae.select do |dep| - dep.installed? && !dep.keg_only? && !dep.linked_keg.directory? - end + unless ENV["HOMEBREW_NO_CHECK_UNLINKED_DEPENDENCIES"] + unlinked_deps = recursive_formulae.select do |dep| + dep.installed? && !dep.keg_only? && !dep.linked_keg.directory? + end - unless unlinked_deps.empty? - raise CannotInstallFormulaError, "You must `brew link #{unlinked_deps*" "}` before #{formula.full_name} can be installed" + unless unlinked_deps.empty? + raise CannotInstallFormulaError, "You must `brew link #{unlinked_deps*" "}` before #{formula.full_name} can be installed" + end end pinned_unsatisfied_deps = recursive_deps.select do |dep| @@ -250,6 +277,12 @@ class FormulaInstaller category = "install" action = ([formula.full_name] + options).join(" ") Utils::Analytics.report_event(category, action) + + if installed_on_request + category = "install_on_request" + action = ([formula.full_name] + options).join(" ") + Utils::Analytics.report_event(category, action) + end end @@attempted << formula @@ -287,6 +320,12 @@ class FormulaInstaller brew_prefix = formula.prefix/".brew" brew_prefix.mkdir Pathname(brew_prefix/"#{formula.name}.rb").atomic_write(s) + + keg = Keg.new(formula.prefix) + tab = Tab.for_keg(keg) + tab.installed_as_dependency = installed_as_dependency + tab.installed_on_request = installed_on_request + tab.write end build_bottle_postinstall if build_bottle? @@ -370,8 +409,8 @@ class FormulaInstaller raise UnsatisfiedRequirements, fatals end - def install_requirement_default_formula?(req, dependent, build) - return false unless req.default_formula? + def install_requirement_formula?(req, dependent, build) + return false unless req.to_dependency return true unless req.satisfied? return false if req.run? install_bottle_for?(dependent, build) || build_bottle? @@ -390,7 +429,7 @@ class FormulaInstaller Requirement.prune elsif req.build? && install_bottle_for?(dependent, build) Requirement.prune - elsif install_requirement_default_formula?(req, dependent, build) + elsif install_requirement_formula?(req, dependent, build) dep = req.to_dependency deps.unshift(dep) formulae.unshift(dep.to_formula) @@ -416,7 +455,7 @@ class FormulaInstaller inherited_options[dep.name] |= inherited_options_for(dep) build = effective_build_options_for( dependent, - inherited_options.fetch(dependent.name, []) + inherited_options.fetch(dependent.name, []), ) if (dep.optional? || dep.recommended?) && build.without?(dep) @@ -483,6 +522,8 @@ class FormulaInstaller fi.build_from_source = ARGV.build_formula_from_source?(df) fi.verbose = verbose? && !quieter? fi.debug = debug? + fi.installed_as_dependency = true + fi.installed_on_request = false fi.prelude oh1 "Installing #{formula.full_name} dependency: #{Formatter.identifier(dep.name)}" fi.install @@ -809,6 +850,8 @@ class FormulaInstaller tab.time = Time.now.to_i tab.head = HOMEBREW_REPOSITORY.git_head tab.source["path"] = formula.specified_path.to_s + tab.installed_as_dependency = installed_as_dependency + tab.installed_on_request = installed_on_request tab.write end diff --git a/Library/Homebrew/formula_support.rb b/Library/Homebrew/formula_support.rb index e4f800364..dcb995a6b 100644 --- a/Library/Homebrew/formula_support.rb +++ b/Library/Homebrew/formula_support.rb @@ -29,27 +29,32 @@ class KegOnlyReason def to_s return @explanation unless @explanation.empty? case @reason - when :provided_by_macos, :provided_by_osx then <<-EOS -macOS already provides this software and installing another version in -parallel can cause all kinds of trouble. -EOS - when :shadowed_by_macos, :shadowed_by_osx then <<-EOS -macOS provides similar software and installing this software in -parallel can cause all kinds of trouble. -EOS - when :provided_pre_mountain_lion then <<-EOS -macOS already provides this software in versions before Mountain Lion. -EOS - when :provided_pre_mavericks then <<-EOS -macOS already provides this software in versions before Mavericks. -EOS - when :provided_pre_el_capitan then <<-EOS -macOS already provides this software in versions before El Capitan. -EOS - when :provided_until_xcode43 - "Xcode provides this software prior to version 4.3." - when :provided_until_xcode5 - "Xcode provides this software prior to version 5." + when :versioned_formula then <<-EOS.undent + This is an alternate version of another formula. + EOS + when :provided_by_macos, :provided_by_osx then <<-EOS.undent + macOS already provides this software and installing another version in + parallel can cause all kinds of trouble. + EOS + when :shadowed_by_macos, :shadowed_by_osx then <<-EOS.undent + macOS provides similar software and installing this software in + parallel can cause all kinds of trouble. + EOS + when :provided_pre_mountain_lion then <<-EOS.undent + macOS already provides this software in versions before Mountain Lion. + EOS + when :provided_pre_mavericks then <<-EOS.undent + macOS already provides this software in versions before Mavericks. + EOS + when :provided_pre_el_capitan then <<-EOS.undent + macOS already provides this software in versions before El Capitan. + EOS + when :provided_until_xcode43 then <<-EOS.undent + Xcode provides this software prior to version 4.3. + EOS + when :provided_until_xcode5 then <<-EOS.undent + Xcode provides this software prior to version 5. + EOS else @reason end.strip diff --git a/Library/Homebrew/formula_versions.rb b/Library/Homebrew/formula_versions.rb index 34b766fde..28c2a3be8 100644 --- a/Library/Homebrew/formula_versions.rb +++ b/Library/Homebrew/formula_versions.rb @@ -15,7 +15,6 @@ class FormulaVersions @repository = formula.tap.path @entry_name = @path.relative_path_from(repository).to_s @max_depth = options[:max_depth] - @current_formula = formula end def rev_list(branch) @@ -65,33 +64,25 @@ class FormulaVersions attributes.each do |attribute| attributes_map[attribute] ||= {} - # Set the attributes for the current formula in case it's not been - # committed yet. - set_attribute_map(attributes_map[attribute], @current_formula, attribute) end rev_list(branch) do |rev| formula_at_revision(rev) do |f| attributes.each do |attribute| - set_attribute_map(attributes_map[attribute], f, attribute) + map = attributes_map[attribute] + if f.stable + map[:stable] ||= {} + map[:stable][f.stable.version] ||= [] + map[:stable][f.stable.version] << f.send(attribute) + end + next unless f.devel + map[:devel] ||= {} + map[:devel][f.devel.version] ||= [] + map[:devel][f.devel.version] << f.send(attribute) end end end attributes_map end - - private - - def set_attribute_map(map, f, attribute) - if f.stable - map[:stable] ||= {} - map[:stable][f.stable.version] ||= [] - map[:stable][f.stable.version] << f.send(attribute) - end - return unless f.devel - map[:devel] ||= {} - map[:devel][f.devel.version] ||= [] - map[:devel][f.devel.version] << f.send(attribute) - end end diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb index 25df57cdc..4a65f8704 100644 --- a/Library/Homebrew/formulary.rb +++ b/Library/Homebrew/formulary.rb @@ -4,7 +4,7 @@ require "tap" # The Formulary is responsible for creating instances of Formula. # It is not meant to be used directly from formulae. -class Formulary +module Formulary FORMULAE = {} def self.formula_class_defined?(path) @@ -22,7 +22,11 @@ class Formulary mod = Module.new const_set(namespace, mod) - mod.module_eval(contents, path) + begin + mod.module_eval(contents, path) + rescue ScriptError => e + raise FormulaUnreadableError.new(name, e) + end class_name = class_s(name) begin diff --git a/Library/Homebrew/global.rb b/Library/Homebrew/global.rb index 031178421..391f5b012 100644 --- a/Library/Homebrew/global.rb +++ b/Library/Homebrew/global.rb @@ -15,7 +15,7 @@ ARGV.extend(HomebrewArgvExtension) HOMEBREW_PRODUCT = ENV["HOMEBREW_PRODUCT"] HOMEBREW_VERSION = ENV["HOMEBREW_VERSION"] -HOMEBREW_WWW = "http://brew.sh".freeze +HOMEBREW_WWW = "https://brew.sh".freeze require "config" @@ -26,7 +26,7 @@ RUBY_BIN = RUBY_PATH.dirname HOMEBREW_USER_AGENT_CURL = ENV["HOMEBREW_USER_AGENT_CURL"] HOMEBREW_USER_AGENT_RUBY = "#{ENV["HOMEBREW_USER_AGENT"]} ruby/#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}".freeze -HOMEBREW_USER_AGENT_FAKE_SAFARI = "Mozilla/5.0 (#{ENV["HOMEBREW_SYSTEM"]}; #{ENV["HOMEBREW_PROCESSOR"]} #{ENV["HOMEBREW_OS_VERSION"]}) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0.2 Safari/602.3.12".freeze +HOMEBREW_USER_AGENT_FAKE_SAFARI = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/602.4.8 (KHTML, like Gecko) Version/10.0.3 Safari/602.4.8".freeze require "tap_constants" @@ -69,6 +69,7 @@ HOMEBREW_INTERNAL_COMMAND_ALIASES = { "up" => "update", "ln" => "link", "instal" => "install", # gem does the same + "uninstal" => "uninstall", "rm" => "uninstall", "remove" => "uninstall", "configure" => "diy", diff --git a/Library/Homebrew/keg.rb b/Library/Homebrew/keg.rb index 14eb0e3f3..94e3ff55b 100644 --- a/Library/Homebrew/keg.rb +++ b/Library/Homebrew/keg.rb @@ -174,6 +174,12 @@ class Keg attr_reader :path, :name, :linked_keg_record, :opt_record protected :path + extend Forwardable + + def_delegators :path, + :to_s, :hash, :abv, :disk_usage, :file_count, :directory?, :exist?, :/, + :join, :rename, :find + def initialize(path) path = path.resolved_path if path.to_s.start_with?("#{HOMEBREW_PREFIX}/opt/") raise "#{path} is not a valid keg" unless path.parent.parent.realpath == HOMEBREW_CELLAR.realpath @@ -182,21 +188,14 @@ class Keg @name = path.parent.basename.to_s @linked_keg_record = HOMEBREW_LINKED_KEGS/name @opt_record = HOMEBREW_PREFIX/"opt/#{name}" - end - - def to_s - path.to_s + @require_relocation = false end def rack path.parent end - if Pathname.method_defined?(:to_path) - alias to_path to_s - else - alias to_str to_s - end + alias to_path to_s def inspect "#<#{self.class.name}:#{path}>" @@ -207,30 +206,6 @@ class Keg end alias eql? == - def hash - path.hash - end - - def abv - path.abv - end - - def disk_usage - path.disk_usage - end - - def file_count - path.file_count - end - - def directory? - path.directory? - end - - def exist? - path.exist? - end - def empty_installation? Pathname.glob("#{path}/**/*") do |file| next if file.directory? @@ -243,16 +218,8 @@ class Keg true end - def /(other) - path / other - end - - def join(*args) - path.join(*args) - end - - def rename(*args) - path.rename(*args) + def require_relocation? + @require_relocation end def linked? @@ -272,6 +239,10 @@ class Keg def remove_opt_record opt_record.unlink + aliases.each do |a| + next if !opt_record.symlink? && !opt_record.exist? + (opt_record.parent/a).delete + end opt_record.parent.rmdir_if_possible end @@ -400,10 +371,6 @@ class Keg end end - def find(*args, &block) - path.find(*args, &block) - end - def oldname_opt_record @oldname_opt_record ||= if (opt_dir = HOMEBREW_PREFIX/"opt").directory? opt_dir.subdirs.detect do |dir| @@ -498,9 +465,20 @@ class Keg @oldname_opt_record = nil end + def aliases + Formula[rack.basename.to_s].aliases + rescue FormulaUnavailableError + [] + end + def optlink(mode = OpenStruct.new) opt_record.delete if opt_record.symlink? || opt_record.exist? make_relative_symlink(opt_record, path, mode) + aliases.each do |a| + alias_opt_record = opt_record.parent/a + alias_opt_record.delete if alias_opt_record.symlink? || alias_opt_record.exist? + make_relative_symlink(alias_opt_record, path, mode) + end return unless oldname_opt_record oldname_opt_record.delete diff --git a/Library/Homebrew/keg_relocate.rb b/Library/Homebrew/keg_relocate.rb index 0ab4b9731..d17e7f75a 100644 --- a/Library/Homebrew/keg_relocate.rb +++ b/Library/Homebrew/keg_relocate.rb @@ -34,7 +34,7 @@ class Keg old_repository: HOMEBREW_REPOSITORY.to_s, new_prefix: PREFIX_PLACEHOLDER, new_cellar: CELLAR_PLACEHOLDER, - new_repository: REPOSITORY_PLACEHOLDER + new_repository: REPOSITORY_PLACEHOLDER, ) relocate_dynamic_linkage(relocation) replace_text_in_files(relocation) @@ -47,7 +47,7 @@ class Keg old_repository: REPOSITORY_PLACEHOLDER, new_prefix: HOMEBREW_PREFIX.to_s, new_cellar: HOMEBREW_CELLAR.to_s, - new_repository: HOMEBREW_REPOSITORY.to_s + new_repository: HOMEBREW_REPOSITORY.to_s, ) relocate_dynamic_linkage(relocation) unless skip_linkage replace_text_in_files(relocation, files: files) @@ -71,7 +71,7 @@ class Keg regexp = Regexp.union( relocation.old_cellar, relocation.old_repository, - relocation.old_prefix + relocation.old_prefix, ) changed = s.gsub!(regexp, replacements) diff --git a/Library/Homebrew/manpages/brew-cask.1.md b/Library/Homebrew/manpages/brew-cask.1.md index f0a70d4a7..e882f09d1 100644 --- a/Library/Homebrew/manpages/brew-cask.1.md +++ b/Library/Homebrew/manpages/brew-cask.1.md @@ -86,19 +86,19 @@ names, and other aspects of this manual are still subject to change. If <token> is given, summarize the staged files associated with the given Cask. - * `reinstall` <token> [ <token> ...] + * `reinstall` <token> [ <token> ... ]: Reinstall the given Cask. * `search` or `-S` [<text> | /<regexp>/]: - Without argument, display all Casks available for install, otherwise + Without an argument, display all Casks available for install; otherwise perform a substring search of known Cask tokens for <text> or, if the text is delimited by slashes (/<regexp>/), it is interpreted as a Ruby regular expression. * `style` [--fix] [ <token> ... ]: - Check the given Casks for correct style using [RuboCop Cask](https://github.com/caskroom/rubocop-cask). - If no tokens are given on the command line, all Casks are checked. - With `--fix`, auto-correct any style errors if possible. + Check the given Casks for correct style using [RuboCop Cask](https://github.com/caskroom/rubocop-cask). + If no tokens are given on the command line, all Casks are checked. + With `--fix`, auto-correct any style errors if possible. * `uninstall` or `rm` or `remove` [--force] <token> [ <token> ... ]: Uninstall the given Cask. With `--force`, uninstall even if the Cask @@ -111,7 +111,7 @@ names, and other aspects of this manual are still subject to change. the Cask does not appear to be currently installed. Removes all staged versions of the Cask distribution found under - `<Caskroom_path>/<token>`. + `<Caskroom_path>/`<token>. If the Cask definition contains a `zap` stanza, performs additional `zap` actions as defined there, such as removing local preference @@ -120,9 +120,21 @@ names, and other aspects of this manual are still subject to change. **`zap` may remove files which are shared between applications.** +## INTERNAL COMMANDS + + * `_appcast_checkpoint` [--calculate] [ <token> ... | <URL> ... ]: + Given a <token>, returns the current appcast checkpoint, or calculates + the appcast checkpoint if the `--calculate` flag is specified. + + Given a <URL>, calculates the appcast checkpoint for it. + + * `_stanza` <stanza_name> [ --table | --yaml | --inspect | --quiet ] [ <token> ... ]: + Given a <stanza_name> and a <token>, returns the current stanza for a + given Cask. If no <token> is given, then data for all Casks is returned. + ## OPTIONS -To make these options persistent, see the ENVIRONMENT section, below. +To make these options persistent, see the [ENVIRONMENT][] section, below. Some of these (such as `--prefpanedir`) may be subject to removal in a future version. @@ -138,7 +150,7 @@ in a future version. Abort Cask installation if the Cask does not have a checksum defined. * `--caskroom=<path>`: - Location of the Caskroom, where all binaries are stored. The default value is: `$(brew --prefix)/Caskroom`. + Set location of the Caskroom, where all binaries are stored. The default value is `$(brew --prefix)/Caskroom`. * `--verbose`: Give additional feedback during installation. @@ -206,17 +218,17 @@ the Homebrew command: Most Homebrew-Cask commands can accept a Cask token as an argument. As described above, the argument can take the form of: - * A token as returned by `brew cask search`, _eg_ `google-chrome` + * A token as returned by `brew cask search`, e.g. `google-chrome` Homebrew-Cask also accepts three other forms in place of plain tokens: - * A fully-qualified token which includes the Tap name, _eg_ + * A fully-qualified token which includes the Tap name, e.g. `caskroom/fonts/font-symbola` - * A fully-qualified pathname to a Cask file, _eg_ + * A fully-qualified pathname to a Cask file, e.g. `/usr/local/Library/Taps/caskroom/homebrew-cask/Casks/google-chrome.rb` - * A `curl`-retrievable URI to a Cask file, _eg_ + * A `curl`-retrievable URI to a Cask file, e.g. `https://raw.githubusercontent.com/caskroom/homebrew-cask/f25b6babcd398abf48e33af3d887b2d00de1d661/Casks/google-chrome.rb` ## ENVIRONMENT @@ -227,17 +239,18 @@ information. Environment variables specific to Homebrew-Cask: - * HOMEBREW\_CASK\_OPTS: + * `HOMEBREW_CASK_OPTS`: This variable may contain any arguments normally used as options on the command-line. This is particularly useful to make options persistent. For example, you might add to your .bash_profile or .zshenv something like: - `export HOMEBREW_CASK_OPTS='--appdir=/Applications --caskroom=/etc/Caskroom'`. + + export HOMEBREW_CASK_OPTS='--appdir=/Applications --caskroom=/etc/Caskroom' ## SEE ALSO -The Homebrew-Cask home page: <http://caskroom.io>. +The Homebrew-Cask home page: <http://caskroom.io> -The Homebrew-Cask GitHub page: <https://github.com/caskroom/homebrew-cask>. +The Homebrew-Cask GitHub page: <https://github.com/caskroom/homebrew-cask> `brew`(1), `curl`(1) @@ -249,7 +262,7 @@ Man page format based on `brew.1.md` from Homebrew. ## BUGS -We still have bugs — and we are busy fixing them! If you have a problem, don’t +We still have bugs - and we are busy fixing them! If you have a problem, don't be shy about reporting it on our [GitHub issues page](https://github.com/caskroom/homebrew-cask/issues?state=open). When reporting bugs, remember that Homebrew-Cask is an independent project from diff --git a/Library/Homebrew/manpages/brew.1.md.erb b/Library/Homebrew/manpages/brew.1.md.erb index a7f099e9d..05fc1cb23 100644 --- a/Library/Homebrew/manpages/brew.1.md.erb +++ b/Library/Homebrew/manpages/brew.1.md.erb @@ -40,7 +40,7 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note * `list`: List all installed formulae. - * `search` <text>|`/`<text>`/`: + * `search` (<text>|`/`<text>`/`): Perform a substring search of formula names for <text>. If <text> is surrounded with slashes, then it is interpreted as a regular expression. The search for <text> is extended online to some popular taps. @@ -214,7 +214,7 @@ can take several different forms: to insecure HTTP. While ensuring your downloads are fully secure, this is likely - to cause from-source Sourceforge, some GNU & GNOME based + to cause from-source SourceForge, some GNU & GNOME based formulae to fail to download. * `HOMEBREW_NO_GITHUB_API`: diff --git a/Library/Homebrew/official_taps.rb b/Library/Homebrew/official_taps.rb index c1ef431b6..c7b96ae64 100644 --- a/Library/Homebrew/official_taps.rb +++ b/Library/Homebrew/official_taps.rb @@ -1,17 +1,11 @@ OFFICIAL_TAPS = %w[ apache - completions dupes - emacs fuse - games - gui nginx php - python science tex - x11 ].freeze OFFICIAL_CMD_TAPS = { diff --git a/Library/Homebrew/os/mac.rb b/Library/Homebrew/os/mac.rb index 9468a6c1e..e09a9b3fd 100644 --- a/Library/Homebrew/os/mac.rb +++ b/Library/Homebrew/os/mac.rb @@ -27,6 +27,11 @@ module OS @full_version ||= Version.new((ENV["HOMEBREW_MACOS_VERSION"] || ENV["HOMEBREW_OSX_VERSION"]).chomp) end + def full_version=(version) + @full_version = Version.new(version.chomp) + @version = nil + end + def prerelease? # TODO: bump version when new OS is released version >= "10.13" diff --git a/Library/Homebrew/os/mac/keg.rb b/Library/Homebrew/os/mac/keg.rb index b2a769849..674ea3330 100644 --- a/Library/Homebrew/os/mac/keg.rb +++ b/Library/Homebrew/os/mac/keg.rb @@ -24,8 +24,4 @@ class Keg EOS raise end - - def require_relocation? - @require_relocation - end end diff --git a/Library/Homebrew/os/mac/xcode.rb b/Library/Homebrew/os/mac/xcode.rb index e85f21c63..aa4504a17 100644 --- a/Library/Homebrew/os/mac/xcode.rb +++ b/Library/Homebrew/os/mac/xcode.rb @@ -226,7 +226,7 @@ module OS def minimum_version case MacOS.version when "10.12" then "8.0.0" - else "4.0.0" + else "1.0.0" end end diff --git a/Library/Homebrew/requirement.rb b/Library/Homebrew/requirement.rb index fe1a3c020..49108ca75 100644 --- a/Library/Homebrew/requirement.rb +++ b/Library/Homebrew/requirement.rb @@ -15,6 +15,7 @@ class Requirement @default_formula = self.class.default_formula @cask ||= self.class.cask @download ||= self.class.download + @formula = nil tags.each do |tag| next unless tag.is_a? Hash @cask ||= tag[:cask] @@ -56,7 +57,14 @@ class Requirement def satisfied? result = self.class.satisfy.yielder { |p| instance_eval(&p) } @satisfied_result = result - result ? true : false + return false unless result + + if parent = satisfied_result_parent + parent.to_s =~ %r{(#{Regexp.escape(HOMEBREW_CELLAR)}|#{Regexp.escape(HOMEBREW_PREFIX)}/opt)/([\w+-.@]+)} + @formula = $2 + end + + true end # Overriding #fatal? is deprecated. @@ -69,6 +77,11 @@ class Requirement self.class.default_formula || false end + def satisfied_result_parent + return unless @satisfied_result.is_a?(Pathname) + @satisfied_result.resolved_path.parent + end + # Overriding #modify_build_environment is deprecated. # Pass a block to the env DSL method instead. # Note: #satisfied? should be called before invoking this method @@ -81,11 +94,8 @@ class Requirement # satisfy { which("executable") } # work, even under superenv where "executable" wouldn't normally be on the # PATH. - # This is undocumented magic and it should be removed, but we need to add - # a way to declare path-based requirements that work with superenv first. - return unless @satisfied_result.is_a?(Pathname) - parent = @satisfied_result.parent - + parent = satisfied_result_parent + return unless parent return if ENV["PATH"].split(File::PATH_SEPARATOR).include?(parent.to_s) ENV.append_path("PATH", parent) end @@ -111,13 +121,15 @@ class Requirement "#<#{self.class.name}: #{name.inspect} #{tags.inspect}>" end + def formula + @formula || self.class.default_formula + end + def to_dependency - f = self.class.default_formula - raise "No default formula defined for #{inspect}" if f.nil? - if f =~ HOMEBREW_TAP_FORMULA_REGEX - TapDependency.new(f, tags, method(:modify_build_environment), name) - else - Dependency.new(f, tags, method(:modify_build_environment), name) + if formula =~ HOMEBREW_TAP_FORMULA_REGEX + TapDependency.new(formula, tags, method(:modify_build_environment), name) + elsif formula + Dependency.new(formula, tags, method(:modify_build_environment), name) end end diff --git a/Library/Homebrew/requirements/java_requirement.rb b/Library/Homebrew/requirements/java_requirement.rb index 33fc01229..010b7dbc9 100644 --- a/Library/Homebrew/requirements/java_requirement.rb +++ b/Library/Homebrew/requirements/java_requirement.rb @@ -2,28 +2,12 @@ require "language/java" class JavaRequirement < Requirement fatal true - cask "java" download "http://www.oracle.com/technetwork/java/javase/downloads/index.html" satisfy build_env: false do - next false unless File.executable? "/usr/libexec/java_home" - - args = %w[--failfast] - args << "--version" << @version.to_s if @version - @java_home = Utils.popen_read("/usr/libexec/java_home", *args).chomp - $?.success? - end - - env do - java_home = Pathname.new(@java_home) - ENV["JAVA_HOME"] = java_home - ENV.prepend_path "PATH", java_home/"bin" - if (java_home/"include").exist? # Oracle JVM - ENV.append_to_cflags "-I#{java_home}/include" - ENV.append_to_cflags "-I#{java_home}/include/darwin" - else # Apple JVM - ENV.append_to_cflags "-I/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers/" - end + setup_java + next false unless @java + next true end def initialize(tags) @@ -45,16 +29,90 @@ class JavaRequirement < Requirement def display_s if @version - if @version[-1] == "+" - op = ">=" - version = @version[0, @version.length-1] - else + if exact_version? op = "=" - version = @version + else + op = ">=" end - "#{name} #{op} #{version}" + "#{name} #{op} #{version_without_plus}" else name end end + + private + + def version_without_plus + if exact_version? + @version + else + @version[0, @version.length-1] + end + end + + def exact_version? + @version && @version.to_s.chars.last != "+" + end + + def setup_java + java = preferred_java + return unless java + @java = java + @java_home = java.parent.parent + end + + def possible_javas + javas = [] + javas << Pathname.new(ENV["JAVA_HOME"])/"bin/java" if ENV["JAVA_HOME"] + jdk = begin + Formula["jdk"] + rescue FormulaUnavailableError + nil + end + javas << jdk.bin/"java" if jdk && jdk.installed? + javas << which("java") + javas + end + + def preferred_java + possible_javas.detect do |java| + next false unless java && java.executable? + next true unless @version + next true if satisfies_version(java) + end + end + + def env_java_common + return unless @java_home + java_home = Pathname.new(@java_home) + ENV["JAVA_HOME"] = java_home + ENV.prepend_path "PATH", java_home/"bin" + end + + def env_oracle_jdk + return unless @java_home + java_home = Pathname.new(@java_home) + return unless (java_home/"include").exist? + ENV.append_to_cflags "-I#{java_home}/include" + ENV.append_to_cflags "-I#{java_home}/include/#{oracle_java_os}" + true + end + + def oracle_java_os + nil + end + + def satisfies_version(java) + java_version_s = Utils.popen_read("#{java} -version 2>&1")[/1.\d/] + return false unless java_version_s + java_version = Version.create(java_version_s) + needed_version = Version.create(version_without_plus) + if exact_version? + java_version == needed_version + else + java_version >= needed_version + end + end end + +require "extend/os/requirements/java_requirement" diff --git a/Library/Homebrew/requirements/language_module_requirement.rb b/Library/Homebrew/requirements/language_module_requirement.rb index e20f48361..392bc9b7a 100644 --- a/Library/Homebrew/requirements/language_module_requirement.rb +++ b/Library/Homebrew/requirements/language_module_requirement.rb @@ -32,12 +32,18 @@ class LanguageModuleRequirement < Requirement def the_test case @language - when :lua then %W[/usr/bin/env luarocks-5.2 show #{@import_name}] - when :lua51 then %W[/usr/bin/env luarocks-5.1 show #{@import_name}] - when :perl then %W[/usr/bin/env perl -e use\ #{@import_name}] - when :python then %W[/usr/bin/env python -c import\ #{@import_name}] - when :python3 then %W[/usr/bin/env python3 -c import\ #{@import_name}] - when :ruby then %W[/usr/bin/env ruby -rubygems -e require\ '#{@import_name}'] + when :lua + ["/usr/bin/env", "luarocks-5.2", "show", @import_name.to_s] + when :lua51 + ["/usr/bin/env", "luarocks-5.1", "show", @import_name.to_s] + when :perl + ["/usr/bin/env", "perl", "-e", "use #{@import_name}"] + when :python + ["/usr/bin/env", "python", "-c", "import #{@import_name}"] + when :python3 + ["/usr/bin/env", "python3", "-c", "import #{@import_name}"] + when :ruby + ["/usr/bin/env", "ruby", "-rubygems", "-e", "require '#{@import_name}'"] end end diff --git a/Library/Homebrew/requirements/ruby_requirement.rb b/Library/Homebrew/requirements/ruby_requirement.rb index a890435a5..327c13170 100644 --- a/Library/Homebrew/requirements/ruby_requirement.rb +++ b/Library/Homebrew/requirements/ruby_requirement.rb @@ -8,16 +8,14 @@ class RubyRequirement < Requirement super end - satisfy build_env: false do - which_all("ruby").detect do |ruby| - version = /\d\.\d/.match Utils.popen_read(ruby, "--version") - next unless version - Version.create(version.to_s) >= Version.create(@version) - end + satisfy(build_env: false) { new_enough_ruby } + + env do + ENV.prepend_path "PATH", new_enough_ruby end def message - s = "Ruby #{@version} is required to install this formula." + s = "Ruby >= #{@version} is required to install this formula." s += super s end @@ -33,4 +31,28 @@ class RubyRequirement < Requirement name end end + + private + + def new_enough_ruby + rubies.detect { |ruby| new_enough?(ruby) } + end + + def rubies + rubies = which_all("ruby") + ruby_formula = Formula["ruby"] + if ruby_formula && ruby_formula.installed? + rubies.unshift ruby_formula.bin/"ruby" + end + rubies.uniq + end + + def new_enough?(ruby) + version = Utils.popen_read(ruby, "-e", "print RUBY_VERSION").strip + version =~ /^\d+\.\d+/ && Version.create(version) >= min_version + end + + def min_version + @min_version ||= Version.create(@version) + end end diff --git a/Library/Homebrew/rubocops.rb b/Library/Homebrew/rubocops.rb new file mode 100644 index 000000000..1a28dd213 --- /dev/null +++ b/Library/Homebrew/rubocops.rb @@ -0,0 +1 @@ +require_relative "./rubocops/bottle_block_cop" diff --git a/Library/Homebrew/rubocops/bottle_block_cop.rb b/Library/Homebrew/rubocops/bottle_block_cop.rb new file mode 100644 index 000000000..55eb55152 --- /dev/null +++ b/Library/Homebrew/rubocops/bottle_block_cop.rb @@ -0,0 +1,36 @@ +module RuboCop + module Cop + module Homebrew + class CorrectBottleBlock < Cop + MSG = "Use rebuild instead of revision in bottle block".freeze + + def on_block(node) + return if block_length(node).zero? + method, _args, body = *node + _keyword, method_name = *method + + return unless method_name == :bottle + check_revision?(body) + end + + private + + def autocorrect(node) + lambda do |corrector| + correction = node.source.sub("revision", "rebuild") + corrector.insert_before(node.source_range, correction) + corrector.remove(node.source_range) + end + end + + def check_revision?(body) + body.children.each do |method_call_node| + _receiver, method_name, _args = *method_call_node + next unless method_name == :revision + add_offense(method_call_node, :expression) + end + end + end + end + end +end diff --git a/Library/Homebrew/system_config.rb b/Library/Homebrew/system_config.rb index 043f60919..56826f62d 100644 --- a/Library/Homebrew/system_config.rb +++ b/Library/Homebrew/system_config.rb @@ -7,19 +7,35 @@ require "development_tools" class SystemConfig class << self def gcc_4_2 - @gcc_4_2 ||= DevelopmentTools.gcc_4_2_build_version if DevelopmentTools.installed? + @gcc_4_2 ||= if DevelopmentTools.installed? + DevelopmentTools.gcc_4_2_build_version + else + Version::NULL + end end def gcc_4_0 - @gcc_4_0 ||= DevelopmentTools.gcc_4_0_build_version if DevelopmentTools.installed? + @gcc_4_0 ||= if DevelopmentTools.installed? + DevelopmentTools.gcc_4_0_build_version + else + Version::NULL + end end def clang - @clang ||= DevelopmentTools.clang_version if DevelopmentTools.installed? + @clang ||= if DevelopmentTools.installed? + DevelopmentTools.clang_version + else + Version::NULL + end end def clang_build - @clang_build ||= DevelopmentTools.clang_build_version if DevelopmentTools.installed? + @clang_build ||= if DevelopmentTools.installed? + DevelopmentTools.clang_build_version + else + Version::NULL + end end def head diff --git a/Library/Homebrew/tab.rb b/Library/Homebrew/tab.rb index 746c3dd92..fd59539df 100644 --- a/Library/Homebrew/tab.rb +++ b/Library/Homebrew/tab.rb @@ -25,6 +25,8 @@ class Tab < OpenStruct "unused_options" => build.unused_options.as_flags, "tabfile" => formula.prefix.join(FILENAME), "built_as_bottle" => build.bottle?, + "installed_as_dependency" => false, + "installed_on_request" => true, "poured_from_bottle" => false, "time" => Time.now.to_i, "source_modified_time" => formula.source_modified_time.to_i, @@ -172,6 +174,8 @@ class Tab < OpenStruct "used_options" => [], "unused_options" => [], "built_as_bottle" => false, + "installed_as_dependency" => false, + "installed_on_request" => true, "poured_from_bottle" => false, "time" => nil, "source_modified_time" => 0, @@ -313,6 +317,8 @@ class Tab < OpenStruct "unused_options" => unused_options.as_flags, "built_as_bottle" => built_as_bottle, "poured_from_bottle" => poured_from_bottle, + "installed_as_dependency" => installed_as_dependency, + "installed_on_request" => installed_on_request, "changed_files" => changed_files && changed_files.map(&:to_s), "time" => time, "source_modified_time" => source_modified_time.to_i, diff --git a/Library/Homebrew/test/ARGV_spec.rb b/Library/Homebrew/test/ARGV_spec.rb new file mode 100644 index 000000000..89ef9cabc --- /dev/null +++ b/Library/Homebrew/test/ARGV_spec.rb @@ -0,0 +1,149 @@ +require "extend/ARGV" + +describe HomebrewArgvExtension do + subject { argv.extend(described_class) } + let(:argv) { ["mxcl"] } + + describe "#formulae" do + it "raises an error when a Formula is unavailable" do + expect { subject.formulae }.to raise_error FormulaUnavailableError + end + + context "when there are no Formulae" do + let(:argv) { [] } + + it "returns an empty array" do + expect(subject.formulae).to be_empty + end + end + end + + describe "#casks" do + it "returns an empty array if there is no match" do + expect(subject.casks).to eq [] + end + end + + describe "#kegs" do + context "when there are matching Kegs" do + before(:each) do + keg = HOMEBREW_CELLAR + "mxcl/10.0" + keg.mkpath + end + + it "returns an array of Kegs" do + expect(subject.kegs.length).to eq 1 + end + end + + context "when there are no matching Kegs" do + let(:argv) { [] } + + it "returns an empty array" do + expect(subject.kegs).to be_empty + end + end + end + + describe "#named" do + let(:argv) { ["foo", "--debug", "-v"] } + + it "returns an array of non-option arguments" do + expect(subject.named).to eq ["foo"] + end + + context "when there are no named arguments" do + let(:argv) { [] } + + it "returns an empty array" do + expect(subject.named).to be_empty + end + end + end + + describe "#options_only" do + let(:argv) { ["--foo", "-vds", "a", "b", "cdefg"] } + + it "returns an array of option arguments" do + expect(subject.options_only).to eq ["--foo", "-vds"] + end + end + + describe "#flags_only" do + let(:argv) { ["--foo", "-vds", "a", "b", "cdefg"] } + + it "returns an array of flags" do + expect(subject.flags_only).to eq ["--foo"] + end + end + + describe "#empty?" do + let(:argv) { [] } + + it "returns true if it is empty" do + expect(subject).to be_empty + end + end + + describe "#switch?" do + let(:argv) { ["-ns", "-i", "--bar", "-a-bad-arg"] } + + it "returns true if the given string is a switch" do + %w[n s i].each do |s| + expect(subject.switch?(s)).to be true + end + end + + it "returns false if the given string is not a switch" do + %w[b ns bar --bar -n a bad arg].each do |s| + expect(subject.switch?(s)).to be false + end + end + end + + describe "#flag?" do + let(:argv) { ["--foo", "-bq", "--bar"] } + + it "returns true if the given string is a flag" do + expect(subject.flag?("--foo")).to eq true + expect(subject.flag?("--bar")).to eq true + end + + it "returns true if there is a switch with the same initial character" do + expect(subject.flag?("--baz")).to eq true + expect(subject.flag?("--qux")).to eq true + end + + it "returns false if there is no matching flag" do + expect(subject.flag?("--frotz")).to eq false + expect(subject.flag?("--debug")).to eq false + end + end + + describe "#value" do + let(:argv) { ["--foo=", "--bar=ab"] } + + it "returns the value for a given string" do + expect(subject.value("foo")).to eq "" + expect(subject.value("bar")).to eq "ab" + end + + it "returns nil if there is no matching argument" do + expect(subject.value("baz")).to be nil + end + end + + describe "#values" do + let(:argv) { ["--foo=", "--bar=a", "--baz=b,c"] } + + it "returns the value for a given argument" do + expect(subject.values("foo")).to eq [] + expect(subject.values("bar")).to eq ["a"] + expect(subject.values("baz")).to eq ["b", "c"] + end + + it "returns nil if there is no matching argument" do + expect(subject.values("qux")).to be nil + end + end +end diff --git a/Library/Homebrew/test/ARGV_test.rb b/Library/Homebrew/test/ARGV_test.rb deleted file mode 100644 index 6805e0c62..000000000 --- a/Library/Homebrew/test/ARGV_test.rb +++ /dev/null @@ -1,80 +0,0 @@ -require "testing_env" -require "extend/ARGV" - -class ArgvExtensionTests < Homebrew::TestCase - def setup - @argv = [].extend(HomebrewArgvExtension) - end - - def test_argv_formulae - @argv.unshift "mxcl" - assert_raises(FormulaUnavailableError) { @argv.formulae } - end - - def test_argv_casks - @argv.unshift "mxcl" - assert_equal [], @argv.casks - end - - def test_argv_kegs - keg = HOMEBREW_CELLAR + "mxcl/10.0" - keg.mkpath - @argv << "mxcl" - assert_equal 1, @argv.kegs.length - ensure - keg.parent.rmtree - end - - def test_argv_named - @argv << "foo" << "--debug" << "-v" - assert_equal %w[foo], @argv.named - end - - def test_options_only - @argv << "--foo" << "-vds" << "a" << "b" << "cdefg" - assert_equal %w[--foo -vds], @argv.options_only - end - - def test_flags_only - @argv << "--foo" << "-vds" << "a" << "b" << "cdefg" - assert_equal %w[--foo], @argv.flags_only - end - - def test_empty_argv - assert_empty @argv.named - assert_empty @argv.kegs - assert_empty @argv.formulae - assert_empty @argv - end - - def test_switch? - @argv << "-ns" << "-i" << "--bar" << "-a-bad-arg" - %w[n s i].each { |s| assert @argv.switch?(s) } - %w[b ns bar --bar -n a bad arg].each { |s| assert !@argv.switch?(s) } - end - - def test_flag? - @argv << "--foo" << "-bq" << "--bar" - assert @argv.flag?("--foo") - assert @argv.flag?("--bar") - assert @argv.flag?("--baz") - assert @argv.flag?("--qux") - assert !@argv.flag?("--frotz") - assert !@argv.flag?("--debug") - end - - def test_value - @argv << "--foo=" << "--bar=ab" - assert_equal "", @argv.value("foo") - assert_equal "ab", @argv.value("bar") - assert_nil @argv.value("baz") - end - - def test_values - @argv << "--foo=" << "--bar=a" << "--baz=b,c" - assert_equal [], @argv.values("foo") - assert_equal ["a"], @argv.values("bar") - assert_equal ["b", "c"], @argv.values("baz") - assert_nil @argv.values("qux") - end -end diff --git a/Library/Homebrew/test/ENV_spec.rb b/Library/Homebrew/test/ENV_spec.rb new file mode 100644 index 000000000..7b50ca1d4 --- /dev/null +++ b/Library/Homebrew/test/ENV_spec.rb @@ -0,0 +1,189 @@ +require "extend/ENV" + +shared_examples EnvActivation do + subject { env.extend(described_class) } + let(:env) { {}.extend(EnvActivation) } + + it "supports switching compilers" do + subject.clang + expect(subject["LD"]).to be nil + expect(subject["CC"]).to eq(subject["OBJC"]) + end + + describe "#with_build_environment" do + it "restores the environment" do + before = subject.dup + + subject.with_build_environment do + subject["foo"] = "bar" + end + + expect(subject["foo"]).to be nil + expect(subject).to eq(before) + end + + it "ensures the environment is restored" do + before = subject.dup + + expect { + subject.with_build_environment do + subject["foo"] = "bar" + raise StandardError + end + }.to raise_error(StandardError) + + expect(subject["foo"]).to be nil + expect(subject).to eq(before) + end + + it "returns the value of the block" do + expect(subject.with_build_environment { 1 }).to eq(1) + end + + it "does not mutate the interface" do + expected = subject.methods + + subject.with_build_environment do + expect(subject.methods).to eq(expected) + end + + expect(subject.methods).to eq(expected) + end + end + + describe "#append" do + it "appends to an existing key" do + subject["foo"] = "bar" + subject.append "foo", "1" + expect(subject["foo"]).to eq("bar 1") + end + + it "appends to an existing empty key" do + subject["foo"] = "" + subject.append "foo", "1" + expect(subject["foo"]).to eq("1") + end + + it "appends to a non-existant key" do + subject.append "foo", "1" + expect(subject["foo"]).to eq("1") + end + + # NOTE: this may be a wrong behavior; we should probably reject objects that + # do not respond to #to_str. For now this documents existing behavior. + it "coerces a value to a string" do + subject.append "foo", 42 + expect(subject["foo"]).to eq("42") + end + end + + describe "#prepend" do + it "prepends to an existing key" do + subject["foo"] = "bar" + subject.prepend "foo", "1" + expect(subject["foo"]).to eq("1 bar") + end + + it "prepends to an existing empty key" do + subject["foo"] = "" + subject.prepend "foo", "1" + expect(subject["foo"]).to eq("1") + end + + it "prepends to a non-existant key" do + subject.prepend "foo", "1" + expect(subject["foo"]).to eq("1") + end + + # NOTE: this may be a wrong behavior; we should probably reject objects that + # do not respond to #to_str. For now this documents existing behavior. + it "coerces a value to a string" do + subject.prepend "foo", 42 + expect(subject["foo"]).to eq("42") + end + end + + describe "#append_path" do + it "appends to a path" do + subject.append_path "FOO", "/usr/bin" + expect(subject["FOO"]).to eq("/usr/bin") + + subject.append_path "FOO", "/bin" + expect(subject["FOO"]).to eq("/usr/bin#{File::PATH_SEPARATOR}/bin") + end + end + + describe "#prepend_path" do + it "prepends to a path" do + subject.prepend_path "FOO", "/usr/bin" + expect(subject["FOO"]).to eq("/usr/bin") + + subject.prepend_path "FOO", "/bin" + expect(subject["FOO"]).to eq("/bin#{File::PATH_SEPARATOR}/usr/bin") + end + end + + describe "#compiler" do + it "allows switching compilers" do + [:clang, :gcc_4_2, :gcc_4_0].each do |compiler| + subject.public_send(compiler) + expect(subject.compiler).to eq(compiler) + end + end + end + + example "deparallelize_block_form_restores_makeflags" do + subject["MAKEFLAGS"] = "-j4" + + subject.deparallelize do + expect(subject["MAKEFLAGS"]).to be nil + end + + expect(subject["MAKEFLAGS"]).to eq("-j4") + end +end + +describe Stdenv do + include_examples EnvActivation +end + +describe Superenv do + include_examples EnvActivation + + it "initializes deps" do + expect(subject.deps).to eq([]) + expect(subject.keg_only_deps).to eq([]) + end + + describe "#cxx11" do + it "raises an error when the compiler isn't supported" do + %w[gcc gcc-4.7].each do |compiler| + subject["HOMEBREW_CC"] = compiler + + expect { subject.cxx11 } + .to raise_error(/The selected compiler doesn't support C\+\+11:/) + + expect(subject["HOMEBREW_CCCFG"]).to be nil + end + end + + it "supports gcc-5" do + subject["HOMEBREW_CC"] = "gcc-5" + subject.cxx11 + expect(subject["HOMEBREW_CCCFG"]).to include("x") + end + + example "supports gcc-6" do + subject["HOMEBREW_CC"] = "gcc-6" + subject.cxx11 + expect(subject["HOMEBREW_CCCFG"]).to include("x") + end + + it "supports clang" do + subject["HOMEBREW_CC"] = "clang" + subject.cxx11 + expect(subject["HOMEBREW_CCCFG"]).to include("x") + expect(subject["HOMEBREW_CCCFG"]).to include("g") + end + end +end diff --git a/Library/Homebrew/test/ENV_test.rb b/Library/Homebrew/test/ENV_test.rb deleted file mode 100644 index dd6025084..000000000 --- a/Library/Homebrew/test/ENV_test.rb +++ /dev/null @@ -1,201 +0,0 @@ -require "testing_env" -require "extend/ENV" -require "testing_env" - -class IntegrationCommandTestEnv < IntegrationCommandTestCase - def test_env - assert_match(/CMAKE_PREFIX_PATH="#{Regexp.escape(HOMEBREW_PREFIX)}[:"]/, - cmd("--env")) - end - - def test_env_fish - assert_match(/set [-]gx CMAKE_PREFIX_PATH "#{Regexp.quote(HOMEBREW_PREFIX.to_s)}"/, - cmd("--env", "--shell=fish")) - end - - def test_env_csh - assert_match(/setenv CMAKE_PREFIX_PATH #{Regexp.quote(HOMEBREW_PREFIX.to_s)};/, - cmd("--env", "--shell=tcsh")) - end - - def test_env_bash - assert_match(/export CMAKE_PREFIX_PATH="#{Regexp.quote(HOMEBREW_PREFIX.to_s)}"/, - cmd("--env", "--shell=bash")) - end - - def test_env_plain - assert_match(/CMAKE_PREFIX_PATH: #{Regexp.quote(HOMEBREW_PREFIX)}/, - cmd("--env", "--plain")) - end -end - -module SharedEnvTests - def setup - @env = {}.extend(EnvActivation) - end - - def test_switching_compilers - @env.clang - assert_nil @env["LD"] - assert_equal @env["OBJC"], @env["CC"] - end - - def test_with_build_environment_restores_env - before = @env.dup - @env.with_build_environment do - @env["foo"] = "bar" - end - assert_nil @env["foo"] - assert_equal before, @env - end - - def test_with_build_environment_ensures_env_restored - before = @env.dup - begin - @env.with_build_environment do - @env["foo"] = "bar" - raise Exception - end - rescue Exception - end - assert_nil @env["foo"] - assert_equal before, @env - end - - def test_with_build_environment_returns_block_value - assert_equal 1, @env.with_build_environment { 1 } - end - - def test_with_build_environment_does_not_mutate_interface - expected = @env.methods - @env.with_build_environment { assert_equal expected, @env.methods } - assert_equal expected, @env.methods - end - - def test_append_existing_key - @env["foo"] = "bar" - @env.append "foo", "1" - assert_equal "bar 1", @env["foo"] - end - - def test_append_existing_key_empty - @env["foo"] = "" - @env.append "foo", "1" - assert_equal "1", @env["foo"] - end - - def test_append_missing_key - @env.append "foo", "1" - assert_equal "1", @env["foo"] - end - - def test_prepend_existing_key - @env["foo"] = "bar" - @env.prepend "foo", "1" - assert_equal "1 bar", @env["foo"] - end - - def test_prepend_existing_key_empty - @env["foo"] = "" - @env.prepend "foo", "1" - assert_equal "1", @env["foo"] - end - - def test_prepend_missing_key - @env.prepend "foo", "1" - assert_equal "1", @env["foo"] - end - - # NOTE: this may be a wrong behavior; we should probably reject objects that - # do not respond to #to_str. For now this documents existing behavior. - def test_append_coerces_value_to_string - @env.append "foo", 42 - assert_equal "42", @env["foo"] - end - - def test_prepend_coerces_value_to_string - @env.prepend "foo", 42 - assert_equal "42", @env["foo"] - end - - def test_append_path - @env.append_path "FOO", "/usr/bin" - assert_equal "/usr/bin", @env["FOO"] - @env.append_path "FOO", "/bin" - assert_equal "/usr/bin#{File::PATH_SEPARATOR}/bin", @env["FOO"] - end - - def test_prepend_path - @env.prepend_path "FOO", "/usr/bin" - assert_equal "/usr/bin", @env["FOO"] - @env.prepend_path "FOO", "/bin" - assert_equal "/bin#{File::PATH_SEPARATOR}/usr/bin", @env["FOO"] - end - - def test_switching_compilers_updates_compiler - [:clang, :gcc_4_2, :gcc_4_0].each do |compiler| - @env.send(compiler) - assert_equal compiler, @env.compiler - end - end - - def test_deparallelize_block_form_restores_makeflags - @env["MAKEFLAGS"] = "-j4" - @env.deparallelize do - assert_nil @env["MAKEFLAGS"] - end - assert_equal "-j4", @env["MAKEFLAGS"] - end -end - -class StdenvTests < Homebrew::TestCase - include SharedEnvTests - - def setup - super - @env.extend(Stdenv) - end -end - -class SuperenvTests < Homebrew::TestCase - include SharedEnvTests - - def setup - super - @env.extend(Superenv) - end - - def test_initializes_deps - assert_equal [], @env.deps - assert_equal [], @env.keg_only_deps - end - - def test_unsupported_cxx11 - %w[gcc gcc-4.7].each do |compiler| - @env["HOMEBREW_CC"] = compiler - assert_raises do - @env.cxx11 - end - refute_match "x", @env["HOMEBREW_CCCFG"] - end - end - - def test_supported_cxx11_gcc_5 - @env["HOMEBREW_CC"] = "gcc-5" - @env.cxx11 - assert_match "x", @env["HOMEBREW_CCCFG"] - end - - def test_supported_cxx11_gcc_6 - @env["HOMEBREW_CC"] = "gcc-6" - @env.cxx11 - assert_match "x", @env["HOMEBREW_CCCFG"] - end - - def test_supported_cxx11_clang - @env["HOMEBREW_CC"] = "clang" - @env.cxx11 - assert_match "x", @env["HOMEBREW_CCCFG"] - assert_match "g", @env["HOMEBREW_CCCFG"] - end -end diff --git a/Library/Homebrew/test/Gemfile b/Library/Homebrew/test/Gemfile index a7e9eb834..25c8ce7ec 100644 --- a/Library/Homebrew/test/Gemfile +++ b/Library/Homebrew/test/Gemfile @@ -1,20 +1,14 @@ source "https://rubygems.org" -gem "mocha", "~> 1.1" -gem "minitest", "~> 5.3" -gem "rake", "~> 10.3" -gem "parallel_tests", "~> 2.9" +gem "mocha" +gem "minitest" +gem "minitest-reporters" +gem "parallel_tests" +gem "rspec" +gem "rspec-its", require: false +gem "rspec-wait", require: false group :coverage do - # This is SimpleCov v0.12.0 with two fixes merged on top, that finally resolve - # all issues with parallel tests, uncovered files, and tracked files. Switch - # back to stable as soon as v0.12.1 or v0.13.0 is released. For details, see: - # - https://github.com/colszowka/simplecov/pull/513 - # - https://github.com/colszowka/simplecov/pull/520 - gem "simplecov", "0.12.0", - git: "https://github.com/colszowka/simplecov.git", - branch: "master", - ref: "83d8031ddde0927f87ef9327200a98583ca18d77", - require: false + gem "simplecov", require: false gem "codecov", require: false end diff --git a/Library/Homebrew/test/Gemfile.lock b/Library/Homebrew/test/Gemfile.lock index aa4800f34..fba45d77b 100644 --- a/Library/Homebrew/test/Gemfile.lock +++ b/Library/Homebrew/test/Gemfile.lock @@ -1,31 +1,50 @@ -GIT - remote: https://github.com/colszowka/simplecov.git - revision: 83d8031ddde0927f87ef9327200a98583ca18d77 - ref: 83d8031ddde0927f87ef9327200a98583ca18d77 - branch: master - specs: - simplecov (0.12.0) - docile (~> 1.1.0) - json (>= 1.8, < 3) - simplecov-html (~> 0.10.0) - GEM remote: https://rubygems.org/ specs: - codecov (0.1.6) + ansi (1.5.0) + builder (3.2.3) + codecov (0.1.9) json simplecov url + diff-lcs (1.3) docile (1.1.5) - json (2.0.2) + json (2.0.3) metaclass (0.0.4) - minitest (5.9.1) + minitest (5.10.1) + minitest-reporters (1.1.14) + ansi + builder + minitest (>= 5.0) + ruby-progressbar mocha (1.2.1) metaclass (~> 0.0.1) - parallel (1.9.0) - parallel_tests (2.10.0) + parallel (1.10.0) + parallel_tests (2.13.0) parallel - rake (10.5.0) + rspec (3.5.0) + rspec-core (~> 3.5.0) + rspec-expectations (~> 3.5.0) + rspec-mocks (~> 3.5.0) + rspec-core (3.5.4) + rspec-support (~> 3.5.0) + rspec-expectations (3.5.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.5.0) + rspec-its (1.2.0) + rspec-core (>= 3.0.0) + rspec-expectations (>= 3.0.0) + rspec-mocks (3.5.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.5.0) + rspec-support (3.5.0) + rspec-wait (0.0.9) + rspec (>= 3, < 4) + ruby-progressbar (1.8.1) + simplecov (0.13.0) + docile (~> 1.1.0) + json (>= 1.8, < 3) + simplecov-html (~> 0.10.0) simplecov-html (0.10.0) url (0.3.2) @@ -34,11 +53,14 @@ PLATFORMS DEPENDENCIES codecov - minitest (~> 5.3) - mocha (~> 1.1) - parallel_tests (~> 2.9) - rake (~> 10.3) - simplecov (= 0.12.0)! + minitest + minitest-reporters + mocha + parallel_tests + rspec + rspec-its + rspec-wait + simplecov BUNDLED WITH - 1.13.6 + 1.14.3 diff --git a/Library/Homebrew/test/analytics_test.rb b/Library/Homebrew/test/analytics_test.rb deleted file mode 100644 index 37040f3cd..000000000 --- a/Library/Homebrew/test/analytics_test.rb +++ /dev/null @@ -1,26 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestAnalytics < IntegrationCommandTestCase - def test_analytics - HOMEBREW_REPOSITORY.cd do - shutup do - system "git", "init" - end - end - - assert_match "Analytics is disabled (by HOMEBREW_NO_ANALYTICS)", - cmd("analytics", "HOMEBREW_NO_ANALYTICS" => "1") - - cmd("analytics", "off") - assert_match "Analytics is disabled", - cmd("analytics", "HOMEBREW_NO_ANALYTICS" => nil) - - cmd("analytics", "on") - assert_match "Analytics is enabled", cmd("analytics", - "HOMEBREW_NO_ANALYTICS" => nil) - - assert_match "Invalid usage", cmd_fail("analytics", "on", "off") - assert_match "Invalid usage", cmd_fail("analytics", "testball") - cmd("analytics", "regenerate-uuid") - end -end diff --git a/Library/Homebrew/test/audit_test.rb b/Library/Homebrew/test/audit_test.rb index dace4dc2b..f4b7cae4a 100644 --- a/Library/Homebrew/test/audit_test.rb +++ b/Library/Homebrew/test/audit_test.rb @@ -6,13 +6,10 @@ require "dev-cmd/audit" class FormulaTextTests < Homebrew::TestCase def setup + super @dir = mktmpdir end - def teardown - FileUtils.rm_rf @dir - end - def formula_text(name, body = nil, options = {}) path = Pathname.new "#{@dir}/#{name}.rb" path.open("w") do |f| @@ -58,13 +55,10 @@ end class FormulaAuditorTests < Homebrew::TestCase def setup + super @dir = mktmpdir end - def teardown - FileUtils.rm_rf @dir - end - def formula_auditor(name, text, options = {}) path = Pathname.new "#{@dir}/#{name}.rb" path.open("w") do |f| @@ -249,7 +243,7 @@ class FormulaAuditorTests < Homebrew::TestCase needs_compat require "compat/formula_specialties" - ARGV.stubs(:homebrew_developer?).returns false + ENV.delete("HOMEBREW_DEVELOPER") fa = shutup do formula_auditor "foo", <<-EOS.undent class Foo < GithubGistFormula @@ -266,7 +260,7 @@ class FormulaAuditorTests < Homebrew::TestCase needs_compat require "compat/formula_specialties" - ARGV.stubs(:homebrew_developer?).returns false + ENV.delete("HOMEBREW_DEVELOPER") fa = formula_auditor "foo", <<-EOS.undent class Foo < ScriptFileFormula url "http://example.com/foo-1.0.tgz" @@ -281,7 +275,7 @@ class FormulaAuditorTests < Homebrew::TestCase needs_compat require "compat/formula_specialties" - ARGV.stubs(:homebrew_developer?).returns false + ENV.delete("HOMEBREW_DEVELOPER") fa = formula_auditor "foo", <<-EOS.undent class Foo < AmazonWebServicesFormula url "http://example.com/foo-1.0.tgz" @@ -367,13 +361,10 @@ class FormulaAuditorTests < Homebrew::TestCase end EOS - original_value = ENV["HOMEBREW_NO_GITHUB_API"] ENV["HOMEBREW_NO_GITHUB_API"] = "1" fa.audit_github_repository assert_equal [], fa.problems - ensure - ENV["HOMEBREW_NO_GITHUB_API"] = original_value end def test_audit_caveats @@ -428,9 +419,8 @@ class FormulaAuditorTests < Homebrew::TestCase EOS fa.audit_homepage - assert_equal ["The homepage should start with http or https " \ - "(URL is #{fa.formula.homepage}).", "The homepage #{fa.formula.homepage} is not reachable " \ - "(HTTP status code 000)"], fa.problems + assert_equal ["The homepage should start with http or https (URL is #{fa.formula.homepage})."], + fa.problems formula_homepages = { "bar" => "http://www.freedesktop.org/wiki/bar", @@ -440,6 +430,10 @@ class FormulaAuditorTests < Homebrew::TestCase "corge" => "http://savannah.nongnu.org/corge", "grault" => "http://grault.github.io/", "garply" => "http://www.gnome.org/garply", + "sf1" => "http://foo.sourceforge.net/", + "sf2" => "http://foo.sourceforge.net", + "sf3" => "http://foo.sf.net/", + "sf4" => "http://foo.sourceforge.io/", "waldo" => "http://www.gnu.org/waldo", } @@ -464,9 +458,45 @@ class FormulaAuditorTests < Homebrew::TestCase end elsif homepage =~ %r{https:\/\/code\.google\.com} assert_match "#{homepage} should end with a slash", fa.problems.first + elsif homepage =~ /foo\.(sf|sourceforge)\.net/ + assert_match "#{homepage} should be `https://foo.sourceforge.io/`", fa.problems.first else assert_match "Please use https:// for #{homepage}", fa.problems.first end end end + + def test_audit_xcodebuild_suggests_symroot + fa = formula_auditor "foo", <<-EOS.undent + class Foo < Formula + url "http://example.com/foo-1.0.tgz" + homepage "http://example.com" + + def install + xcodebuild "-project", "meow.xcodeproject" + end + end + EOS + + fa.audit_text + + assert_match 'xcodebuild should be passed an explicit "SYMROOT"', fa.problems.first + end + + def test_audit_bare_xcodebuild_suggests_symroot_also + fa = formula_auditor "foo", <<-EOS.undent + class Foo < Formula + url "http://example.com/foo-1.0.tgz" + homepage "http://example.com" + + def install + xcodebuild + end + end + EOS + + fa.audit_text + + assert_match 'xcodebuild should be passed an explicit "SYMROOT"', fa.problems.first + end end diff --git a/Library/Homebrew/test/bash_spec.rb b/Library/Homebrew/test/bash_spec.rb new file mode 100644 index 000000000..1b0f15066 --- /dev/null +++ b/Library/Homebrew/test/bash_spec.rb @@ -0,0 +1,52 @@ +require "open3" + +RSpec::Matchers.define :have_valid_bash_syntax do + match do |file| + stdout, stderr, status = Open3.capture3("/bin/bash", "-n", file) + + @actual = [file, stderr] + + stdout.empty? && status.success? + end + + failure_message do |(file, stderr)| + "expected that #{file} is a valid Bash file:\n#{stderr}" + end +end + +describe "Bash" do + context "brew" do + subject { HOMEBREW_LIBRARY_PATH.parent.parent/"bin/brew" } + it { is_expected.to have_valid_bash_syntax } + end + + context "every `.sh` file" do + it "has valid bash syntax" do + Pathname.glob("#{HOMEBREW_LIBRARY_PATH}/**/*.sh").each do |path| + relative_path = path.relative_path_from(HOMEBREW_LIBRARY_PATH) + next if relative_path.to_s.start_with?("shims/", "test/", "vendor/") + + expect(path).to have_valid_bash_syntax + end + end + end + + context "Bash completion" do + subject { HOMEBREW_LIBRARY_PATH.parent.parent/"completions/bash/brew" } + it { is_expected.to have_valid_bash_syntax } + end + + context "every shim script" do + it "has valid bash syntax" do + # These have no file extension, but can be identified by their shebang. + (HOMEBREW_LIBRARY_PATH/"shims").find do |path| + next if path.directory? + next if path.symlink? + next unless path.executable? + next unless path.read(12) == "#!/bin/bash\n" + + expect(path).to have_valid_bash_syntax + end + end + end +end diff --git a/Library/Homebrew/test/bash_test.rb b/Library/Homebrew/test/bash_test.rb deleted file mode 100644 index 671ab5ec8..000000000 --- a/Library/Homebrew/test/bash_test.rb +++ /dev/null @@ -1,35 +0,0 @@ -require "testing_env" - -class BashTests < Homebrew::TestCase - def assert_valid_bash_syntax(file) - return unless file.exist? - output = Utils.popen_read("/bin/bash -n #{file} 2>&1") - assert $?.success?, output - end - - def test_bin_brew - assert_valid_bash_syntax HOMEBREW_LIBRARY_PATH.parent.parent/"bin/brew" - end - - def test_bash_code - Pathname.glob("#{HOMEBREW_LIBRARY_PATH}/**/*.sh").each do |pn| - pn_relative = pn.relative_path_from(HOMEBREW_LIBRARY_PATH) - next if pn_relative.to_s.start_with?("shims/", "test/", "vendor/") - assert_valid_bash_syntax pn - end - end - - def test_bash_completion - script = HOMEBREW_LIBRARY_PATH.parent.parent/"completions/bash/brew" - assert_valid_bash_syntax script - end - - def test_bash_shims - # These have no file extension, but can be identified by their shebang. - (HOMEBREW_LIBRARY_PATH/"shims").find do |pn| - next if pn.directory? || pn.symlink? - next unless pn.executable? && pn.read(12) == "#!/bin/bash\n" - assert_valid_bash_syntax pn - end - end -end diff --git a/Library/Homebrew/test/blacklist_spec.rb b/Library/Homebrew/test/blacklist_spec.rb new file mode 100644 index 000000000..01882167d --- /dev/null +++ b/Library/Homebrew/test/blacklist_spec.rb @@ -0,0 +1,115 @@ +require "blacklist" + +describe "Blacklist" do + matcher(:be_blacklisted) { match(&method(:blacklisted?)) } + + context "rubygems" do + %w[gem rubygem rubygems].each do |s| + subject { s } + + it { is_expected.to be_blacklisted } + end + end + + context "latex" do + %w[latex tex tex-live texlive TexLive].each do |s| + subject { s } + + it { is_expected.to be_blacklisted } + end + end + + context "pip" do + subject { "pip" } + + it { is_expected.to be_blacklisted } + end + + context "pil" do + subject { "pil" } + + it { is_expected.to be_blacklisted } + end + + context "macruby" do + subject { "MacRuby" } + + it { is_expected.to be_blacklisted } + end + + context "lzma" do + %w[lzma liblzma].each do |s| + subject { s } + + it { is_expected.to be_blacklisted } + end + end + + context "gtest" do + %w[gtest googletest google-test].each do |s| + subject { s } + + it { is_expected.to be_blacklisted } + end + end + + context "gmock" do + %w[gmock googlemock google-mock].each do |s| + subject { s } + + it { is_expected.to be_blacklisted } + end + end + + context "sshpass" do + subject { "sshpass" } + + it { is_expected.to be_blacklisted } + end + + context "gsutil" do + subject { "gsutil" } + + it { is_expected.to be_blacklisted } + end + + context "clojure" do + subject { "clojure" } + + it { is_expected.to be_blacklisted } + end + + context "osmium" do + %w[osmium Osmium].each do |s| + subject { s } + + it { is_expected.to be_blacklisted } + end + end + + context "gfortran" do + subject { "gfortran" } + + it { is_expected.to be_blacklisted } + end + + context "play" do + subject { "play" } + + it { is_expected.to be_blacklisted } + end + + context "haskell-platform" do + subject { "haskell-platform" } + + it { is_expected.to be_blacklisted } + end + + context "xcode", :needs_macos do + %w[xcode Xcode].each do |s| + subject { s } + + it { is_expected.to be_blacklisted } + end + end +end diff --git a/Library/Homebrew/test/blacklist_test.rb b/Library/Homebrew/test/blacklist_test.rb deleted file mode 100644 index 585a35484..000000000 --- a/Library/Homebrew/test/blacklist_test.rb +++ /dev/null @@ -1,68 +0,0 @@ -require "testing_env" -require "blacklist" - -class BlacklistTests < Homebrew::TestCase - def assert_blacklisted(s) - assert blacklisted?(s), "'#{s}' should be blacklisted" - end - - def test_rubygems - %w[gem rubygem rubygems].each { |s| assert_blacklisted s } - end - - def test_latex - %w[latex tex tex-live texlive TexLive].each { |s| assert_blacklisted s } - end - - def test_pip - assert_blacklisted "pip" - end - - def test_pil - assert_blacklisted "pil" - end - - def test_macruby - assert_blacklisted "MacRuby" - end - - def test_lzma - %w[lzma liblzma].each { |s| assert_blacklisted s } - end - - def test_gtest - %w[gtest googletest google-test].each { |s| assert_blacklisted s } - end - - def test_gmock - %w[gmock googlemock google-mock].each { |s| assert_blacklisted s } - end - - def test_sshpass - assert_blacklisted "sshpass" - end - - def test_gsutil - assert_blacklisted "gsutil" - end - - def test_clojure - assert_blacklisted "clojure" - end - - def test_osmium - %w[osmium Osmium].each { |s| assert_blacklisted s } - end - - def test_gfortran - assert_blacklisted "gfortran" - end - - def test_play - assert_blacklisted "play" - end - - def test_haskell_platform - assert_blacklisted "haskell-platform" - end -end diff --git a/Library/Homebrew/test/bottle_collector_test.rb b/Library/Homebrew/test/bottle_collector_test.rb deleted file mode 100644 index d75e29ec8..000000000 --- a/Library/Homebrew/test/bottle_collector_test.rb +++ /dev/null @@ -1,38 +0,0 @@ -require "testing_env" -require "utils/bottles" - -class BottleCollectorTests < Homebrew::TestCase - def setup - @collector = Utils::Bottles::Collector.new - end - - def checksum_for(tag) - @collector.fetch_checksum_for(tag) - end - - def test_collector_returns_passed_tags - @collector[:lion] = "foo" - @collector[:mountain_lion] = "bar" - assert_equal ["bar", :mountain_lion], checksum_for(:mountain_lion) - end - - def test_collector_returns_when_empty - assert_nil checksum_for(:foo) - end - - def test_collector_returns_nil_for_no_match - @collector[:lion] = "foo" - assert_nil checksum_for(:foo) - end - - def test_collector_returns_nil_for_no_match_when_later_tag_present - @collector[:lion_or_later] = "foo" - assert_nil checksum_for(:foo) - end - - def test_collector_prefers_exact_matches - @collector[:lion_or_later] = "foo" - @collector[:mountain_lion] = "bar" - assert_equal ["bar", :mountain_lion], checksum_for(:mountain_lion) - end -end diff --git a/Library/Homebrew/test/bottle_hooks_spec.rb b/Library/Homebrew/test/bottle_hooks_spec.rb new file mode 100644 index 000000000..05c6ea7f0 --- /dev/null +++ b/Library/Homebrew/test/bottle_hooks_spec.rb @@ -0,0 +1,50 @@ +require "formula_installer" +require "hooks/bottles" + +RSpec::Matchers.alias_matcher :pour_bottle, :be_pour_bottle + +describe Homebrew::Hooks::Bottles do + subject { FormulaInstaller.new formula } + + let(:formula) do + double( + bottle: nil, + local_bottle_path: nil, + bottle_disabled?: false, + some_random_method: true, + ) + end + + after(:each) do + described_class.reset_hooks + end + + describe "#setup_formula_has_bottle" do + context "given a block which evaluates to true" do + before(:each) do + described_class.setup_formula_has_bottle(&:some_random_method) + end + + it { is_expected.to pour_bottle } + end + + context "given a block which evaluates to false" do + before(:each) do + described_class.setup_formula_has_bottle { |f| !f.some_random_method } + end + + it { is_expected.not_to pour_bottle } + end + end + + describe "#setup_pour_formula_bottle" do + before(:each) do + described_class.setup_formula_has_bottle { true } + described_class.setup_pour_formula_bottle(&:some_random_method) + end + + it "does not raise an error" do + expect { subject.pour }.not_to raise_error + end + end +end diff --git a/Library/Homebrew/test/bottle_hooks_test.rb b/Library/Homebrew/test/bottle_hooks_test.rb deleted file mode 100644 index 3535d80ef..000000000 --- a/Library/Homebrew/test/bottle_hooks_test.rb +++ /dev/null @@ -1,47 +0,0 @@ -require "testing_env" -require "formula_installer" -require "hooks/bottles" - -class BottleHookTests < Homebrew::TestCase - class FormulaDouble - def bottle; end - def local_bottle_path; end - - def bottle_disabled? - false - end - - def some_random_method - true - end - end - - def setup - @fi = FormulaInstaller.new FormulaDouble.new - end - - def test_has_bottle - Homebrew::Hooks::Bottles.setup_formula_has_bottle(&:some_random_method) - assert_predicate @fi, :pour_bottle? - end - - def test_has_no_bottle - Homebrew::Hooks::Bottles.setup_formula_has_bottle do |f| - !f.some_random_method - end - refute_predicate @fi, :pour_bottle? - end - - def test_pour_formula_bottle - Homebrew::Hooks::Bottles.setup_formula_has_bottle do |_f| - true - end - - Homebrew::Hooks::Bottles.setup_pour_formula_bottle(&:some_random_method) - @fi.pour - end - - def teardown - Homebrew::Hooks::Bottles.reset_hooks - end -end diff --git a/Library/Homebrew/test/bottle_test.rb b/Library/Homebrew/test/bottle_test.rb deleted file mode 100644 index c10746e09..000000000 --- a/Library/Homebrew/test/bottle_test.rb +++ /dev/null @@ -1,21 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestBottle < IntegrationCommandTestCase - def test_bottle - cmd("install", "--build-bottle", testball) - assert_match "Formula not from core or any taps", - cmd_fail("bottle", "--no-rebuild", testball) - - setup_test_formula "testball" - - # `brew bottle` should not fail with dead symlink - # https://github.com/Homebrew/legacy-homebrew/issues/49007 - (HOMEBREW_CELLAR/"testball/0.1").cd do - FileUtils.ln_s "not-exist", "symlink" - end - assert_match(/testball-0\.1.*\.bottle\.tar\.gz/, - cmd_output("bottle", "--no-rebuild", "testball")) - ensure - FileUtils.rm_f Dir["testball-0.1*.bottle.tar.gz"] - end -end diff --git a/Library/Homebrew/test/build_environment_spec.rb b/Library/Homebrew/test/build_environment_spec.rb new file mode 100644 index 000000000..5a3cec452 --- /dev/null +++ b/Library/Homebrew/test/build_environment_spec.rb @@ -0,0 +1,66 @@ +require "build_environment" + +RSpec::Matchers.alias_matcher :use_userpaths, :be_userpaths + +describe BuildEnvironment do + let(:env) { described_class.new } + + describe "#<<" do + it "returns itself" do + expect(env << :foo).to be env + end + end + + describe "#merge" do + it "returns itself" do + expect(env.merge([])).to be env + end + end + + describe "#std?" do + it "returns true if the environment contains :std" do + env << :std + expect(env).to be_std + end + + it "returns false if the environment does not contain :std" do + expect(env).not_to be_std + end + end + + describe "#userpaths?" do + it "returns true if the environment contains :userpaths" do + env << :userpaths + expect(env).to use_userpaths + end + + it "returns false if the environment does not contain :userpaths" do + expect(env).not_to use_userpaths + end + end +end + +describe BuildEnvironmentDSL do + subject { double.extend(described_class) } + + context "single argument" do + before(:each) do + subject.instance_eval do + env :userpaths + end + end + + its(:env) { is_expected.to use_userpaths } + end + + context "multiple arguments" do + before(:each) do + subject.instance_eval do + env :userpaths, :std + end + end + + its(:env) { is_expected.to be_std } + its(:env) { is_expected.to use_userpaths } + end +end diff --git a/Library/Homebrew/test/build_environment_test.rb b/Library/Homebrew/test/build_environment_test.rb deleted file mode 100644 index 73a1c95f7..000000000 --- a/Library/Homebrew/test/build_environment_test.rb +++ /dev/null @@ -1,45 +0,0 @@ -require "testing_env" -require "build_environment" - -class BuildEnvironmentTests < Homebrew::TestCase - def setup - @env = BuildEnvironment.new - end - - def test_shovel_returns_self - assert_same @env, @env << :foo - end - - def test_merge_returns_self - assert_same @env, @env.merge([]) - end - - def test_std? - @env << :std - assert_predicate @env, :std? - end - - def test_userpaths? - @env << :userpaths - assert_predicate @env, :userpaths? - end -end - -class BuildEnvironmentDSLTests < Homebrew::TestCase - def make_instance(&block) - obj = Object.new.extend(BuildEnvironmentDSL) - obj.instance_eval(&block) - obj - end - - def test_env_single_argument - obj = make_instance { env :userpaths } - assert_predicate obj.env, :userpaths? - end - - def test_env_multiple_arguments - obj = make_instance { env :userpaths, :std } - assert_predicate obj.env, :userpaths? - assert_predicate obj.env, :std? - end -end diff --git a/Library/Homebrew/test/build_options_spec.rb b/Library/Homebrew/test/build_options_spec.rb new file mode 100644 index 000000000..5acc12f30 --- /dev/null +++ b/Library/Homebrew/test/build_options_spec.rb @@ -0,0 +1,52 @@ +require "build_options" +require "options" + +RSpec::Matchers.alias_matcher :be_built_with, :be_with +RSpec::Matchers.alias_matcher :be_built_without, :be_without + +describe BuildOptions do + 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]) } + let(:bad_args) { Options.create(%w[--with-foo --with-bar --without-bas --without-qux --without-abc]) } + + specify "#include?" do + expect(subject).to include("with-foo") + expect(subject).not_to include("with-qux") + expect(subject).not_to include("--with-foo") + end + + specify "#with?" do + expect(subject).to be_built_with("foo") + expect(subject).to be_built_with("bar") + expect(subject).to be_built_with("baz") + end + + specify "#without?" do + expect(subject).to be_built_without("qux") + expect(subject).to be_built_without("xyz") + end + + specify "#used_options" do + expect(subject.used_options).to include("--with-foo") + expect(subject.used_options).to include("--with-bar") + end + + specify "#unused_options" do + expect(subject.unused_options).to include("--without-baz") + end + + specify "#invalid_options" do + expect(subject.invalid_options).to be_empty + expect(bad_build.invalid_options).to include("--without-bas") + expect(bad_build.invalid_options).to include("--without-abc") + expect(bad_build.invalid_options).not_to include("--with-foo") + expect(bad_build.invalid_options).not_to include("--with-baz") + end + + specify "#invalid_option_names" do + expect(subject.invalid_option_names).to be_empty + expect(bad_build.invalid_option_names).to eq(%w[--without-abc --without-bas]) + end +end diff --git a/Library/Homebrew/test/build_options_test.rb b/Library/Homebrew/test/build_options_test.rb deleted file mode 100644 index e460d25cc..000000000 --- a/Library/Homebrew/test/build_options_test.rb +++ /dev/null @@ -1,49 +0,0 @@ -require "testing_env" -require "build_options" -require "options" - -class BuildOptionsTests < Homebrew::TestCase - def setup - args = Options.create(%w[--with-foo --with-bar --without-qux]) - opts = Options.create(%w[--with-foo --with-bar --without-baz --without-qux]) - @build = BuildOptions.new(args, opts) - bad_args = Options.create(%w[--with-foo --with-bar --without-bas --without-qux --without-abc]) - @bad_build = BuildOptions.new(bad_args, opts) - end - - def test_include - assert_includes @build, "with-foo" - refute_includes @build, "with-qux" - refute_includes @build, "--with-foo" - end - - def test_with_without - assert @build.with?("foo") - assert @build.with?("bar") - assert @build.with?("baz") - assert @build.without?("qux") - assert @build.without?("xyz") - end - - def test_used_options - assert_includes @build.used_options, "--with-foo" - assert_includes @build.used_options, "--with-bar" - end - - def test_unused_options - assert_includes @build.unused_options, "--without-baz" - end - - def test_invalid_options - assert_empty @build.invalid_options - assert_includes @bad_build.invalid_options, "--without-bas" - assert_includes @bad_build.invalid_options, "--without-abc" - refute_includes @bad_build.invalid_options, "--with-foo" - refute_includes @bad_build.invalid_options, "--with-baz" - end - - def test_invalid_option_names - assert_empty @build.invalid_option_names - assert_equal @bad_build.invalid_option_names, %w[--without-abc --without-bas] - end -end diff --git a/Library/Homebrew/test/bundle_test.rb b/Library/Homebrew/test/bundle_test.rb deleted file mode 100644 index ae47977d8..000000000 --- a/Library/Homebrew/test/bundle_test.rb +++ /dev/null @@ -1,22 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestBundle < IntegrationCommandTestCase - def test_bundle - needs_test_cmd_taps - setup_remote_tap("homebrew/bundle") - HOMEBREW_REPOSITORY.cd do - shutup do - system "git", "init" - system "git", "commit", "--allow-empty", "-m", "This is a test commit" - end - end - - mktmpdir do |path| - FileUtils.touch "#{path}/Brewfile" - Dir.chdir path do - assert_equal "The Brewfile's dependencies are satisfied.", - cmd("bundle", "check") - end - end - end -end diff --git a/Library/Homebrew/test/cache_formula_test.rb b/Library/Homebrew/test/cache_formula_test.rb deleted file mode 100644 index 6dcb6a745..000000000 --- a/Library/Homebrew/test/cache_formula_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestCacheFormula < IntegrationCommandTestCase - def test_cache_formula - assert_match %r{#{HOMEBREW_CACHE}/testball-}, - cmd("--cache", testball) - end -end diff --git a/Library/Homebrew/test/cache_test.rb b/Library/Homebrew/test/cache_test.rb deleted file mode 100644 index 3a9e6b011..000000000 --- a/Library/Homebrew/test/cache_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestCache < IntegrationCommandTestCase - def test_cache - assert_equal HOMEBREW_CACHE.to_s, - cmd("--cache") - end -end diff --git a/Library/Homebrew/test/cask_test.rb b/Library/Homebrew/test/cask_test.rb deleted file mode 100644 index d5b81facb..000000000 --- a/Library/Homebrew/test/cask_test.rb +++ /dev/null @@ -1,10 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestCask < IntegrationCommandTestCase - def test_cask - needs_test_cmd_taps - needs_macos - setup_remote_tap("caskroom/cask") - cmd("cask", "list", "--caskroom=#{HOMEBREW_PREFIX}/Caskroom") - end -end diff --git a/Library/Homebrew/test/cat_test.rb b/Library/Homebrew/test/cat_test.rb deleted file mode 100644 index bb37b5fde..000000000 --- a/Library/Homebrew/test/cat_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestCat < IntegrationCommandTestCase - def test_cat - formula_file = setup_test_formula "testball" - assert_equal formula_file.read.chomp, cmd("cat", "testball") - end -end diff --git a/Library/Homebrew/test/caveats_spec.rb b/Library/Homebrew/test/caveats_spec.rb new file mode 100644 index 000000000..d8be9dc52 --- /dev/null +++ b/Library/Homebrew/test/caveats_spec.rb @@ -0,0 +1,29 @@ +require "formula" +require "caveats" + +describe Caveats do + subject { described_class.new(f) } + let(:f) { formula { url "foo-1.0" } } + + specify "#f" do + expect(subject.f).to eq(f) + end + + describe "#empty?" do + it "returns true if the Formula has no caveats" do + expect(subject).to be_empty + end + + it "returns false if the Formula has caveats" do + f = formula do + url "foo-1.0" + + def caveats + "something" + end + end + + expect(described_class.new(f)).not_to be_empty + end + end +end diff --git a/Library/Homebrew/test/caveats_test.rb b/Library/Homebrew/test/caveats_test.rb deleted file mode 100644 index 9eaac5792..000000000 --- a/Library/Homebrew/test/caveats_test.rb +++ /dev/null @@ -1,29 +0,0 @@ -require "testing_env" -require "formula" -require "caveats" - -class CaveatsTests < Homebrew::TestCase - def setup - @f = formula { url "foo-1.0" } - @c = Caveats.new @f - end - - def test_f - assert_equal @f, @c.f - end - - def test_empty? - assert @c.empty? - - f = formula do - url "foo-1.0" - - def caveats - "something" - end - end - c = Caveats.new f - - refute c.empty? - end -end diff --git a/Library/Homebrew/test/cellar_formula_test.rb b/Library/Homebrew/test/cellar_formula_test.rb deleted file mode 100644 index 38a934a7b..000000000 --- a/Library/Homebrew/test/cellar_formula_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestCellarFormula < IntegrationCommandTestCase - def test_cellar_formula - assert_match "#{HOMEBREW_CELLAR}/testball", - cmd("--cellar", testball) - end -end diff --git a/Library/Homebrew/test/cellar_test.rb b/Library/Homebrew/test/cellar_test.rb deleted file mode 100644 index 74d5389f8..000000000 --- a/Library/Homebrew/test/cellar_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestCellar < IntegrationCommandTestCase - def test_cellar - assert_equal HOMEBREW_CELLAR.to_s, - cmd("--cellar") - end -end diff --git a/Library/Homebrew/test/checksum_spec.rb b/Library/Homebrew/test/checksum_spec.rb new file mode 100644 index 000000000..acab348b7 --- /dev/null +++ b/Library/Homebrew/test/checksum_spec.rb @@ -0,0 +1,19 @@ +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) } + + it { is_expected.to eq(other) } + it { is_expected.not_to eq(other_reversed) } + it { is_expected.not_to eq(other_sha1) } + end +end diff --git a/Library/Homebrew/test/checksum_test.rb b/Library/Homebrew/test/checksum_test.rb deleted file mode 100644 index 5505f6824..000000000 --- a/Library/Homebrew/test/checksum_test.rb +++ /dev/null @@ -1,22 +0,0 @@ -require "testing_env" -require "checksum" - -class ChecksumTests < Homebrew::TestCase - def test_empty? - assert_empty Checksum.new(:sha256, "") - end - - def test_equality - a = Checksum.new(:sha256, TEST_SHA256) - b = Checksum.new(:sha256, TEST_SHA256) - assert_equal a, b - - a = Checksum.new(:sha256, TEST_SHA256) - b = Checksum.new(:sha256, TEST_SHA256.reverse) - refute_equal a, b - - a = Checksum.new(:sha1, TEST_SHA1) - b = Checksum.new(:sha256, TEST_SHA256) - refute_equal a, b - end -end diff --git a/Library/Homebrew/test/checksum_verification_test.rb b/Library/Homebrew/test/checksum_verification_test.rb index 9017b528d..4c674edd2 100644 --- a/Library/Homebrew/test/checksum_verification_test.rb +++ b/Library/Homebrew/test/checksum_verification_test.rb @@ -17,10 +17,6 @@ class ChecksumVerificationTests < Homebrew::TestCase end end - def teardown - @_f.clear_cache - end - def test_good_sha256 formula do sha256 TESTBALL_SHA256 diff --git a/Library/Homebrew/test/cleaner_test.rb b/Library/Homebrew/test/cleaner_test.rb index ac108421c..05a91b90b 100644 --- a/Library/Homebrew/test/cleaner_test.rb +++ b/Library/Homebrew/test/cleaner_test.rb @@ -6,14 +6,11 @@ class CleanerTests < Homebrew::TestCase include FileUtils def setup + super @f = formula("cleaner_test") { url "foo-1.0" } @f.prefix.mkpath end - def teardown - @f.rack.rmtree if @f.rack.exist? - end - def test_clean_file @f.bin.mkpath @f.lib.mkpath diff --git a/Library/Homebrew/test/cleanup_test.rb b/Library/Homebrew/test/cleanup_test.rb index bb8e1cdc6..bc7a6713c 100644 --- a/Library/Homebrew/test/cleanup_test.rb +++ b/Library/Homebrew/test/cleanup_test.rb @@ -5,23 +5,16 @@ require "fileutils" require "pathname" require "testing_env" -class IntegrationCommandTestCleanup < IntegrationCommandTestCase - def test_cleanup - (HOMEBREW_CACHE/"test").write "test" - assert_match "#{HOMEBREW_CACHE}/test", cmd("cleanup", "--prune=all") - end -end - class CleanupTests < Homebrew::TestCase def setup + super @ds_store = Pathname.new "#{HOMEBREW_PREFIX}/Library/.DS_Store" FileUtils.touch @ds_store end def teardown FileUtils.rm_f @ds_store - ARGV.delete "--dry-run" - ARGV.delete "--prune=all" + super end def test_cleanup @@ -36,28 +29,40 @@ class CleanupTests < Homebrew::TestCase end def test_cleanup_formula - f1 = Class.new(Testball) { version "0.1" }.new - f2 = Class.new(Testball) { version "0.2" }.new - f3 = Class.new(Testball) { version "0.3" }.new + f1 = Class.new(Testball) do + version "1.0" + end.new + f2 = Class.new(Testball) do + version "0.2" + version_scheme 1 + end.new + f3 = Class.new(Testball) do + version "0.3" + version_scheme 1 + end.new + f4 = Class.new(Testball) do + version "0.1" + version_scheme 2 + end.new shutup do - f1.brew { f1.install } - f2.brew { f2.install } - f3.brew { f3.install } + [f1, f2, f3, f4].each do |f| + f.brew { f.install } + Tab.create(f, DevelopmentTools.default_compiler, :libcxx).write + end end assert_predicate f1, :installed? assert_predicate f2, :installed? assert_predicate f3, :installed? + assert_predicate f4, :installed? shutup { Homebrew::Cleanup.cleanup_formula f3 } refute_predicate f1, :installed? refute_predicate f2, :installed? assert_predicate f3, :installed? - ensure - [f1, f2, f3].each(&:clear_cache) - f3.rack.rmtree + assert_predicate f4, :installed? end def test_cleanup_logs diff --git a/Library/Homebrew/test/cmd/--cache_spec.rb b/Library/Homebrew/test/cmd/--cache_spec.rb new file mode 100644 index 000000000..fb3c9cee6 --- /dev/null +++ b/Library/Homebrew/test/cmd/--cache_spec.rb @@ -0,0 +1,15 @@ +describe "brew --cache", :integration_test do + it "print the location of Homebrew's cache when no argument is given" do + expect { brew "--cache" } + .to output("#{HOMEBREW_CACHE}\n").to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + + it "prints all cache files for a given Formula" do + expect { brew "--cache", testball } + .to output(%r{#{HOMEBREW_CACHE}/testball-}).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end +end diff --git a/Library/Homebrew/test/cmd/--cellar_spec.rb b/Library/Homebrew/test/cmd/--cellar_spec.rb new file mode 100644 index 000000000..6c8d7dea6 --- /dev/null +++ b/Library/Homebrew/test/cmd/--cellar_spec.rb @@ -0,0 +1,15 @@ +describe "brew --cellar", :integration_test do + it "print the location of Homebrew's Cellar when no argument is given" do + expect { brew "--cellar" } + .to output("#{HOMEBREW_CELLAR}\n").to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + + it "returns the Cellar subdirectory for a given Formula" do + expect { brew "--cellar", testball } + .to output(%r{#{HOMEBREW_CELLAR}/testball}).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end +end diff --git a/Library/Homebrew/test/cmd/--env_spec.rb b/Library/Homebrew/test/cmd/--env_spec.rb new file mode 100644 index 000000000..7dd84132a --- /dev/null +++ b/Library/Homebrew/test/cmd/--env_spec.rb @@ -0,0 +1,44 @@ +describe "brew --env", :integration_test do + it "prints the Homebrew build environment variables" do + expect { brew "--env" } + .to output(/CMAKE_PREFIX_PATH="#{Regexp.escape(HOMEBREW_PREFIX)}[:"]/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + + describe "--shell=bash" do + it "prints the Homebrew build environment variables in Bash syntax" do + expect { brew "--env", "--shell=bash" } + .to output(/export CMAKE_PREFIX_PATH="#{Regexp.quote(HOMEBREW_PREFIX.to_s)}"/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + end + + describe "--shell=fish" do + it "prints the Homebrew build environment variables in Fish syntax" do + expect { brew "--env", "--shell=fish" } + .to output(/set [-]gx CMAKE_PREFIX_PATH "#{Regexp.quote(HOMEBREW_PREFIX.to_s)}"/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + end + + describe "--shell=tcsh" do + it "prints the Homebrew build environment variables in Tcsh syntax" do + expect { brew "--env", "--shell=tcsh" } + .to output(/setenv CMAKE_PREFIX_PATH #{Regexp.quote(HOMEBREW_PREFIX.to_s)};/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + end + + describe "--plain" do + it "prints the Homebrew build environment variables without quotes" do + expect { brew "--env", "--plain" } + .to output(/CMAKE_PREFIX_PATH: #{Regexp.quote(HOMEBREW_PREFIX)}/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + end +end diff --git a/Library/Homebrew/test/cmd/--prefix_spec.rb b/Library/Homebrew/test/cmd/--prefix_spec.rb new file mode 100644 index 000000000..80ef73a97 --- /dev/null +++ b/Library/Homebrew/test/cmd/--prefix_spec.rb @@ -0,0 +1,15 @@ +describe "brew --prefix", :integration_test do + it "prints the Homebrew prefix when no argument is given" do + expect { brew "--prefix" } + .to output("#{HOMEBREW_PREFIX}\n").to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + + it "prints a given Formula's prefix" do + expect { brew "--prefix", testball } + .to output(%r{#{HOMEBREW_CELLAR}/testball}).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end +end diff --git a/Library/Homebrew/test/cmd/--repository_spec.rb b/Library/Homebrew/test/cmd/--repository_spec.rb new file mode 100644 index 000000000..d3e531f7b --- /dev/null +++ b/Library/Homebrew/test/cmd/--repository_spec.rb @@ -0,0 +1,15 @@ +describe "brew --repository", :integration_test do + it "prints the path of the Homebrew repository" do + expect { brew "--repository" } + .to output("#{HOMEBREW_REPOSITORY}\n").to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + + it "prints the path of a given Tap" do + expect { brew "--repository", "foo/bar" } + .to output("#{HOMEBREW_LIBRARY}/Taps/foo/homebrew-bar\n").to_stdout + .and not_to_output.to_stderr + .and be_a_success + end +end diff --git a/Library/Homebrew/test/cmd/--version_spec.rb b/Library/Homebrew/test/cmd/--version_spec.rb new file mode 100644 index 000000000..8992629d7 --- /dev/null +++ b/Library/Homebrew/test/cmd/--version_spec.rb @@ -0,0 +1,8 @@ +describe "brew --version", :integration_test do + it "prints the Homebrew version" do + expect { brew "--version" } + .to output(/^Homebrew #{Regexp.escape(HOMEBREW_VERSION.to_s)}\n/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end +end diff --git a/Library/Homebrew/test/cmd/analytics_spec.rb b/Library/Homebrew/test/cmd/analytics_spec.rb new file mode 100644 index 000000000..aed3a7a33 --- /dev/null +++ b/Library/Homebrew/test/cmd/analytics_spec.rb @@ -0,0 +1,52 @@ +describe "brew analytics", :integration_test do + before(:each) do + HOMEBREW_REPOSITORY.cd do + shutup do + system "git", "init" + end + end + end + + it "is disabled when HOMEBREW_NO_ANALYTICS is set" do + expect { brew "analytics", "HOMEBREW_NO_ANALYTICS" => "1" } + .to output(/Analytics is disabled \(by HOMEBREW_NO_ANALYTICS\)/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + + context "when HOMEBREW_NO_ANALYTICS is unset" do + it "is disabled after running `brew analytics off`" do + brew "analytics", "off" + expect { brew "analytics", "HOMEBREW_NO_ANALYTICS" => nil } + .to output(/Analytics is disabled/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + + it "is enabled after running `brew analytics on`" do + brew "analytics", "on" + expect { brew "analytics", "HOMEBREW_NO_ANALYTICS" => nil } + .to output(/Analytics is enabled/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + end + + it "fails when running `brew analytics on off`" do + expect { brew "analytics", "on", "off" } + .to output(/Invalid usage/).to_stderr + .and not_to_output.to_stdout + .and be_a_failure + end + + it "fails when running `brew analytics testball`" do + expect { brew "analytics", "testball" } + .to output(/Invalid usage/).to_stderr + .and not_to_output.to_stdout + .and be_a_failure + end + + it "can generate a new UUID" do + expect { brew "analytics", "regenerate-uuid" }.to be_a_success + end +end diff --git a/Library/Homebrew/test/cmd/bundle_spec.rb b/Library/Homebrew/test/cmd/bundle_spec.rb new file mode 100644 index 000000000..755f9ab3d --- /dev/null +++ b/Library/Homebrew/test/cmd/bundle_spec.rb @@ -0,0 +1,24 @@ +describe "brew bundle", :integration_test, :needs_test_cmd_taps do + describe "check" do + it "checks if a Brewfile's dependencies are satisfied" do + setup_remote_tap "homebrew/bundle" + + HOMEBREW_REPOSITORY.cd do + shutup do + system "git", "init" + system "git", "commit", "--allow-empty", "-m", "This is a test commit" + end + end + + Dir.mktmpdir do |path| + FileUtils.touch "#{path}/Brewfile" + Dir.chdir path do + expect { brew "bundle", "check" } + .to output("The Brewfile's dependencies are satisfied.\n").to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + end + end + end +end diff --git a/Library/Homebrew/test/cmd/cask_spec.rb b/Library/Homebrew/test/cmd/cask_spec.rb new file mode 100644 index 000000000..e46843cab --- /dev/null +++ b/Library/Homebrew/test/cmd/cask_spec.rb @@ -0,0 +1,8 @@ +describe "brew cask", :integration_test, :needs_macos, :needs_official_cmd_taps do + describe "list" do + it "returns a list of installed Casks" do + setup_remote_tap("caskroom/cask") + expect { brew "cask", "list" }.to be_a_success + end + end +end diff --git a/Library/Homebrew/test/cmd/cat_spec.rb b/Library/Homebrew/test/cmd/cat_spec.rb new file mode 100644 index 000000000..8c230abee --- /dev/null +++ b/Library/Homebrew/test/cmd/cat_spec.rb @@ -0,0 +1,11 @@ +describe "brew cat", :integration_test do + it "prints the content of a given Formula" do + formula_file = setup_test_formula "testball" + content = formula_file.read + + expect { brew "cat", "testball" } + .to output(content).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end +end diff --git a/Library/Homebrew/test/cmd/cleanup_spec.rb b/Library/Homebrew/test/cmd/cleanup_spec.rb new file mode 100644 index 000000000..9e2cf493f --- /dev/null +++ b/Library/Homebrew/test/cmd/cleanup_spec.rb @@ -0,0 +1,12 @@ +describe "brew cleanup", :integration_test do + describe "--prune=all" do + it "removes all files in Homebrew's cache" do + (HOMEBREW_CACHE/"test").write "test" + + expect { brew "cleanup", "--prune=all" } + .to output(%r{#{Regexp.escape(HOMEBREW_CACHE)}/test}).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + end +end diff --git a/Library/Homebrew/test/cmd/command_spec.rb b/Library/Homebrew/test/cmd/command_spec.rb new file mode 100644 index 000000000..5d6a67b70 --- /dev/null +++ b/Library/Homebrew/test/cmd/command_spec.rb @@ -0,0 +1,13 @@ +describe "brew command", :integration_test do + it "returns the file for a given command" do + expect { brew "command", "info" } + .to output(%r{#{Regexp.escape(HOMEBREW_LIBRARY_PATH)}/cmd/info.rb}).to_stdout + .and be_a_success + end + + it "fails when the given command is unknown" do + expect { brew "command", "does-not-exist" } + .to output(/Unknown command/).to_stderr + .and be_a_failure + end +end diff --git a/Library/Homebrew/test/cmd/commands_spec.rb b/Library/Homebrew/test/cmd/commands_spec.rb new file mode 100644 index 000000000..f42072956 --- /dev/null +++ b/Library/Homebrew/test/cmd/commands_spec.rb @@ -0,0 +1,7 @@ +describe "brew commands", :integration_test do + it "prints a list of all available commands" do + expect { brew "commands" } + .to output(/Built-in commands/).to_stdout + .and be_a_success + end +end diff --git a/Library/Homebrew/test/cmd/config_spec.rb b/Library/Homebrew/test/cmd/config_spec.rb new file mode 100644 index 000000000..7687fcdc7 --- /dev/null +++ b/Library/Homebrew/test/cmd/config_spec.rb @@ -0,0 +1,8 @@ +describe "brew config", :integration_test do + it "prints information about the current Homebrew configuration" do + expect { brew "config" } + .to output(/HOMEBREW_VERSION: #{HOMEBREW_VERSION}/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end +end diff --git a/Library/Homebrew/test/cmd/custom-external-command_spec.rb b/Library/Homebrew/test/cmd/custom-external-command_spec.rb new file mode 100644 index 000000000..8ccc21fa7 --- /dev/null +++ b/Library/Homebrew/test/cmd/custom-external-command_spec.rb @@ -0,0 +1,21 @@ +describe "brew custom-external-command", :integration_test do + it "is supported" do + Dir.mktmpdir do |path| + path = Pathname.new(path) + + cmd = "custom-external-command-#{rand}" + file = path/"brew-#{cmd}" + + file.write <<-EOS.undent + #!/bin/sh + echo 'I am #{cmd}.' + EOS + FileUtils.chmod "+x", file + + expect { brew cmd, "PATH" => "#{path}#{File::PATH_SEPARATOR}#{ENV["PATH"]}" } + .to output("I am #{cmd}.\n").to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + end +end diff --git a/Library/Homebrew/test/cmd/desc_spec.rb b/Library/Homebrew/test/cmd/desc_spec.rb new file mode 100644 index 000000000..b09819d81 --- /dev/null +++ b/Library/Homebrew/test/cmd/desc_spec.rb @@ -0,0 +1,40 @@ +describe "brew desc", :integration_test do + let(:desc_cache) { HOMEBREW_CACHE/"desc_cache.json" } + + it "shows a given Formula's description" do + setup_test_formula "testball" + + expect { brew "desc", "testball" } + .to output("testball: Some test\n").to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + + it "fails when both --search and --name are specified" do + expect { brew "desc", "--search", "--name" } + .to output(/Pick one, and only one/).to_stderr + .and not_to_output.to_stdout + .and be_a_failure + end + + describe "--search" do + it "fails when no search term is given" do + expect { brew "desc", "--search" } + .to output(/You must provide a search term/).to_stderr + .and not_to_output.to_stdout + .and be_a_failure + end + end + + describe "--description" do + it "creates a description cache" do + expect(desc_cache).not_to exist + + shutup do + expect { brew "desc", "--description", "testball" }.to be_a_success + end + + expect(desc_cache).to exist + end + end +end diff --git a/Library/Homebrew/test/cmd/doctor_spec.rb b/Library/Homebrew/test/cmd/doctor_spec.rb new file mode 100644 index 000000000..530adcd98 --- /dev/null +++ b/Library/Homebrew/test/cmd/doctor_spec.rb @@ -0,0 +1,6 @@ +describe "brew doctor", :integration_test do + specify "check_integration_test" do + expect { brew "doctor", "check_integration_test" } + .to output(/This is an integration test/).to_stderr + end +end diff --git a/Library/Homebrew/test/cmd/fetch_spec.rb b/Library/Homebrew/test/cmd/fetch_spec.rb new file mode 100644 index 000000000..111d9f85c --- /dev/null +++ b/Library/Homebrew/test/cmd/fetch_spec.rb @@ -0,0 +1,13 @@ +describe "brew fetch", :integration_test do + it "downloads the Formula's URL" do + setup_test_formula "testball" + + expect(HOMEBREW_CACHE/"testball-0.1.tbz").not_to exist + + shutup do + expect { brew "fetch", "testball" }.to be_a_success + end + + expect(HOMEBREW_CACHE/"testball-0.1.tbz").to exist + end +end diff --git a/Library/Homebrew/test/cmd/help_spec.rb b/Library/Homebrew/test/cmd/help_spec.rb new file mode 100644 index 000000000..6d94d7444 --- /dev/null +++ b/Library/Homebrew/test/cmd/help_spec.rb @@ -0,0 +1,47 @@ +describe "brew", :integration_test do + it "prints help when no argument is given" do + expect { brew } + .to output(/Example usage:\n/).to_stderr + .and be_a_failure + end + + describe "help" do + it "prints help" do + expect { brew "help" } + .to output(/Example usage:\n/).to_stdout + .and be_a_success + end + + it "prints help for a documented Ruby command" do + expect { brew "help", "cat" } + .to output(/^brew cat/).to_stdout + .and be_a_success + end + + it "prints help for a documented shell command" do + expect { brew "help", "update" } + .to output(/^brew update/).to_stdout + .and be_a_success + end + + it "prints help for a documented Ruby developer command" do + expect { brew "help", "update-test" } + .to output(/^brew update-test/).to_stdout + .and be_a_success + end + + it "fails when given an unknown command" do + expect { brew "help", "command-that-does-not-exist" } + .to output(/Unknown command: command-that-does-not-exist/).to_stderr + .and be_a_failure + end + end + + describe "cat" do + it "prints help when no argument is given" do + expect { brew "cat" } + .to output(/^brew cat/).to_stderr + .and be_a_failure + end + end +end diff --git a/Library/Homebrew/test/cmd/home_spec.rb b/Library/Homebrew/test/cmd/home_spec.rb new file mode 100644 index 000000000..5a4070492 --- /dev/null +++ b/Library/Homebrew/test/cmd/home_spec.rb @@ -0,0 +1,17 @@ +describe "brew home", :integration_test do + it "opens the Homebrew homepage when no argument is given" do + expect { brew "home", "HOMEBREW_BROWSER" => "echo" } + .to output("#{HOMEBREW_WWW}\n").to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + + it "opens the homepage for a given Formula" do + setup_test_formula "testball" + + expect { brew "home", "testball", "HOMEBREW_BROWSER" => "echo" } + .to output("#{Formula["testball"].homepage}\n").to_stdout + .and not_to_output.to_stderr + .and be_a_success + end +end diff --git a/Library/Homebrew/test/cmd/info_spec.rb b/Library/Homebrew/test/cmd/info_spec.rb new file mode 100644 index 000000000..8deef3d23 --- /dev/null +++ b/Library/Homebrew/test/cmd/info_spec.rb @@ -0,0 +1,30 @@ +require "cmd/info" + +describe "brew info", :integration_test do + it "prints information about a given Formula" do + setup_test_formula "testball" + + expect { brew "info", "testball" } + .to output(/testball: stable 0.1/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end +end + +describe Homebrew do + let(:remote) { "https://github.com/Homebrew/homebrew-core" } + + specify "::github_remote_path" do + expect(subject.github_remote_path(remote, "Formula/git.rb")) + .to eq("https://github.com/Homebrew/homebrew-core/blob/master/Formula/git.rb") + + expect(subject.github_remote_path("#{remote}.git", "Formula/git.rb")) + .to eq("https://github.com/Homebrew/homebrew-core/blob/master/Formula/git.rb") + + expect(subject.github_remote_path("git@github.com:user/repo", "foo.rb")) + .to eq("https://github.com/user/repo/blob/master/foo.rb") + + expect(subject.github_remote_path("https://mywebsite.com", "foo/bar.rb")) + .to eq("https://mywebsite.com/foo/bar.rb") + end +end diff --git a/Library/Homebrew/test/cmd/install_spec.rb b/Library/Homebrew/test/cmd/install_spec.rb new file mode 100644 index 000000000..c1240a30e --- /dev/null +++ b/Library/Homebrew/test/cmd/install_spec.rb @@ -0,0 +1,243 @@ +describe "brew install", :integration_test do + it "installs Formulae" do + setup_test_formula "testball1" + + expect { brew "install", "testball1", "--head" } + .to output(/Specify `\-\-HEAD`/).to_stderr + .and not_to_output.to_stdout + .and be_a_failure + + expect { brew "install", "testball1", "--HEAD" } + .to output(/No head is defined/).to_stderr + .and not_to_output.to_stdout + .and be_a_failure + + expect { brew "install", "testball1", "--devel" } + .to output(/No devel block/).to_stderr + .and not_to_output.to_stdout + .and be_a_failure + + expect { brew "install", "testball1" } + .to output(%r{#{HOMEBREW_CELLAR}/testball1/0\.1}).to_stdout + .and not_to_output.to_stderr + .and be_a_success + + expect { brew "install", "testball1" } + .to output(/testball1\-0\.1 already installed/).to_stderr + .and not_to_output.to_stdout + .and be_a_success + + expect { brew "install", "macruby" } + .to output(/MacRuby is not packaged/).to_stderr + .and not_to_output.to_stdout + .and be_a_failure + + expect { brew "install", "formula" } + .to output(/No available formula/).to_stderr + .and output(/Searching for similarly named formulae/).to_stdout + .and be_a_failure + + expect { brew "install", "testball" } + .to output(/This similarly named formula was found/).to_stdout + .and output(/No available formula/).to_stderr + .and be_a_failure + + setup_test_formula "testball2" + expect { brew "install", "testball" } + .to output(/These similarly named formulae were found/).to_stdout + .and output(/No available formula/).to_stderr + .and be_a_failure + + install_and_rename_coretap_formula "testball1", "testball2" + expect { brew "install", "testball2" } + .to output(/testball1 already installed, it's just not migrated/).to_stderr + .and output(/You can migrate formula with `brew migrate testball2`/).to_stdout + .and be_a_success + end + + specify "install failures" do + path = setup_test_formula "testball1", <<-EOS.undent + version "1.0" + EOS + + expect { brew "install", "testball1" } + .to output(%r{#{HOMEBREW_CELLAR}/testball1/1\.0}).to_stdout + .and not_to_output.to_stderr + .and be_a_success + + FileUtils.rm path + setup_test_formula "testball1", <<-EOS.undent + version "2.0" + + devel do + url "#{Formulary.factory("testball1").stable.url}" + sha256 "#{TESTBALL_SHA256}" + version "3.0" + end + EOS + + expect { brew "install", "testball1" } + .to output(/first `brew unlink testball1`/).to_stderr + .and not_to_output.to_stdout + .and be_a_failure + + expect { brew "unlink", "testball1" } + .to output(%r{#{HOMEBREW_CELLAR}/testball1/1\.0}).to_stdout + .and not_to_output.to_stderr + .and be_a_success + + expect { brew "install", "testball1", "--devel" } + .to output(%r{#{HOMEBREW_CELLAR}/testball1/3\.0}).to_stdout + .and not_to_output.to_stderr + .and be_a_success + + expect { brew "unlink", "testball1" } + .to output(%r{#{HOMEBREW_CELLAR}/testball1/3\.0}).to_stdout + .and not_to_output.to_stderr + .and be_a_success + + expect { brew "install", "testball1" } + .to output(%r{#{HOMEBREW_CELLAR}/testball1/2\.0}).to_stdout + .and not_to_output.to_stderr + .and be_a_success + + shutup do + expect { brew "switch", "testball1", "3.0" }.to be_a_success + end + + expect { brew "install", "testball1" } + .to output(/already installed, however linked version is/).to_stderr + .and output(/`brew switch testball1 2.0`/).to_stdout + .and be_a_success + + expect { brew "unlink", "testball1" } + .to output(%r{#{HOMEBREW_CELLAR}/testball1/3\.0}).to_stdout + .and not_to_output.to_stderr + .and be_a_success + + expect { brew "install", "testball1" } + .to output(/just not linked/).to_stderr + .and not_to_output.to_stdout + .and be_a_success + end + + it "can install keg-only Formulae" do + path_keg_only = setup_test_formula "testball1", <<-EOS.undent + version "1.0" + + keg_only "test reason" + EOS + + expect { brew "install", "testball1" } + .to output(%r{#{HOMEBREW_CELLAR}/testball1/1\.0}).to_stdout + .and not_to_output.to_stderr + .and be_a_success + + FileUtils.rm path_keg_only + setup_test_formula "testball1", <<-EOS.undent + version "2.0" + + keg_only "test reason" + EOS + + expect { brew "install", "testball1" } + .to output(/keg-only and another version is linked to opt/).to_stderr + .and output(/Use `brew install --force`/).to_stdout + .and be_a_success + + expect { brew "install", "testball1", "--force" } + .to output(%r{#{HOMEBREW_CELLAR}/testball1/2\.0}).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + + it "can install HEAD Formulae" do + repo_path = HOMEBREW_CACHE.join("repo") + repo_path.join("bin").mkpath + + repo_path.cd do + shutup do + system "git", "init" + system "git", "remote", "add", "origin", "https://github.com/Homebrew/homebrew-foo" + FileUtils.touch "bin/something.bin" + FileUtils.touch "README" + system "git", "add", "--all" + system "git", "commit", "-m", "Initial repo commit" + end + end + + setup_test_formula "testball1", <<-EOS.undent + version "1.0" + + head "file://#{repo_path}", :using => :git + + def install + prefix.install Dir["*"] + end + EOS + + # Ignore dependencies, because we'll try to resolve requirements in build.rb + # and there will be the git requirement, but we cannot instantiate git + # formula since we only have testball1 formula. + expect { brew "install", "testball1", "--HEAD", "--ignore-dependencies" } + .to output(%r{#{HOMEBREW_CELLAR}/testball1/HEAD\-d5eb689}).to_stdout + .and output(/Cloning into/).to_stderr + .and be_a_success + + expect { brew "install", "testball1", "--HEAD", "--ignore-dependencies" } + .to output(/testball1\-HEAD\-d5eb689 already installed/).to_stderr + .and not_to_output.to_stdout + .and be_a_success + + expect { brew "unlink", "testball1" } + .to output(%r{#{HOMEBREW_CELLAR}/testball1/HEAD\-d5eb689}).to_stdout + .and not_to_output.to_stderr + .and be_a_success + + expect { brew "install", "testball1" } + .to output(%r{#{HOMEBREW_CELLAR}/testball1/1\.0}).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + + it "ignores invalid options" do + setup_test_formula "testball1" + expect { brew "install", "testball1", "--with-fo" } + .to output(/testball1: this formula has no \-\-with\-fo option so it will be ignored!/).to_stderr + .and output(/Downloading file/).to_stdout + .and be_a_success + end + + it "succeeds when a non-fatal requirement isn't satisfied" do + setup_test_formula "testball1", <<-EOS.undent + class NonFatalRequirement < Requirement + satisfy { false } + end + + depends_on NonFatalRequirement + EOS + + # FIXME: This should output to STDERR. + expect { brew "install", "testball1" } + .to output(/NonFatalRequirement unsatisfied!/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + + it "fails when a fatal requirement isn't satisfied" do + setup_test_formula "testball1", <<-EOS.undent + class FatalRequirement < Requirement + fatal true + satisfy { false } + end + + depends_on FatalRequirement + EOS + + # FIXME: This should output to STDERR. + expect { brew "install", "testball1" } + .to output(/FatalRequirement unsatisfied!/).to_stdout + .and output(/An unsatisfied requirement failed this build./).to_stderr + .and be_a_failure + end +end diff --git a/Library/Homebrew/test/cmd/irb_spec.rb b/Library/Homebrew/test/cmd/irb_spec.rb new file mode 100644 index 000000000..44410fabe --- /dev/null +++ b/Library/Homebrew/test/cmd/irb_spec.rb @@ -0,0 +1,24 @@ +describe "brew irb", :integration_test do + it "starts an interactive Homebrew shell session" do + setup_test_formula "testball" + + irb_test = HOMEBREW_TEMP/"irb-test.rb" + irb_test.write <<-EOS.undent + "testball".f + :testball.f + exit + EOS + + expect { brew "irb", irb_test } + .to output(/Interactive Homebrew Shell/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + + specify "--examples" do + expect { brew "irb", "--examples" } + .to output(/'v8'\.f # => instance of the v8 formula/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end +end diff --git a/Library/Homebrew/test/cmd/leaves_spec.rb b/Library/Homebrew/test/cmd/leaves_spec.rb new file mode 100644 index 000000000..cd93d7e3d --- /dev/null +++ b/Library/Homebrew/test/cmd/leaves_spec.rb @@ -0,0 +1,23 @@ +describe "brew leaves", :integration_test do + it "prints all Formulae that are not dependencies of other Formulae" do + setup_test_formula "foo" + setup_test_formula "bar" + + expect { brew "leaves" } + .to be_a_success + .and not_to_output.to_stdout + .and not_to_output.to_stderr + + (HOMEBREW_CELLAR/"foo/0.1/somedir").mkpath + expect { brew "leaves" } + .to output("foo\n").to_stdout + .and not_to_output.to_stderr + .and be_a_success + + (HOMEBREW_CELLAR/"bar/0.1/somedir").mkpath + expect { brew "leaves" } + .to output("bar\n").to_stdout + .and not_to_output.to_stderr + .and be_a_success + end +end diff --git a/Library/Homebrew/test/cmd/link_spec.rb b/Library/Homebrew/test/cmd/link_spec.rb new file mode 100644 index 000000000..7b85c96dc --- /dev/null +++ b/Library/Homebrew/test/cmd/link_spec.rb @@ -0,0 +1,56 @@ +describe "brew link", :integration_test do + it "fails when no argument is given" do + expect { brew "link" } + .to output(/This command requires a keg argument/).to_stderr + .and not_to_output.to_stdout + .and be_a_failure + end + + it "does not fail if the given Formula is already linked" do + setup_test_formula "testball1" + + shutup do + expect { brew "install", "testball1" }.to be_a_success + expect { brew "link", "testball1" }.to be_a_success + end + end + + it "links a given Formula" do + setup_test_formula "testball1" + + shutup do + expect { brew "install", "testball1" }.to be_a_success + expect { brew "unlink", "testball1" }.to be_a_success + end + + expect { brew "link", "--dry-run", "testball1" } + .to output(/Would link/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + + expect { brew "link", "--dry-run", "--overwrite", "testball1" } + .to output(/Would remove/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + + expect { brew "link", "testball1" } + .to output(/Linking/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + + it "refuses to link keg-only Formulae" do + setup_test_formula "testball1", <<-EOS.undent + keg_only "just because" + EOS + + shutup do + expect { brew "install", "testball1" }.to be_a_success + end + + expect { brew "link", "testball1" } + .to output(/testball1 is keg-only/).to_stderr + .and output(/Note that doing so can interfere with building software\./).to_stdout + .and be_a_success + end +end diff --git a/Library/Homebrew/test/cmd/linkapps_spec.rb b/Library/Homebrew/test/cmd/linkapps_spec.rb new file mode 100644 index 000000000..42118a215 --- /dev/null +++ b/Library/Homebrew/test/cmd/linkapps_spec.rb @@ -0,0 +1,24 @@ +describe "brew linkapps", :integration_test do + let(:home_dir) { @home_dir = Pathname.new(Dir.mktmpdir) } + let(:apps_dir) { home_dir/"Applications" } + + after(:each) do + home_dir.rmtree unless @home_dir.nil? + end + + it "symlinks applications" do + apps_dir.mkpath + + setup_test_formula "testball" + + source_app = HOMEBREW_CELLAR/"testball/0.1/TestBall.app" + source_app.mkpath + + expect { brew "linkapps", "--local", "HOME" => home_dir } + .to output(/Linking: #{Regexp.escape(source_app)}/).to_stdout + .and output(/`brew linkapps` has been deprecated/).to_stderr + .and be_a_success + + expect(apps_dir/"TestBall.app").to be_a_symlink + end +end diff --git a/Library/Homebrew/test/cmd/list_spec.rb b/Library/Homebrew/test/cmd/list_spec.rb new file mode 100644 index 000000000..df7394d7b --- /dev/null +++ b/Library/Homebrew/test/cmd/list_spec.rb @@ -0,0 +1,14 @@ +describe "brew list", :integration_test do + let(:formulae) { %w[bar foo qux] } + + it "prints all installed Formulae" do + formulae.each do |f| + (HOMEBREW_CELLAR/f/"1.0/somedir").mkpath + end + + expect { brew "list" } + .to output("#{formulae.join("\n")}\n").to_stdout + .and not_to_output.to_stderr + .and be_a_success + end +end diff --git a/Library/Homebrew/test/cmd/log_spec.rb b/Library/Homebrew/test/cmd/log_spec.rb new file mode 100644 index 000000000..bdbca8912 --- /dev/null +++ b/Library/Homebrew/test/cmd/log_spec.rb @@ -0,0 +1,41 @@ +describe "brew log", :integration_test do + it "shows the Git log for the Homebrew repository when no argument is given" do + HOMEBREW_REPOSITORY.cd do + shutup do + system "git", "init" + system "git", "commit", "--allow-empty", "-m", "This is a test commit" + end + end + + expect { brew "log" } + .to output(/This is a test commit/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + + it "shows the Git log for a given Formula" do + setup_test_formula "testball" + + core_tap = CoreTap.new + core_tap.path.cd do + shutup do + system "git", "init" + system "git", "add", "--all" + system "git", "commit", "-m", "This is a test commit for Testball" + end + end + + core_tap_url = "file://#{core_tap.path}" + shallow_tap = Tap.fetch("homebrew", "shallow") + shutup do + system "git", "clone", "--depth=1", core_tap_url, shallow_tap.path + end + + expect { brew "log", "#{shallow_tap}/testball" } + .to output(/This is a test commit for Testball/).to_stdout + .and output(/Warning: The git repository is a shallow clone/).to_stderr + .and be_a_success + + expect(shallow_tap.path/".git/shallow").to exist, "A shallow clone should have been created." + end +end diff --git a/Library/Homebrew/test/cmd/migrate_spec.rb b/Library/Homebrew/test/cmd/migrate_spec.rb new file mode 100644 index 000000000..18c94fa01 --- /dev/null +++ b/Library/Homebrew/test/cmd/migrate_spec.rb @@ -0,0 +1,46 @@ +describe "brew migrate", :integration_test do + before(:each) do + setup_test_formula "testball1" + setup_test_formula "testball2" + end + + it "fails when no argument is given" do + expect { brew "migrate" } + .to output(/Invalid usage/).to_stderr + .and not_to_output.to_stdout + .and be_a_failure + end + + it "fails when a given Formula doesn't exist" do + expect { brew "migrate", "testball" } + .to output(/No available formula with the name "testball"/).to_stderr + .and not_to_output.to_stdout + .and be_a_failure + end + + it "fails if a given Formula doesn't replace another one" do + expect { brew "migrate", "testball1" } + .to output(/testball1 doesn't replace any formula/).to_stderr + .and not_to_output.to_stdout + .and be_a_failure + end + + it "migrates a renamed Formula" do + install_and_rename_coretap_formula "testball1", "testball2" + + expect { brew "migrate", "testball1" } + .to output(/Migrating testball1 to testball2/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + + it "fails if a given Formula is not installed" do + install_and_rename_coretap_formula "testball1", "testball2" + (HOMEBREW_CELLAR/"testball1").rmtree + + expect { brew "migrate", "testball1" } + .to output(/Error: No such keg/).to_stderr + .and not_to_output.to_stdout + .and be_a_failure + end +end diff --git a/Library/Homebrew/test/cmd/missing_spec.rb b/Library/Homebrew/test/cmd/missing_spec.rb new file mode 100644 index 000000000..4668e72e0 --- /dev/null +++ b/Library/Homebrew/test/cmd/missing_spec.rb @@ -0,0 +1,41 @@ +describe "brew missing", :integration_test do + before(:each) do + setup_test_formula "foo" + setup_test_formula "bar" + end + + def make_prefix(name) + (HOMEBREW_CELLAR/name/"1.0").mkpath + end + + it "prints missing dependencies" do + make_prefix "bar" + + expect { brew "missing" } + .to output("foo\n").to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + + it "prints nothing if all dependencies are installed" do + make_prefix "foo" + make_prefix "bar" + + expect { brew "missing" } + .to be_a_success + .and not_to_output.to_stdout + .and not_to_output.to_stderr + end + + describe "--hide=" do + it "pretends that the specified Formulae are not installed" do + make_prefix "foo" + make_prefix "bar" + + expect { brew "missing", "--hide=foo" } + .to output("bar: foo\n").to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + end +end diff --git a/Library/Homebrew/test/cmd/options_spec.rb b/Library/Homebrew/test/cmd/options_spec.rb new file mode 100644 index 000000000..33fe8b107 --- /dev/null +++ b/Library/Homebrew/test/cmd/options_spec.rb @@ -0,0 +1,12 @@ +describe "brew options", :integration_test do + it "prints a given Formula's options" do + setup_test_formula "testball", <<-EOS.undent + depends_on "bar" => :recommended + EOS + + expect { brew "options", "testball" } + .to output("--with-foo\n\tBuild with foo\n--without-bar\n\tBuild without bar support\n\n").to_stdout + .and not_to_output.to_stderr + .and be_a_success + end +end diff --git a/Library/Homebrew/test/cmd/outdated_spec.rb b/Library/Homebrew/test/cmd/outdated_spec.rb new file mode 100644 index 000000000..2ce0825e8 --- /dev/null +++ b/Library/Homebrew/test/cmd/outdated_spec.rb @@ -0,0 +1,11 @@ +describe "brew outdated", :integration_test do + it "prints outdated Formulae" do + setup_test_formula "testball" + (HOMEBREW_CELLAR/"testball/0.0.1/foo").mkpath + + expect { brew "outdated" } + .to output("testball\n").to_stdout + .and not_to_output.to_stderr + .and be_a_success + end +end diff --git a/Library/Homebrew/test/cmd/pin_spec.rb b/Library/Homebrew/test/cmd/pin_spec.rb new file mode 100644 index 000000000..9ffc052c3 --- /dev/null +++ b/Library/Homebrew/test/cmd/pin_spec.rb @@ -0,0 +1,13 @@ +describe "brew pin", :integration_test do + it "pins a Formula's version" do + setup_test_formula "testball" + (HOMEBREW_CELLAR/"testball/0.0.1/foo").mkpath + + shutup do + expect { brew "pin", "testball" }.to be_a_success + expect { brew "upgrade" }.to be_a_success + end + + expect(HOMEBREW_CELLAR/"testball/0.1").not_to be_a_directory + end +end diff --git a/Library/Homebrew/test/cmd/prune_spec.rb b/Library/Homebrew/test/cmd/prune_spec.rb new file mode 100644 index 000000000..c5a9df70c --- /dev/null +++ b/Library/Homebrew/test/cmd/prune_spec.rb @@ -0,0 +1,28 @@ +describe "brew prune", :integration_test do + it "removes empty directories and broken symlinks" do + share = (HOMEBREW_PREFIX/"share") + + (share/"pruneable/directory/here").mkpath + (share/"notpruneable/file").write "I'm here" + FileUtils.ln_s "/i/dont/exist/no/really/i/dont", share/"pruneable_symlink" + + expect { brew "prune", "--dry-run" } + .to output(%r{Would remove \(empty directory\): .*/pruneable/directory/here}).to_stdout + .and not_to_output.to_stderr + .and be_a_success + + expect { brew "prune" } + .to output(/Pruned 1 symbolic links and 3 directories/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + + expect(share/"pruneable").not_to be_a_directory + expect(share/"notpruneable").to be_a_directory + expect(share/"pruneable_symlink").not_to be_a_symlink + + expect { brew "prune", "--verbose" } + .to output(/Nothing pruned/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end +end diff --git a/Library/Homebrew/test/cmd/readall_spec.rb b/Library/Homebrew/test/cmd/readall_spec.rb new file mode 100644 index 000000000..9165e0cb0 --- /dev/null +++ b/Library/Homebrew/test/cmd/readall_spec.rb @@ -0,0 +1,20 @@ +describe "brew readall", :integration_test do + it "imports all Formulae for a given Tap" do + formula_file = setup_test_formula "testball" + + alias_file = CoreTap.new.alias_dir/"foobar" + alias_file.parent.mkpath + + FileUtils.ln_s formula_file, alias_file + + expect { brew "readall", "--aliases", "--syntax" } + .to be_a_success + .and not_to_output.to_stdout + .and not_to_output.to_stderr + + expect { brew "readall", "homebrew/core" } + .to be_a_success + .and not_to_output.to_stdout + .and not_to_output.to_stderr + end +end diff --git a/Library/Homebrew/test/cmd/reinstall_spec.rb b/Library/Homebrew/test/cmd/reinstall_spec.rb new file mode 100644 index 000000000..63584e6be --- /dev/null +++ b/Library/Homebrew/test/cmd/reinstall_spec.rb @@ -0,0 +1,44 @@ +require "extend/ENV" + +describe "brew reinstall", :integration_test do + before(:each) do + setup_test_formula "testball" + + shutup do + expect { brew "install", "testball", "--with-foo" }.to be_a_success + end + end + + it "reinstalls a Formula" do + foo_dir = HOMEBREW_CELLAR/"testball/0.1/foo" + expect(foo_dir).to exist + foo_dir.rmtree + + expect { brew "reinstall", "testball" } + .to output(/Reinstalling testball --with-foo/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + + expect(foo_dir).to exist + end + + it "reinstalls a Formula even when one of the options is invalid" do + expect { brew "reinstall", "testball", "--with-fo" } + .to output(/Reinstalling testball --with-foo/).to_stdout + .and output(/testball: this formula has no \-\-with-fo option so it will be ignored!/).to_stderr + .and be_a_success + end + + it "refuses to reinstall a pinned Formula, but doesn't fail" do + (HOMEBREW_CELLAR/"testball/0.1").mkpath + HOMEBREW_PINNED_KEGS.mkpath + FileUtils.ln_s HOMEBREW_CELLAR/"testball/0.1", HOMEBREW_PINNED_KEGS/"testball" + + expect { brew "reinstall", "testball" } + .to output(/testball is pinned. You must unpin it to reinstall./).to_stderr + .and not_to_output.to_stdout + .and be_a_success + + HOMEBREW_PINNED_KEGS.rmtree + end +end diff --git a/Library/Homebrew/test/cmd/search_remote_tap_spec.rb b/Library/Homebrew/test/cmd/search_remote_tap_spec.rb new file mode 100644 index 000000000..99c2cc20b --- /dev/null +++ b/Library/Homebrew/test/cmd/search_remote_tap_spec.rb @@ -0,0 +1,19 @@ +require "cmd/search" + +describe Homebrew do + specify "#search_tap" do + json_response = { + "tree" => [ + { + "path" => "Formula/not-a-formula.rb", + "type" => "blob", + }, + ], + } + + allow(GitHub).to receive(:open).and_yield(json_response) + + expect(described_class.search_tap("homebrew", "not-a-tap", "not-a-formula")) + .to eq(["homebrew/not-a-tap/not-a-formula"]) + end +end diff --git a/Library/Homebrew/test/cmd/search_spec.rb b/Library/Homebrew/test/cmd/search_spec.rb new file mode 100644 index 000000000..06b7073d8 --- /dev/null +++ b/Library/Homebrew/test/cmd/search_spec.rb @@ -0,0 +1,57 @@ +describe "brew search", :integration_test do + before(:each) do + setup_test_formula "testball" + end + + it "lists all available Formulae when no argument is given" do + expect { brew "search" } + .to output(/testball/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + + it "supports searching by name" do + expect { brew "search", "testball" } + .to output(/testball/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + + it "supports searching a fully-qualified name " do + expect { brew "search", "homebrew/homebrew-core/testball" } + .to output(/testball/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + + describe "--desc" do + let(:desc_cache) { HOMEBREW_CACHE/"desc_cache.json" } + + it "supports searching in descriptions and creates a description cache" do + expect(desc_cache).not_to exist + + expect { brew "search", "--desc", "Some test" } + .to output(/testball/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + + expect(desc_cache).to exist + end + end + + { + "macports" => "https://www.macports.org/ports.php?by=name&substr=testball", + "fink" => "http://pdb.finkproject.org/pdb/browse.php?summary=testball", + "debian" => "https://packages.debian.org/search?keywords=testball&searchon=names&suite=all§ion=all", + "opensuse" => "https://software.opensuse.org/search?q=testball", + "fedora" => "https://admin.fedoraproject.org/pkgdb/packages/%2Atestball%2A/", + "ubuntu" => "http://packages.ubuntu.com/search?keywords=testball&searchon=names&suite=all§ion=all", + }.each do |flag, url| + specify "--#{flag}" do + expect { brew "search", "--#{flag}", "testball", "HOMEBREW_BROWSER" => "echo" } + .to output("#{url}\n").to_stdout + .and not_to_output.to_stderr + .and be_a_success + end + end +end diff --git a/Library/Homebrew/test/cmd/services_spec.rb b/Library/Homebrew/test/cmd/services_spec.rb new file mode 100644 index 000000000..c456fea17 --- /dev/null +++ b/Library/Homebrew/test/cmd/services_spec.rb @@ -0,0 +1,10 @@ +describe "brew services", :integration_test, :needs_macos, :needs_official_cmd_taps do + it "allows controlling services" do + setup_remote_tap "homebrew/services" + + expect { brew "services", "list" } + .to output("Warning: No services available to control with `brew services`\n").to_stderr + .and not_to_output.to_stdout + .and be_a_success + end +end diff --git a/Library/Homebrew/test/cmd/sh_spec.rb b/Library/Homebrew/test/cmd/sh_spec.rb new file mode 100644 index 000000000..5260ddb75 --- /dev/null +++ b/Library/Homebrew/test/cmd/sh_spec.rb @@ -0,0 +1,8 @@ +describe "brew sh", :integration_test do + it "runs a shell with the Homebrew environment" do + expect { brew "sh", "SHELL" => which("true") } + .to output(/Your shell has been configured/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end +end diff --git a/Library/Homebrew/test/cmd/switch_spec.rb b/Library/Homebrew/test/cmd/switch_spec.rb new file mode 100644 index 000000000..c27c96c14 --- /dev/null +++ b/Library/Homebrew/test/cmd/switch_spec.rb @@ -0,0 +1,34 @@ +describe "brew switch", :integration_test do + it "allows switching between Formula versions" do + expect { brew "switch" } + .to output(/Usage: brew switch <name> <version>/).to_stderr + .and not_to_output.to_stdout + .and be_a_failure + + expect { brew "switch", "testball", "0.1" } + .to output(/testball not found/).to_stderr + .and not_to_output.to_stdout + .and be_a_failure + + setup_test_formula "testball", <<-EOS.undent + keg_only "just because" + EOS + + shutup do + expect { brew "install", "testball" }.to be_a_success + end + + testball_rack = HOMEBREW_CELLAR/"testball" + FileUtils.cp_r testball_rack/"0.1", testball_rack/"0.2" + + expect { brew "switch", "testball", "0.2" } + .to output(/link created/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + + expect { brew "switch", "testball", "0.3" } + .to output("Versions available: 0.1, 0.2\n").to_stdout + .and output(/testball does not have a version "0.3"/).to_stderr + .and be_a_failure + end +end diff --git a/Library/Homebrew/test/cmd/tap-new_spec.rb b/Library/Homebrew/test/cmd/tap-new_spec.rb new file mode 100644 index 000000000..ea4b8aa73 --- /dev/null +++ b/Library/Homebrew/test/cmd/tap-new_spec.rb @@ -0,0 +1,10 @@ +describe "brew tap-new", :integration_test do + it "initializes a new Tap with a ReadMe file" do + expect { brew "tap-new", "homebrew/foo", "--verbose" } + .to be_a_success + .and not_to_output.to_stdout + .and not_to_output.to_stderr + + expect(HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-foo/README.md").to exist + end +end diff --git a/Library/Homebrew/test/cmd/uninstall_spec.rb b/Library/Homebrew/test/cmd/uninstall_spec.rb new file mode 100644 index 000000000..65f69e802 --- /dev/null +++ b/Library/Homebrew/test/cmd/uninstall_spec.rb @@ -0,0 +1,12 @@ +describe "brew uninstall", :integration_test do + it "uninstalls a given Formula" do + shutup do + expect { brew "install", testball }.to be_a_success + end + + expect { brew "uninstall", "--force", testball } + .to output(/Uninstalling testball/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end +end diff --git a/Library/Homebrew/test/cmd/unlink_spec.rb b/Library/Homebrew/test/cmd/unlink_spec.rb new file mode 100644 index 000000000..5961651fe --- /dev/null +++ b/Library/Homebrew/test/cmd/unlink_spec.rb @@ -0,0 +1,14 @@ +describe "brew unlink", :integration_test do + it "unlinks a Formula" do + setup_test_formula "testball" + + shutup do + expect { brew "install", "testball" }.to be_a_success + end + + expect { brew "unlink", "--dry-run", "testball" } + .to output(/Would remove/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end +end diff --git a/Library/Homebrew/test/cmd/unlinkapps_spec.rb b/Library/Homebrew/test/cmd/unlinkapps_spec.rb new file mode 100644 index 000000000..1e21bd851 --- /dev/null +++ b/Library/Homebrew/test/cmd/unlinkapps_spec.rb @@ -0,0 +1,24 @@ +describe "brew unlinkapps", :integration_test do + let(:home_dir) { @home_dir = Pathname.new(Dir.mktmpdir) } + let(:apps_dir) { home_dir/"Applications" } + + after(:each) do + home_dir.rmtree unless @home_dir.nil? + end + + it "unlinks symlinked applications" do + apps_dir.mkpath + + setup_test_formula "testball" + + source_app = HOMEBREW_CELLAR/"testball/0.1/TestBall.app" + source_app.mkpath + + FileUtils.ln_s source_app, apps_dir/"TestBall.app" + + expect { brew "unlinkapps", "--local", "HOME" => home_dir } + .to output(%r{Unlinking: #{Regexp.escape(apps_dir)}/TestBall.app}).to_stdout + .and output(/`brew unlinkapps` has been deprecated/).to_stderr + .and be_a_success + end +end diff --git a/Library/Homebrew/test/cmd/unpack_spec.rb b/Library/Homebrew/test/cmd/unpack_spec.rb new file mode 100644 index 000000000..244fc0852 --- /dev/null +++ b/Library/Homebrew/test/cmd/unpack_spec.rb @@ -0,0 +1,16 @@ +describe "brew unpack", :integration_test do + it "unpacks a given Formula's archive" do + setup_test_formula "testball" + + Dir.mktmpdir do |path| + path = Pathname.new(path) + + shutup do + expect { brew "unpack", "testball", "--destdir=#{path}" } + .to be_a_success + end + + expect(path/"testball-0.1").to be_a_directory + end + end +end diff --git a/Library/Homebrew/test/cmd/unpin_spec.rb b/Library/Homebrew/test/cmd/unpin_spec.rb new file mode 100644 index 000000000..4f14626d8 --- /dev/null +++ b/Library/Homebrew/test/cmd/unpin_spec.rb @@ -0,0 +1,14 @@ +describe "brew unpin", :integration_test do + it "unpins a Formula's version" do + setup_test_formula "testball" + (HOMEBREW_CELLAR/"testball/0.0.1/foo").mkpath + + shutup do + expect { brew "pin", "testball" }.to be_a_success + expect { brew "unpin", "testball" }.to be_a_success + expect { brew "upgrade" }.to be_a_success + end + + expect(HOMEBREW_CELLAR/"testball/0.1").to be_a_directory + end +end diff --git a/Library/Homebrew/test/cmd/update-report_spec.rb b/Library/Homebrew/test/cmd/update-report_spec.rb new file mode 100644 index 000000000..3665e3c78 --- /dev/null +++ b/Library/Homebrew/test/cmd/update-report_spec.rb @@ -0,0 +1,127 @@ +require "cmd/update-report" +require "formula_versions" +require "yaml" + +describe Reporter do + def perform_update(fixture_name = "") + allow(Formulary).to receive(:factory).and_return(double(pkg_version: "1.0")) + allow(FormulaVersions).to receive(:new).and_return(double(formula_at_revision: "2.0")) + + diff = YAML.load_file("#{TEST_FIXTURE_DIR}/updater_fixture.yaml")[fixture_name] + allow(subject).to receive(:diff).and_return(diff || "") + + hub.add(subject) if subject.updated? + end + + let(:reporter_class) do + Class.new(described_class) do + def initialize(tap) + @tap = tap + + ENV["HOMEBREW_UPDATE_BEFORE#{repo_var}"] = "12345678" + ENV["HOMEBREW_UPDATE_AFTER#{repo_var}"] = "abcdef00" + + super(tap) + end + end + end + subject { reporter_class.new(tap) } + let(:tap) { CoreTap.new } + let(:hub) { ReporterHub.new } + + specify "without revision variable" do + ENV.delete_if { |k, _v| k.start_with? "HOMEBREW_UPDATE" } + + expect { + described_class.new(tap) + }.to raise_error(Reporter::ReporterRevisionUnsetError) + end + + specify "without any changes" do + perform_update + expect(hub).to be_empty + end + + specify "without Formula changes" do + perform_update("update_git_diff_output_without_formulae_changes") + + expect(hub.select_formula(:M)).to be_empty + expect(hub.select_formula(:A)).to be_empty + expect(hub.select_formula(:D)).to be_empty + end + + specify "with Formula changes" do + perform_update("update_git_diff_output_with_formulae_changes") + + expect(hub.select_formula(:M)).to eq(%w[xar yajl]) + expect(hub.select_formula(:A)).to eq(%w[antiword bash-completion ddrescue dict lua]) + end + + specify "with removed Formulae" do + perform_update("update_git_diff_output_with_removed_formulae") + + expect(hub.select_formula(:D)).to eq(%w[libgsasl]) + end + + specify "with changed file type" do + perform_update("update_git_diff_output_with_changed_filetype") + + expect(hub.select_formula(:M)).to eq(%w[elixir]) + expect(hub.select_formula(:A)).to eq(%w[libbson]) + expect(hub.select_formula(:D)).to eq(%w[libgsasl]) + end + + specify "with renamed Formula" do + allow(tap).to receive(:formula_renames).and_return("cv" => "progress") + perform_update("update_git_diff_output_with_formula_rename") + + expect(hub.select_formula(:A)).to be_empty + expect(hub.select_formula(:D)).to be_empty + expect(hub.select_formula(:R)).to eq([["cv", "progress"]]) + end + + context "when updating a Tap other than the core Tap" do + let(:tap) { Tap.new("foo", "bar") } + + before(:each) do + (tap.path/"Formula").mkpath + end + + after(:each) do + tap.path.parent.rmtree + end + + specify "with restructured Tap" do + perform_update("update_git_diff_output_with_restructured_tap") + + expect(hub.select_formula(:A)).to be_empty + expect(hub.select_formula(:D)).to be_empty + expect(hub.select_formula(:R)).to be_empty + end + + specify "with renamed Formula and restructured Tap" do + allow(tap).to receive(:formula_renames).and_return("xchat" => "xchat2") + perform_update("update_git_diff_output_with_formula_rename_and_restructuring") + + expect(hub.select_formula(:A)).to be_empty + expect(hub.select_formula(:D)).to be_empty + expect(hub.select_formula(:R)).to eq([%w[foo/bar/xchat foo/bar/xchat2]]) + end + + specify "with simulated 'homebrew/php' restructuring" do + perform_update("update_git_diff_simulate_homebrew_php_restructuring") + + expect(hub.select_formula(:A)).to be_empty + expect(hub.select_formula(:D)).to be_empty + expect(hub.select_formula(:R)).to be_empty + end + + specify "with Formula changes" do + perform_update("update_git_diff_output_with_tap_formulae_changes") + + expect(hub.select_formula(:A)).to eq(%w[foo/bar/lua]) + expect(hub.select_formula(:M)).to eq(%w[foo/bar/git]) + expect(hub.select_formula(:D)).to be_empty + end + end +end diff --git a/Library/Homebrew/test/cmd/upgrade_spec.rb b/Library/Homebrew/test/cmd/upgrade_spec.rb new file mode 100644 index 000000000..84f5c09f4 --- /dev/null +++ b/Library/Homebrew/test/cmd/upgrade_spec.rb @@ -0,0 +1,12 @@ +describe "brew upgrade", :integration_test do + it "upgrades a Formula to the latest version" do + setup_test_formula "testball" + (HOMEBREW_CELLAR/"testball/0.0.1/foo").mkpath + + shutup do + expect { brew "upgrade" }.to be_a_success + end + + expect(HOMEBREW_CELLAR/"testball/0.1").to be_a_directory + end +end diff --git a/Library/Homebrew/test/cmd/uses_spec.rb b/Library/Homebrew/test/cmd/uses_spec.rb new file mode 100644 index 000000000..2a6f48cb7 --- /dev/null +++ b/Library/Homebrew/test/cmd/uses_spec.rb @@ -0,0 +1,25 @@ +describe "brew uses", :integration_test do + it "prints the Formulae a given Formula is used by" do + setup_test_formula "foo" + setup_test_formula "bar" + setup_test_formula "baz", <<-EOS.undent + url "https://example.com/baz-1.0" + depends_on "bar" + EOS + + expect { brew "uses", "baz" } + .to be_a_success + .and not_to_output.to_stdout + .and not_to_output.to_stderr + + expect { brew "uses", "bar" } + .to output("baz\n").to_stdout + .and not_to_output.to_stderr + .and be_a_success + + expect { brew "uses", "--recursive", "foo" } + .to output(/(bar\nbaz|baz\nbar)/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end +end diff --git a/Library/Homebrew/test/command_test.rb b/Library/Homebrew/test/command_test.rb deleted file mode 100644 index d5c7aaa88..000000000 --- a/Library/Homebrew/test/command_test.rb +++ /dev/null @@ -1,11 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestCommand < IntegrationCommandTestCase - def test_command - assert_equal "#{HOMEBREW_LIBRARY_PATH}/cmd/info.rb", - cmd("command", "info") - - assert_match "Unknown command", - cmd_fail("command", "I-don't-exist") - end -end diff --git a/Library/Homebrew/test/commands_test.rb b/Library/Homebrew/test/commands_test.rb index d44d2da0e..da88ee2d5 100644 --- a/Library/Homebrew/test/commands_test.rb +++ b/Library/Homebrew/test/commands_test.rb @@ -4,15 +4,9 @@ require "cmd/commands" require "fileutils" require "testing_env" -class IntegrationCommandTestCommands < IntegrationCommandTestCase - def test_commands - assert_match "Built-in commands", - cmd("commands") - end -end - class CommandsTests < Homebrew::TestCase def setup + super @cmds = [ # internal commands HOMEBREW_LIBRARY_PATH/"cmd/rbcmd.rb", @@ -28,6 +22,7 @@ class CommandsTests < Homebrew::TestCase def teardown @cmds.each(&:unlink) + super end def test_internal_commands @@ -45,8 +40,6 @@ class CommandsTests < Homebrew::TestCase end def test_external_commands - env = ENV.to_hash - mktmpdir do |dir| %w[brew-t1 brew-t2.rb brew-t3.py].each do |file| path = "#{dir}/#{file}" @@ -65,8 +58,6 @@ class CommandsTests < Homebrew::TestCase "Executable files with a non Ruby extension shoudn't be included" refute cmds.include?("t4"), "Non-executable files shouldn't be included" end - ensure - ENV.replace(env) end def test_internal_command_path diff --git a/Library/Homebrew/test/compiler_failure_spec.rb b/Library/Homebrew/test/compiler_failure_spec.rb new file mode 100644 index 000000000..b4fab0b27 --- /dev/null +++ b/Library/Homebrew/test/compiler_failure_spec.rb @@ -0,0 +1,37 @@ +require "compilers" + +RSpec::Matchers.alias_matcher :fail_with, :be_fails_with + +describe CompilerFailure do + describe "::create" do + it "creates a failure when given a symbol" do + failure = described_class.create(:clang) + expect(failure).to fail_with(double("Compiler", name: :clang, version: 425)) + end + + it "can be given a build number in a block" do + failure = described_class.create(:clang) { build 211 } + expect(failure).to fail_with(double("Compiler", name: :clang, version: 210)) + expect(failure).not_to fail_with(double("Compiler", name: :clang, version: 318)) + end + + it "can be given an empty block" do + failure = described_class.create(:clang) {} + expect(failure).to fail_with(double("Compiler", name: :clang, version: 425)) + end + + it "creates a failure when given a hash" do + failure = described_class.create(gcc: "4.8") + expect(failure).to fail_with(double("Compiler", name: "gcc-4.8", version: "4.8")) + expect(failure).to fail_with(double("Compiler", name: "gcc-4.8", version: "4.8.1")) + expect(failure).not_to fail_with(double("Compiler", name: "gcc-4.7", version: "4.7")) + end + + it "creates a failure when given a hash and a block with aversion" do + failure = described_class.create(gcc: "4.8") { version "4.8.1" } + expect(failure).to fail_with(double("Compiler", name: "gcc-4.8", version: "4.8")) + expect(failure).to fail_with(double("Compiler", name: "gcc-4.8", version: "4.8.1")) + expect(failure).not_to fail_with(double("Compiler", name: "gcc-4.8", version: "4.8.2")) + end + end +end diff --git a/Library/Homebrew/test/compiler_failure_test.rb b/Library/Homebrew/test/compiler_failure_test.rb deleted file mode 100644 index c0b74d128..000000000 --- a/Library/Homebrew/test/compiler_failure_test.rb +++ /dev/null @@ -1,52 +0,0 @@ -require "testing_env" -require "compilers" - -class CompilerFailureTests < Homebrew::TestCase - Compiler = Struct.new(:name, :version) - - def assert_fails_with(compiler, failure) - assert_operator failure, :fails_with?, compiler - end - - def refute_fails_with(compiler, failure) - refute_operator failure, :fails_with?, compiler - end - - def compiler(name, version) - Compiler.new(name, version) - end - - def create(spec, &block) - CompilerFailure.create(spec, &block) - end - - def test_create_with_symbol - failure = create(:clang) - assert_fails_with compiler(:clang, 425), failure - end - - def test_create_with_block - failure = create(:clang) { build 211 } - assert_fails_with compiler(:clang, 210), failure - refute_fails_with compiler(:clang, 318), failure - end - - def test_create_with_block_without_build - failure = create(:clang) {} - assert_fails_with compiler(:clang, 425), failure - end - - def test_create_with_hash - failure = create(gcc: "4.8") - assert_fails_with compiler("gcc-4.8", "4.8"), failure - assert_fails_with compiler("gcc-4.8", "4.8.1"), failure - refute_fails_with compiler("gcc-4.7", "4.7"), failure - end - - def test_create_with_hash_and_version - failure = create(gcc: "4.8") { version "4.8.1" } - assert_fails_with compiler("gcc-4.8", "4.8"), failure - assert_fails_with compiler("gcc-4.8", "4.8.1"), failure - refute_fails_with compiler("gcc-4.8", "4.8.2"), failure - end -end diff --git a/Library/Homebrew/test/compiler_selector_spec.rb b/Library/Homebrew/test/compiler_selector_spec.rb new file mode 100644 index 000000000..0f6f6b5f2 --- /dev/null +++ b/Library/Homebrew/test/compiler_selector_spec.rb @@ -0,0 +1,122 @@ +require "compilers" +require "software_spec" + +describe CompilerSelector do + subject { described_class.new(software_spec, versions, compilers) } + let(:compilers) { [:clang, :gcc, :llvm, :gnu] } + let(:software_spec) { SoftwareSpec.new } + let(:cc) { :clang } + let(:versions) do + double( + gcc_4_0_build_version: Version::NULL, + gcc_build_version: Version.create("5666"), + llvm_build_version: Version::NULL, + clang_build_version: Version.create("425"), + ) + end + + before(:each) do + allow(versions).to receive(:non_apple_gcc_version) do |name| + case name + when "gcc-4.8" then Version.create("4.8.1") + when "gcc-4.7" then Version.create("4.7.1") + else Version::NULL + end + end + end + + describe "#compiler" do + it "raises an error if no matching compiler can be found" do + software_spec.fails_with(:clang) + software_spec.fails_with(:llvm) + software_spec.fails_with(:gcc) + software_spec.fails_with(gcc: "4.8") + software_spec.fails_with(gcc: "4.7") + + expect { subject.compiler }.to raise_error(CompilerSelectionError) + end + + it "defaults to cc" do + expect(subject.compiler).to eq(cc) + end + + it "returns gcc if it fails with clang" do + software_spec.fails_with(:clang) + expect(subject.compiler).to eq(:gcc) + end + + it "returns clang if it fails with llvm" do + software_spec.fails_with(:llvm) + expect(subject.compiler).to eq(:clang) + end + + it "returns clang if it fails with gcc" do + software_spec.fails_with(:gcc) + expect(subject.compiler).to eq(:clang) + end + + it "returns clang if it fails with non-Apple gcc" do + software_spec.fails_with(gcc: "4.8") + expect(subject.compiler).to eq(:clang) + end + + it "still returns gcc-4.8 if it fails with gcc without a specific version" do + software_spec.fails_with(:clang) + software_spec.fails_with(:gcc) + expect(subject.compiler).to eq("gcc-4.8") + end + + it "returns gcc if it fails with clang and llvm" do + software_spec.fails_with(:clang) + software_spec.fails_with(:llvm) + expect(subject.compiler).to eq(:gcc) + end + + it "returns clang if it fails with gcc and llvm" do + software_spec.fails_with(:gcc) + software_spec.fails_with(:llvm) + expect(subject.compiler).to eq(:clang) + end + + example "returns gcc if it fails with a specific gcc version" do + software_spec.fails_with(:clang) + software_spec.fails_with(gcc: "4.8") + expect(subject.compiler).to eq(:gcc) + end + + example "returns a lower version of gcc if it fails with the highest version" do + software_spec.fails_with(:clang) + software_spec.fails_with(:gcc) + software_spec.fails_with(:llvm) + software_spec.fails_with(gcc: "4.8") + expect(subject.compiler).to eq("gcc-4.7") + end + + it "prefers gcc" do + software_spec.fails_with(:clang) + software_spec.fails_with(:gcc) + expect(subject.compiler).to eq("gcc-4.8") + end + + it "raises an error when gcc is missing" do + allow(versions).to receive(:gcc_build_version).and_return(Version::NULL) + + software_spec.fails_with(:clang) + software_spec.fails_with(:llvm) + software_spec.fails_with(gcc: "4.8") + software_spec.fails_with(gcc: "4.7") + + expect { subject.compiler }.to raise_error(CompilerSelectionError) + end + + it "raises an error when llvm and gcc are missing" do + allow(versions).to receive(:gcc_build_version).and_return(Version::NULL) + + software_spec.fails_with(:clang) + software_spec.fails_with(gcc: "4.8") + software_spec.fails_with(gcc: "4.7") + + expect { subject.compiler }.to raise_error(CompilerSelectionError) + end + end +end diff --git a/Library/Homebrew/test/compiler_selector_test.rb b/Library/Homebrew/test/compiler_selector_test.rb deleted file mode 100644 index b1591bdbe..000000000 --- a/Library/Homebrew/test/compiler_selector_test.rb +++ /dev/null @@ -1,116 +0,0 @@ -require "testing_env" -require "compilers" -require "software_spec" - -class CompilerSelectorTests < Homebrew::TestCase - class Double < SoftwareSpec - def <<(cc) - fails_with(cc) - self - end - end - - class CompilerVersions - attr_accessor :gcc_4_0_build_version, :gcc_build_version, - :clang_build_version - - def initialize - @gcc_4_0_build_version = Version::NULL - @gcc_build_version = Version.create("5666") - @llvm_build_version = Version::NULL - @clang_build_version = Version.create("425") - end - - def non_apple_gcc_version(name) - case name - when "gcc-4.8" then Version.create("4.8.1") - when "gcc-4.7" then Version.create("4.7.1") - else Version::NULL - end - end - end - - def setup - @f = Double.new - @cc = :clang - @versions = CompilerVersions.new - @selector = CompilerSelector.new( - @f, @versions, [:clang, :gcc, :llvm, :gnu] - ) - end - - def actual_cc - @selector.compiler - end - - def test_all_compiler_failures - @f << :clang << :llvm << :gcc << { gcc: "4.8" } << { gcc: "4.7" } - assert_raises(CompilerSelectionError) { actual_cc } - end - - def test_no_compiler_failures - assert_equal @cc, actual_cc - end - - def test_fails_with_clang - @f << :clang - assert_equal :gcc, actual_cc - end - - def test_fails_with_llvm - @f << :llvm - assert_equal :clang, actual_cc - end - - def test_fails_with_gcc - @f << :gcc - assert_equal :clang, actual_cc - end - - def test_fails_with_non_apple_gcc - @f << { gcc: "4.8" } - assert_equal :clang, actual_cc - end - - def test_mixed_failures_1 - @f << :clang << :gcc - assert_equal "gcc-4.8", actual_cc - end - - def test_mixed_failures_2 - @f << :clang << :llvm - assert_equal :gcc, actual_cc - end - - def test_mixed_failures_3 - @f << :gcc << :llvm - assert_equal :clang, actual_cc - end - - def test_mixed_failures_4 - @f << :clang << { gcc: "4.8" } - assert_equal :gcc, actual_cc - end - - def test_mixed_failures_5 - @f << :clang << :gcc << :llvm << { gcc: "4.8" } - assert_equal "gcc-4.7", actual_cc - end - - def test_gcc_precedence - @f << :clang << :gcc - assert_equal "gcc-4.8", actual_cc - end - - def test_missing_gcc - @versions.gcc_build_version = Version::NULL - @f << :clang << :llvm << { gcc: "4.8" } << { gcc: "4.7" } - assert_raises(CompilerSelectionError) { actual_cc } - end - - def test_missing_llvm_and_gcc - @versions.gcc_build_version = Version::NULL - @f << :clang << { gcc: "4.8" } << { gcc: "4.7" } - assert_raises(CompilerSelectionError) { actual_cc } - end -end diff --git a/Library/Homebrew/test/config_test.rb b/Library/Homebrew/test/config_test.rb deleted file mode 100644 index 81da4660a..000000000 --- a/Library/Homebrew/test/config_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestConfig < IntegrationCommandTestCase - def test_config - assert_match "HOMEBREW_VERSION: #{HOMEBREW_VERSION}", - cmd("config") - end -end diff --git a/Library/Homebrew/test/create_test.rb b/Library/Homebrew/test/create_test.rb deleted file mode 100644 index aeee428aa..000000000 --- a/Library/Homebrew/test/create_test.rb +++ /dev/null @@ -1,12 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestCreate < IntegrationCommandTestCase - def test_create - url = "file://#{TEST_FIXTURE_DIR}/tarballs/testball-0.1.tbz" - cmd("create", url, "HOMEBREW_EDITOR" => "/bin/cat") - - formula_file = CoreTap.new.formula_dir/"testball.rb" - assert formula_file.exist?, "The formula source should have been created" - assert_match %Q(sha256 "#{TESTBALL_SHA256}"), formula_file.read - end -end diff --git a/Library/Homebrew/test/custom_command_test.rb b/Library/Homebrew/test/custom_command_test.rb deleted file mode 100644 index 8d05bc6c7..000000000 --- a/Library/Homebrew/test/custom_command_test.rb +++ /dev/null @@ -1,18 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestCustomCommand < IntegrationCommandTestCase - def test_custom_command - mktmpdir do |path| - cmd = "int-test-#{rand}" - file = "#{path}/brew-#{cmd}" - - File.open(file, "w") do |f| - f.write "#!/bin/sh\necho 'I am #{cmd}'\n" - end - FileUtils.chmod 0777, file - - assert_match "I am #{cmd}", - cmd(cmd, "PATH" => "#{path}#{File::PATH_SEPARATOR}#{ENV["PATH"]}") - end - end -end diff --git a/Library/Homebrew/test/cxxstdlib_spec.rb b/Library/Homebrew/test/cxxstdlib_spec.rb new file mode 100644 index 000000000..dd2e4e1c6 --- /dev/null +++ b/Library/Homebrew/test/cxxstdlib_spec.rb @@ -0,0 +1,68 @@ +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) } + + describe "#compatible_with?" do + specify "Apple libstdcxx intercompatibility" do + expect(clang).to be_compatible_with(gcc) + expect(clang).to be_compatible_with(gcc42) + end + + specify "compatibility with itself" do + expect(gcc).to be_compatible_with(gcc) + expect(gcc48).to be_compatible_with(gcc48) + expect(clang).to be_compatible_with(clang) + end + + specify "Apple/GNU libstdcxx incompatibility" do + expect(clang).not_to be_compatible_with(gcc48) + expect(gcc48).not_to be_compatible_with(clang) + end + + specify "GNU cross-version incompatibility" do + expect(gcc48).not_to be_compatible_with(gcc49) + expect(gcc49).not_to be_compatible_with(gcc48) + end + + specify "libstdcxx and libcxx incompatibility" do + expect(clang).not_to be_compatible_with(lcxx) + expect(lcxx).not_to be_compatible_with(clang) + end + + specify "compatibility for non-cxx software" do + expect(purec).to be_compatible_with(clang) + expect(clang).to be_compatible_with(purec) + expect(purec).to be_compatible_with(purec) + expect(purec).to be_compatible_with(gcc48) + expect(gcc48).to be_compatible_with(purec) + end + end + + describe "#apple_compiler?" do + it "returns true for Apple compilers" do + expect(clang).to be_an_apple_compiler + expect(gcc).to be_an_apple_compiler + expect(gcc42).to be_an_apple_compiler + end + + it "returns false for non-Apple compilers" do + expect(gcc48).not_to be_an_apple_compiler + end + end + + describe "#type_string" do + specify "formatting" do + expect(clang.type_string).to eq("libstdc++") + expect(lcxx.type_string).to eq("libc++") + end + end +end diff --git a/Library/Homebrew/test/dependencies_test.rb b/Library/Homebrew/test/dependencies_test.rb index db3b78226..c5444fcbc 100644 --- a/Library/Homebrew/test/dependencies_test.rb +++ b/Library/Homebrew/test/dependencies_test.rb @@ -5,6 +5,7 @@ require "requirements" class DependenciesTests < Homebrew::TestCase def setup + super @deps = Dependencies.new end @@ -89,6 +90,7 @@ end class RequirementsTests < Homebrew::TestCase def setup + super @reqs = Requirements.new end diff --git a/Library/Homebrew/test/dependency_collector_test.rb b/Library/Homebrew/test/dependency_collector_test.rb index 1c7f70118..c63d04637 100644 --- a/Library/Homebrew/test/dependency_collector_test.rb +++ b/Library/Homebrew/test/dependency_collector_test.rb @@ -11,11 +11,13 @@ class DependencyCollectorTests < Homebrew::TestCase end def setup + super @d = DependencyCollector.new end def teardown DependencyCollector.clear_cache + super end def test_dependency_creation diff --git a/Library/Homebrew/test/dependency_expansion_spec.rb b/Library/Homebrew/test/dependency_expansion_spec.rb new file mode 100644 index 000000000..f955237a9 --- /dev/null +++ b/Library/Homebrew/test/dependency_expansion_spec.rb @@ -0,0 +1,136 @@ +require "dependency" + +describe Dependency do + def build_dep(name, tags = [], deps = []) + dep = described_class.new(name.to_s, tags) + allow(dep).to receive(:to_formula).and_return(double(deps: deps, name: name)) + dep + end + + let(:foo) { build_dep(:foo) } + let(:bar) { build_dep(:bar) } + let(:baz) { build_dep(:baz) } + let(:qux) { build_dep(:qux) } + let(:deps) { [foo, bar, baz, qux] } + let(:formula) { double(deps: deps, name: "f") } + + describe "::expand" do + it "yields dependent and dependency pairs" do + i = 0 + described_class.expand(formula) do |dependent, dep| + expect(dependent).to eq(formula) + expect(deps[i]).to eq(dep) + i += 1 + end + end + + it "returns the dependencies" do + expect(described_class.expand(formula)).to eq(deps) + end + + it "prunes all when given a block with ::prune" do + expect(described_class.expand(formula) { described_class.prune }).to be_empty + end + + it "can prune selectively" do + deps = described_class.expand(formula) do |_, dep| + described_class.prune if dep.name == "foo" + end + + expect(deps).to eq([bar, baz, qux]) + end + + it "preserves dependency order" do + allow(foo).to receive(:to_formula).and_return(double(name: "f", deps: [qux, baz])) + expect(described_class.expand(formula)).to eq([qux, baz, foo, bar]) + end + end + + it "skips optionals by default" do + deps = [build_dep(:foo, [:optional]), bar, baz, qux] + f = double(deps: deps, build: double(with?: false), name: "f") + expect(described_class.expand(f)).to eq([bar, baz, qux]) + end + + it "keeps recommended dependencies by default" do + deps = [build_dep(:foo, [:recommended]), bar, baz, qux] + f = double(deps: deps, build: double(with?: true), name: "f") + expect(described_class.expand(f)).to eq(deps) + end + + it "merges repeated dependencies with differing options" do + foo2 = build_dep(:foo, ["option"]) + baz2 = build_dep(:baz, ["option"]) + deps << foo2 << baz2 + deps = [foo2, bar, baz2, qux] + deps.zip(described_class.expand(formula)) do |expected, actual| + expect(expected.tags).to eq(actual.tags) + expect(expected).to eq(actual) + end + end + + it "merges dependencies and perserves env_proc" do + env_proc = double + dep = described_class.new("foo", [], env_proc) + allow(dep).to receive(:to_formula).and_return(double(deps: [], name: "foo")) + deps.replace([dep]) + expect(described_class.expand(formula).first.env_proc).to eq(env_proc) + end + + it "merges tags without duplicating them" do + foo2 = build_dep(:foo, ["option"]) + foo3 = build_dep(:foo, ["option"]) + deps << foo2 << foo3 + + expect(described_class.expand(formula).first.tags).to eq(%w[option]) + end + + it "skips parent but yields children with ::skip" do + f = double( + name: "f", + deps: [ + build_dep(:foo, [], [bar, baz]), + build_dep(:foo, [], [baz]), + ], + ) + + deps = described_class.expand(f) do |_dependent, dep| + described_class.skip if %w[foo qux].include? dep.name + end + + expect(deps).to eq([bar, baz]) + 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]) + 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? + end + + expect(deps).to eq([foo, baz]) + end + + it "returns only the dependencies given as a collection as second argument" do + expect(formula.deps).to eq([foo, bar, baz, qux]) + expect(described_class.expand(formula, [bar, baz])).to eq([bar, baz]) + end + + it "doesn't raise an error when a dependency is cyclic" do + foo = build_dep(:foo) + bar = build_dep(:bar, [], [foo]) + allow(foo).to receive(:to_formula).and_return(double(deps: [bar], name: foo.name)) + f = double(name: "f", deps: [foo, bar]) + expect { described_class.expand(f) }.not_to raise_error + end + + it "cleans the expand stack" do + foo = build_dep(:foo) + allow(foo).to receive(:to_formula).and_raise(FormulaUnavailableError, foo.name) + f = double(name: "f", deps: [foo]) + expect { described_class.expand(f) }.to raise_error(FormulaUnavailableError) + expect(described_class.instance_variable_get(:@expand_stack)).to be_empty + end +end diff --git a/Library/Homebrew/test/dependency_expansion_test.rb b/Library/Homebrew/test/dependency_expansion_test.rb deleted file mode 100644 index 9d6de35e2..000000000 --- a/Library/Homebrew/test/dependency_expansion_test.rb +++ /dev/null @@ -1,137 +0,0 @@ -require "testing_env" -require "dependency" - -class DependencyExpansionTests < Homebrew::TestCase - def build_dep(name, tags = [], deps = []) - dep = Dependency.new(name.to_s, tags) - dep.stubs(:to_formula).returns(stub(deps: deps, name: name)) - dep - end - - def setup - @foo = build_dep(:foo) - @bar = build_dep(:bar) - @baz = build_dep(:baz) - @qux = build_dep(:qux) - @deps = [@foo, @bar, @baz, @qux] - @f = stub(deps: @deps, name: "f") - end - - def test_expand_yields_dependent_and_dep_pairs - i = 0 - Dependency.expand(@f) do |dependent, dep| - assert_equal @f, dependent - assert_equal dep, @deps[i] - i += 1 - end - end - - def test_expand_no_block - assert_equal @deps, Dependency.expand(@f) - end - - def test_expand_prune_all - assert_empty Dependency.expand(@f) { Dependency.prune } - end - - def test_expand_selective_pruning - deps = Dependency.expand(@f) do |_, dep| - Dependency.prune if dep.name == "foo" - end - - assert_equal [@bar, @baz, @qux], deps - end - - def test_expand_preserves_dependency_order - @foo.stubs(:to_formula).returns(stub(name: "f", deps: [@qux, @baz])) - assert_equal [@qux, @baz, @foo, @bar], Dependency.expand(@f) - end - - def test_expand_skips_optionals_by_default - deps = [build_dep(:foo, [:optional]), @bar, @baz, @qux] - f = stub(deps: deps, build: stub(with?: false), name: "f") - assert_equal [@bar, @baz, @qux], Dependency.expand(f) - end - - def test_expand_keeps_recommendeds_by_default - deps = [build_dep(:foo, [:recommended]), @bar, @baz, @qux] - f = stub(deps: deps, build: stub(with?: true), name: "f") - assert_equal deps, Dependency.expand(f) - end - - def test_merges_repeated_deps_with_differing_options - @foo2 = build_dep(:foo, ["option"]) - @baz2 = build_dep(:baz, ["option"]) - @deps << @foo2 << @baz2 - deps = [@foo2, @bar, @baz2, @qux] - deps.zip(Dependency.expand(@f)) do |expected, actual| - assert_equal expected.tags, actual.tags - assert_equal expected, actual - end - end - - def test_merger_preserves_env_proc - env_proc = stub - dep = Dependency.new("foo", [], env_proc) - dep.stubs(:to_formula).returns(stub(deps: [], name: "foo")) - @deps.replace [dep] - assert_equal env_proc, Dependency.expand(@f).first.env_proc - end - - def test_merged_tags_no_dupes - @foo2 = build_dep(:foo, ["option"]) - @foo3 = build_dep(:foo, ["option"]) - @deps << @foo2 << @foo3 - - assert_equal %w[option], Dependency.expand(@f).first.tags - end - - def test_skip_skips_parent_but_yields_children - f = stub( - name: "f", - deps: [ - build_dep(:foo, [], [@bar, @baz]), - build_dep(:foo, [], [@baz]), - ] - ) - - deps = Dependency.expand(f) do |_dependent, dep| - Dependency.skip if %w[foo qux].include? dep.name - end - - assert_equal [@bar, @baz], deps - end - - def test_keep_dep_but_prune_recursive_deps - foo = build_dep(:foo, [:build], @bar) - baz = build_dep(:baz, [:build]) - f = stub(name: "f", deps: [foo, baz]) - - deps = Dependency.expand(f) do |_dependent, dep| - Dependency.keep_but_prune_recursive_deps if dep.build? - end - - assert_equal [foo, baz], deps - end - - def test_deps_with_collection_argument - assert_equal [@foo, @bar, @baz, @qux], @f.deps - assert_equal [@bar, @baz], Dependency.expand(@f, [@bar, @baz]) - end - - def test_cyclic_dependency - foo = build_dep(:foo) - bar = build_dep(:bar, [], [foo]) - foo.stubs(:to_formula).returns(stub(deps: [bar], name: "foo")) - f = stub(name: "f", deps: [foo, bar]) - assert_nothing_raised { Dependency.expand(f) } - end - - def test_clean_expand_stack - foo = build_dep(:foo) - foo.stubs(:to_formula).raises(FormulaUnavailableError, "foo") - f = stub(name: "f", deps: [foo]) - assert_raises(FormulaUnavailableError) { Dependency.expand(f) } - assert_empty Dependency.instance_variable_get(:@expand_stack) - end -end diff --git a/Library/Homebrew/test/dependency_test.rb b/Library/Homebrew/test/dependency_test.rb index 65255995e..404f26d79 100644 --- a/Library/Homebrew/test/dependency_test.rb +++ b/Library/Homebrew/test/dependency_test.rb @@ -3,6 +3,7 @@ require "dependency" class DependableTests < Homebrew::TestCase def setup + super @tags = ["foo", "bar", :build] @dep = Struct.new(:tags).new(@tags).extend(Dependable) end @@ -118,6 +119,11 @@ class DependencyTests < Homebrew::TestCase end class TapDependencyTests < Homebrew::TestCase + def test_tap + dep = TapDependency.new("foo/bar/dog") + assert_equal Tap.new("foo", "bar"), dep.tap + end + def test_option_names dep = TapDependency.new("foo/bar/dog") assert_equal %w[dog], dep.option_names diff --git a/Library/Homebrew/test/deps_spec.rb b/Library/Homebrew/test/deps_spec.rb new file mode 100644 index 000000000..4c892c93d --- /dev/null +++ b/Library/Homebrew/test/deps_spec.rb @@ -0,0 +1,31 @@ +describe "brew deps", :integration_test do + before(:each) do + setup_test_formula "foo" + setup_test_formula "bar" + setup_test_formula "baz", <<-EOS.undent + url "https://example.com/baz-1.0" + depends_on "bar" + EOS + end + + it "outputs no dependencies for a Formula that has no dependencies" do + expect { brew "deps", "foo" } + .to be_a_success + .and not_to_output.to_stdout + .and not_to_output.to_stderr + end + + it "outputs a dependency for a Formula that has one dependency" do + expect { brew "deps", "bar" } + .to be_a_success + .and output("foo\n").to_stdout + .and not_to_output.to_stderr + end + + it "outputs all of a Formula's dependencies and their dependencies on separate lines" do + expect { brew "deps", "baz" } + .to be_a_success + .and output("bar\nfoo\n").to_stdout + .and not_to_output.to_stderr + end +end diff --git a/Library/Homebrew/test/deps_test.rb b/Library/Homebrew/test/deps_test.rb deleted file mode 100644 index 01639857c..000000000 --- a/Library/Homebrew/test/deps_test.rb +++ /dev/null @@ -1,16 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestDeps < IntegrationCommandTestCase - def test_deps - setup_test_formula "foo" - setup_test_formula "bar" - setup_test_formula "baz", <<-EOS.undent - url "https://example.com/baz-1.0" - depends_on "bar" - EOS - - assert_equal "", cmd("deps", "foo") - assert_equal "foo", cmd("deps", "bar") - assert_equal "bar\nfoo", cmd("deps", "baz") - end -end diff --git a/Library/Homebrew/test/desc_test.rb b/Library/Homebrew/test/desc_test.rb deleted file mode 100644 index 2ba498135..000000000 --- a/Library/Homebrew/test/desc_test.rb +++ /dev/null @@ -1,17 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestDesc < IntegrationCommandTestCase - def test_desc - setup_test_formula "testball" - - assert_equal "testball: Some test", cmd("desc", "testball") - assert_match "Pick one, and only one", cmd_fail("desc", "--search", "--name") - assert_match "You must provide a search term", cmd_fail("desc", "--search") - - desc_cache = HOMEBREW_CACHE/"desc_cache.json" - refute_predicate desc_cache, :exist?, "Cached file should not exist" - - cmd("desc", "--description", "testball") - assert_predicate desc_cache, :exist?, "Cached file should not exist" - end -end diff --git a/Library/Homebrew/test/descriptions_spec.rb b/Library/Homebrew/test/descriptions_spec.rb new file mode 100644 index 000000000..e873c73b4 --- /dev/null +++ b/Library/Homebrew/test/descriptions_spec.rb @@ -0,0 +1,42 @@ +require "descriptions" + +describe Descriptions do + subject { described_class.new(descriptions_hash) } + let(:descriptions_hash) { {} } + + it "can print description for a core Formula" do + descriptions_hash["homebrew/core/foo"] = "Core foo" + expect { subject.print }.to output("foo: Core foo\n").to_stdout + end + + it "can print description for an external Formula" do + descriptions_hash["somedev/external/foo"] = "External foo" + expect { subject.print }.to output("foo: External foo\n").to_stdout + end + + it "can print descriptions for duplicate Formulae" do + descriptions_hash["homebrew/core/foo"] = "Core foo" + descriptions_hash["somedev/external/foo"] = "External foo" + + expect { subject.print }.to output( + <<-EOS.undent + homebrew/core/foo: Core foo + somedev/external/foo: External foo + EOS + ).to_stdout + end + + it "can print descriptions for duplicate core and external Formulae" do + descriptions_hash["homebrew/core/foo"] = "Core foo" + descriptions_hash["somedev/external/foo"] = "External foo" + descriptions_hash["otherdev/external/foo"] = "Other external foo" + + expect { subject.print }.to output( + <<-EOS.undent + homebrew/core/foo: Core foo + otherdev/external/foo: Other external foo + somedev/external/foo: External foo + EOS + ).to_stdout + end +end diff --git a/Library/Homebrew/test/descriptions_test.rb b/Library/Homebrew/test/descriptions_test.rb deleted file mode 100644 index de38fdbd1..000000000 --- a/Library/Homebrew/test/descriptions_test.rb +++ /dev/null @@ -1,45 +0,0 @@ -require "testing_env" -require "descriptions" - -class DescriptionsTest < Homebrew::TestCase - def setup - @descriptions_hash = {} - @descriptions = Descriptions.new(@descriptions_hash) - - @old_stdout = $stdout - $stdout = StringIO.new - end - - def teardown - $stdout = @old_stdout - end - - def test_single_core_formula - @descriptions_hash["homebrew/core/foo"] = "Core foo" - @descriptions.print - assert_equal "foo: Core foo", $stdout.string.chomp - end - - def test_single_external_formula - @descriptions_hash["somedev/external/foo"] = "External foo" - @descriptions.print - assert_equal "foo: External foo", $stdout.string.chomp - end - - def test_even_dupes - @descriptions_hash["homebrew/core/foo"] = "Core foo" - @descriptions_hash["somedev/external/foo"] = "External foo" - @descriptions.print - assert_equal "homebrew/core/foo: Core foo\nsomedev/external/foo: External foo", - $stdout.string.chomp - end - - def test_odd_dupes - @descriptions_hash["homebrew/core/foo"] = "Core foo" - @descriptions_hash["somedev/external/foo"] = "External foo" - @descriptions_hash["otherdev/external/foo"] = "Other external foo" - @descriptions.print - assert_equal "homebrew/core/foo: Core foo\notherdev/external/foo: Other external foo\nsomedev/external/foo: External foo", - $stdout.string.chomp - end -end diff --git a/Library/Homebrew/test/dev-cmd/bottle_spec.rb b/Library/Homebrew/test/dev-cmd/bottle_spec.rb new file mode 100644 index 000000000..468ef2e90 --- /dev/null +++ b/Library/Homebrew/test/dev-cmd/bottle_spec.rb @@ -0,0 +1,30 @@ +describe "brew bottle", :integration_test do + it "builds a bottle for the given Formula" do + begin + shutup do + expect { brew "install", "--build-bottle", testball } + .to be_a_success + end + + expect { brew "bottle", "--no-rebuild", testball } + .to output(/Formula not from core or any taps/).to_stderr + .and not_to_output.to_stdout + .and be_a_failure + + setup_test_formula "testball" + + # `brew bottle` should not fail with dead symlink + # https://github.com/Homebrew/legacy-homebrew/issues/49007 + (HOMEBREW_CELLAR/"testball/0.1").cd do + FileUtils.ln_s "not-exist", "symlink" + end + + expect { brew "bottle", "--no-rebuild", "testball" } + .to output(/testball-0\.1.*\.bottle\.tar\.gz/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + ensure + FileUtils.rm_f Dir.glob("testball-0.1*.bottle.tar.gz") + end + end +end diff --git a/Library/Homebrew/test/dev-cmd/create_spec.rb b/Library/Homebrew/test/dev-cmd/create_spec.rb new file mode 100644 index 000000000..b7f96ec7f --- /dev/null +++ b/Library/Homebrew/test/dev-cmd/create_spec.rb @@ -0,0 +1,13 @@ +describe "brew create", :integration_test do + let(:url) { "file://#{TEST_FIXTURE_DIR}/tarballs/testball-0.1.tbz" } + let(:formula_file) { CoreTap.new.formula_dir/"testball.rb" } + + it "creates a new Formula file for a given URL" do + shutup do + brew "create", url, "HOMEBREW_EDITOR" => "/bin/cat" + end + + expect(formula_file).to exist + expect(formula_file.read).to match(%Q(sha256 "#{TESTBALL_SHA256}")) + end +end diff --git a/Library/Homebrew/test/dev-cmd/edit_spec.rb b/Library/Homebrew/test/dev-cmd/edit_spec.rb new file mode 100644 index 000000000..5cedb0524 --- /dev/null +++ b/Library/Homebrew/test/dev-cmd/edit_spec.rb @@ -0,0 +1,16 @@ +describe "brew edit", :integration_test do + it "opens a given Formula in an editor" do + HOMEBREW_REPOSITORY.cd do + shutup do + system "git", "init" + end + end + + setup_test_formula "testball" + + expect { brew "edit", "testball", "HOMEBREW_EDITOR" => "/bin/cat" } + .to output(/# something here/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end +end diff --git a/Library/Homebrew/test/dev-cmd/formula_spec.rb b/Library/Homebrew/test/dev-cmd/formula_spec.rb new file mode 100644 index 000000000..cc5b3e9e8 --- /dev/null +++ b/Library/Homebrew/test/dev-cmd/formula_spec.rb @@ -0,0 +1,10 @@ +describe "brew formula", :integration_test do + it "prints a given Formula's path" do + formula_file = setup_test_formula "testball" + + expect { brew "formula", "testball" } + .to output("#{formula_file}\n").to_stdout + .and not_to_output.to_stderr + .and be_a_success + end +end diff --git a/Library/Homebrew/test/dev-cmd/pull_spec.rb b/Library/Homebrew/test/dev-cmd/pull_spec.rb new file mode 100644 index 000000000..3c0108df2 --- /dev/null +++ b/Library/Homebrew/test/dev-cmd/pull_spec.rb @@ -0,0 +1,60 @@ +describe "brew pull", :integration_test do + it "fails when no argument is given" do + expect { brew "pull" } + .to output(/This command requires at least one argument/).to_stderr + .and not_to_output.to_stdout + .and be_a_failure + end + + it "fetches a patch from a GitHub commit or pull request and applies it" do + skip "Requires network connection." if ENV["HOMEBREW_NO_GITHUB_API"] + + CoreTap.instance.path.cd do + shutup do + system "git", "init" + system "git", "checkout", "-b", "new-branch" + end + end + + expect { brew "pull", "https://bot.brew.sh/job/Homebrew\%20Testing/1028/" } + .to output(/Testing URLs require `\-\-bottle`!/).to_stderr + .and not_to_output.to_stdout + .and be_a_failure + + expect { brew "pull", "1" } + .to output(/Fetching patch/).to_stdout + .and output(/Current branch is new\-branch/).to_stderr + .and be_a_failure + + expect { brew "pull", "--bump", "8" } + .to output(/Fetching patch/).to_stdout + .and output(/No changed formulae found to bump/).to_stderr + .and be_a_failure + + expect { brew "pull", "--bump", "https://api.github.com/repos/Homebrew/homebrew-core/pulls/122" } + .to output(/Fetching patch/).to_stdout + .and output(/Can only bump one changed formula/).to_stderr + .and be_a_failure + + expect { brew "pull", "https://github.com/Homebrew/homebrew-core/pull/1" } + .to output(/Fetching patch/).to_stdout + .and output(/Patch failed to apply/).to_stderr + .and be_a_failure + end + + describe "--rebase" do + it "fails" do + expect { brew "pull", "--rebase" } + .to output(/You meant `git pull --rebase`./).to_stderr + .and not_to_output.to_stdout + .and be_a_failure + end + end + + it "fails when given 0" do + expect { brew "pull", "0" } + .to output(/Not a GitHub pull request or commit/).to_stderr + .and not_to_output.to_stdout + .and be_a_failure + end +end diff --git a/Library/Homebrew/test/dev-cmd/tap_spec.rb b/Library/Homebrew/test/dev-cmd/tap_spec.rb new file mode 100644 index 000000000..a24c67aae --- /dev/null +++ b/Library/Homebrew/test/dev-cmd/tap_spec.rb @@ -0,0 +1,75 @@ +describe "brew tap", :integration_test do + it "taps a given Tap" do + path = Tap::TAP_DIRECTORY/"homebrew/homebrew-foo" + path.mkpath + path.cd do + shutup do + system "git", "init" + system "git", "remote", "add", "origin", "https://github.com/Homebrew/homebrew-foo" + FileUtils.touch "readme" + system "git", "add", "--all" + system "git", "commit", "-m", "init" + end + end + + expect { brew "tap" } + .to output(%r{homebrew/foo}).to_stdout + .and not_to_output.to_stderr + .and be_a_success + + expect { brew "tap", "--list-official" } + .to output(%r{homebrew/science}).to_stdout + .and not_to_output.to_stderr + .and be_a_success + + expect { brew "tap-info" } + .to output(/2 taps/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + + expect { brew "tap-info", "homebrew/foo" } + .to output(%r{https://github\.com/Homebrew/homebrew-foo}).to_stdout + .and not_to_output.to_stderr + .and be_a_success + + expect { brew "tap-info", "--json=v1", "--installed" } + .to output(%r{https://github\.com/Homebrew/homebrew-foo}).to_stdout + .and not_to_output.to_stderr + .and be_a_success + + expect { brew "tap-pin", "homebrew/foo" } + .to output(%r{Pinned homebrew/foo}).to_stdout + .and not_to_output.to_stderr + .and be_a_success + + expect { brew "tap", "--list-pinned" } + .to output(%r{homebrew/foo}).to_stdout + .and not_to_output.to_stderr + .and be_a_success + + expect { brew "tap-unpin", "homebrew/foo" } + .to output(%r{Unpinned homebrew/foo}).to_stdout + .and not_to_output.to_stderr + .and be_a_success + + expect { brew "tap", "homebrew/bar", path/".git" } + .to output(/Tapped/).to_stdout + .and output(/Cloning/).to_stderr + .and be_a_success + + expect { brew "untap", "homebrew/bar" } + .to output(/Untapped/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + + expect { brew "tap", "homebrew/bar", path/".git", "-q", "--full" } + .to be_a_success + .and not_to_output.to_stdout + .and not_to_output.to_stderr + + expect { brew "untap", "homebrew/bar" } + .to output(/Untapped/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end +end diff --git a/Library/Homebrew/test/dev-cmd/test_spec.rb b/Library/Homebrew/test/dev-cmd/test_spec.rb new file mode 100644 index 000000000..b73d042e4 --- /dev/null +++ b/Library/Homebrew/test/dev-cmd/test_spec.rb @@ -0,0 +1,56 @@ +describe "brew test", :integration_test do + it "fails when no argument is given" do + expect { brew "test" } + .to output(/This command requires a formula argument/).to_stderr + .and not_to_output.to_stdout + .and be_a_failure + end + + it "fails when a Formula is not installed" do + expect { brew "test", testball } + .to output(/Testing requires the latest version of testball/).to_stderr + .and not_to_output.to_stdout + .and be_a_failure + end + + it "fails when a Formula has no test" do + shutup do + expect { brew "install", testball }.to be_a_success + end + + expect { brew "test", testball } + .to output(/testball defines no test/).to_stderr + .and not_to_output.to_stdout + .and be_a_failure + end + + it "tests a given Formula" do + setup_test_formula "testball", <<-EOS.undent + head "https://github.com/example/testball2.git" + + devel do + url "file://#{TEST_FIXTURE_DIR}/tarballs/testball-0.1.tbz" + sha256 "#{TESTBALL_SHA256}" + end + + keg_only "just because" + + test do + end + EOS + + shutup do + expect { brew "install", "testball" }.to be_a_success + end + + expect { brew "test", "--HEAD", "testball" } + .to output(/Testing testball/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + + expect { brew "test", "--devel", "testball" } + .to output(/Testing testball/).to_stdout + .and not_to_output.to_stderr + .and be_a_success + end +end diff --git a/Library/Homebrew/test/diagnostic_spec.rb b/Library/Homebrew/test/diagnostic_spec.rb new file mode 100644 index 000000000..e749a3b0f --- /dev/null +++ b/Library/Homebrew/test/diagnostic_spec.rb @@ -0,0 +1,188 @@ +require "diagnostic" + +describe Homebrew::Diagnostic::Checks do + specify "#inject_file_list" do + expect(subject.inject_file_list([], "foo:\n")).to eq("foo:\n") + expect(subject.inject_file_list(%w[/a /b], "foo:\n")).to eq("foo:\n /a\n /b\n") + end + + specify "#check_path_for_trailing_slashes" do + ENV["PATH"] += File::PATH_SEPARATOR + "/foo/bar/" + expect(subject.check_path_for_trailing_slashes) + .to match("Some directories in your path end in a slash") + end + + specify "#check_for_anaconda" do + Dir.mktmpdir do |path| + anaconda = "#{path}/anaconda" + python = "#{path}/python" + FileUtils.touch anaconda + File.open(python, "w") do |file| + file.write("#! #{`which bash`}\necho -n '#{python}'\n") + end + FileUtils.chmod 0755, anaconda + FileUtils.chmod 0755, python + + ENV["PATH"] = path + File::PATH_SEPARATOR + ENV["PATH"] + + expect(subject.check_for_anaconda).to match("Anaconda") + end + end + + specify "#check_access_homebrew_repository" do + begin + mode = HOMEBREW_REPOSITORY.stat.mode & 0777 + HOMEBREW_REPOSITORY.chmod 0555 + + expect(subject.check_access_homebrew_repository) + .to match("#{HOMEBREW_REPOSITORY} is not writable.") + ensure + HOMEBREW_REPOSITORY.chmod mode + end + end + + specify "#check_access_logs" do + begin + mode = HOMEBREW_LOGS.stat.mode & 0777 + HOMEBREW_LOGS.chmod 0555 + + expect(subject.check_access_logs) + .to match("#{HOMEBREW_LOGS} isn't writable.") + ensure + HOMEBREW_LOGS.chmod mode + end + end + + specify "#check_access_cache" do + begin + mode = HOMEBREW_CACHE.stat.mode & 0777 + HOMEBREW_CACHE.chmod 0555 + expect(subject.check_access_cache) + .to match("#{HOMEBREW_CACHE} isn't writable.") + ensure + HOMEBREW_CACHE.chmod mode + end + end + + specify "#check_access_cellar" do + begin + mode = HOMEBREW_CELLAR.stat.mode & 0777 + HOMEBREW_CELLAR.chmod 0555 + + expect(subject.check_access_cellar) + .to match("#{HOMEBREW_CELLAR} isn't writable.") + ensure + HOMEBREW_CELLAR.chmod mode + end + end + + specify "#check_homebrew_prefix" do + ENV.delete("JENKINS_HOME") + # the integration tests are run in a special prefix + expect(subject.check_homebrew_prefix) + .to match("Your Homebrew's prefix is not /usr/local.") + end + + specify "#check_user_path_1" do + bin = HOMEBREW_PREFIX/"bin" + sep = File::PATH_SEPARATOR + # ensure /usr/bin is before HOMEBREW_PREFIX/bin in the PATH + ENV["PATH"] = "/usr/bin#{sep}#{bin}#{sep}" + + ENV["PATH"].gsub(%r{(?:^|#{sep})(?:/usr/bin|#{bin})}, "") + + # ensure there's at least one file with the same name in both /usr/bin/ and + # HOMEBREW_PREFIX/bin/ + (bin/File.basename(Dir["/usr/bin/*"].first)).mkpath + + expect(subject.check_user_path_1) + .to match("/usr/bin occurs before #{HOMEBREW_PREFIX}/bin") + end + + specify "#check_user_path_2" do + ENV["PATH"] = ENV["PATH"].gsub \ + %r{(?:^|#{File::PATH_SEPARATOR})#{HOMEBREW_PREFIX}/bin}, "" + + expect(subject.check_user_path_1).to be nil + expect(subject.check_user_path_2) + .to match("Homebrew's bin was not found in your PATH.") + end + + specify "#check_user_path_3" do + begin + sbin = HOMEBREW_PREFIX/"sbin" + ENV["PATH"] = "#{HOMEBREW_PREFIX}/bin#{File::PATH_SEPARATOR}" + + ENV["PATH"].gsub(/(?:^|#{Regexp.escape(File::PATH_SEPARATOR)})#{Regexp.escape(sbin)}/, "") + (sbin/"something").mkpath + + expect(subject.check_user_path_1).to be nil + expect(subject.check_user_path_2).to be nil + expect(subject.check_user_path_3) + .to match("Homebrew's sbin was not found in your PATH") + ensure + sbin.rmtree + end + end + + specify "#check_user_curlrc" do + Dir.mktmpdir do |path| + FileUtils.touch "#{path}/.curlrc" + ENV["CURL_HOME"] = path + + expect(subject.check_user_curlrc).to match("You have a curlrc file") + end + end + + specify "#check_for_config_scripts" do + Dir.mktmpdir do |path| + file = "#{path}/foo-config" + FileUtils.touch file + FileUtils.chmod 0755, file + ENV["PATH"] = "#{path}#{File::PATH_SEPARATOR}#{ENV["PATH"]}" + + expect(subject.check_for_config_scripts) + .to match('"config" scripts exist') + end + end + + specify "#check_dyld_vars" do + ENV["DYLD_INSERT_LIBRARIES"] = "foo" + expect(subject.check_dyld_vars).to match("Setting DYLD_INSERT_LIBRARIES") + end + + specify "#check_for_symlinked_cellar" do + begin + HOMEBREW_CELLAR.rmtree + + Dir.mktmpdir do |path| + FileUtils.ln_s path, HOMEBREW_CELLAR + + expect(subject.check_for_symlinked_cellar).to match(path) + end + ensure + HOMEBREW_CELLAR.unlink + HOMEBREW_CELLAR.mkpath + end + end + + specify "#check_tmpdir" do + ENV["TMPDIR"] = "/i/don/t/exis/t" + expect(subject.check_tmpdir).to match("doesn't exist") + end + + specify "#check_for_external_cmd_name_conflict" do + Dir.mktmpdir do |path1| + Dir.mktmpdir do |path2| + [path1, path2].each do |path| + cmd = "#{path}/brew-foo" + FileUtils.touch cmd + FileUtils.chmod 0755, cmd + end + + ENV["PATH"] = [path1, path2, ENV["PATH"]].join File::PATH_SEPARATOR + + expect(subject.check_for_external_cmd_name_conflict) + .to match("brew-foo") + end + end + end +end diff --git a/Library/Homebrew/test/diagnostic_test.rb b/Library/Homebrew/test/diagnostic_test.rb deleted file mode 100644 index c9bb524b0..000000000 --- a/Library/Homebrew/test/diagnostic_test.rb +++ /dev/null @@ -1,198 +0,0 @@ -require "testing_env" -require "fileutils" -require "pathname" -require "diagnostic" - -class DiagnosticChecksTest < Homebrew::TestCase - def setup - @env = ENV.to_hash - @checks = Homebrew::Diagnostic::Checks.new - end - - def teardown - ENV.replace(@env) - end - - def test_inject_file_list - assert_equal "foo:\n", - @checks.inject_file_list([], "foo:\n") - assert_equal "foo:\n /a\n /b\n", - @checks.inject_file_list(%w[/a /b], "foo:\n") - end - - def test_check_path_for_trailing_slashes - ENV["PATH"] += File::PATH_SEPARATOR + "/foo/bar/" - assert_match "Some directories in your path end in a slash", - @checks.check_path_for_trailing_slashes - end - - def test_check_for_anaconda - mktmpdir do |path| - anaconda = "#{path}/anaconda" - python = "#{path}/python" - FileUtils.touch anaconda - File.open(python, "w") do |file| - file.write("#! #{`which bash`}\necho -n '#{python}'\n") - end - FileUtils.chmod 0755, anaconda - FileUtils.chmod 0755, python - - ENV["PATH"] = path + File::PATH_SEPARATOR + ENV["PATH"] - - assert_match "Anaconda", - @checks.check_for_anaconda - end - end - - def test_check_access_homebrew_repository - mod = HOMEBREW_REPOSITORY.stat.mode & 0777 - HOMEBREW_REPOSITORY.chmod 0555 - - assert_match "#{HOMEBREW_REPOSITORY} is not writable.", - @checks.check_access_homebrew_repository - ensure - HOMEBREW_REPOSITORY.chmod mod - end - - def test_check_access_logs - mod = HOMEBREW_LOGS.stat.mode & 0777 - HOMEBREW_LOGS.chmod 0555 - - assert_match "#{HOMEBREW_LOGS} isn't writable.", - @checks.check_access_logs - ensure - HOMEBREW_LOGS.chmod mod - end - - def test_check_access_cache - mod = HOMEBREW_CACHE.stat.mode & 0777 - HOMEBREW_CACHE.chmod 0555 - assert_match "#{HOMEBREW_CACHE} isn't writable.", - @checks.check_access_cache - ensure - HOMEBREW_CACHE.chmod mod - end - - def test_check_access_cellar - mod = HOMEBREW_CELLAR.stat.mode & 0777 - HOMEBREW_CELLAR.chmod 0555 - - assert_match "#{HOMEBREW_CELLAR} isn't writable.", - @checks.check_access_cellar - ensure - HOMEBREW_CELLAR.chmod mod - end - - def test_check_homebrew_prefix - ENV.delete("JENKINS_HOME") - # the integration tests are run in a special prefix - assert_match "Your Homebrew's prefix is not /usr/local.", - @checks.check_homebrew_prefix - end - - def test_check_user_path_usr_bin_before_homebrew - bin = HOMEBREW_PREFIX/"bin" - sep = File::PATH_SEPARATOR - # ensure /usr/bin is before HOMEBREW_PREFIX/bin in the PATH - ENV["PATH"] = "/usr/bin#{sep}#{bin}#{sep}" + - ENV["PATH"].gsub(%r{(?:^|#{sep})(?:/usr/bin|#{bin})}, "") - - # ensure there's at least one file with the same name in both /usr/bin/ and - # HOMEBREW_PREFIX/bin/ - (bin/File.basename(Dir["/usr/bin/*"].first)).mkpath - - assert_match "/usr/bin occurs before #{HOMEBREW_PREFIX}/bin", - @checks.check_user_path_1 - ensure - bin.rmtree - end - - def test_check_user_path_bin - ENV["PATH"] = ENV["PATH"].gsub \ - %r{(?:^|#{File::PATH_SEPARATOR})#{HOMEBREW_PREFIX}/bin}, "" - - assert_nil @checks.check_user_path_1 - assert_match "Homebrew's bin was not found in your PATH.", - @checks.check_user_path_2 - end - - def test_check_user_path_sbin - sbin = HOMEBREW_PREFIX/"sbin" - ENV["PATH"] = "#{HOMEBREW_PREFIX}/bin#{File::PATH_SEPARATOR}" + - ENV["PATH"].gsub(/(?:^|#{Regexp.escape(File::PATH_SEPARATOR)})#{Regexp.escape(sbin)}/, "") - (sbin/"something").mkpath - - assert_nil @checks.check_user_path_1 - assert_nil @checks.check_user_path_2 - assert_match "Homebrew's sbin was not found in your PATH", - @checks.check_user_path_3 - ensure - sbin.rmtree - end - - def test_check_user_curlrc - mktmpdir do |path| - FileUtils.touch "#{path}/.curlrc" - ENV["CURL_HOME"] = path - - assert_match "You have a curlrc file", - @checks.check_user_curlrc - end - end - - def test_check_for_config_scripts - mktmpdir do |path| - file = "#{path}/foo-config" - FileUtils.touch file - FileUtils.chmod 0755, file - ENV["PATH"] = "#{path}#{File::PATH_SEPARATOR}#{ENV["PATH"]}" - - assert_match '"config" scripts exist', - @checks.check_for_config_scripts - end - end - - def test_check_dyld_vars - ENV["DYLD_INSERT_LIBRARIES"] = "foo" - assert_match "Setting DYLD_INSERT_LIBRARIES", - @checks.check_dyld_vars - end - - def test_check_for_symlinked_cellar - HOMEBREW_CELLAR.rmtree - - mktmpdir do |path| - FileUtils.ln_s path, HOMEBREW_CELLAR - - assert_match path, - @checks.check_for_symlinked_cellar - end - - ensure - HOMEBREW_CELLAR.unlink - HOMEBREW_CELLAR.mkpath - end - - def test_check_tmpdir - ENV["TMPDIR"] = "/i/don/t/exis/t" - assert_match "doesn't exist", - @checks.check_tmpdir - end - - def test_check_for_external_cmd_name_conflict - mktmpdir do |path1| - mktmpdir do |path2| - [path1, path2].each do |path| - cmd = "#{path}/brew-foo" - FileUtils.touch cmd - FileUtils.chmod 0755, cmd - end - - ENV["PATH"] = [path1, path2, ENV["PATH"]].join File::PATH_SEPARATOR - - assert_match "brew-foo", - @checks.check_for_external_cmd_name_conflict - end - end - end -end diff --git a/Library/Homebrew/test/doctor_test.rb b/Library/Homebrew/test/doctor_test.rb deleted file mode 100644 index d2dc871f4..000000000 --- a/Library/Homebrew/test/doctor_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestDoctor < IntegrationCommandTestCase - def test_doctor - assert_match "This is an integration test", - cmd_fail("doctor", "check_integration_test") - end -end diff --git a/Library/Homebrew/test/download_strategies_spec.rb b/Library/Homebrew/test/download_strategies_spec.rb new file mode 100644 index 000000000..f466b97f4 --- /dev/null +++ b/Library/Homebrew/test/download_strategies_spec.rb @@ -0,0 +1,232 @@ +require "download_strategy" + +describe AbstractDownloadStrategy 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: {}, version: nil) } + let(:args) { %w[foo bar baz] } + + describe "#expand_safe_system_args" do + it "works with an explicit quiet flag" do + args << { quiet_flag: "--flag" } + expanded_args = subject.expand_safe_system_args(args) + expect(expanded_args).to eq(%w[foo bar baz --flag]) + end + + it "adds an implicit quiet flag" do + expanded_args = subject.expand_safe_system_args(args) + expect(expanded_args).to eq(%w[foo bar -q baz]) + end + + it "does not mutate the arguments" do + result = subject.expand_safe_system_args(args) + expect(args).to eq(%w[foo bar baz]) + expect(result).not_to be args + end + end + + specify "#source_modified_time" do + FileUtils.mktemp "mtime" do + FileUtils.touch "foo", mtime: Time.now - 10 + FileUtils.touch "bar", mtime: Time.now - 100 + FileUtils.ln_s "not-exist", "baz" + expect(subject.source_modified_time).to eq(File.mtime("foo")) + end + end +end + +describe VCSDownloadStrategy do + let(:url) { "http://example.com/bar" } + let(:resource) { double(Resource, url: url, mirrors: [], specs: {}, version: nil) } + + describe "#cached_location" do + it "returns the path of the cached resource" do + allow_any_instance_of(described_class).to receive(:cache_tag).and_return("foo") + downloader = described_class.new("baz", resource) + expect(downloader.cached_location).to eq(HOMEBREW_CACHE/"baz--foo") + end + end +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 + ENV["HOMEBREW_GITHUB_API_TOKEN"] = "token" + allow(GitHub).to receive(:repository).and_return({}) + end + + it "sets the @github_token instance variable" do + expect(subject.instance_variable_get(:@github_token)).to eq("token") + end + + it "parses the URL and sets the corresponding instance variables" do + expect(subject.instance_variable_get(:@owner)).to eq("owner") + expect(subject.instance_variable_get(:@repo)).to eq("repo") + expect(subject.instance_variable_get(:@filepath)).to eq("archive/1.1.5.tar.gz") + end + + its(:download_url) { is_expected.to eq("https://token@github.com/owner/repo/archive/1.1.5.tar.gz") } +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 + ENV["HOMEBREW_GITHUB_API_TOKEN"] = "token" + allow(GitHub).to receive(:repository).and_return({}) + end + + it "parses the URL and sets the corresponding instance variables" do + expect(subject.instance_variable_get(:@owner)).to eq("owner") + expect(subject.instance_variable_get(:@repo)).to eq("repo") + expect(subject.instance_variable_get(:@tag)).to eq("tag") + expect(subject.instance_variable_get(:@filename)).to eq("foo_v0.1.0_darwin_amd64.tar.gz") + end + + describe "#download_url" do + it "returns the download URL for a given resource" do + allow(subject).to receive(:resolve_asset_id).and_return(456) + expect(subject.download_url).to eq("https://token@api.github.com/repos/owner/repo/releases/assets/456") + end + end + + specify "#resolve_asset_id" do + release_metadata = { + "assets" => [ + { + "id" => 123, + "name" => "foo_v0.1.0_linux_amd64.tar.gz", + }, + { + "id" => 456, + "name" => "foo_v0.1.0_darwin_amd64.tar.gz", + }, + ], + } + allow(subject).to receive(:fetch_release_metadata).and_return(release_metadata) + expect(subject.send(:resolve_asset_id)).to eq(456) + end + + describe "#fetch_release_metadata" do + it "fetches release metadata from GitHub" do + expected_release_url = "https://api.github.com/repos/owner/repo/releases/tags/tag" + expect(GitHub).to receive(:open).with(expected_release_url).and_return({}) + subject.send(:fetch_release_metadata) + end + end +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) } + + it "parses the URL and sets the corresponding instance variables" do + expect(subject.instance_variable_get(:@user)).to eq("homebrew") + expect(subject.instance_variable_get(:@repo)).to eq("brew") + end +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 + @commit_id = 1 + FileUtils.mkpath cached_location + end + + def git_commit_all + shutup do + system "git", "add", "--all" + system "git", "commit", "-m", "commit number #{@commit_id}" + @commit_id += 1 + end + end + + def setup_git_repo + shutup do + system "git", "init" + system "git", "remote", "add", "origin", "https://github.com/Homebrew/homebrew-foo" + end + FileUtils.touch "README" + git_commit_all + end + + describe "#source_modified_time" do + it "returns the right modification time" do + cached_location.cd do + setup_git_repo + end + expect(subject.source_modified_time.to_i).to eq(1_485_115_153) + end + end + + specify "#last_commit" do + cached_location.cd do + setup_git_repo + FileUtils.touch "LICENSE" + git_commit_all + end + expect(subject.last_commit).to eq("f68266e") + end + + describe "#fetch_last_commit" do + let(:url) { "file://#{remote_repo}" } + let(:version) { Version.create("HEAD") } + let(:resource) { double(Resource, url: url, mirrors: [], specs: {}, version: version) } + let(:remote_repo) { HOMEBREW_PREFIX/"remote_repo" } + + before(:each) { remote_repo.mkpath } + + after(:each) { FileUtils.rm_rf remote_repo } + + it "fetches the hash of the last commit" do + remote_repo.cd do + setup_git_repo + FileUtils.touch "LICENSE" + git_commit_all + end + + subject.shutup! + expect(subject.fetch_last_commit).to eq("f68266e") + end + end +end + +describe DownloadStrategyDetector do + describe "::detect" do + subject { described_class.detect(url) } + let(:url) { Object.new } + + 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 + + it "defaults to cURL" do + expect(subject).to eq(CurlDownloadStrategy) + end + + it "raises an error when passed an unrecognized strategy" do + expect { + described_class.detect("foo", Class.new) + }.to raise_error(TypeError) + end + end +end diff --git a/Library/Homebrew/test/download_strategies_test.rb b/Library/Homebrew/test/download_strategies_test.rb deleted file mode 100644 index 2b64abbf9..000000000 --- a/Library/Homebrew/test/download_strategies_test.rb +++ /dev/null @@ -1,262 +0,0 @@ -require "testing_env" -require "download_strategy" - -class ResourceDouble - attr_reader :url, :specs, :version, :mirrors - - def initialize(url = "http://example.com/foo.tar.gz", specs = {}) - @url = url - @specs = specs - @mirrors = [] - end -end - -class AbstractDownloadStrategyTests < Homebrew::TestCase - include FileUtils - - def setup - @name = "foo" - @resource = ResourceDouble.new - @strategy = AbstractDownloadStrategy.new(@name, @resource) - @args = %w[foo bar baz] - end - - def test_expand_safe_system_args_with_explicit_quiet_flag - @args << { quiet_flag: "--flag" } - expanded_args = @strategy.expand_safe_system_args(@args) - assert_equal %w[foo bar baz --flag], expanded_args - end - - def test_expand_safe_system_args_with_implicit_quiet_flag - expanded_args = @strategy.expand_safe_system_args(@args) - assert_equal %w[foo bar -q baz], expanded_args - end - - def test_expand_safe_system_args_does_not_mutate_argument - result = @strategy.expand_safe_system_args(@args) - assert_equal %w[foo bar baz], @args - refute_same @args, result - end - - def test_source_modified_time - mktemp "mtime" do - touch "foo", mtime: Time.now - 10 - touch "bar", mtime: Time.now - 100 - ln_s "not-exist", "baz" - assert_equal File.mtime("foo"), @strategy.source_modified_time - end - end -end - -class VCSDownloadStrategyTests < Homebrew::TestCase - def test_cache_filename - resource = ResourceDouble.new("http://example.com/bar") - strategy = Class.new(VCSDownloadStrategy) do - def cache_tag - "foo" - end - end - downloader = strategy.new("baz", resource) - assert_equal HOMEBREW_CACHE.join("baz--foo"), downloader.cached_location - end -end - -class GitHubPrivateRepositoryDownloadStrategyTests < Homebrew::TestCase - def setup - resource = ResourceDouble.new("https://github.com/owner/repo/archive/1.1.5.tar.gz") - ENV["HOMEBREW_GITHUB_API_TOKEN"] = "token" - GitHub.stubs(:repository).returns {} - @strategy = GitHubPrivateRepositoryDownloadStrategy.new("foo", resource) - end - - def test_set_github_token - assert_equal "token", @strategy.instance_variable_get(:@github_token) - end - - def test_parse_url_pattern - assert_equal "owner", @strategy.instance_variable_get(:@owner) - assert_equal "repo", @strategy.instance_variable_get(:@repo) - assert_equal "archive/1.1.5.tar.gz", @strategy.instance_variable_get(:@filepath) - end - - def test_download_url - expected = "https://token@github.com/owner/repo/archive/1.1.5.tar.gz" - assert_equal expected, @strategy.download_url - end -end - -class GitHubPrivateRepositoryReleaseDownloadStrategyTests < Homebrew::TestCase - def setup - resource = ResourceDouble.new("https://github.com/owner/repo/releases/download/tag/foo_v0.1.0_darwin_amd64.tar.gz") - ENV["HOMEBREW_GITHUB_API_TOKEN"] = "token" - GitHub.stubs(:repository).returns {} - @strategy = GitHubPrivateRepositoryReleaseDownloadStrategy.new("foo", resource) - end - - def test_parse_url_pattern - assert_equal "owner", @strategy.instance_variable_get(:@owner) - assert_equal "repo", @strategy.instance_variable_get(:@repo) - assert_equal "tag", @strategy.instance_variable_get(:@tag) - assert_equal "foo_v0.1.0_darwin_amd64.tar.gz", @strategy.instance_variable_get(:@filename) - end - - def test_download_url - @strategy.stubs(:resolve_asset_id).returns(456) - expected = "https://token@api.github.com/repos/owner/repo/releases/assets/456" - assert_equal expected, @strategy.download_url - end - - def test_resolve_asset_id - release_metadata = { - "assets" => [ - { - "id" => 123, - "name" => "foo_v0.1.0_linux_amd64.tar.gz", - }, - { - "id" => 456, - "name" => "foo_v0.1.0_darwin_amd64.tar.gz", - }, - ], - } - @strategy.stubs(:fetch_release_metadata).returns(release_metadata) - assert_equal 456, @strategy.send(:resolve_asset_id) - end - - def test_fetch_release_metadata - expected_release_url = "https://api.github.com/repos/owner/repo/releases/tags/tag" - github_mock = MiniTest::Mock.new - github_mock.expect :call, {}, [expected_release_url] - GitHub.stub :open, github_mock do - @strategy.send(:fetch_release_metadata) - end - github_mock.verify - end -end - -class GitDownloadStrategyTests < Homebrew::TestCase - include FileUtils - - def setup - resource = ResourceDouble.new("https://github.com/homebrew/foo") - @commit_id = 1 - @strategy = GitDownloadStrategy.new("baz", resource) - @cached_location = @strategy.cached_location - mkpath @cached_location - end - - def teardown - rmtree @cached_location - end - - def git_commit_all - shutup do - system "git", "add", "--all" - system "git", "commit", "-m", "commit number #{@commit_id}" - @commit_id += 1 - end - end - - def using_git_env - initial_env = ENV.to_hash - %w[AUTHOR COMMITTER].each do |role| - ENV["GIT_#{role}_NAME"] = "brew tests" - ENV["GIT_#{role}_EMAIL"] = "brew-tests@localhost" - ENV["GIT_#{role}_DATE"] = "Thu May 21 00:04:11 2009 +0100" - end - yield - ensure - ENV.replace(initial_env) - end - - def setup_git_repo - using_git_env do - @cached_location.cd do - shutup do - system "git", "init" - system "git", "remote", "add", "origin", "https://github.com/Homebrew/homebrew-foo" - end - touch "README" - git_commit_all - end - end - end - - def test_github_git_download_strategy_user_repo - resource = ResourceDouble.new("https://github.com/homebrew/brew.git") - strategy = GitHubGitDownloadStrategy.new("brew", resource) - - assert_equal strategy.instance_variable_get(:@user), "homebrew" - assert_equal strategy.instance_variable_get(:@repo), "brew" - end - - def test_source_modified_time - setup_git_repo - assert_equal 1_242_860_651, @strategy.source_modified_time.to_i - end - - def test_last_commit - setup_git_repo - using_git_env do - @cached_location.cd do - touch "LICENSE" - git_commit_all - end - end - assert_equal "c50c79b", @strategy.last_commit - end - - def test_fetch_last_commit - remote_repo = HOMEBREW_PREFIX.join("remote_repo") - remote_repo.mkdir - - resource = ResourceDouble.new("file://#{remote_repo}") - resource.instance_variable_set(:@version, Version.create("HEAD")) - @strategy = GitDownloadStrategy.new("baz", resource) - - using_git_env do - remote_repo.cd do - shutup do - system "git", "init" - system "git", "remote", "add", "origin", "https://github.com/Homebrew/homebrew-foo" - end - touch "README" - git_commit_all - touch "LICENSE" - git_commit_all - end - end - - @strategy.shutup! - assert_equal "c50c79b", @strategy.fetch_last_commit - ensure - remote_repo.rmtree if remote_repo.directory? - end -end - -class DownloadStrategyDetectorTests < Homebrew::TestCase - def setup - @d = DownloadStrategyDetector.new - end - - def test_detect_git_download_startegy - @d = DownloadStrategyDetector.detect("git://example.com/foo.git") - assert_equal GitDownloadStrategy, @d - end - - def test_detect_github_git_download_strategy - @d = DownloadStrategyDetector.detect("https://github.com/homebrew/brew.git") - assert_equal GitHubGitDownloadStrategy, @d - end - - def test_default_to_curl_strategy - @d = DownloadStrategyDetector.detect(Object.new) - assert_equal CurlDownloadStrategy, @d - end - - def test_raises_when_passed_unrecognized_strategy - assert_raises(TypeError) do - DownloadStrategyDetector.detect("foo", Class.new) - end - end -end diff --git a/Library/Homebrew/test/edit_test.rb b/Library/Homebrew/test/edit_test.rb deleted file mode 100644 index 9b6ded651..000000000 --- a/Library/Homebrew/test/edit_test.rb +++ /dev/null @@ -1,11 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestEdit < IntegrationCommandTestCase - def test_edit - (HOMEBREW_REPOSITORY/".git").mkpath - setup_test_formula "testball" - - assert_match "# something here", - cmd("edit", "testball", "HOMEBREW_EDITOR" => "/bin/cat") - end -end diff --git a/Library/Homebrew/test/emoji_spec.rb b/Library/Homebrew/test/emoji_spec.rb new file mode 100644 index 000000000..35d077ebe --- /dev/null +++ b/Library/Homebrew/test/emoji_spec.rb @@ -0,0 +1,16 @@ +require "emoji" + +describe Emoji do + describe "#install_badge" do + subject { described_class.install_badge } + + it "returns 🍺 by default" do + expect(subject).to eq "🍺" + end + + it "returns the contents of HOMEBREW_INSTALL_BADGE if set" do + ENV["HOMEBREW_INSTALL_BADGE"] = "foo" + expect(subject).to eq "foo" + end + end +end diff --git a/Library/Homebrew/test/exceptions_spec.rb b/Library/Homebrew/test/exceptions_spec.rb new file mode 100644 index 000000000..33547ea32 --- /dev/null +++ b/Library/Homebrew/test/exceptions_spec.rb @@ -0,0 +1,188 @@ +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"))) + } +end + +describe FormulaUnavailableError do + subject { described_class.new("foo") } + + describe "#dependent_s" do + it "returns nil if there is no dependent" do + expect(subject.dependent_s).to be nil + end + + it "returns nil if it depended on by itself" do + subject.dependent = "foo" + expect(subject.dependent_s).to be nil + end + + it "returns a string if there is a dependent" do + subject.dependent = "foobar" + expect(subject.dependent_s).to eq("(dependency of foobar)") + end + end + + context "without a dependent" do + its(:to_s) { is_expected.to eq('No available formula with the name "foo" ') } + end + + context "with a dependent" do + before(:each) do + subject.dependent = "foobar" + end + + its(:to_s) { + is_expected.to eq('No available formula with the name "foo" (dependency of foobar)') + } + end +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 + class Baz < Formula; end + end + end + + context "no classes" do + let(:list) { [] } + its(:to_s) { + is_expected.to match(/Expected to find class Foo, but found no classes\./) + } + end + + 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!\)\./) + } + end + + 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: "<resource foo>") } + its(:to_s) { is_expected.to eq("bar does not define resource <resource foo>") } +end + +describe DuplicateResourceError do + subject { described_class.new(resource) } + let(:resource) { double(inspect: "<resource foo>") } + its(:to_s) { is_expected.to eq("Resource <resource foo> is defined more than once") } +end + +describe BottleVersionMismatchError do + subject { described_class.new("/foo.bottle.tar.gz", "1.0", formula, "1.1") } + let(:formula) { double(Formula, full_name: "foo") } + its(:to_s) { is_expected.to match(/Bottle version mismatch/) } +end diff --git a/Library/Homebrew/test/exceptions_test.rb b/Library/Homebrew/test/exceptions_test.rb deleted file mode 100644 index 689531c6e..000000000 --- a/Library/Homebrew/test/exceptions_test.rb +++ /dev/null @@ -1,142 +0,0 @@ -require "testing_env" -require "exceptions" - -class ExceptionsTest < Homebrew::TestCase - def test_multiple_versions_installed_error - assert_equal "foo has multiple installed versions", - MultipleVersionsInstalledError.new("foo").to_s - end - - def test_no_such_keg_error - assert_equal "No such keg: #{HOMEBREW_CELLAR}/foo", - NoSuchKegError.new("foo").to_s - end - - def test_formula_validation_error - assert_equal %q(invalid attribute for formula 'foo': sha257 ("magic")), - FormulaValidationError.new("foo", "sha257", "magic").to_s - end - - def test_formula_unavailable_error - e = FormulaUnavailableError.new "foo" - assert_nil e.dependent_s - - e.dependent = "foo" - assert_nil e.dependent_s - - e.dependent = "foobar" - assert_equal "(dependency of foobar)", e.dependent_s - - assert_equal "No available formula with the name \"foo\" (dependency of foobar)", - e.to_s - end - - def test_tap_formula_unavailable_error - t = stub(user: "u", repo: "r", to_s: "u/r", installed?: false) - assert_match "Please tap it and then try again: brew tap u/r", - TapFormulaUnavailableError.new(t, "foo").to_s - end - - def test_formula_class_unavailable_error - mod = Module.new - mod.module_eval <<-EOS.undent - class Bar < Requirement; end - class Baz < Formula; end - EOS - - assert_match "Expected to find class Foo, but found no classes.", - FormulaClassUnavailableError.new("foo", "foo.rb", "Foo", []).to_s - - list = [mod.const_get(:Bar)] - assert_match "Expected to find class Foo, but only found: Bar (not derived from Formula!).", - FormulaClassUnavailableError.new("foo", "foo.rb", "Foo", list).to_s - - list = [mod.const_get(:Baz)] - assert_match "Expected to find class Foo, but only found: Baz.", - FormulaClassUnavailableError.new("foo", "foo.rb", "Foo", list).to_s - end - - def test_tap_unavailable_error - assert_equal "No available tap foo.\n", TapUnavailableError.new("foo").to_s - end - - def test_tap_already_tapped_error - assert_equal "Tap foo already tapped.\n", - TapAlreadyTappedError.new("foo").to_s - end - - def test_pin_status_error - assert_equal "foo is already pinned.", - TapPinStatusError.new("foo", true).to_s - assert_equal "foo is already unpinned.", - TapPinStatusError.new("foo", false).to_s - end - - def test_build_error - f = stub(name: "foo") - assert_equal "Failed executing: badprg arg1 arg2", - BuildError.new(f, "badprg", %w[arg1 arg2], {}).to_s - end - - def test_operation_in_progress_error - assert_match "Operation already in progress for bar", - OperationInProgressError.new("bar").to_s - end - - def test_formula_installation_already_attempted_error - f = stub(full_name: "foo/bar") - assert_equal "Formula installation already attempted: foo/bar", - FormulaInstallationAlreadyAttemptedError.new(f).to_s - end - - def test_formula_conflict_error - f = stub(full_name: "foo/qux") - c = stub(name: "bar", reason: "I decided to") - assert_match "Please `brew unlink bar` before continuing.", - FormulaConflictError.new(f, [c]).to_s - end - - def test_compiler_selection_error - f = stub(full_name: "foo") - assert_match "foo cannot be built with any available compilers.", - CompilerSelectionError.new(f).to_s - end - - def test_curl_download_strategy_error - assert_equal "File does not exist: /tmp/foo", - CurlDownloadStrategyError.new("file:///tmp/foo").to_s - assert_equal "Download failed: http://brew.sh", - CurlDownloadStrategyError.new("http://brew.sh").to_s - end - - def test_error_during_execution - assert_equal "Failure while executing: badprg arg1 arg2", - ErrorDuringExecution.new("badprg", %w[arg1 arg2]).to_s - end - - def test_checksum_mismatch_error - h1 = stub(hash_type: "sha256", to_s: "deadbeef") - h2 = stub(hash_type: "sha256", to_s: "deadcafe") - assert_match "SHA256 mismatch", - ChecksumMismatchError.new("/file.tar.gz", h1, h2).to_s - end - - def test_resource_missing_error - f = stub(full_name: "bar") - r = stub(inspect: "<resource foo>") - assert_match "bar does not define resource <resource foo>", - ResourceMissingError.new(f, r).to_s - end - - def test_duplicate_resource_error - r = stub(inspect: "<resource foo>") - assert_equal "Resource <resource foo> is defined more than once", - DuplicateResourceError.new(r).to_s - end - - def test_bottle_version_mismatch_error - f = stub(full_name: "foo") - assert_match "Bottle version mismatch", - BottleVersionMismatchError.new("/foo.bottle.tar.gz", "1.0", f, "1.1").to_s - end -end diff --git a/Library/Homebrew/test/fetch_test.rb b/Library/Homebrew/test/fetch_test.rb deleted file mode 100644 index e08e545e3..000000000 --- a/Library/Homebrew/test/fetch_test.rb +++ /dev/null @@ -1,11 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestFetch < IntegrationCommandTestCase - def test_fetch - setup_test_formula "testball" - - cmd("fetch", "testball") - assert((HOMEBREW_CACHE/"testball-0.1.tbz").exist?, - "The tarball should have been cached") - end -end diff --git a/Library/Homebrew/test/formula_installer_test.rb b/Library/Homebrew/test/formula_installer_test.rb index 652548bd7..c99b2de74 100644 --- a/Library/Homebrew/test/formula_installer_test.rb +++ b/Library/Homebrew/test/formula_installer_test.rb @@ -84,13 +84,10 @@ class InstallTests < Homebrew::TestCase cc_arg = "--cc=clang" ARGV << cc_arg - begin - temporary_install(TestballBottle.new) do |f| - tab = Tab.for_formula(f) - assert_equal "clang", tab.compiler - end - ensure - ARGV.delete_if { |x| x == cc_arg } + + temporary_install(TestballBottle.new) do |f| + tab = Tab.for_formula(f) + assert_equal "clang", tab.compiler end end end @@ -128,11 +125,7 @@ class FormulaInstallerTests < Homebrew::TestCase fi = FormulaInstaller.new(dependent) assert_raises(CannotInstallFormulaError) { fi.check_install_sanity } ensure - dependency.unpin dependency_keg.unlink - dependency_keg.uninstall - dependency.clear_cache - dep_path.unlink Formulary::FORMULAE.delete(dep_path) end end diff --git a/Library/Homebrew/test/formula_lock_spec.rb b/Library/Homebrew/test/formula_lock_spec.rb new file mode 100644 index 000000000..9b5ece813 --- /dev/null +++ b/Library/Homebrew/test/formula_lock_spec.rb @@ -0,0 +1,34 @@ +require "formula_lock" + +describe FormulaLock do + subject { described_class.new("foo") } + + describe "#lock" do + it "does not raise an error when already locked" do + subject.lock + + expect { subject.lock }.not_to raise_error + end + + it "raises an error if a lock already exists" do + subject.lock + + expect { + described_class.new("foo").lock + }.to raise_error(OperationInProgressError) + end + end + + describe "#unlock" do + it "does not raise an error when already unlocked" do + expect { subject.unlock }.not_to raise_error + end + + it "unlocks a locked Formula" do + subject.lock + subject.unlock + + expect { described_class.new("foo").lock }.not_to raise_error + end + end +end diff --git a/Library/Homebrew/test/formula_lock_test.rb b/Library/Homebrew/test/formula_lock_test.rb deleted file mode 100644 index 80ee9dd25..000000000 --- a/Library/Homebrew/test/formula_lock_test.rb +++ /dev/null @@ -1,22 +0,0 @@ -require "testing_env" -require "formula_lock" - -class FormulaLockTests < Homebrew::TestCase - def setup - @lock = FormulaLock.new("foo") - @lock.lock - end - - def teardown - @lock.unlock - HOMEBREW_LOCK_DIR.children.each(&:unlink) - end - - def test_locking_file_with_existing_lock_raises_error - assert_raises(OperationInProgressError) { FormulaLock.new("foo").lock } - end - - def test_locking_existing_lock_suceeds - assert_nothing_raised { @lock.lock } - end -end diff --git a/Library/Homebrew/test/formula_pin_spec.rb b/Library/Homebrew/test/formula_pin_spec.rb new file mode 100644 index 000000000..909bfbc2b --- /dev/null +++ b/Library/Homebrew/test/formula_pin_spec.rb @@ -0,0 +1,41 @@ +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 + formula.rack.mkpath + + allow(formula).to receive(:installed_prefixes) do + formula.rack.directory? ? formula.rack.subdirs : [] + end + + allow(formula).to receive(:installed_kegs) do + formula.installed_prefixes.map { |prefix| Keg.new(prefix) } + end + end + + it "is not pinnable by default" do + expect(subject).not_to be_pinnable + end + + it "is pinnable if the Keg exists" do + (formula.rack/"0.1").mkpath + expect(subject).to be_pinnable + end + + specify "#pin and #unpin" do + (formula.rack/"0.1").mkpath + + subject.pin + expect(subject).to be_pinned + expect(HOMEBREW_PINNED_KEGS/name).to be_a_directory + expect(HOMEBREW_PINNED_KEGS.children.count).to eq(1) + + subject.unpin + expect(subject).not_to be_pinned + expect(HOMEBREW_PINNED_KEGS).not_to be_a_directory + end +end diff --git a/Library/Homebrew/test/formula_pin_test.rb b/Library/Homebrew/test/formula_pin_test.rb deleted file mode 100644 index 297d7703e..000000000 --- a/Library/Homebrew/test/formula_pin_test.rb +++ /dev/null @@ -1,54 +0,0 @@ -require "testing_env" -require "formula_pin" - -class FormulaPinTests < Homebrew::TestCase - class FormulaDouble - def name - "double" - end - - def rack - HOMEBREW_CELLAR/name - end - - def installed_prefixes - rack.directory? ? rack.subdirs : [] - end - - def installed_kegs - installed_prefixes.map { |d| Keg.new d } - end - end - - def setup - @f = FormulaDouble.new - @pin = FormulaPin.new(@f) - @f.rack.mkpath - end - - def test_not_pinnable - refute_predicate @pin, :pinnable? - end - - def test_pinnable_if_kegs_exist - (@f.rack/"0.1").mkpath - assert_predicate @pin, :pinnable? - end - - def test_unpin - (@f.rack/"0.1").mkpath - @pin.pin - - assert_predicate @pin, :pinned? - assert_equal 1, HOMEBREW_PINNED_KEGS.children.length - - @pin.unpin - - refute_predicate @pin, :pinned? - refute_predicate HOMEBREW_PINNED_KEGS, :directory? - end - - def teardown - @f.rack.rmtree - end -end diff --git a/Library/Homebrew/test/formula_spec.rb b/Library/Homebrew/test/formula_spec.rb new file mode 100644 index 000000000..1e064912f --- /dev/null +++ b/Library/Homebrew/test/formula_spec.rb @@ -0,0 +1,1295 @@ +require "test/support/fixtures/testball" +require "formula" + +RSpec::Matchers.alias_matcher :follow_installed_alias, :be_follow_installed_alias +RSpec::Matchers.alias_matcher :have_any_version_installed, :be_any_version_installed +RSpec::Matchers.alias_matcher :need_migration, :be_migration_needed + +RSpec::Matchers.alias_matcher :have_changed_installed_alias_target, :be_installed_alias_target_changed +RSpec::Matchers.alias_matcher :supersede_an_installed_formula, :be_supersedes_an_installed_formula +RSpec::Matchers.alias_matcher :have_changed_alias, :be_alias_changed + +RSpec::Matchers.alias_matcher :have_option_defined, :be_option_defined +RSpec::Matchers.alias_matcher :have_post_install_defined, :be_post_install_defined +RSpec::Matchers.alias_matcher :have_test_defined, :be_test_defined +RSpec::Matchers.alias_matcher :pour_bottle, :be_pour_bottle + +describe Formula do + describe "::new" do + let(:klass) do + Class.new(described_class) do + url "http://example.com/foo-1.0.tar.gz" + end + end + + let(:name) { "formula_name" } + let(:path) { Formulary.core_path(name) } + let(:spec) { :stable } + let(:alias_name) { "baz@1" } + let(:alias_path) { CoreTap.instance.alias_dir/alias_name } + let(:f) { klass.new(name, path, spec) } + let(:f_alias) { klass.new(name, path, spec, alias_path: alias_path) } + + specify "formula instantiation" do + expect(f.name).to eq(name) + expect(f.specified_name).to eq(name) + expect(f.full_name).to eq(name) + expect(f.full_specified_name).to eq(name) + expect(f.path).to eq(path) + expect(f.alias_path).to be nil + expect(f.alias_name).to be nil + expect(f.full_alias_name).to be nil + expect { klass.new }.to raise_error(ArgumentError) + end + + specify "formula instantiation with alias" do + expect(f_alias.name).to eq(name) + expect(f_alias.full_name).to eq(name) + expect(f_alias.path).to eq(path) + expect(f_alias.alias_path).to eq(alias_path) + expect(f_alias.alias_name).to eq(alias_name) + expect(f_alias.specified_name).to eq(alias_name) + expect(f_alias.full_alias_name).to eq(alias_name) + expect(f_alias.full_specified_name).to eq(alias_name) + expect { klass.new }.to raise_error(ArgumentError) + end + + context "in a Tap" do + let(:tap) { Tap.new("foo", "bar") } + let(:path) { (tap.path/"Formula/#{name}.rb") } + let(:full_name) { "#{tap.user}/#{tap.repo}/#{name}" } + let(:full_alias_name) { "#{tap.user}/#{tap.repo}/#{alias_name}" } + + specify "formula instantiation" do + expect(f.name).to eq(name) + expect(f.specified_name).to eq(name) + expect(f.full_name).to eq(full_name) + expect(f.full_specified_name).to eq(full_name) + expect(f.path).to eq(path) + expect(f.alias_path).to be nil + expect(f.alias_name).to be nil + expect(f.full_alias_name).to be nil + expect { klass.new }.to raise_error(ArgumentError) + end + + specify "formula instantiation with alias" do + expect(f_alias.name).to eq(name) + expect(f_alias.full_name).to eq(full_name) + expect(f_alias.path).to eq(path) + expect(f_alias.alias_path).to eq(alias_path) + expect(f_alias.alias_name).to eq(alias_name) + expect(f_alias.specified_name).to eq(alias_name) + expect(f_alias.full_alias_name).to eq(full_alias_name) + expect(f_alias.full_specified_name).to eq(full_alias_name) + expect { klass.new }.to raise_error(ArgumentError) + end + end + end + + describe "#follow_installed_alias?" do + let(:f) do + formula do + url "foo-1.0" + end + end + + it "returns true by default" do + expect(f).to follow_installed_alias + end + + it "can be set to true" do + f.follow_installed_alias = true + expect(f).to follow_installed_alias + end + + it "can be set to false" do + f.follow_installed_alias = false + expect(f).not_to follow_installed_alias + end + end + + example "installed alias with core" do + f = formula do + url "foo-1.0" + end + + build_values_with_no_installed_alias = [ + nil, + BuildOptions.new({}, {}), + Tab.new(source: { "path" => f.path.to_s }), + ] + build_values_with_no_installed_alias.each do |build| + f.build = build + expect(f.installed_alias_path).to be nil + expect(f.installed_alias_name).to be nil + expect(f.full_installed_alias_name).to be nil + expect(f.installed_specified_name).to eq(f.name) + expect(f.full_installed_specified_name).to eq(f.name) + end + + alias_name = "bar" + alias_path = "#{CoreTap.instance.alias_dir}/#{alias_name}" + + f.build = Tab.new(source: { "path" => alias_path }) + + expect(f.installed_alias_path).to eq(alias_path) + expect(f.installed_alias_name).to eq(alias_name) + expect(f.full_installed_alias_name).to eq(alias_name) + expect(f.installed_specified_name).to eq(alias_name) + expect(f.full_installed_specified_name).to eq(alias_name) + end + + example "installed alias with tap" do + tap = Tap.new("user", "repo") + name = "foo" + path = "#{tap.path}/Formula/#{name}.rb" + f = formula name, path: path do + url "foo-1.0" + end + + build_values_with_no_installed_alias = [nil, BuildOptions.new({}, {}), Tab.new(source: { "path" => f.path })] + build_values_with_no_installed_alias.each do |build| + f.build = build + expect(f.installed_alias_path).to be nil + expect(f.installed_alias_name).to be nil + expect(f.full_installed_alias_name).to be nil + expect(f.installed_specified_name).to eq(f.name) + expect(f.full_installed_specified_name).to eq(f.full_name) + end + + alias_name = "bar" + full_alias_name = "#{tap.user}/#{tap.repo}/#{alias_name}" + alias_path = "#{tap.alias_dir}/#{alias_name}" + + f.build = Tab.new(source: { "path" => alias_path }) + + expect(f.installed_alias_path).to eq(alias_path) + expect(f.installed_alias_name).to eq(alias_name) + expect(f.full_installed_alias_name).to eq(full_alias_name) + expect(f.installed_specified_name).to eq(alias_name) + expect(f.full_installed_specified_name).to eq(full_alias_name) + end + + specify "#prefix" do + f = Testball.new + expect(f.prefix).to eq(HOMEBREW_CELLAR/f.name/"0.1") + expect(f.prefix).to be_kind_of(Pathname) + end + + example "revised prefix" do + f = Class.new(Testball) { revision(1) }.new + expect(f.prefix).to eq(HOMEBREW_CELLAR/f.name/"0.1_1") + end + + specify "#any_version_installed?" do + f = formula do + url "foo" + version "1.0" + end + + expect(f).not_to have_any_version_installed + + prefix = HOMEBREW_CELLAR/f.name/"0.1" + prefix.mkpath + FileUtils.touch prefix/Tab::FILENAME + + expect(f).to have_any_version_installed + end + + specify "#migration_needed" do + f = Testball.new("newname") + f.instance_variable_set(:@oldname, "oldname") + f.instance_variable_set(:@tap, CoreTap.instance) + + oldname_prefix = (HOMEBREW_CELLAR/"oldname/2.20") + newname_prefix = (HOMEBREW_CELLAR/"newname/2.10") + + oldname_prefix.mkpath + oldname_tab = Tab.empty + oldname_tab.tabfile = oldname_prefix/Tab::FILENAME + oldname_tab.write + + expect(f).not_to need_migration + + oldname_tab.tabfile.unlink + oldname_tab.source["tap"] = "homebrew/core" + oldname_tab.write + + expect(f).to need_migration + + newname_prefix.mkpath + + expect(f).not_to need_migration + end + + describe "#installed?" do + let(:f) { Testball.new } + + it "returns false if the #installed_prefix is not a directory" do + allow(f).to receive(:installed_prefix).and_return(double(directory?: false)) + expect(f).not_to be_installed + end + + it "returns false if the #installed_prefix does not have children" do + allow(f).to receive(:installed_prefix).and_return(double(directory?: true, children: [])) + expect(f).not_to be_installed + end + + it "returns true if the #installed_prefix has children" do + allow(f).to receive(:installed_prefix).and_return(double(directory?: true, children: [double])) + expect(f).to be_installed + end + end + + describe "#installed prefix" do + let(:f) do + formula do + url "foo" + version "1.9" + + head "foo" + + devel do + url "foo" + version "2.1-devel" + end + end + end + + let(:stable_prefix) { HOMEBREW_CELLAR/f.name/f.version } + let(:devel_prefix) { HOMEBREW_CELLAR/f.name/f.devel.version } + let(:head_prefix) { HOMEBREW_CELLAR/f.name/f.head.version } + + it "is the same as #prefix by default" do + expect(f.installed_prefix).to eq(f.prefix) + end + + it "returns the stable prefix if it is installed" do + stable_prefix.mkpath + expect(f.installed_prefix).to eq(stable_prefix) + end + + it "returns the devel prefix if it is installed" do + devel_prefix.mkpath + expect(f.installed_prefix).to eq(devel_prefix) + end + + it "returns the head prefix if it is installed" do + head_prefix.mkpath + expect(f.installed_prefix).to eq(head_prefix) + end + + it "returns the stable prefix if head is outdated" do + head_prefix.mkpath + + tab = Tab.empty + tab.tabfile = head_prefix/Tab::FILENAME + tab.source["versions"] = { "stable" => "1.0" } + tab.write + + expect(f.installed_prefix).to eq(stable_prefix) + end + + it "returns the stable prefix if head and devel are outdated" do + head_prefix.mkpath + + tab = Tab.empty + tab.tabfile = head_prefix/Tab::FILENAME + tab.source["versions"] = { "stable" => "1.9", "devel" => "2.0" } + tab.write + + expect(f.installed_prefix).to eq(stable_prefix) + end + + it "returns the devel prefix if the active specification is :devel" do + f.active_spec = :devel + expect(f.installed_prefix).to eq(devel_prefix) + end + + it "returns the head prefix if the active specification is :head" do + f.active_spec = :head + expect(f.installed_prefix).to eq(head_prefix) + end + end + + describe "#latest_head_prefix" do + let(:f) { Testball.new } + + it "returns the latest head prefix" do + stamps_with_revisions = [ + [111111, 1], + [222222, 0], + [222222, 1], + [222222, 2], + ] + + stamps_with_revisions.each do |stamp, revision| + version = "HEAD-#{stamp}" + version << "_#{revision}" unless revision.zero? + + prefix = f.rack/version + prefix.mkpath + + tab = Tab.empty + tab.tabfile = prefix/Tab::FILENAME + tab.source_modified_time = stamp + tab.write + end + + prefix = HOMEBREW_CELLAR/f.name/"HEAD-222222_2" + + expect(f.latest_head_prefix).to eq(prefix) + end + end + + specify "equality" do + x = Testball.new + y = Testball.new + + expect(x).to eq(y) + expect(x).to eql(y) + expect(x.hash).to eq(y.hash) + end + + specify "inequality" do + x = Testball.new("foo") + y = Testball.new("bar") + + expect(x).not_to eq(y) + expect(x).not_to eql(y) + expect(x.hash).not_to eq(y.hash) + end + + specify "comparison with non formula objects does not raise" do + expect(Object.new).not_to eq(Testball.new) + end + + specify "#<=>" do + expect(Testball.new <=> Object.new).to be nil + end + + describe "#installed_alias_path" do + example "alias paths with build options" do + alias_path = (CoreTap.instance.alias_dir/"another_name") + + f = formula alias_path: alias_path do + url "foo-1.0" + end + f.build = BuildOptions.new({}, {}) + + expect(f.alias_path).to eq(alias_path) + expect(f.installed_alias_path).to be nil + end + + example "alias paths with tab with non alias source path" do + alias_path = (CoreTap.instance.alias_dir/"another_name") + source_path = (CoreTap.instance.formula_dir/"another_other_name") + + f = formula alias_path: alias_path do + url "foo-1.0" + end + f.build = Tab.new(source: { "path" => source_path.to_s }) + + expect(f.alias_path).to eq(alias_path) + expect(f.installed_alias_path).to be nil + end + + example "alias paths with tab with alias source path" do + alias_path = (CoreTap.instance.alias_dir/"another_name") + source_path = (CoreTap.instance.alias_dir/"another_other_name") + + f = formula alias_path: alias_path do + url "foo-1.0" + end + f.build = Tab.new(source: { "path" => source_path.to_s }) + + expect(f.alias_path).to eq(alias_path) + expect(f.installed_alias_path).to eq(source_path.to_s) + end + end + + describe "::installed_with_alias_path" do + specify "with alias path with nil" do + expect(described_class.installed_with_alias_path(nil)).to be_empty + end + + specify "with alias path with a path" do + alias_path = "#{CoreTap.instance.alias_dir}/alias" + different_alias_path = "#{CoreTap.instance.alias_dir}/another_alias" + + formula_with_alias = formula "foo" do + url "foo-1.0" + end + formula_with_alias.build = Tab.empty + formula_with_alias.build.source["path"] = alias_path + + formula_without_alias = formula "bar" do + url "bar-1.0" + end + formula_without_alias.build = Tab.empty + formula_without_alias.build.source["path"] = formula_without_alias.path.to_s + + formula_with_different_alias = formula "baz" do + url "baz-1.0" + end + formula_with_different_alias.build = Tab.empty + formula_with_different_alias.build.source["path"] = different_alias_path + + formulae = [ + formula_with_alias, + formula_without_alias, + formula_with_different_alias, + ] + + allow(described_class).to receive(:installed).and_return(formulae) + + expect(described_class.installed_with_alias_path(alias_path)) + .to eq([formula_with_alias]) + end + end + + specify "spec integration" do + f = formula do + homepage "http://example.com" + + url "http://example.com/test-0.1.tbz" + mirror "http://example.org/test-0.1.tbz" + sha256 TEST_SHA256 + + head "http://example.com/test.git", tag: "foo" + + devel do + url "http://example.com/test-0.2.tbz" + mirror "http://example.org/test-0.2.tbz" + sha256 TEST_SHA256 + end + end + + expect(f.homepage).to eq("http://example.com") + expect(f.version).to eq(Version.create("0.1")) + expect(f).to be_stable + expect(f.stable.version).to eq(Version.create("0.1")) + expect(f.devel.version).to eq(Version.create("0.2")) + expect(f.head.version).to eq(Version.create("HEAD")) + end + + specify "#active_spec=" do + f = formula do + url "foo" + version "1.0" + revision 1 + + devel do + url "foo" + version "1.0beta" + end + end + + expect(f.active_spec_sym).to eq(:stable) + expect(f.send(:active_spec)).to eq(f.stable) + expect(f.pkg_version.to_s).to eq("1.0_1") + + f.active_spec = :devel + + expect(f.active_spec_sym).to eq(:devel) + expect(f.send(:active_spec)).to eq(f.devel) + expect(f.pkg_version.to_s).to eq("1.0beta_1") + expect { f.active_spec = :head }.to raise_error(FormulaSpecificationError) + end + + specify "class specs are always initialized" do + f = formula do + url "foo-1.0" + end + + expect(f.class.stable).to be_kind_of(SoftwareSpec) + expect(f.class.devel).to be_kind_of(SoftwareSpec) + expect(f.class.head).to be_kind_of(SoftwareSpec) + end + + specify "incomplete instance specs are not accessible" do + f = formula do + url "foo-1.0" + end + + expect(f.devel).to be nil + expect(f.head).to be nil + end + + it "honors attributes declared before specs" do + f = formula do + url "foo-1.0" + + depends_on "foo" + + devel do + url "foo-1.1" + end + end + + expect(f.class.stable.deps.first.name).to eq("foo") + expect(f.class.devel.deps.first.name).to eq("foo") + expect(f.class.head.deps.first.name).to eq("foo") + end + + describe "#pkg_version" do + specify "simple version" do + f = formula do + url "foo-1.0.bar" + end + + expect(f.pkg_version).to eq(PkgVersion.parse("1.0")) + end + + specify "version with revision" do + f = formula do + url "foo-1.0.bar" + revision 1 + end + + expect(f.pkg_version).to eq(PkgVersion.parse("1.0_1")) + end + + specify "head uses revisions" do + f = formula "test", spec: :head do + url "foo-1.0.bar" + revision 1 + + head "foo" + end + + expect(f.pkg_version).to eq(PkgVersion.parse("HEAD_1")) + end + end + + specify "#update_head_version" do + f = formula do + head "foo", using: :git + end + + cached_location = f.head.downloader.cached_location + cached_location.mkpath + cached_location.cd do + FileUtils.touch "LICENSE" + + shutup do + system("git", "init") + system("git", "add", "--all") + system("git", "commit", "-m", "Initial commit") + end + end + + f.update_head_version + + expect(f.head.version).to eq(Version.create("HEAD-5658946")) + end + + specify "legacy options" do + f = formula do + url "foo-1.0" + + def options + [ + ["--foo", "desc"], + ["--bar", "desc"], + ] + end + + option("baz") + end + + expect(f).to have_option_defined("foo") + expect(f).to have_option_defined("bar") + expect(f).to have_option_defined("baz") + end + + specify "#desc" do + f = formula do + desc "a formula" + + url "foo-1.0" + end + + expect(f.desc).to eq("a formula") + end + + specify "#post_install_defined?" do + f1 = formula do + url "foo-1.0" + + def post_install + # do nothing + end + end + + f2 = formula do + url "foo-1.0" + end + + expect(f1).to have_post_install_defined + expect(f2).not_to have_post_install_defined + end + + specify "#test_defined?" do + f1 = formula do + url "foo-1.0" + + def test + # do nothing + end + end + + f2 = formula do + url "foo-1.0" + end + + expect(f1).to have_test_defined + expect(f2).not_to have_test_defined + end + + specify "test fixtures" do + f1 = formula do + url "foo-1.0" + end + + expect(f1.test_fixtures("foo")).to eq(Pathname.new("#{HOMEBREW_LIBRARY_PATH}/test/support/fixtures/foo")) + end + + specify "dependencies" do + f1 = formula "f1" do + url "f1-1.0" + end + + f2 = formula "f2" do + url "f2-1.0" + end + + f3 = formula "f3" do + url "f3-1.0" + + depends_on "f1" => :build + depends_on "f2" + end + + f4 = formula "f4" do + url "f4-1.0" + + depends_on "f1" + end + + stub_formula_loader(f1) + stub_formula_loader(f2) + stub_formula_loader(f3) + stub_formula_loader(f4) + + f5 = formula "f5" do + url "f5-1.0" + + depends_on "f3" => :build + depends_on "f4" + end + + expect(f5.deps.map(&:name)).to eq(["f3", "f4"]) + expect(f5.recursive_dependencies.map(&:name)).to eq(["f1", "f2", "f3", "f4"]) + expect(f5.runtime_dependencies.map(&:name)).to eq(["f1", "f4"]) + end + + specify "runtime dependencies with optional deps from tap" do + tap_loader = double + + allow(tap_loader).to receive(:get_formula).and_raise(RuntimeError, "tried resolving tap formula") + allow(Formulary).to receive(:loader_for).with("foo/bar/f1", from: nil).and_return(tap_loader) + stub_formula_loader(formula("f2") { url("f2-1.0") }, "baz/qux/f2") + + f3 = formula "f3" do + url "f3-1.0" + + depends_on "foo/bar/f1" => :optional + depends_on "baz/qux/f2" + end + + expect(f3.runtime_dependencies.map(&:name)).to eq(["baz/qux/f2"]) + + stub_formula_loader(formula("f1") { url("f1-1.0") }, "foo/bar/f1") + f3.build = BuildOptions.new(Options.create(["--with-f1"]), f3.options) + + expect(f3.runtime_dependencies.map(&:name)).to eq(["foo/bar/f1", "baz/qux/f2"]) + end + + specify "requirements" do + f1 = formula "f1" do + url "f1-1" + + depends_on :python + depends_on x11: :recommended + depends_on xcode: ["1.0", :optional] + end + stub_formula_loader(f1) + + python = PythonRequirement.new + x11 = X11Requirement.new("x11", [:recommended]) + xcode = XcodeRequirement.new(["1.0", :optional]) + + expect(Set.new(f1.recursive_requirements)).to eq(Set[python, x11]) + + f1.build = BuildOptions.new(["--with-xcode", "--without-x11"], f1.options) + + expect(Set.new(f1.recursive_requirements)).to eq(Set[python, xcode]) + + f1.build = f1.stable.build + f2 = formula "f2" do + url "f2-1" + + depends_on "f1" + end + + expect(Set.new(f2.recursive_requirements)).to eq(Set[python, x11]) + expect(Set.new(f2.recursive_requirements {})).to eq(Set[python, x11, xcode]) + + requirements = f2.recursive_requirements do |_dependent, requirement| + Requirement.prune if requirement.is_a?(PythonRequirement) + end + + expect(Set.new(requirements)).to eq(Set[x11, xcode]) + end + + specify "#to_hash" do + f1 = formula "foo" do + url "foo-1.0" + + bottle do + cellar(:any) + sha256(TEST_SHA256 => Utils::Bottles.tag) + end + end + + h = f1.to_hash + + expect(h).to be_a(Hash) + expect(h["name"]).to eq("foo") + expect(h["full_name"]).to eq("foo") + expect(h["versions"]["stable"]).to eq("1.0") + expect(h["versions"]["bottle"]).to be_truthy + end + + describe "#eligible_kegs_for_cleanup" do + it "returns Kegs eligible for cleanup" do + f1 = Class.new(Testball) do + version("1.0") + end.new + + f2 = Class.new(Testball) do + version("0.2") + version_scheme(1) + end.new + + f3 = Class.new(Testball) do + version("0.3") + version_scheme(1) + end.new + + f4 = Class.new(Testball) do + version("0.1") + version_scheme(2) + end.new + + shutup do + [f1, f2, f3, f4].each do |f| + f.brew { f.install } + Tab.create(f, DevelopmentTools.default_compiler, :libcxx).write + end + end + + expect(f1).to be_installed + expect(f2).to be_installed + expect(f3).to be_installed + expect(f4).to be_installed + expect(f3.eligible_kegs_for_cleanup.sort_by(&:version)) + .to eq([f2, f1].map { |f| Keg.new(f.prefix) }) + end + + specify "with pinned Keg" do + f1 = Class.new(Testball) { version("0.1") }.new + f2 = Class.new(Testball) { version("0.2") }.new + f3 = Class.new(Testball) { version("0.3") }.new + + shutup do + f1.brew { f1.install } + f1.pin + f2.brew { f2.install } + f3.brew { f3.install } + end + + expect(f1.prefix).to eq((HOMEBREW_PINNED_KEGS/f1.name).resolved_path) + expect(f1).to be_installed + expect(f2).to be_installed + expect(f3).to be_installed + expect(shutup { f3.eligible_kegs_for_cleanup }).to eq([Keg.new(f2.prefix)]) + end + + specify "with HEAD installed" do + f = formula do + version("0.1") + head("foo") + end + + stable_prefix = f.installed_prefix + stable_prefix.mkpath + + [["000000_1", 1], ["111111", 2], ["111111_1", 2]].each do |pkg_version_suffix, stamp| + prefix = f.prefix("HEAD-#{pkg_version_suffix}") + prefix.mkpath + tab = Tab.empty + tab.tabfile = prefix/Tab::FILENAME + tab.source_modified_time = stamp + tab.write + end + + eligible_kegs = f.installed_kegs - [Keg.new(f.prefix("HEAD-111111_1"))] + expect(f.eligible_kegs_for_cleanup).to eq(eligible_kegs) + end + end + + describe "#pour_bottle?" do + it "returns false if set to false" do + f = formula "foo" do + url "foo-1.0" + + def pour_bottle? + false + end + end + + expect(f).not_to pour_bottle + end + + it "returns true if set to true" do + f = formula "foo" do + url "foo-1.0" + + def pour_bottle? + true + end + end + + expect(f).to pour_bottle + end + + it "returns false if set to false via DSL" do + f = formula "foo" do + url "foo-1.0" + + pour_bottle? do + reason "false reason" + satisfy { (var == etc) } + end + end + + expect(f).not_to pour_bottle + end + + it "returns true if set to true via DSL" do + f = formula "foo" do + url "foo-1.0" + + pour_bottle? do + reason "true reason" + satisfy { true } + end + end + + expect(f).to pour_bottle + end + end + + describe "alias changes" do + let(:f) do + formula "formula_name", alias_path: alias_path do + url "foo-1.0" + end + end + + let(:new_formula) do + formula "new_formula_name", alias_path: alias_path do + url "foo-1.1" + end + end + + let(:tab) { Tab.empty } + let(:alias_path) { "#{CoreTap.instance.alias_dir}/bar" } + + before(:each) do + allow(described_class).to receive(:installed).and_return([f]) + + f.build = tab + new_formula.build = tab + end + + specify "alias changes when not installed with alias" do + tab.source["path"] = Formulary.core_path(f.name).to_s + + expect(f.current_installed_alias_target).to be nil + expect(f.latest_formula).to eq(f) + expect(f).not_to have_changed_installed_alias_target + expect(f).not_to supersede_an_installed_formula + expect(f).not_to have_changed_alias + expect(f.old_installed_formulae).to be_empty + end + + specify "alias changes when not changed" do + tab.source["path"] = alias_path + stub_formula_loader(f, alias_path) + + expect(f.current_installed_alias_target).to eq(f) + expect(f.latest_formula).to eq(f) + expect(f).not_to have_changed_installed_alias_target + expect(f).not_to supersede_an_installed_formula + expect(f).not_to have_changed_alias + expect(f.old_installed_formulae).to be_empty + end + + specify "alias changes when new alias target" do + tab.source["path"] = alias_path + stub_formula_loader(new_formula, alias_path) + + expect(f.current_installed_alias_target).to eq(new_formula) + expect(f.latest_formula).to eq(new_formula) + expect(f).to have_changed_installed_alias_target + expect(f).not_to supersede_an_installed_formula + expect(f).to have_changed_alias + expect(f.old_installed_formulae).to be_empty + end + + specify "alias changes when old formulae installed" do + tab.source["path"] = alias_path + stub_formula_loader(new_formula, alias_path) + + expect(new_formula.current_installed_alias_target).to eq(new_formula) + expect(new_formula.latest_formula).to eq(new_formula) + expect(new_formula).not_to have_changed_installed_alias_target + expect(new_formula).to supersede_an_installed_formula + expect(new_formula).to have_changed_alias + expect(new_formula.old_installed_formulae).to eq([f]) + end + end + + describe "#outdated_kegs" do + let(:outdated_prefix) { (HOMEBREW_CELLAR/"#{f.name}/1.11") } + let(:same_prefix) { (HOMEBREW_CELLAR/"#{f.name}/1.20") } + let(:greater_prefix) { (HOMEBREW_CELLAR/"#{f.name}/1.21") } + let(:head_prefix) { (HOMEBREW_CELLAR/"#{f.name}/HEAD") } + let(:old_alias_target_prefix) { (HOMEBREW_CELLAR/"#{old_formula.name}/1.0") } + + let(:f) do + formula do + url "foo" + version "1.20" + end + end + + let(:old_formula) do + formula "foo@1" do + url "foo-1.0" + end + end + + let(:new_formula) do + formula "foo@2" do + url "foo-2.0" + end + end + + let(:alias_path) { "#{f.tap.alias_dir}/bar" } + + def setup_tab_for_prefix(prefix, options = {}) + prefix.mkpath + tab = Tab.empty + tab.tabfile = prefix/Tab::FILENAME + tab.source["path"] = options[:path].to_s if options[:path] + tab.source["tap"] = options[:tap] if options[:tap] + tab.source["versions"] = options[:versions] if options[:versions] + tab.source_modified_time = options[:source_modified_time].to_i + tab.write unless options[:no_write] + tab + end + + def reset_outdated_kegs + f.instance_variable_set(:@outdated_kegs, nil) + end + + example "greater different tap installed" do + setup_tab_for_prefix(greater_prefix, tap: "user/repo") + expect(f.outdated_kegs).to be_empty + end + + example "greater same tap installed" do + f.instance_variable_set(:@tap, CoreTap.instance) + setup_tab_for_prefix(greater_prefix, tap: "homebrew/core") + expect(f.outdated_kegs).to be_empty + end + + example "outdated different tap installed" do + setup_tab_for_prefix(outdated_prefix, tap: "user/repo") + expect(f.outdated_kegs).not_to be_empty + end + + example "outdated same tap installed" do + f.instance_variable_set(:@tap, CoreTap.instance) + setup_tab_for_prefix(outdated_prefix, tap: "homebrew/core") + expect(f.outdated_kegs).not_to be_empty + end + + example "outdated follow alias and alias unchanged" do + f.follow_installed_alias = true + f.build = setup_tab_for_prefix(same_prefix, path: alias_path) + stub_formula_loader(f, alias_path) + expect(f.outdated_kegs).to be_empty + end + + example "outdated follow alias and alias changed and new target not installed" do + f.follow_installed_alias = true + f.build = setup_tab_for_prefix(same_prefix, path: alias_path) + stub_formula_loader(new_formula, alias_path) + expect(f.outdated_kegs).not_to be_empty + end + + example "outdated follow alias and alias changed and new target installed" do + f.follow_installed_alias = true + f.build = setup_tab_for_prefix(same_prefix, path: alias_path) + stub_formula_loader(new_formula, alias_path) + setup_tab_for_prefix(new_formula.prefix) + expect(f.outdated_kegs).to be_empty + end + + example "outdated no follow alias and alias unchanged" do + f.follow_installed_alias = false + f.build = setup_tab_for_prefix(same_prefix, path: alias_path) + stub_formula_loader(f, alias_path) + expect(f.outdated_kegs).to be_empty + end + + example "outdated no follow alias and alias changed" do + f.follow_installed_alias = false + f.build = setup_tab_for_prefix(same_prefix, path: alias_path) + + f2 = formula "foo@2" do + url "foo-2.0" + end + + stub_formula_loader(f2, alias_path) + expect(f.outdated_kegs).to be_empty + end + + example "outdated old alias targets installed" do + f = formula alias_path: alias_path do + url "foo-1.0" + end + + tab = setup_tab_for_prefix(old_alias_target_prefix, path: alias_path) + old_formula.build = tab + allow(described_class).to receive(:installed).and_return([old_formula]) + expect(f.outdated_kegs).not_to be_empty + end + + example "outdated old alias targets not installed" do + f = formula alias_path: alias_path do + url "foo-1.0" + end + + tab = setup_tab_for_prefix(old_alias_target_prefix, path: old_formula.path) + old_formula.build = tab + allow(described_class).to receive(:installed).and_return([old_formula]) + expect(f.outdated_kegs).to be_empty + end + + example "outdated same head installed" do + f.instance_variable_set(:@tap, CoreTap.instance) + setup_tab_for_prefix(head_prefix, tap: "homebrew/core") + expect(f.outdated_kegs).to be_empty + end + + example "outdated different head installed" do + f.instance_variable_set(:@tap, CoreTap.instance) + setup_tab_for_prefix(head_prefix, tap: "user/repo") + expect(f.outdated_kegs).to be_empty + end + + example "outdated mixed taps greater version installed" do + f.instance_variable_set(:@tap, CoreTap.instance) + setup_tab_for_prefix(outdated_prefix, tap: "homebrew/core") + setup_tab_for_prefix(greater_prefix, tap: "user/repo") + + expect(f.outdated_kegs).to be_empty + + setup_tab_for_prefix(greater_prefix, tap: "homebrew/core") + reset_outdated_kegs + + expect(f.outdated_kegs).to be_empty + end + + example "outdated mixed taps outdated version installed" do + f.instance_variable_set(:@tap, CoreTap.instance) + + extra_outdated_prefix = HOMEBREW_CELLAR/f.name/"1.0" + + setup_tab_for_prefix(outdated_prefix) + setup_tab_for_prefix(extra_outdated_prefix, tap: "homebrew/core") + reset_outdated_kegs + + expect(f.outdated_kegs).not_to be_empty + + setup_tab_for_prefix(outdated_prefix, tap: "user/repo") + reset_outdated_kegs + + expect(f.outdated_kegs).not_to be_empty + end + + example "outdated same version tap installed" do + f.instance_variable_set(:@tap, CoreTap.instance) + setup_tab_for_prefix(same_prefix, tap: "homebrew/core") + + expect(f.outdated_kegs).to be_empty + + setup_tab_for_prefix(same_prefix, tap: "user/repo") + reset_outdated_kegs + + expect(f.outdated_kegs).to be_empty + end + + example "outdated installed head less than stable" do + tab = setup_tab_for_prefix(head_prefix, versions: { "stable" => "1.0" }) + + expect(f.outdated_kegs).not_to be_empty + + tab.source["versions"] = { "stable" => f.version.to_s } + tab.write + reset_outdated_kegs + + expect(f.outdated_kegs).to be_empty + end + + describe ":fetch_head" do + let(:f) do + repo = testball_repo + formula "testball" do + url "foo" + version "2.10" + head "file://#{repo}", using: :git + end + end + let(:testball_repo) { HOMEBREW_PREFIX/"testball_repo" } + + example do + begin + outdated_stable_prefix = HOMEBREW_CELLAR/"testball/1.0" + head_prefix_a = HOMEBREW_CELLAR/"testball/HEAD" + head_prefix_b = HOMEBREW_CELLAR/"testball/HEAD-aaaaaaa_1" + head_prefix_c = HOMEBREW_CELLAR/"testball/HEAD-18a7103" + + setup_tab_for_prefix(outdated_stable_prefix) + tab_a = setup_tab_for_prefix(head_prefix_a, versions: { "stable" => "1.0" }) + setup_tab_for_prefix(head_prefix_b) + + testball_repo.mkdir + testball_repo.cd do + FileUtils.touch "LICENSE" + + shutup do + system("git", "init") + system("git", "add", "--all") + system("git", "commit", "-m", "Initial commit") + end + end + + expect(f.outdated_kegs(fetch_head: true)).not_to be_empty + + tab_a.source["versions"] = { "stable" => f.version.to_s } + tab_a.write + reset_outdated_kegs + expect(f.outdated_kegs(fetch_head: true)).not_to be_empty + + head_prefix_a.rmtree + reset_outdated_kegs + expect(f.outdated_kegs(fetch_head: true)).not_to be_empty + + setup_tab_for_prefix(head_prefix_c, source_modified_time: 1) + reset_outdated_kegs + expect(f.outdated_kegs(fetch_head: true)).to be_empty + ensure + testball_repo.rmtree if testball_repo.exist? + end + end + end + + describe "with changed version scheme" do + let(:f) do + formula "testball" do + url "foo" + version "20141010" + version_scheme 1 + end + end + + example do + prefix = HOMEBREW_CELLAR/"testball/0.1" + setup_tab_for_prefix(prefix, versions: { "stable" => "0.1" }) + + expect(f.outdated_kegs).not_to be_empty + end + end + + describe "with mixed version schemes" do + let(:f) do + formula "testball" do + url "foo" + version "20141010" + version_scheme 3 + end + end + + example do + prefix_a = HOMEBREW_CELLAR/"testball/20141009" + setup_tab_for_prefix(prefix_a, versions: { "stable" => "20141009", "version_scheme" => 1 }) + + prefix_b = HOMEBREW_CELLAR/"testball/2.14" + setup_tab_for_prefix(prefix_b, versions: { "stable" => "2.14", "version_scheme" => 2 }) + + expect(f.outdated_kegs).not_to be_empty + reset_outdated_kegs + + prefix_c = HOMEBREW_CELLAR/"testball/20141009" + setup_tab_for_prefix(prefix_c, versions: { "stable" => "20141009", "version_scheme" => 3 }) + + expect(f.outdated_kegs).not_to be_empty + reset_outdated_kegs + + prefix_d = HOMEBREW_CELLAR/"testball/20141011" + setup_tab_for_prefix(prefix_d, versions: { "stable" => "20141009", "version_scheme" => 3 }) + expect(f.outdated_kegs).to be_empty + end + end + + describe "with version scheme" do + let(:f) do + formula "testball" do + url "foo" + version "1.0" + version_scheme 2 + end + end + + example do + head_prefix = HOMEBREW_CELLAR/"testball/HEAD" + + setup_tab_for_prefix(head_prefix, versions: { "stable" => "1.0", "version_scheme" => 1 }) + expect(f.outdated_kegs).not_to be_empty + + reset_outdated_kegs + head_prefix.rmtree + + setup_tab_for_prefix(head_prefix, versions: { "stable" => "1.0", "version_scheme" => 2 }) + expect(f.outdated_kegs).to be_empty + end + end + end +end diff --git a/Library/Homebrew/test/formula_test.rb b/Library/Homebrew/test/formula_test.rb deleted file mode 100644 index 81022d220..000000000 --- a/Library/Homebrew/test/formula_test.rb +++ /dev/null @@ -1,1210 +0,0 @@ -require "testing_env" -require "test/support/fixtures/testball" -require "formula" - -class FormulaTests < Homebrew::TestCase - def test_formula_instantiation - klass = Class.new(Formula) { url "http://example.com/foo-1.0.tar.gz" } - name = "formula_name" - path = Formulary.core_path(name) - spec = :stable - - f = klass.new(name, path, spec) - assert_equal name, f.name - assert_equal name, f.specified_name - assert_equal name, f.full_name - assert_equal name, f.full_specified_name - assert_equal path, f.path - assert_nil f.alias_path - assert_nil f.alias_name - assert_nil f.full_alias_name - assert_raises(ArgumentError) { klass.new } - end - - def test_formula_instantiation_with_alias - klass = Class.new(Formula) { url "http://example.com/foo-1.0.tar.gz" } - name = "formula_name" - path = Formulary.core_path(name) - spec = :stable - alias_name = "baz@1" - alias_path = CoreTap.instance.alias_dir/alias_name - - f = klass.new(name, path, spec, alias_path: alias_path) - assert_equal name, f.name - assert_equal name, f.full_name - assert_equal path, f.path - assert_equal alias_path, f.alias_path - assert_equal alias_name, f.alias_name - assert_equal alias_name, f.specified_name - assert_equal alias_name, f.full_alias_name - assert_equal alias_name, f.full_specified_name - assert_raises(ArgumentError) { klass.new } - end - - def test_tap_formula_instantiation - tap = Tap.new("foo", "bar") - klass = Class.new(Formula) { url "baz-1.0" } - name = "baz" - full_name = "#{tap.user}/#{tap.repo}/#{name}" - path = tap.path/"Formula/#{name}.rb" - spec = :stable - - f = klass.new(name, path, spec) - assert_equal name, f.name - assert_equal name, f.specified_name - assert_equal full_name, f.full_name - assert_equal full_name, f.full_specified_name - assert_equal path, f.path - assert_nil f.alias_path - assert_nil f.alias_name - assert_nil f.full_alias_name - assert_raises(ArgumentError) { klass.new } - end - - def test_tap_formula_instantiation_with_alias - tap = Tap.new("foo", "bar") - klass = Class.new(Formula) { url "baz-1.0" } - name = "baz" - full_name = "#{tap.user}/#{tap.repo}/#{name}" - path = tap.path/"Formula/#{name}.rb" - spec = :stable - alias_name = "baz@1" - full_alias_name = "#{tap.user}/#{tap.repo}/#{alias_name}" - alias_path = CoreTap.instance.alias_dir/alias_name - - f = klass.new(name, path, spec, alias_path: alias_path) - assert_equal name, f.name - assert_equal full_name, f.full_name - assert_equal path, f.path - assert_equal alias_path, f.alias_path - assert_equal alias_name, f.alias_name - assert_equal alias_name, f.specified_name - assert_equal full_alias_name, f.full_alias_name - assert_equal full_alias_name, f.full_specified_name - assert_raises(ArgumentError) { klass.new } - end - - def test_follow_installed_alias - f = formula { url "foo-1.0" } - assert_predicate f, :follow_installed_alias? - - f.follow_installed_alias = true - assert_predicate f, :follow_installed_alias? - - f.follow_installed_alias = false - refute_predicate f, :follow_installed_alias? - end - - def test_installed_alias_with_core - f = formula { url "foo-1.0" } - - build_values_with_no_installed_alias = [ - nil, - BuildOptions.new({}, {}), - Tab.new(source: { "path" => f.path.to_s }), - ] - - build_values_with_no_installed_alias.each do |build| - f.build = build - assert_nil f.installed_alias_path - assert_nil f.installed_alias_name - assert_nil f.full_installed_alias_name - assert_equal f.name, f.installed_specified_name - assert_equal f.name, f.full_installed_specified_name - end - - alias_name = "bar" - alias_path = "#{CoreTap.instance.alias_dir}/#{alias_name}" - f.build = Tab.new(source: { "path" => alias_path }) - assert_equal alias_path, f.installed_alias_path - assert_equal alias_name, f.installed_alias_name - assert_equal alias_name, f.full_installed_alias_name - assert_equal alias_name, f.installed_specified_name - assert_equal alias_name, f.full_installed_specified_name - end - - def test_installed_alias_with_tap - tap = Tap.new("user", "repo") - name = "foo" - path = "#{tap.path}/Formula/#{name}.rb" - f = formula(name, path) { url "foo-1.0" } - - build_values_with_no_installed_alias = [ - nil, - BuildOptions.new({}, {}), - Tab.new(source: { "path" => f.path }), - ] - - build_values_with_no_installed_alias.each do |build| - f.build = build - assert_nil f.installed_alias_path - assert_nil f.installed_alias_name - assert_nil f.full_installed_alias_name - assert_equal f.name, f.installed_specified_name - assert_equal f.full_name, f.full_installed_specified_name - end - - alias_name = "bar" - full_alias_name = "#{tap.user}/#{tap.repo}/#{alias_name}" - alias_path = "#{tap.alias_dir}/#{alias_name}" - f.build = Tab.new(source: { "path" => alias_path }) - assert_equal alias_path, f.installed_alias_path - assert_equal alias_name, f.installed_alias_name - assert_equal full_alias_name, f.full_installed_alias_name - assert_equal alias_name, f.installed_specified_name - assert_equal full_alias_name, f.full_installed_specified_name - end - - def test_prefix - f = Testball.new - assert_equal HOMEBREW_CELLAR/f.name/"0.1", f.prefix - assert_kind_of Pathname, f.prefix - end - - def test_revised_prefix - f = Class.new(Testball) { revision 1 }.new - assert_equal HOMEBREW_CELLAR/f.name/"0.1_1", f.prefix - end - - def test_any_version_installed? - f = formula do - url "foo" - version "1.0" - end - refute_predicate f, :any_version_installed? - prefix = HOMEBREW_CELLAR+f.name+"0.1" - prefix.mkpath - FileUtils.touch prefix+Tab::FILENAME - assert_predicate f, :any_version_installed? - ensure - f.rack.rmtree - end - - def test_migration_needed - f = Testball.new("newname") - f.instance_variable_set(:@oldname, "oldname") - f.instance_variable_set(:@tap, CoreTap.instance) - - oldname_prefix = HOMEBREW_CELLAR/"oldname/2.20" - newname_prefix = HOMEBREW_CELLAR/"newname/2.10" - oldname_prefix.mkpath - oldname_tab = Tab.empty - oldname_tab.tabfile = oldname_prefix.join("INSTALL_RECEIPT.json") - oldname_tab.write - - refute_predicate f, :migration_needed? - - oldname_tab.tabfile.unlink - oldname_tab.source["tap"] = "homebrew/core" - oldname_tab.write - - assert_predicate f, :migration_needed? - - newname_prefix.mkpath - - refute_predicate f, :migration_needed? - ensure - oldname_prefix.parent.rmtree - newname_prefix.parent.rmtree - end - - def test_installed? - f = Testball.new - f.stubs(:installed_prefix).returns(stub(directory?: false)) - refute_predicate f, :installed? - - f.stubs(:installed_prefix).returns( - stub(directory?: true, children: []) - ) - refute_predicate f, :installed? - - f.stubs(:installed_prefix).returns( - stub(directory?: true, children: [stub]) - ) - assert_predicate f, :installed? - end - - def test_installed_prefix - f = Testball.new - assert_equal f.prefix, f.installed_prefix - end - - def test_installed_prefix_head_installed - f = formula do - head "foo" - devel do - url "foo" - version "1.0" - end - end - prefix = HOMEBREW_CELLAR+f.name+f.head.version - prefix.mkpath - assert_equal prefix, f.installed_prefix - ensure - f.rack.rmtree - end - - def test_installed_prefix_devel_installed - f = formula do - head "foo" - devel do - url "foo" - version "1.0" - end - end - prefix = HOMEBREW_CELLAR+f.name+f.devel.version - prefix.mkpath - assert_equal prefix, f.installed_prefix - ensure - f.rack.rmtree - end - - def test_installed_prefix_stable_installed - f = formula do - head "foo" - devel do - url "foo" - version "1.0-devel" - end - end - prefix = HOMEBREW_CELLAR+f.name+f.version - prefix.mkpath - assert_equal prefix, f.installed_prefix - ensure - f.rack.rmtree - end - - def test_installed_prefix_outdated_stable_head_installed - f = formula do - url "foo" - version "1.9" - head "foo" - end - - head_prefix = HOMEBREW_CELLAR/"#{f.name}/HEAD" - head_prefix.mkpath - tab = Tab.empty - tab.tabfile = head_prefix.join("INSTALL_RECEIPT.json") - tab.source["versions"] = { "stable" => "1.0" } - tab.write - - assert_equal HOMEBREW_CELLAR/"#{f.name}/#{f.version}", f.installed_prefix - ensure - f.rack.rmtree - end - - def test_installed_prefix_outdated_devel_head_installed - f = formula do - url "foo" - version "1.9" - devel do - url "foo" - version "2.1" - end - end - - head_prefix = HOMEBREW_CELLAR/"#{f.name}/HEAD" - head_prefix.mkpath - tab = Tab.empty - tab.tabfile = head_prefix.join("INSTALL_RECEIPT.json") - tab.source["versions"] = { "stable" => "1.9", "devel" => "2.0" } - tab.write - - assert_equal HOMEBREW_CELLAR/"#{f.name}/#{f.version}", f.installed_prefix - ensure - f.rack.rmtree - end - - def test_installed_prefix_head - f = formula("test", Pathname.new(__FILE__).expand_path, :head) do - head "foo" - devel do - url "foo" - version "1.0-devel" - end - end - prefix = HOMEBREW_CELLAR+f.name+f.head.version - assert_equal prefix, f.installed_prefix - end - - def test_installed_prefix_devel - f = formula("test", Pathname.new(__FILE__).expand_path, :devel) do - head "foo" - devel do - url "foo" - version "1.0-devel" - end - end - prefix = HOMEBREW_CELLAR+f.name+f.devel.version - assert_equal prefix, f.installed_prefix - end - - def test_latest_head_prefix - f = Testball.new - - stamps_with_revisions = [[111111, 1], [222222, 1], [222222, 2], [222222, 0]] - - stamps_with_revisions.each do |stamp, revision| - version = "HEAD-#{stamp}" - version += "_#{revision}" if revision > 0 - prefix = f.rack.join(version) - prefix.mkpath - - tab = Tab.empty - tab.tabfile = prefix.join("INSTALL_RECEIPT.json") - tab.source_modified_time = stamp - tab.write - end - - prefix = HOMEBREW_CELLAR/"#{f.name}/HEAD-222222_2" - assert_equal prefix, f.latest_head_prefix - ensure - f.rack.rmtree - end - - def test_equality - x = Testball.new - y = Testball.new - assert_equal x, y - assert_eql x, y - assert_equal x.hash, y.hash - end - - def test_inequality - x = Testball.new("foo") - y = Testball.new("bar") - refute_equal x, y - refute_eql x, y - refute_equal x.hash, y.hash - end - - def test_comparison_with_non_formula_objects_does_not_raise - refute_equal Testball.new, Object.new - end - - def test_sort_operator - assert_nil Testball.new <=> Object.new - end - - def test_alias_paths_with_build_options - alias_path = CoreTap.instance.alias_dir/"another_name" - f = formula(alias_path: alias_path) { url "foo-1.0" } - f.build = BuildOptions.new({}, {}) - assert_equal alias_path, f.alias_path - assert_nil f.installed_alias_path - end - - def test_alias_paths_with_tab_with_non_alias_source_path - alias_path = CoreTap.instance.alias_dir/"another_name" - source_path = CoreTap.instance.formula_dir/"another_other_name" - f = formula(alias_path: alias_path) { url "foo-1.0" } - f.build = Tab.new(source: { "path" => source_path.to_s }) - assert_equal alias_path, f.alias_path - assert_nil f.installed_alias_path - end - - def test_alias_paths_with_tab_with_alias_source_path - alias_path = CoreTap.instance.alias_dir/"another_name" - source_path = CoreTap.instance.alias_dir/"another_other_name" - f = formula(alias_path: alias_path) { url "foo-1.0" } - f.build = Tab.new(source: { "path" => source_path.to_s }) - assert_equal alias_path, f.alias_path - assert_equal source_path.to_s, f.installed_alias_path - end - - def test_installed_with_alias_path_with_nil - assert_predicate Formula.installed_with_alias_path(nil), :empty? - end - - def test_installed_with_alias_path_with_a_path - alias_path = "#{CoreTap.instance.alias_dir}/alias" - different_alias_path = "#{CoreTap.instance.alias_dir}/another_alias" - - formula_with_alias = formula("foo") { url "foo-1.0" } - formula_with_alias.build = Tab.empty - formula_with_alias.build.source["path"] = alias_path - - formula_without_alias = formula("bar") { url "bar-1.0" } - formula_without_alias.build = Tab.empty - formula_without_alias.build.source["path"] = formula_without_alias.path.to_s - - formula_with_different_alias = formula("baz") { url "baz-1.0" } - formula_with_different_alias.build = Tab.empty - formula_with_different_alias.build.source["path"] = different_alias_path - - formulae = [ - formula_with_alias, - formula_without_alias, - formula_with_different_alias, - ] - - Formula.stubs(:installed).returns(formulae) - assert_equal [formula_with_alias], Formula.installed_with_alias_path(alias_path) - end - - def test_formula_spec_integration - f = formula do - homepage "http://example.com" - url "http://example.com/test-0.1.tbz" - mirror "http://example.org/test-0.1.tbz" - sha256 TEST_SHA256 - - head "http://example.com/test.git", tag: "foo" - - devel do - url "http://example.com/test-0.2.tbz" - mirror "http://example.org/test-0.2.tbz" - sha256 TEST_SHA256 - end - end - - assert_equal "http://example.com", f.homepage - assert_version_equal "0.1", f.version - assert_predicate f, :stable? - - assert_version_equal "0.1", f.stable.version - assert_version_equal "0.2", f.devel.version - assert_version_equal "HEAD", f.head.version - end - - def test_formula_active_spec= - f = formula do - url "foo" - version "1.0" - revision 1 - - devel do - url "foo" - version "1.0beta" - end - end - assert_equal :stable, f.active_spec_sym - assert_equal f.stable, f.send(:active_spec) - assert_equal "1.0_1", f.pkg_version.to_s - f.active_spec = :devel - assert_equal :devel, f.active_spec_sym - assert_equal f.devel, f.send(:active_spec) - assert_equal "1.0beta_1", f.pkg_version.to_s - assert_raises(FormulaSpecificationError) { f.active_spec = :head } - end - - def test_path - name = "foo-bar" - assert_equal Pathname.new("#{HOMEBREW_LIBRARY}/Taps/homebrew/homebrew-core/Formula/#{name}.rb"), Formulary.core_path(name) - end - - def test_class_specs_are_always_initialized - f = formula { url "foo-1.0" } - - %w[stable devel head].each do |spec| - assert_kind_of SoftwareSpec, f.class.send(spec) - end - end - - def test_incomplete_instance_specs_are_not_accessible - f = formula { url "foo-1.0" } - - %w[devel head].each { |spec| assert_nil f.send(spec) } - end - - def test_honors_attributes_declared_before_specs - f = formula do - url "foo-1.0" - depends_on "foo" - devel { url "foo-1.1" } - end - - %w[stable devel head].each do |spec| - assert_equal "foo", f.class.send(spec).deps.first.name - end - end - - def test_simple_version - assert_equal PkgVersion.parse("1.0"), formula { url "foo-1.0.bar" }.pkg_version - end - - def test_version_with_revision - f = formula do - url "foo-1.0.bar" - revision 1 - end - - assert_equal PkgVersion.parse("1.0_1"), f.pkg_version - end - - def test_head_uses_revisions - f = formula("test", Pathname.new(__FILE__).expand_path, :head) do - url "foo-1.0.bar" - revision 1 - head "foo" - end - - assert_equal PkgVersion.parse("HEAD_1"), f.pkg_version - end - - def test_update_head_version - initial_env = ENV.to_hash - - f = formula do - head "foo", using: :git - end - - cached_location = f.head.downloader.cached_location - cached_location.mkpath - - %w[AUTHOR COMMITTER].each do |role| - ENV["GIT_#{role}_NAME"] = "brew tests" - ENV["GIT_#{role}_EMAIL"] = "brew-tests@localhost" - ENV["GIT_#{role}_DATE"] = "Thu May 21 00:04:11 2009 +0100" - end - - cached_location.cd do - FileUtils.touch "LICENSE" - shutup do - system "git", "init" - system "git", "add", "--all" - system "git", "commit", "-m", "Initial commit" - end - end - - f.update_head_version - assert_equal Version.create("HEAD-5658946"), f.head.version - ensure - ENV.replace(initial_env) - cached_location.rmtree - end - - def test_legacy_options - f = formula do - url "foo-1.0" - - def options - [["--foo", "desc"], ["--bar", "desc"]] - end - - option "baz" - end - - assert f.option_defined?("foo") - assert f.option_defined?("bar") - assert f.option_defined?("baz") - end - - def test_desc - f = formula do - desc "a formula" - url "foo-1.0" - end - - assert_equal "a formula", f.desc - end - - def test_post_install_defined - f1 = formula do - url "foo-1.0" - - def post_install; end - end - - f2 = formula do - url "foo-1.0" - end - - assert f1.post_install_defined? - refute f2.post_install_defined? - end - - def test_test_defined - f1 = formula do - url "foo-1.0" - - def test; end - end - - f2 = formula do - url "foo-1.0" - end - - assert f1.test_defined? - refute f2.test_defined? - end - - def test_test_fixtures - f1 = formula do - url "foo-1.0" - end - - assert_equal Pathname.new("#{HOMEBREW_LIBRARY_PATH}/test/support/fixtures/foo"), - f1.test_fixtures("foo") - end - - def test_dependencies - stub_formula_loader formula("f1") { url "f1-1.0" } - stub_formula_loader formula("f2") { url "f2-1.0" } - - f3 = formula("f3") do - url "f3-1.0" - depends_on "f1" => :build - depends_on "f2" - end - stub_formula_loader f3 - - f4 = formula("f4") do - url "f4-1.0" - depends_on "f1" - end - stub_formula_loader f4 - - f5 = formula("f5") do - url "f5-1.0" - depends_on "f3" => :build - depends_on "f4" - end - - assert_equal %w[f3 f4], f5.deps.map(&:name) - assert_equal %w[f1 f2 f3 f4], f5.recursive_dependencies.map(&:name) - assert_equal %w[f1 f4], f5.runtime_dependencies.map(&:name) - end - - def test_runtime_dependencies_with_optional_deps_from_tap - tap_loader = mock - tap_loader.stubs(:get_formula).raises(RuntimeError, "tried resolving tap formula") - Formulary.stubs(:loader_for).with("foo/bar/f1", from: nil).returns(tap_loader) - - stub_formula_loader formula("f2") { url "f2-1.0" }, "baz/qux/f2" - - f3 = formula("f3") do - url "f3-1.0" - depends_on "foo/bar/f1" => :optional - depends_on "baz/qux/f2" - end - - # f1 shouldn't be loaded by default. - # If it is, an exception will be raised. - assert_equal %w[baz/qux/f2], f3.runtime_dependencies.map(&:name) - - # If --with-f1, f1 should be loaded. - stub_formula_loader formula("f1") { url "f1-1.0" }, "foo/bar/f1" - f3.build = BuildOptions.new(Options.create(%w[--with-f1]), f3.options) - assert_equal %w[foo/bar/f1 baz/qux/f2], f3.runtime_dependencies.map(&:name) - end - - def test_to_hash - f1 = formula("foo") do - url "foo-1.0" - end - - h = f1.to_hash - assert h.is_a?(Hash), "Formula#to_hash should return a Hash" - assert_equal "foo", h["name"] - assert_equal "foo", h["full_name"] - assert_equal "1.0", h["versions"]["stable"] - end - - def test_to_hash_bottle - f1 = formula("foo") do - url "foo-1.0" - - bottle do - cellar :any - sha256 TEST_SHA256 => Utils::Bottles.tag - end - end - - h = f1.to_hash - assert h.is_a?(Hash), "Formula#to_hash should return a Hash" - assert h["versions"]["bottle"], "The hash should say the formula is bottled" - end - - def test_eligible_kegs_for_cleanup - f1 = Class.new(Testball) { version "0.1" }.new - f2 = Class.new(Testball) { version "0.2" }.new - f3 = Class.new(Testball) { version "0.3" }.new - - shutup do - f1.brew { f1.install } - f2.brew { f2.install } - f3.brew { f3.install } - end - - assert_predicate f1, :installed? - assert_predicate f2, :installed? - assert_predicate f3, :installed? - - assert_equal f3.installed_kegs.sort_by(&:version)[0..1], - f3.eligible_kegs_for_cleanup.sort_by(&:version) - ensure - [f1, f2, f3].each(&:clear_cache) - f3.rack.rmtree - end - - def test_eligible_kegs_for_cleanup_keg_pinned - f1 = Class.new(Testball) { version "0.1" }.new - f2 = Class.new(Testball) { version "0.2" }.new - f3 = Class.new(Testball) { version "0.3" }.new - - shutup do - f1.brew { f1.install } - f1.pin - f2.brew { f2.install } - f3.brew { f3.install } - end - - assert_equal (HOMEBREW_PINNED_KEGS/f1.name).resolved_path, f1.prefix - - assert_predicate f1, :installed? - assert_predicate f2, :installed? - assert_predicate f3, :installed? - - assert_equal [Keg.new(f2.prefix)], shutup { f3.eligible_kegs_for_cleanup } - ensure - f1.unpin - [f1, f2, f3].each(&:clear_cache) - f3.rack.rmtree - end - - def test_eligible_kegs_for_cleanup_head_installed - f = formula do - version "0.1" - head "foo" - end - - stable_prefix = f.installed_prefix - stable_prefix.mkpath - - [["000000_1", 1], ["111111", 2], ["111111_1", 2]].each do |pkg_version_suffix, stamp| - prefix = f.prefix("HEAD-#{pkg_version_suffix}") - prefix.mkpath - tab = Tab.empty - tab.tabfile = prefix.join("INSTALL_RECEIPT.json") - tab.source_modified_time = stamp - tab.write - end - - eligible_kegs = f.installed_kegs - [Keg.new(f.prefix("HEAD-111111_1"))] - assert_equal eligible_kegs, f.eligible_kegs_for_cleanup - ensure - f.rack.rmtree - end - - def test_pour_bottle - f_false = formula("foo") do - url "foo-1.0" - def pour_bottle? - false - end - end - refute f_false.pour_bottle? - - f_true = formula("foo") do - url "foo-1.0" - def pour_bottle? - true - end - end - assert f_true.pour_bottle? - end - - def test_pour_bottle_dsl - f_false = formula("foo") do - url "foo-1.0" - pour_bottle? do - reason "false reason" - satisfy { var == etc } - end - end - refute f_false.pour_bottle? - - f_true = formula("foo") do - url "foo-1.0" - pour_bottle? do - reason "true reason" - satisfy { true } - end - end - assert f_true.pour_bottle? - end -end - -class AliasChangeTests < Homebrew::TestCase - attr_reader :f, :new_formula, :tab, :alias_path - - def make_formula(name, version) - f = formula(name, alias_path: alias_path) { url "foo-#{version}" } - f.build = tab - f - end - - def setup - alias_name = "bar" - @alias_path = "#{CoreTap.instance.alias_dir}/#{alias_name}" - - @tab = Tab.empty - - @f = make_formula("formula_name", "1.0") - @new_formula = make_formula("new_formula_name", "1.1") - - Formula.stubs(:installed).returns([f]) - end - - def test_alias_changes_when_not_installed_with_alias - tab.source["path"] = Formulary.core_path(f.name).to_s - - assert_nil f.current_installed_alias_target - assert_equal f, f.latest_formula - refute_predicate f, :installed_alias_target_changed? - refute_predicate f, :supersedes_an_installed_formula? - refute_predicate f, :alias_changed? - assert_predicate f.old_installed_formulae, :empty? - end - - def test_alias_changes_when_not_changed - tab.source["path"] = alias_path - stub_formula_loader(f, alias_path) - - assert_equal f, f.current_installed_alias_target - assert_equal f, f.latest_formula - refute_predicate f, :installed_alias_target_changed? - refute_predicate f, :supersedes_an_installed_formula? - refute_predicate f, :alias_changed? - assert_predicate f.old_installed_formulae, :empty? - end - - def test_alias_changes_when_new_alias_target - tab.source["path"] = alias_path - stub_formula_loader(new_formula, alias_path) - - assert_equal new_formula, f.current_installed_alias_target - assert_equal new_formula, f.latest_formula - assert_predicate f, :installed_alias_target_changed? - refute_predicate f, :supersedes_an_installed_formula? - assert_predicate f, :alias_changed? - assert_predicate f.old_installed_formulae, :empty? - end - - def test_alias_changes_when_old_formulae_installed - tab.source["path"] = alias_path - stub_formula_loader(new_formula, alias_path) - - assert_equal new_formula, new_formula.current_installed_alias_target - assert_equal new_formula, new_formula.latest_formula - refute_predicate new_formula, :installed_alias_target_changed? - assert_predicate new_formula, :supersedes_an_installed_formula? - assert_predicate new_formula, :alias_changed? - assert_equal [f], new_formula.old_installed_formulae - end -end - -class OutdatedVersionsTests < Homebrew::TestCase - attr_reader :outdated_prefix, - :same_prefix, - :greater_prefix, - :head_prefix, - :old_alias_target_prefix - attr_reader :f, :old_formula, :new_formula - - def setup - @f = formula do - url "foo" - version "1.20" - end - - @old_formula = formula("foo@1") { url "foo-1.0" } - @new_formula = formula("foo@2") { url "foo-2.0" } - - @outdated_prefix = HOMEBREW_CELLAR/"#{f.name}/1.11" - @same_prefix = HOMEBREW_CELLAR/"#{f.name}/1.20" - @greater_prefix = HOMEBREW_CELLAR/"#{f.name}/1.21" - @head_prefix = HOMEBREW_CELLAR/"#{f.name}/HEAD" - @old_alias_target_prefix = HOMEBREW_CELLAR/"#{old_formula.name}/1.0" - end - - def teardown - formulae = [@f, @old_formula, @new_formula] - formulae.map(&:rack).select(&:exist?).each(&:rmtree) - end - - def alias_path - "#{@f.tap.alias_dir}/bar" - end - - def setup_tab_for_prefix(prefix, options = {}) - prefix.mkpath - tab = Tab.empty - tab.tabfile = prefix.join("INSTALL_RECEIPT.json") - tab.source["path"] = options[:path].to_s if options[:path] - tab.source["tap"] = options[:tap] if options[:tap] - tab.source["versions"] = options[:versions] if options[:versions] - tab.source_modified_time = options[:source_modified_time].to_i - tab.write unless options[:no_write] - tab - end - - def reset_outdated_kegs - f.instance_variable_set(:@outdated_kegs, nil) - end - - def test_greater_different_tap_installed - setup_tab_for_prefix(greater_prefix, tap: "user/repo") - assert_predicate f.outdated_kegs, :empty? - end - - def test_greater_same_tap_installed - f.instance_variable_set(:@tap, CoreTap.instance) - setup_tab_for_prefix(greater_prefix, tap: "homebrew/core") - assert_predicate f.outdated_kegs, :empty? - end - - def test_outdated_different_tap_installed - setup_tab_for_prefix(outdated_prefix, tap: "user/repo") - refute_predicate f.outdated_kegs, :empty? - end - - def test_outdated_same_tap_installed - f.instance_variable_set(:@tap, CoreTap.instance) - setup_tab_for_prefix(outdated_prefix, tap: "homebrew/core") - refute_predicate f.outdated_kegs, :empty? - end - - def test_outdated_follow_alias_and_alias_unchanged - f.follow_installed_alias = true - f.build = setup_tab_for_prefix(same_prefix, path: alias_path) - stub_formula_loader(f, alias_path) - assert_predicate f.outdated_kegs, :empty? - end - - def test_outdated_follow_alias_and_alias_changed_and_new_target_not_installed - f.follow_installed_alias = true - f.build = setup_tab_for_prefix(same_prefix, path: alias_path) - stub_formula_loader(new_formula, alias_path) - refute_predicate f.outdated_kegs, :empty? - end - - def test_outdated_follow_alias_and_alias_changed_and_new_target_installed - f.follow_installed_alias = true - f.build = setup_tab_for_prefix(same_prefix, path: alias_path) - stub_formula_loader(new_formula, alias_path) - setup_tab_for_prefix(new_formula.prefix) # install new_formula - assert_predicate f.outdated_kegs, :empty? - end - - def test_outdated_no_follow_alias_and_alias_unchanged - f.follow_installed_alias = false - f.build = setup_tab_for_prefix(same_prefix, path: alias_path) - stub_formula_loader(f, alias_path) - assert_predicate f.outdated_kegs, :empty? - end - - def test_outdated_no_follow_alias_and_alias_changed - f.follow_installed_alias = false - f.build = setup_tab_for_prefix(same_prefix, path: alias_path) - stub_formula_loader(formula("foo@2") { url "foo-2.0" }, alias_path) - assert_predicate f.outdated_kegs, :empty? - end - - def test_outdated_old_alias_targets_installed - @f = formula(alias_path: alias_path) { url "foo-1.0" } - tab = setup_tab_for_prefix(old_alias_target_prefix, path: alias_path) - old_formula.build = tab - Formula.stubs(:installed).returns([old_formula]) - refute_predicate f.outdated_kegs, :empty? - end - - def test_outdated_old_alias_targets_not_installed - @f = formula(alias_path: alias_path) { url "foo-1.0" } - tab = setup_tab_for_prefix(old_alias_target_prefix, path: old_formula.path) - old_formula.build = tab - Formula.stubs(:installed).returns([old_formula]) - assert_predicate f.outdated_kegs, :empty? - end - - def test_outdated_same_head_installed - f.instance_variable_set(:@tap, CoreTap.instance) - setup_tab_for_prefix(head_prefix, tap: "homebrew/core") - assert_predicate f.outdated_kegs, :empty? - end - - def test_outdated_different_head_installed - f.instance_variable_set(:@tap, CoreTap.instance) - setup_tab_for_prefix(head_prefix, tap: "user/repo") - assert_predicate f.outdated_kegs, :empty? - end - - def test_outdated_mixed_taps_greater_version_installed - f.instance_variable_set(:@tap, CoreTap.instance) - setup_tab_for_prefix(outdated_prefix, tap: "homebrew/core") - setup_tab_for_prefix(greater_prefix, tap: "user/repo") - - assert_predicate f.outdated_kegs, :empty? - - setup_tab_for_prefix(greater_prefix, tap: "homebrew/core") - reset_outdated_kegs - - assert_predicate f.outdated_kegs, :empty? - end - - def test_outdated_mixed_taps_outdated_version_installed - f.instance_variable_set(:@tap, CoreTap.instance) - - extra_outdated_prefix = HOMEBREW_CELLAR/"#{f.name}/1.0" - - setup_tab_for_prefix(outdated_prefix) - setup_tab_for_prefix(extra_outdated_prefix, tap: "homebrew/core") - reset_outdated_kegs - - refute_predicate f.outdated_kegs, :empty? - - setup_tab_for_prefix(outdated_prefix, tap: "user/repo") - reset_outdated_kegs - - refute_predicate f.outdated_kegs, :empty? - end - - def test_outdated_same_version_tap_installed - f.instance_variable_set(:@tap, CoreTap.instance) - setup_tab_for_prefix(same_prefix, tap: "homebrew/core") - - assert_predicate f.outdated_kegs, :empty? - - setup_tab_for_prefix(same_prefix, tap: "user/repo") - reset_outdated_kegs - - assert_predicate f.outdated_kegs, :empty? - end - - def test_outdated_installed_head_less_than_stable - tab = setup_tab_for_prefix(head_prefix, versions: { "stable" => "1.0" }) - refute_predicate f.outdated_kegs, :empty? - - # Tab.for_keg(head_prefix) will be fetched from CACHE but we write it anyway - tab.source["versions"] = { "stable" => f.version.to_s } - tab.write - reset_outdated_kegs - - assert_predicate f.outdated_kegs, :empty? - end - - def test_outdated_fetch_head - outdated_stable_prefix = HOMEBREW_CELLAR.join("testball/1.0") - head_prefix_a = HOMEBREW_CELLAR.join("testball/HEAD") - head_prefix_b = HOMEBREW_CELLAR.join("testball/HEAD-aaaaaaa_1") - head_prefix_c = HOMEBREW_CELLAR.join("testball/HEAD-5658946") - - setup_tab_for_prefix(outdated_stable_prefix) - tab_a = setup_tab_for_prefix(head_prefix_a, versions: { "stable" => "1.0" }) - setup_tab_for_prefix(head_prefix_b) - - initial_env = ENV.to_hash - testball_repo = HOMEBREW_PREFIX.join("testball_repo") - testball_repo.mkdir - - @f = formula("testball") do - url "foo" - version "2.10" - head "file://#{testball_repo}", using: :git - end - - %w[AUTHOR COMMITTER].each do |role| - ENV["GIT_#{role}_NAME"] = "brew tests" - ENV["GIT_#{role}_EMAIL"] = "brew-tests@localhost" - ENV["GIT_#{role}_DATE"] = "Thu May 21 00:04:11 2009 +0100" - end - - testball_repo.cd do - FileUtils.touch "LICENSE" - shutup do - system "git", "init" - system "git", "add", "--all" - system "git", "commit", "-m", "Initial commit" - end - end - - refute_predicate f.outdated_kegs(fetch_head: true), :empty? - - tab_a.source["versions"] = { "stable" => f.version.to_s } - tab_a.write - reset_outdated_kegs - refute_predicate f.outdated_kegs(fetch_head: true), :empty? - - head_prefix_a.rmtree - reset_outdated_kegs - refute_predicate f.outdated_kegs(fetch_head: true), :empty? - - setup_tab_for_prefix(head_prefix_c, source_modified_time: 1) - reset_outdated_kegs - assert_predicate f.outdated_kegs(fetch_head: true), :empty? - ensure - ENV.replace(initial_env) - testball_repo.rmtree if testball_repo.exist? - outdated_stable_prefix.rmtree if outdated_stable_prefix.exist? - head_prefix_b.rmtree if head_prefix.exist? - head_prefix_c.rmtree if head_prefix_c.exist? - FileUtils.rm_rf HOMEBREW_CACHE/"testball--git" - FileUtils.rm_rf HOMEBREW_CELLAR/"testball" - end - - def test_outdated_kegs_version_scheme_changed - @f = formula("testball") do - url "foo" - version "20141010" - version_scheme 1 - end - - prefix = HOMEBREW_CELLAR.join("testball/0.1") - setup_tab_for_prefix(prefix, versions: { "stable" => "0.1" }) - - refute_predicate f.outdated_kegs, :empty? - ensure - prefix.rmtree - end - - def test_outdated_kegs_mixed_version_schemes - @f = formula("testball") do - url "foo" - version "20141010" - version_scheme 3 - end - - prefix_a = HOMEBREW_CELLAR.join("testball/20141009") - setup_tab_for_prefix(prefix_a, versions: { "stable" => "20141009", "version_scheme" => 1 }) - - prefix_b = HOMEBREW_CELLAR.join("testball/2.14") - setup_tab_for_prefix(prefix_b, versions: { "stable" => "2.14", "version_scheme" => 2 }) - - refute_predicate f.outdated_kegs, :empty? - reset_outdated_kegs - - prefix_c = HOMEBREW_CELLAR.join("testball/20141009") - setup_tab_for_prefix(prefix_c, versions: { "stable" => "20141009", "version_scheme" => 3 }) - - refute_predicate f.outdated_kegs, :empty? - reset_outdated_kegs - - prefix_d = HOMEBREW_CELLAR.join("testball/20141011") - setup_tab_for_prefix(prefix_d, versions: { "stable" => "20141009", "version_scheme" => 3 }) - assert_predicate f.outdated_kegs, :empty? - ensure - f.rack.rmtree - end - - def test_outdated_kegs_head_with_version_scheme - @f = formula("testball") do - url "foo" - version "1.0" - version_scheme 2 - end - - head_prefix = HOMEBREW_CELLAR.join("testball/HEAD") - - setup_tab_for_prefix(head_prefix, versions: { "stable" => "1.0", "version_scheme" => 1 }) - refute_predicate f.outdated_kegs, :empty? - - reset_outdated_kegs - head_prefix.rmtree - - setup_tab_for_prefix(head_prefix, versions: { "stable" => "1.0", "version_scheme" => 2 }) - assert_predicate f.outdated_kegs, :empty? - ensure - head_prefix.rmtree - end -end diff --git a/Library/Homebrew/test/formulary_spec.rb b/Library/Homebrew/test/formulary_spec.rb new file mode 100644 index 000000000..213ad511d --- /dev/null +++ b/Library/Homebrew/test/formulary_spec.rb @@ -0,0 +1,227 @@ +require "formula" +require "formula_installer" +require "utils/bottles" + +describe Formulary do + let(:formula_name) { "testball_bottle" } + let(:formula_path) { CoreTap.new.formula_dir/"#{formula_name}.rb" } + let(:formula_content) do + <<-EOS.undent + class #{subject.class_s(formula_name)} < Formula + url "file://#{TEST_FIXTURE_DIR}/tarballs/testball-0.1.tbz" + sha256 TESTBALL_SHA256 + + bottle do + cellar :any_skip_relocation + root_url "file://#{bottle_dir}" + sha256 "9abc8ce779067e26556002c4ca6b9427b9874d25f0cafa7028e05b5c5c410cb4" => :#{Utils::Bottles.tag} + end + + def install + prefix.install "bin" + prefix.install "libexec" + end + end + EOS + end + let(:bottle_dir) { Pathname.new("#{TEST_FIXTURE_DIR}/bottles") } + let(:bottle) { bottle_dir/"testball_bottle-0.1.#{Utils::Bottles.tag}.bottle.tar.gz" } + + describe "::class_s" do + it "replaces '+' with 'x'" do + expect(subject.class_s("foo++")).to eq("Fooxx") + end + + it "converts a string to PascalCase" do + expect(subject.class_s("shell.fm")).to eq("ShellFm") + expect(subject.class_s("s-lang")).to eq("SLang") + expect(subject.class_s("pkg-config")).to eq("PkgConfig") + expect(subject.class_s("foo_bar")).to eq("FooBar") + end + + it "replaces '@' with 'AT'" do + expect(subject.class_s("openssl@1.1")).to eq("OpensslAT11") + end + end + + describe "::factory" do + before(:each) do + formula_path.write formula_content + end + + it "returns a Formula" do + expect(subject.factory(formula_name)).to be_kind_of(Formula) + end + + it "returns a Formula when given a fully qualified name" do + expect(subject.factory("homebrew/core/#{formula_name}")).to be_kind_of(Formula) + end + + it "raises an error if the Formula cannot be found" do + expect { + subject.factory("not_existed_formula") + }.to raise_error(FormulaUnavailableError) + end + + context "if the Formula has the wrong class" do + let(:formula_name) { "giraffe" } + let(:formula_content) do + <<-EOS.undent + class Wrong#{subject.class_s(formula_name)} < Formula + end + EOS + end + + it "raises an error" do + expect { + subject.factory(formula_name) + }.to raise_error(FormulaClassUnavailableError) + end + end + + it "returns a Formula when given a path" do + expect(subject.factory(formula_path)).to be_kind_of(Formula) + end + + it "returns a Formula when given a URL" do + formula = shutup do + subject.factory("file://#{formula_path}") + end + + expect(formula).to be_kind_of(Formula) + end + + it "returns a Formula when given a bottle" do + formula = subject.factory(bottle) + expect(formula).to be_kind_of(Formula) + expect(formula.local_bottle_path).to eq(bottle.realpath) + end + + it "returns a Formula when given an alias" do + alias_dir = CoreTap.instance.alias_dir + alias_dir.mkpath + alias_path = alias_dir/"foo" + FileUtils.ln_s formula_path, alias_path + result = subject.factory("foo") + expect(result).to be_kind_of(Formula) + expect(result.alias_path).to eq(alias_path.to_s) + end + + context "with installed Formula" do + let(:formula) { subject.factory(formula_path) } + let(:installer) { FormulaInstaller.new(formula) } + + it "returns a Formula when given a rack" do + shutup do + installer.install + end + + f = subject.from_rack(formula.rack) + expect(f).to be_kind_of(Formula) + expect(f.build).to be_kind_of(Tab) + end + + it "returns a Formula when given a Keg" do + shutup do + installer.install + end + + keg = Keg.new(formula.prefix) + f = subject.from_keg(keg) + expect(f).to be_kind_of(Formula) + expect(f.build).to be_kind_of(Tab) + end + end + + context "from Tap" do + let(:tap) { Tap.new("homebrew", "foo") } + let(:formula_path) { tap.path/"#{formula_name}.rb" } + + it "returns a Formula when given a name" do + expect(subject.factory(formula_name)).to be_kind_of(Formula) + end + + it "returns a Formula from an Alias path" do + alias_dir = tap.path/"Aliases" + alias_dir.mkpath + FileUtils.ln_s formula_path, alias_dir/"bar" + expect(subject.factory("bar")).to be_kind_of(Formula) + end + + it "raises an error when the Formula cannot be found" do + expect { + subject.factory("#{tap}/not_existed_formula") + }.to raise_error(TapFormulaUnavailableError) + end + + it "returns a Formula when given a fully qualified name" do + expect(subject.factory("#{tap}/#{formula_name}")).to be_kind_of(Formula) + end + + it "raises an error if a Formula is in multiple Taps" do + begin + another_tap = Tap.new("homebrew", "bar") + (another_tap.path/"#{formula_name}.rb").write formula_content + expect { + subject.factory(formula_name) + }.to raise_error(TapFormulaAmbiguityError) + ensure + another_tap.path.rmtree + end + end + end + end + + specify "::from_contents" do + expect(subject.from_contents(formula_name, formula_path, formula_content)).to be_kind_of(Formula) + end + + specify "::to_rack" do + expect(subject.to_rack(formula_name)).to eq(HOMEBREW_CELLAR/formula_name) + + (HOMEBREW_CELLAR/formula_name).mkpath + expect(subject.to_rack(formula_name)).to eq(HOMEBREW_CELLAR/formula_name) + + expect { + subject.to_rack("a/b/#{formula_name}") + }.to raise_error(TapFormulaUnavailableError) + end + + describe "::find_with_priority" do + let(:core_path) { CoreTap.new.formula_dir/"#{formula_name}.rb" } + let(:tap) { Tap.new("homebrew", "foo") } + let(:tap_path) { tap.path/"#{formula_name}.rb" } + + before(:each) do + core_path.write formula_content + tap_path.write formula_content + end + + it "prioritizes core Formulae" do + formula = subject.find_with_priority(formula_name) + expect(formula).to be_kind_of(Formula) + expect(formula.path).to eq(core_path) + end + + it "prioritizes Formulae from pinned Taps" do + begin + tap.pin + formula = shutup do + subject.find_with_priority(formula_name) + end + expect(formula).to be_kind_of(Formula) + expect(formula.path).to eq(tap_path.realpath) + ensure + tap.pinned_symlink_path.parent.parent.rmtree + end + end + end + + describe "::core_path" do + it "returns the path to a Formula in the core tap" do + name = "foo-bar" + expect(subject.core_path(name)) + .to eq(Pathname.new("#{HOMEBREW_LIBRARY}/Taps/homebrew/homebrew-core/Formula/#{name}.rb")) + end + end +end diff --git a/Library/Homebrew/test/formulary_test.rb b/Library/Homebrew/test/formulary_test.rb deleted file mode 100644 index 3d88c8407..000000000 --- a/Library/Homebrew/test/formulary_test.rb +++ /dev/null @@ -1,208 +0,0 @@ -require "testing_env" -require "formula" -require "formula_installer" -require "utils/bottles" - -class FormularyTest < Homebrew::TestCase - def test_class_naming - assert_equal "ShellFm", Formulary.class_s("shell.fm") - assert_equal "Fooxx", Formulary.class_s("foo++") - assert_equal "SLang", Formulary.class_s("s-lang") - assert_equal "PkgConfig", Formulary.class_s("pkg-config") - assert_equal "FooBar", Formulary.class_s("foo_bar") - assert_equal "OpensslAT11", Formulary.class_s("openssl@1.1") - end -end - -class FormularyFactoryTest < Homebrew::TestCase - def setup - @name = "testball_bottle" - @path = CoreTap.new.formula_dir/"#{@name}.rb" - @bottle_dir = Pathname.new("#{TEST_FIXTURE_DIR}/bottles") - @bottle = @bottle_dir/"testball_bottle-0.1.#{Utils::Bottles.tag}.bottle.tar.gz" - @path.write <<-EOS.undent - class #{Formulary.class_s(@name)} < Formula - url "file://#{TEST_FIXTURE_DIR}/tarballs/testball-0.1.tbz" - sha256 TESTBALL_SHA256 - - bottle do - cellar :any_skip_relocation - root_url "file://#{@bottle_dir}" - sha256 "9abc8ce779067e26556002c4ca6b9427b9874d25f0cafa7028e05b5c5c410cb4" => :#{Utils::Bottles.tag} - end - - def install - prefix.install "bin" - prefix.install "libexec" - end - end - EOS - end - - def teardown - @path.unlink - end - - def test_factory - assert_kind_of Formula, Formulary.factory(@name) - end - - def test_factory_with_fully_qualified_name - assert_kind_of Formula, Formulary.factory("homebrew/core/#{@name}") - end - - def test_formula_unavailable_error - assert_raises(FormulaUnavailableError) { Formulary.factory("not_existed_formula") } - end - - def test_formula_class_unavailable_error - name = "giraffe" - path = CoreTap.new.formula_dir/"#{name}.rb" - path.write "class Wrong#{Formulary.class_s(name)} < Formula\nend\n" - - assert_raises(FormulaClassUnavailableError) { Formulary.factory(name) } - ensure - path.unlink - end - - def test_factory_from_path - assert_kind_of Formula, Formulary.factory(@path) - end - - def test_factory_from_url - formula = shutup { Formulary.factory("file://#{@path}") } - assert_kind_of Formula, formula - ensure - formula.path.unlink - end - - def test_factory_from_bottle - formula = Formulary.factory(@bottle) - assert_kind_of Formula, formula - assert_equal @bottle.realpath, formula.local_bottle_path - end - - def test_factory_from_alias - alias_dir = CoreTap.instance.alias_dir - alias_dir.mkpath - alias_path = alias_dir/"foo" - FileUtils.ln_s @path, alias_path - result = Formulary.factory("foo") - assert_kind_of Formula, result - assert_equal alias_path.to_s, result.alias_path - ensure - alias_dir.rmtree - end - - def test_factory_from_rack_and_from_keg - formula = Formulary.factory(@path) - installer = FormulaInstaller.new(formula) - shutup { installer.install } - keg = Keg.new(formula.prefix) - f = Formulary.from_rack(formula.rack) - assert_kind_of Formula, f - assert_kind_of Tab, f.build - f = Formulary.from_keg(keg) - assert_kind_of Formula, f - assert_kind_of Tab, f.build - ensure - keg.unlink - keg.uninstall - formula.clear_cache - formula.bottle.clear_cache - end - - def test_load_from_contents - assert_kind_of Formula, Formulary.from_contents(@name, @path, @path.read) - end - - def test_to_rack - assert_equal HOMEBREW_CELLAR/@name, Formulary.to_rack(@name) - (HOMEBREW_CELLAR/@name).mkpath - assert_equal HOMEBREW_CELLAR/@name, Formulary.to_rack(@name) - assert_raises(TapFormulaUnavailableError) { Formulary.to_rack("a/b/#{@name}") } - ensure - FileUtils.rm_rf HOMEBREW_CELLAR/@name - end -end - -class FormularyTapFactoryTest < Homebrew::TestCase - def setup - @name = "foo" - @tap = Tap.new "homebrew", "foo" - @path = @tap.path/"#{@name}.rb" - @code = <<-EOS.undent - class #{Formulary.class_s(@name)} < Formula - url "foo-1.0" - end - EOS - @path.write @code - end - - def teardown - @tap.path.rmtree - end - - def test_factory_tap_formula - assert_kind_of Formula, Formulary.factory(@name) - end - - def test_factory_tap_alias - alias_dir = @tap.path/"Aliases" - alias_dir.mkpath - FileUtils.ln_s @path, alias_dir/"bar" - assert_kind_of Formula, Formulary.factory("bar") - end - - def test_tap_formula_unavailable_error - assert_raises(TapFormulaUnavailableError) { Formulary.factory("#{@tap}/not_existed_formula") } - end - - def test_factory_tap_formula_with_fully_qualified_name - assert_kind_of Formula, Formulary.factory("#{@tap}/#{@name}") - end - - def test_factory_ambiguity_tap_formulae - another_tap = Tap.new "homebrew", "bar" - (another_tap.path/"#{@name}.rb").write @code - assert_raises(TapFormulaAmbiguityError) { Formulary.factory(@name) } - ensure - another_tap.path.rmtree - end -end - -class FormularyTapPriorityTest < Homebrew::TestCase - def setup - @name = "foo" - @core_path = CoreTap.new.formula_dir/"#{@name}.rb" - @tap = Tap.new "homebrew", "foo" - @tap_path = @tap.path/"#{@name}.rb" - code = <<-EOS.undent - class #{Formulary.class_s(@name)} < Formula - url "foo-1.0" - end - EOS - @core_path.write code - @tap_path.write code - end - - def teardown - @core_path.unlink - @tap.path.rmtree - end - - def test_find_with_priority_core_formula - formula = Formulary.find_with_priority(@name) - assert_kind_of Formula, formula - assert_equal @core_path, formula.path - end - - def test_find_with_priority_tap_formula - @tap.pin - formula = shutup { Formulary.find_with_priority(@name) } - assert_kind_of Formula, formula - assert_equal @tap_path.realpath, formula.path - ensure - @tap.pinned_symlink_path.parent.parent.rmtree - end -end diff --git a/Library/Homebrew/test/gpg2_requirement_spec.rb b/Library/Homebrew/test/gpg2_requirement_spec.rb new file mode 100644 index 000000000..f46b31196 --- /dev/null +++ b/Library/Homebrew/test/gpg2_requirement_spec.rb @@ -0,0 +1,23 @@ +require "requirements/gpg2_requirement" +require "fileutils" + +describe GPG2Requirement do + let(:dir) { @dir = Pathname.new(Dir.mktmpdir) } + + after(:each) do + FileUtils.rm_rf dir unless @dir.nil? + end + + describe "#satisfied?" do + it "returns true if GPG2 is installed" do + ENV["PATH"] = dir/"bin" + (dir/"bin/gpg").write <<-EOS.undent + #!/bin/bash + echo 2.0.30 + EOS + FileUtils.chmod 0755, dir/"bin/gpg" + + expect(subject).to be_satisfied + end + end +end diff --git a/Library/Homebrew/test/gpg2_requirement_test.rb b/Library/Homebrew/test/gpg2_requirement_test.rb deleted file mode 100644 index fa7fc9ea4..000000000 --- a/Library/Homebrew/test/gpg2_requirement_test.rb +++ /dev/null @@ -1,24 +0,0 @@ -require "testing_env" -require "requirements/gpg2_requirement" -require "fileutils" - -class GPG2RequirementTests < Homebrew::TestCase - def setup - @dir = Pathname.new(mktmpdir) - (@dir/"bin/gpg").write <<-EOS.undent - #!/bin/bash - echo 2.0.30 - EOS - FileUtils.chmod 0755, @dir/"bin/gpg" - end - - def teardown - FileUtils.rm_rf @dir - end - - def test_satisfied - with_environment("PATH" => @dir/"bin") do - assert_predicate GPG2Requirement.new, :satisfied? - end - end -end diff --git a/Library/Homebrew/test/gpg_spec.rb b/Library/Homebrew/test/gpg_spec.rb new file mode 100644 index 000000000..9809dccb5 --- /dev/null +++ b/Library/Homebrew/test/gpg_spec.rb @@ -0,0 +1,21 @@ +require "gpg" + +describe Gpg do + subject { described_class } + + describe "::create_test_key" do + it "creates a test key in the home directory" do + skip "GPG Unavailable" unless subject.available? + + Dir.mktmpdir do |dir| + ENV["HOME"] = dir + dir = Pathname.new(dir) + + shutup do + subject.create_test_key(dir) + end + expect(dir/".gnupg/secring.gpg").to exist + end + end + end +end diff --git a/Library/Homebrew/test/gpg_test.rb b/Library/Homebrew/test/gpg_test.rb deleted file mode 100644 index 0374bdab4..000000000 --- a/Library/Homebrew/test/gpg_test.rb +++ /dev/null @@ -1,20 +0,0 @@ -require "testing_env" -require "gpg" - -class GpgTest < Homebrew::TestCase - def setup - skip "GPG Unavailable" unless Gpg.available? - @dir = Pathname.new(mktmpdir) - end - - def test_create_test_key - Dir.chdir(@dir) do - with_environment("HOME" => @dir) do - shutup { Gpg.create_test_key(@dir) } - assert_predicate @dir/".gnupg/secring.gpg", :exist? - end - end - ensure - @dir.rmtree - end -end diff --git a/Library/Homebrew/test/hardware_spec.rb b/Library/Homebrew/test/hardware_spec.rb new file mode 100644 index 000000000..c5f8daf4e --- /dev/null +++ b/Library/Homebrew/test/hardware_spec.rb @@ -0,0 +1,40 @@ +require "hardware" + +module Hardware + describe CPU do + describe "::type" do + it "returns the current CPU's type as a symbol, or :dunno if it cannot be detected" do + expect( + [ + :intel, + :ppc, + :dunno, + ], + ).to include(described_class.type) + end + end + + describe "::family" do + it "returns the current CPU's family name as a symbol, or :dunno if it cannot be detected" do + skip "Needs an Intel CPU." unless described_class.intel? + + expect( + [ + :core, + :core2, + :penryn, + :nehalem, + :arrandale, + :sandybridge, + :ivybridge, + :haswell, + :broadwell, + :skylake, + :kabylake, + :dunno, + ], + ).to include(described_class.family) + end + end + end +end diff --git a/Library/Homebrew/test/hardware_test.rb b/Library/Homebrew/test/hardware_test.rb deleted file mode 100644 index 69f881a60..000000000 --- a/Library/Homebrew/test/hardware_test.rb +++ /dev/null @@ -1,15 +0,0 @@ -require "testing_env" -require "hardware" - -class HardwareTests < Homebrew::TestCase - def test_hardware_cpu_type - assert_includes [:intel, :ppc, :dunno], Hardware::CPU.type - end - - if Hardware::CPU.intel? - def test_hardware_intel_family - families = [:core, :core2, :penryn, :nehalem, :arrandale, :sandybridge, :ivybridge, :haswell, :broadwell, :skylake, :kabylake, :dunno] - assert_includes families, Hardware::CPU.family - end - end -end diff --git a/Library/Homebrew/test/help_test.rb b/Library/Homebrew/test/help_test.rb deleted file mode 100644 index 92dd99721..000000000 --- a/Library/Homebrew/test/help_test.rb +++ /dev/null @@ -1,21 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestHelp < IntegrationCommandTestCase - def test_help - assert_match "Example usage:\n", - cmd_fail # Generic help (empty argument list). - assert_match "Unknown command: command-that-does-not-exist", - cmd_fail("help", "command-that-does-not-exist") - assert_match(/^brew cat /, - cmd_fail("cat")) # Missing formula argument triggers help. - - assert_match "Example usage:\n", - cmd("help") # Generic help. - assert_match(/^brew cat /, - cmd("help", "cat")) # Internal command (documented, Ruby). - assert_match(/^brew update /, - cmd("help", "update")) # Internal command (documented, Shell). - assert_match(/^brew update-test /, - cmd("help", "update-test")) # Internal developer command (documented, Ruby). - end -end diff --git a/Library/Homebrew/test/home_test.rb b/Library/Homebrew/test/home_test.rb deleted file mode 100644 index ff06b72c1..000000000 --- a/Library/Homebrew/test/home_test.rb +++ /dev/null @@ -1,12 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestHome < IntegrationCommandTestCase - def test_home - setup_test_formula "testball" - - assert_equal HOMEBREW_WWW, - cmd("home", "HOMEBREW_BROWSER" => "echo") - assert_equal Formula["testball"].homepage, - cmd("home", "testball", "HOMEBREW_BROWSER" => "echo") - end -end diff --git a/Library/Homebrew/test/info_test.rb b/Library/Homebrew/test/info_test.rb deleted file mode 100644 index f71044bf0..000000000 --- a/Library/Homebrew/test/info_test.rb +++ /dev/null @@ -1,29 +0,0 @@ -require "testing_env" -require "cmd/info" -require "formula" -require "testing_env" - -class IntegrationCommandTestInfo < IntegrationCommandTestCase - def test_info - setup_test_formula "testball" - - assert_match "testball: stable 0.1", - cmd("info", "testball") - end -end - -class InfoCommandTests < Homebrew::TestCase - def test_github_remote_path - remote = "https://github.com/Homebrew/homebrew-core" - assert_equal "https://github.com/Homebrew/homebrew-core/blob/master/Formula/git.rb", - Homebrew.github_remote_path(remote, "Formula/git.rb") - assert_equal "https://github.com/Homebrew/homebrew-core/blob/master/Formula/git.rb", - Homebrew.github_remote_path("#{remote}.git", "Formula/git.rb") - - assert_equal "https://github.com/user/repo/blob/master/foo.rb", - Homebrew.github_remote_path("git@github.com:user/repo", "foo.rb") - - assert_equal "https://mywebsite.com/foo/bar.rb", - Homebrew.github_remote_path("https://mywebsite.com", "foo/bar.rb") - end -end diff --git a/Library/Homebrew/test/inreplace_spec.rb b/Library/Homebrew/test/inreplace_spec.rb new file mode 100644 index 000000000..5be44f50d --- /dev/null +++ b/Library/Homebrew/test/inreplace_spec.rb @@ -0,0 +1,251 @@ +require "extend/string" +require "tempfile" +require "utils/inreplace" + +describe StringInreplaceExtension do + subject { string.extend(described_class) } + + describe "#change_make_var!" do + context "flag" do + context "with spaces" do + let(:string) do + <<-EOS.undent + OTHER=def + FLAG = abc + FLAG2=abc + EOS + end + + it "is successfully replaced" do + subject.change_make_var! "FLAG", "def" + expect(subject).to eq <<-EOS.undent + OTHER=def + FLAG=def + FLAG2=abc + EOS + end + + it "is successfully appended" do + subject.change_make_var! "FLAG", "\\1 def" + expect(subject).to eq <<-EOS.undent + OTHER=def + FLAG=abc def + FLAG2=abc + EOS + end + end + + context "with tabs" do + let(:string) do + <<-EOS.undent + CFLAGS\t=\t-Wall -O2 + LDFLAGS\t=\t-lcrypto -lssl + EOS + end + + it "is successfully replaced" do + subject.change_make_var! "CFLAGS", "-O3" + expect(subject).to eq <<-EOS.undent + CFLAGS=-O3 + LDFLAGS\t=\t-lcrypto -lssl + EOS + end + end + end + + context "empty flag between other flags" do + let(:string) do + <<-EOS.undent + OTHER=def + FLAG = + FLAG2=abc + EOS + end + + it "is successfully replaced" do + subject.change_make_var! "FLAG", "def" + expect(subject).to eq <<-EOS.undent + OTHER=def + FLAG=def + FLAG2=abc + EOS + end + end + + context "empty flag" do + let(:string) do + <<-EOS.undent + FLAG = + mv file_a file_b + EOS + end + + it "is successfully replaced" do + subject.change_make_var! "FLAG", "def" + expect(subject).to eq <<-EOS.undent + FLAG=def + mv file_a file_b + EOS + end + end + + context "shell-style variable" do + let(:string) do + <<-EOS.undent + OTHER=def + FLAG=abc + FLAG2=abc + EOS + end + + it "is successfully replaced" do + subject.change_make_var! "FLAG", "def" + expect(subject).to eq <<-EOS.undent + OTHER=def + FLAG=def + FLAG2=abc + EOS + end + end + end + + describe "#remove_make_var!" do + context "flag" do + context "with spaces" do + let(:string) do + <<-EOS.undent + OTHER=def + FLAG = abc + FLAG2 = def + EOS + end + + it "is successfully removed" do + subject.remove_make_var! "FLAG" + expect(subject).to eq <<-EOS.undent + OTHER=def + FLAG2 = def + EOS + end + end + + context "with tabs" do + let(:string) do + <<-EOS.undent + CFLAGS\t=\t-Wall -O2 + LDFLAGS\t=\t-lcrypto -lssl + EOS + end + + it "is successfully removed" do + subject.remove_make_var! "LDFLAGS" + expect(subject).to eq <<-EOS.undent + CFLAGS\t=\t-Wall -O2 + EOS + end + end + end + + context "multiple flags" do + let(:string) do + <<-EOS.undent + OTHER=def + FLAG = abc + FLAG2 = def + OTHER2=def + EOS + end + + specify "are be successfully removed" do + subject.remove_make_var! ["FLAG", "FLAG2"] + expect(subject).to eq <<-EOS.undent + OTHER=def + OTHER2=def + EOS + end + end + end + + describe "#get_make_var" do + context "with spaces" do + let(:string) do + <<-EOS.undent + CFLAGS = -Wall -O2 + LDFLAGS = -lcrypto -lssl + EOS + end + + it "extracts the value for a given variable" do + expect(subject.get_make_var("CFLAGS")).to eq("-Wall -O2") + end + end + + context "with tabs" do + let(:string) do + <<-EOS.undent + CFLAGS\t=\t-Wall -O2 + LDFLAGS\t=\t-lcrypto -lssl + EOS + end + + it "extracts the value for a given variable" do + expect(subject.get_make_var("CFLAGS")).to eq("-Wall -O2") + end + end + end + + describe "#sub!" do + let(:string) { "foo" } + + it "replaces the first occurence" do + subject.sub!("o", "e") + expect(subject).to eq("feo") + end + end + + describe "#gsub!" do + let(:string) { "foo" } + + it "replaces the all occurences" do + subject.gsub!("o", "e") # rubocop:disable Performance/StringReplacement + expect(subject).to eq("fee") + end + end +end + +describe Utils::Inreplace do + let(:file) { Tempfile.new("test") } + + before(:each) do + file.write <<-EOS.undent + a + b + c + EOS + end + + after(:each) { file.unlink } + + it "raises error if there is nothing to replace" do + expect { + described_class.inreplace file.path, "d", "f" + }.to raise_error(Utils::InreplaceError) + end + + it "raises error if there is nothing to replace" do + expect { + described_class.inreplace(file.path) do |s| + s.gsub!("d", "f") # rubocop:disable Performance/StringReplacement + end + }.to raise_error(Utils::InreplaceError) + end + + it "raises error if there is nothing to replace" do + expect { + described_class.inreplace(file.path) do |s| + s.change_make_var! "VAR", "value" + s.remove_make_var! "VAR2" + end + }.to raise_error(Utils::InreplaceError) + end +end diff --git a/Library/Homebrew/test/inreplace_test.rb b/Library/Homebrew/test/inreplace_test.rb deleted file mode 100644 index 0e62f9d3f..000000000 --- a/Library/Homebrew/test/inreplace_test.rb +++ /dev/null @@ -1,119 +0,0 @@ -require "testing_env" -require "extend/string" -require "utils/inreplace" - -class InreplaceTest < Homebrew::TestCase - def test_change_make_var - # Replace flag - s1 = "OTHER=def\nFLAG = abc\nFLAG2=abc" - s1.extend(StringInreplaceExtension) - s1.change_make_var! "FLAG", "def" - assert_equal "OTHER=def\nFLAG=def\nFLAG2=abc", s1 - end - - def test_change_make_var_empty - # Replace empty flag - s1 = "OTHER=def\nFLAG = \nFLAG2=abc" - s1.extend(StringInreplaceExtension) - s1.change_make_var! "FLAG", "def" - assert_equal "OTHER=def\nFLAG=def\nFLAG2=abc", s1 - end - - def test_change_make_var_empty_2 - # Replace empty flag - s1 = "FLAG = \nmv file_a file_b" - s1.extend(StringInreplaceExtension) - s1.change_make_var! "FLAG", "def" - assert_equal "FLAG=def\nmv file_a file_b", s1 - end - - def test_change_make_var_append - # Append to flag - s1 = "OTHER=def\nFLAG = abc\nFLAG2=abc" - s1.extend(StringInreplaceExtension) - s1.change_make_var! "FLAG", "\\1 def" - assert_equal "OTHER=def\nFLAG=abc def\nFLAG2=abc", s1 - end - - def test_change_make_var_shell_style - # Shell variables have no spaces around = - s1 = "OTHER=def\nFLAG=abc\nFLAG2=abc" - s1.extend(StringInreplaceExtension) - s1.change_make_var! "FLAG", "def" - assert_equal "OTHER=def\nFLAG=def\nFLAG2=abc", s1 - end - - def test_remove_make_var - # Replace flag - s1 = "OTHER=def\nFLAG = abc\nFLAG2 = def" - s1.extend(StringInreplaceExtension) - s1.remove_make_var! "FLAG" - assert_equal "OTHER=def\nFLAG2 = def", s1 - end - - def test_remove_make_vars - # Replace flag - s1 = "OTHER=def\nFLAG = abc\nFLAG2 = def\nOTHER2=def" - s1.extend(StringInreplaceExtension) - s1.remove_make_var! ["FLAG", "FLAG2"] - assert_equal "OTHER=def\nOTHER2=def", s1 - end - - def test_get_make_var - s = "CFLAGS = -Wall -O2\nLDFLAGS = -lcrypto -lssl" - s.extend(StringInreplaceExtension) - assert_equal "-Wall -O2", s.get_make_var("CFLAGS") - end - - def test_change_make_var_with_tabs - s = "CFLAGS\t=\t-Wall -O2\nLDFLAGS\t=\t-lcrypto -lssl" - s.extend(StringInreplaceExtension) - - assert_equal "-Wall -O2", s.get_make_var("CFLAGS") - - s.change_make_var! "CFLAGS", "-O3" - assert_equal "CFLAGS=-O3\nLDFLAGS\t=\t-lcrypto -lssl", s - - s.remove_make_var! "LDFLAGS" - assert_equal "CFLAGS=-O3\n", s - end - - def test_sub_gsub - s = "foo" - s.extend(StringInreplaceExtension) - - s.sub!("f", "b") - assert_equal "boo", s - - # Under current context, we are testing `String#gsub!`, so let's disable rubocop temporarily. - s.gsub!("o", "e") # rubocop:disable Performance/StringReplacement - assert_equal "bee", s - end - - def test_inreplace_errors - require "tempfile" - extend(Utils::Inreplace) - - file = Tempfile.new("test") - - file.write "a\nb\nc\n" - - assert_raises(Utils::InreplaceError) do - inreplace file.path, "d", "f" - end - - assert_raises(Utils::InreplaceError) do - # Under current context, we are testing `String#gsub!`, so let's disable rubocop temporarily. - inreplace(file.path) { |s| s.gsub!("d", "f") } # rubocop:disable Performance/StringReplacement - end - - assert_raises(Utils::InreplaceError) do - inreplace(file.path) do |s| - s.change_make_var! "VAR", "value" - s.remove_make_var! "VAR2" - end - end - ensure - file.unlink - end -end diff --git a/Library/Homebrew/test/install_test.rb b/Library/Homebrew/test/install_test.rb deleted file mode 100644 index e047c0030..000000000 --- a/Library/Homebrew/test/install_test.rb +++ /dev/null @@ -1,147 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestInstall < IntegrationCommandTestCase - def test_install - setup_test_formula "testball1" - assert_match "Specify `--HEAD`", cmd_fail("install", "testball1", "--head") - assert_match "No head is defined", cmd_fail("install", "testball1", "--HEAD") - assert_match "No devel block", cmd_fail("install", "testball1", "--devel") - assert_match "#{HOMEBREW_CELLAR}/testball1/0.1", cmd("install", "testball1") - assert_match "testball1-0.1 already installed", cmd("install", "testball1") - assert_match "MacRuby is not packaged", cmd_fail("install", "macruby") - assert_match "No available formula", cmd_fail("install", "formula") - assert_match "This similarly named formula was found", - cmd_fail("install", "testball") - - setup_test_formula "testball2" - assert_match "These similarly named formulae were found", - cmd_fail("install", "testball") - - install_and_rename_coretap_formula "testball1", "testball2" - assert_match "testball1 already installed, it's just not migrated", - cmd("install", "testball2") - end - - def test_install_failures - path = setup_test_formula "testball1", "version \"1.0\"" - devel_content = <<-EOS.undent - version "3.0" - devel do - url "#{Formulary.factory("testball1").stable.url}" - sha256 "#{TESTBALL_SHA256}" - version "2.0" - end - EOS - - assert_match "#{HOMEBREW_CELLAR}/testball1/1.0", cmd("install", "testball1") - - FileUtils.rm path - setup_test_formula "testball1", devel_content - - assert_match "first `brew unlink testball1`", cmd_fail("install", "testball1") - assert_match "#{HOMEBREW_CELLAR}/testball1/1.0", cmd("unlink", "testball1") - assert_match "#{HOMEBREW_CELLAR}/testball1/2.0", cmd("install", "testball1", "--devel") - assert_match "#{HOMEBREW_CELLAR}/testball1/2.0", cmd("unlink", "testball1") - assert_match "#{HOMEBREW_CELLAR}/testball1/3.0", cmd("install", "testball1") - - cmd("switch", "testball1", "2.0") - assert_match "already installed, however linked version is", - cmd("install", "testball1") - assert_match "#{HOMEBREW_CELLAR}/testball1/2.0", cmd("unlink", "testball1") - assert_match "just not linked", cmd("install", "testball1") - end - - def test_install_keg_only_outdated - path_keg_only = setup_test_formula "testball1", <<-EOS.undent - version "1.0" - keg_only "test reason" - EOS - - assert_match "#{HOMEBREW_CELLAR}/testball1/1.0", cmd("install", "testball1") - - FileUtils.rm path_keg_only - setup_test_formula "testball1", <<-EOS.undent - version "2.0" - keg_only "test reason" - EOS - - assert_match "keg-only and another version is linked to opt", - cmd("install", "testball1") - - assert_match "#{HOMEBREW_CELLAR}/testball1/2.0", - cmd("install", "testball1", "--force") - end - - def test_install_head_installed - initial_env = ENV.to_hash - %w[AUTHOR COMMITTER].each do |role| - ENV["GIT_#{role}_NAME"] = "brew tests" - ENV["GIT_#{role}_EMAIL"] = "brew-tests@localhost" - ENV["GIT_#{role}_DATE"] = "Thu May 21 00:04:11 2009 +0100" - end - - repo_path = HOMEBREW_CACHE.join("repo") - repo_path.join("bin").mkpath - - repo_path.cd do - shutup do - system "git", "init" - system "git", "remote", "add", "origin", "https://github.com/Homebrew/homebrew-foo" - FileUtils.touch "bin/something.bin" - FileUtils.touch "README" - system "git", "add", "--all" - system "git", "commit", "-m", "Initial repo commit" - end - end - - setup_test_formula "testball1", <<-EOS.undent - version "1.0" - head "file://#{repo_path}", :using => :git - def install - prefix.install Dir["*"] - end - EOS - - # Ignore dependencies, because we'll try to resolve requirements in build.rb - # and there will be the git requirement, but we cannot instantiate git - # formula since we only have testball1 formula. - assert_match "#{HOMEBREW_CELLAR}/testball1/HEAD-2ccdf4f", cmd("install", "testball1", "--HEAD", "--ignore-dependencies") - assert_match "testball1-HEAD-2ccdf4f already installed", - cmd("install", "testball1", "--HEAD", "--ignore-dependencies") - assert_match "#{HOMEBREW_CELLAR}/testball1/HEAD-2ccdf4f", cmd("unlink", "testball1") - assert_match "#{HOMEBREW_CELLAR}/testball1/1.0", cmd("install", "testball1") - - ensure - ENV.replace(initial_env) - repo_path.rmtree - end - - def test_install_with_invalid_option - setup_test_formula "testball1" - assert_match "testball1: this formula has no --with-fo option so it will be ignored!", - cmd("install", "testball1", "--with-fo") - end - - def test_install_with_nonfatal_requirement - setup_test_formula "testball1", <<-EOS.undent - class NonFatalRequirement < Requirement - satisfy { false } - end - depends_on NonFatalRequirement - EOS - message = "NonFatalRequirement unsatisfied!" - assert_equal 1, cmd("install", "testball1").scan(message).size - end - - def test_install_with_fatal_requirement - setup_test_formula "testball1", <<-EOS.undent - class FatalRequirement < Requirement - fatal true - satisfy { false } - end - depends_on FatalRequirement - EOS - message = "FatalRequirement unsatisfied!" - assert_equal 1, cmd_fail("install", "testball1").scan(message).size - end -end diff --git a/Library/Homebrew/test/irb_test.rb b/Library/Homebrew/test/irb_test.rb deleted file mode 100644 index 832ca39a5..000000000 --- a/Library/Homebrew/test/irb_test.rb +++ /dev/null @@ -1,19 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestIrb < IntegrationCommandTestCase - def test_irb - assert_match "'v8'.f # => instance of the v8 formula", - cmd("irb", "--examples") - - setup_test_formula "testball" - - irb_test = HOMEBREW_TEMP/"irb-test.rb" - irb_test.write <<-EOS.undent - "testball".f - :testball.f - exit - EOS - - assert_match "Interactive Homebrew Shell", cmd("irb", irb_test) - end -end diff --git a/Library/Homebrew/test/java_requirement_spec.rb b/Library/Homebrew/test/java_requirement_spec.rb new file mode 100644 index 000000000..5adf64c7c --- /dev/null +++ b/Library/Homebrew/test/java_requirement_spec.rb @@ -0,0 +1,107 @@ +require "requirements/java_requirement" + +describe JavaRequirement do + subject { described_class.new([]) } + + before(:each) do + ENV["JAVA_HOME"] = nil + end + + describe "#message" do + its(:message) { is_expected.to match(/Java is required to install this formula./) } + end + + describe "#inspect" do + subject { described_class.new(%w[1.7+]) } + its(:inspect) { is_expected.to eq('#<JavaRequirement: "java" [] version="1.7+">') } + end + + describe "#display_s" do + context "without specific version" do + its(:display_s) { is_expected.to eq("java") } + 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 + + 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 + + describe "#satisfied?" do + subject { described_class.new(%w[1.8]) } + + it "returns false if no `java` executable can be found" do + allow(File).to receive(:executable?).and_return(false) + expect(subject).not_to be_satisfied + end + + it "returns true if #preferred_java returns a path" do + allow(subject).to receive(:preferred_java).and_return(Pathname.new("/usr/bin/java")) + expect(subject).to be_satisfied + end + + context "when #possible_javas contains paths" do + let(:path) { Pathname.new(Dir.mktmpdir) } + let(:java) { path/"java" } + + def setup_java_with_version(version) + IO.write java, <<-EOS.undent + #!/bin/sh + echo 'java version "#{version}"' + EOS + FileUtils.chmod "+x", java + end + + before(:each) do + allow(subject).to receive(:possible_javas).and_return([java]) + end + + after(:each) do + path.rmtree + end + + context "and 1.7 is required" do + subject { described_class.new(%w[1.7]) } + + it "returns false if all are lower" do + setup_java_with_version "1.6.0_5" + expect(subject).not_to be_satisfied + end + + it "returns true if one is equal" do + setup_java_with_version "1.7.0_5" + expect(subject).to be_satisfied + end + + it "returns false if all are higher" do + setup_java_with_version "1.8.0_5" + expect(subject).not_to be_satisfied + end + end + + context "and 1.7+ is required" do + subject { described_class.new(%w[1.7+]) } + + it "returns false if all are lower" do + setup_java_with_version "1.6.0_5" + expect(subject).not_to be_satisfied + end + + it "returns true if one is equal" do + setup_java_with_version "1.7.0_5" + expect(subject).to be_satisfied + end + + it "returns true if one is higher" do + setup_java_with_version "1.8.0_5" + expect(subject).to be_satisfied + end + end + end + end +end diff --git a/Library/Homebrew/test/json_test.rb b/Library/Homebrew/test/json_test.rb deleted file mode 100644 index 7c4c3671d..000000000 --- a/Library/Homebrew/test/json_test.rb +++ /dev/null @@ -1,20 +0,0 @@ -require "testing_env" -require "json" - -class JsonSmokeTest < Homebrew::TestCase - def test_encode - hash = { "foo" => ["bar", "baz"] } - json = '{"foo":["bar","baz"]}' - assert_equal json, JSON.generate(hash) - end - - def test_decode - hash = { "foo" => ["bar", "baz"], "qux" => 1 } - json = '{"foo":["bar","baz"],"qux":1}' - assert_equal hash, JSON.parse(json) - end - - def test_decode_failure - assert_raises(JSON::ParserError) { JSON.parse("nope") } - end -end diff --git a/Library/Homebrew/test/keg_spec.rb b/Library/Homebrew/test/keg_spec.rb new file mode 100644 index 000000000..f40002dd2 --- /dev/null +++ b/Library/Homebrew/test/keg_spec.rb @@ -0,0 +1,486 @@ +require "keg" +require "stringio" + +describe Keg do + include FileUtils + + def setup_test_keg(name, version) + path = HOMEBREW_CELLAR/name/version + (path/"bin").mkpath + + %w[hiworld helloworld goodbye_cruel_world].each do |file| + touch path/"bin"/file + end + + keg = described_class.new(path) + kegs << keg + keg + end + + around(:each) do |example| + begin + @old_stdout = $stdout + $stdout = StringIO.new + + example.run + ensure + $stdout = @old_stdout + end + end + + let(:dst) { HOMEBREW_PREFIX/"bin"/"helloworld" } + let(:nonexistent) { Pathname.new("/some/nonexistent/path") } + let(:mode) { OpenStruct.new } + let!(:keg) { setup_test_keg("foo", "1.0") } + let(:kegs) { [] } + + before(:each) do + (HOMEBREW_PREFIX/"bin").mkpath + (HOMEBREW_PREFIX/"lib").mkpath + end + + after(:each) do + kegs.each(&:unlink) + rmtree HOMEBREW_PREFIX/"lib" + end + + specify "::all" do + Formula.clear_racks_cache + expect(described_class.all).to eq([keg]) + end + + specify "#empty_installation?" do + %w[.DS_Store INSTALL_RECEIPT.json LICENSE.txt].each do |file| + touch keg/file + end + + expect(keg).to exist + expect(keg).to be_a_directory + expect(keg).not_to be_an_empty_installation + + (keg/"bin").rmtree + expect(keg).to be_an_empty_installation + end + + specify "#oldname_opt_record" do + expect(keg.oldname_opt_record).to be nil + oldname_opt_record = HOMEBREW_PREFIX/"opt/oldfoo" + oldname_opt_record.make_relative_symlink(HOMEBREW_CELLAR/"foo/1.0") + expect(keg.oldname_opt_record).to eq(oldname_opt_record) + end + + specify "#remove_oldname_opt_record" do + oldname_opt_record = HOMEBREW_PREFIX/"opt/oldfoo" + oldname_opt_record.make_relative_symlink(HOMEBREW_CELLAR/"foo/2.0") + keg.remove_oldname_opt_record + expect(oldname_opt_record).to be_a_symlink + oldname_opt_record.unlink + oldname_opt_record.make_relative_symlink(HOMEBREW_CELLAR/"foo/1.0") + keg.remove_oldname_opt_record + expect(oldname_opt_record).not_to be_a_symlink + end + + describe "#link" do + it "links a Keg" do + expect(keg.link).to eq(3) + (HOMEBREW_PREFIX/"bin").children.each do |c| + expect(c.readlink).to be_relative + end + end + + context "with dry run set to true" do + it "only prints what would be done" do + mode.dry_run = true + + expect(keg.link(mode)).to eq(0) + expect(keg).not_to be_linked + + ["hiworld", "helloworld", "goodbye_cruel_world"].each do |file| + expect($stdout.string).to match("#{HOMEBREW_PREFIX}/bin/#{file}") + end + expect($stdout.string.lines.count).to eq(3) + end + end + + it "fails when already linked" do + keg.link + + expect { keg.link }.to raise_error(Keg::AlreadyLinkedError) + end + + it "fails when files exist" do + touch dst + + expect { keg.link }.to raise_error(Keg::ConflictError) + end + + it "ignores broken symlinks at target" do + src = keg/"bin"/"helloworld" + dst.make_symlink(nonexistent) + keg.link + expect(dst.readlink).to eq(src.relative_path_from(dst.dirname)) + end + + context "with overwrite set to true" do + it "overwrite existing files" do + touch dst + mode.overwrite = true + expect(keg.link(mode)).to eq(3) + expect(keg).to be_linked + end + + it "overwrites broken symlinks" do + dst.make_symlink "nowhere" + mode.overwrite = true + expect(keg.link(mode)).to eq(3) + expect(keg).to be_linked + end + + it "still supports dryrun" do + touch dst + mode.overwrite = true + mode.dry_run = true + + expect(keg.link(mode)).to eq(0) + expect(keg).not_to be_linked + + expect($stdout.string).to eq("#{dst}\n") + end + end + + it "also creates an opt link" do + expect(keg).not_to be_optlinked + keg.link + expect(keg).to be_optlinked + end + + specify "pkgconfig directory is created" do + link = HOMEBREW_PREFIX/"lib"/"pkgconfig" + (keg/"lib"/"pkgconfig").mkpath + keg.link + expect(link.lstat).to be_a_directory + end + + specify "cmake directory is created" do + link = HOMEBREW_PREFIX/"lib"/"cmake" + (keg/"lib"/"cmake").mkpath + keg.link + expect(link.lstat).to be_a_directory + end + + specify "symlinks are linked directly" do + link = HOMEBREW_PREFIX/"lib"/"pkgconfig" + + (keg/"lib"/"example").mkpath + (keg/"lib"/"pkgconfig").make_symlink "example" + keg.link + + expect(link.resolved_path).to be_a_symlink + expect(link.lstat).to be_a_symlink + end + end + + describe "#unlink" do + it "unlinks a Keg" do + keg.link + expect(dst).to be_a_symlink + expect(keg.unlink).to eq(3) + expect(dst).not_to be_a_symlink + end + + it "prunes empty top-level directories" do + mkpath HOMEBREW_PREFIX/"lib/foo/bar" + mkpath keg/"lib/foo/bar" + touch keg/"lib/foo/bar/file1" + + keg.unlink + + expect(HOMEBREW_PREFIX/"lib/foo").not_to be_a_directory + end + + it "ignores .DS_Store when pruning empty directories" do + mkpath HOMEBREW_PREFIX/"lib/foo/bar" + touch HOMEBREW_PREFIX/"lib/foo/.DS_Store" + mkpath keg/"lib/foo/bar" + touch keg/"lib/foo/bar/file1" + + keg.unlink + + expect(HOMEBREW_PREFIX/"lib/foo").not_to be_a_directory + expect(HOMEBREW_PREFIX/"lib/foo/.DS_Store").not_to exist + end + + it "doesn't remove opt link" do + keg.link + keg.unlink + expect(keg).to be_optlinked + end + + it "preverves broken symlinks pointing outside the Keg" do + keg.link + dst.delete + dst.make_symlink(nonexistent) + keg.unlink + expect(dst).to be_a_symlink + end + + it "preverves broken symlinks pointing into the Keg" do + keg.link + dst.resolved_path.delete + keg.unlink + expect(dst).to be_a_symlink + end + + it "preverves symlinks pointing outside the Keg" do + keg.link + dst.delete + dst.make_symlink(Pathname.new("/bin/sh")) + keg.unlink + expect(dst).to be_a_symlink + end + + it "preserves real files" do + keg.link + dst.delete + touch dst + keg.unlink + expect(dst).to be_a_file + end + + it "ignores nonexistent file" do + keg.link + dst.delete + expect(keg.unlink).to eq(2) + end + + it "doesn't remove links to symlinks" do + a = HOMEBREW_CELLAR/"a"/"1.0" + b = HOMEBREW_CELLAR/"b"/"1.0" + + (a/"lib"/"example").mkpath + (a/"lib"/"example2").make_symlink "example" + (b/"lib"/"example2").mkpath + + a = described_class.new(a) + b = described_class.new(b) + a.link + + lib = HOMEBREW_PREFIX/"lib" + expect(lib.children.length).to eq(2) + expect { b.link }.to raise_error(Keg::ConflictError) + expect(lib.children.length).to eq(2) + end + + it "removes broken symlinks that conflict with directories" do + a = HOMEBREW_CELLAR/"a"/"1.0" + (a/"lib"/"foo").mkpath + + keg = described_class.new(a) + + link = HOMEBREW_PREFIX/"lib"/"foo" + link.parent.mkpath + link.make_symlink(nonexistent) + + keg.link + end + end + + describe "#optlink" do + it "creates an opt link" do + oldname_opt_record = HOMEBREW_PREFIX/"opt/oldfoo" + oldname_opt_record.make_relative_symlink(HOMEBREW_CELLAR/"foo/1.0") + keg_record = HOMEBREW_CELLAR/"foo"/"2.0" + (keg_record/"bin").mkpath + keg = described_class.new(keg_record) + keg.optlink + expect(keg_record).to eq(oldname_opt_record.resolved_path) + keg.uninstall + expect(oldname_opt_record).not_to be_a_symlink + end + + it "doesn't fail if already opt-linked" do + keg.opt_record.make_relative_symlink Pathname.new(keg) + keg.optlink + expect(keg).to be_optlinked + end + + it "replaces an existing directory" do + keg.opt_record.mkpath + keg.optlink + expect(keg).to be_optlinked + end + + it "replaces an existing file" do + keg.opt_record.parent.mkpath + keg.opt_record.write("foo") + keg.optlink + expect(keg).to be_optlinked + end + end + + specify "#link and #unlink" do + expect(keg).not_to be_linked + keg.link + expect(keg).to be_linked + keg.unlink + expect(keg).not_to be_linked + end + + describe "::find_some_installed_dependents" do + def stub_formula_name(name) + f = formula(name) { url "foo-1.0" } + stub_formula_loader f + stub_formula_loader f, "homebrew/core/#{f}" + f + end + + def setup_test_keg(name, version) + f = stub_formula_name(name) + keg = super + Tab.create(f, DevelopmentTools.default_compiler, :libcxx).write + keg + end + + before(:each) do + keg.link + end + + def alter_tab(keg = dependent) + tab = Tab.for_keg(keg) + yield tab + tab.write + end + + # 1.1.6 is the earliest version of Homebrew that generates correct runtime + # dependency lists in Tabs. + def dependencies(deps, homebrew_version: "1.1.6") + alter_tab do |tab| + tab.homebrew_version = homebrew_version + tab.tabfile = dependent/Tab::FILENAME + tab.runtime_dependencies = deps + end + end + + def unreliable_dependencies(deps) + # 1.1.5 is (hopefully!) the last version of Homebrew that generates + # incorrect runtime dependency lists in Tabs. + dependencies(deps, homebrew_version: "1.1.5") + end + + 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") + + alter_tab(keg) { |t| t.source["tap"] = nil } + + dependencies nil + Formula["bar"].class.depends_on "foo" + Formula["bar"].class.depends_on "baz" + + result = described_class.find_some_installed_dependents([keg, tap_dep]) + expect(result).to eq([[keg, tap_dep], ["bar"]]) + end + + 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 + + specify "renamed dependency" do + dependencies nil + + stub_formula_loader Formula["foo"], "homebrew/core/foo-old" + renamed_path = HOMEBREW_CELLAR/"foo-old" + (HOMEBREW_CELLAR/"foo").rename(renamed_path) + renamed_keg = described_class.new(renamed_path/"1.0") + + Formula["bar"].class.depends_on "foo" + + result = described_class.find_some_installed_dependents([renamed_keg]) + expect(result).to eq([[renamed_keg], ["bar"]]) + end + + 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"]]) + 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"]]) + 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 + + specify "keg-only" 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"]]) + end + end +end diff --git a/Library/Homebrew/test/keg_test.rb b/Library/Homebrew/test/keg_test.rb deleted file mode 100644 index 40b47b5e9..000000000 --- a/Library/Homebrew/test/keg_test.rb +++ /dev/null @@ -1,484 +0,0 @@ -require "testing_env" -require "keg" -require "stringio" - -class LinkTestCase < Homebrew::TestCase - include FileUtils - - def setup_test_keg(name, version) - path = HOMEBREW_CELLAR.join(name, version) - path.join("bin").mkpath - - %w[hiworld helloworld goodbye_cruel_world].each do |file| - touch path.join("bin", file) - end - - keg = Keg.new(path) - @kegs ||= [] - @kegs << keg - keg - end - - def setup - @keg = setup_test_keg("foo", "1.0") - @dst = HOMEBREW_PREFIX.join("bin", "helloworld") - @nonexistent = Pathname.new("/some/nonexistent/path") - - @mode = OpenStruct.new - - @old_stdout = $stdout - $stdout = StringIO.new - - mkpath HOMEBREW_PREFIX/"bin" - mkpath HOMEBREW_PREFIX/"lib" - end - - def teardown - @kegs.each do |keg| - keg.unlink - keg.uninstall - end - - $stdout = @old_stdout - - rmtree HOMEBREW_PREFIX/"bin" - rmtree HOMEBREW_PREFIX/"lib" - end -end - -class LinkTests < LinkTestCase - def test_all - Formula.clear_racks_cache - assert_equal [@keg], Keg.all - end - - def test_empty_installation - %w[.DS_Store INSTALL_RECEIPT.json LICENSE.txt].each do |file| - touch @keg/file - end - assert_predicate @keg, :exist? - assert_predicate @keg, :directory? - refute_predicate @keg, :empty_installation? - - (@keg/"bin").rmtree - assert_predicate @keg, :empty_installation? - end - - def test_linking_keg - assert_equal 3, @keg.link - (HOMEBREW_PREFIX/"bin").children.each { |c| assert_predicate c.readlink, :relative? } - end - - def test_unlinking_keg - @keg.link - assert_predicate @dst, :symlink? - assert_equal 3, @keg.unlink - refute_predicate @dst, :symlink? - end - - def test_oldname_opt_record - assert_nil @keg.oldname_opt_record - oldname_opt_record = HOMEBREW_PREFIX/"opt/oldfoo" - oldname_opt_record.make_relative_symlink(HOMEBREW_CELLAR/"foo/1.0") - assert_equal oldname_opt_record, @keg.oldname_opt_record - end - - def test_optlink_relink - oldname_opt_record = HOMEBREW_PREFIX/"opt/oldfoo" - oldname_opt_record.make_relative_symlink(HOMEBREW_CELLAR/"foo/1.0") - keg_record = HOMEBREW_CELLAR.join("foo", "2.0") - keg_record.join("bin").mkpath - keg = Keg.new(keg_record) - keg.optlink - assert_equal keg_record, oldname_opt_record.resolved_path - keg.uninstall - refute_predicate oldname_opt_record, :symlink? - end - - def test_remove_oldname_opt_record - oldname_opt_record = HOMEBREW_PREFIX/"opt/oldfoo" - oldname_opt_record.make_relative_symlink(HOMEBREW_CELLAR/"foo/2.0") - @keg.remove_oldname_opt_record - assert_predicate oldname_opt_record, :symlink? - oldname_opt_record.unlink - oldname_opt_record.make_relative_symlink(HOMEBREW_CELLAR/"foo/1.0") - @keg.remove_oldname_opt_record - refute_predicate oldname_opt_record, :symlink? - end - - def test_link_dry_run - @mode.dry_run = true - - assert_equal 0, @keg.link(@mode) - refute_predicate @keg, :linked? - - ["hiworld", "helloworld", "goodbye_cruel_world"].each do |file| - assert_match "#{HOMEBREW_PREFIX}/bin/#{file}", $stdout.string - end - assert_equal 3, $stdout.string.lines.count - end - - def test_linking_fails_when_already_linked - @keg.link - assert_raises(Keg::AlreadyLinkedError) { @keg.link } - end - - def test_linking_fails_when_files_exist - touch @dst - assert_raises(Keg::ConflictError) { @keg.link } - end - - def test_link_ignores_broken_symlinks_at_target - src = @keg.join("bin", "helloworld") - @dst.make_symlink(@nonexistent) - @keg.link - assert_equal src.relative_path_from(@dst.dirname), @dst.readlink - end - - def test_link_overwrite - touch @dst - @mode.overwrite = true - assert_equal 3, @keg.link(@mode) - assert_predicate @keg, :linked? - end - - def test_link_overwrite_broken_symlinks - @dst.make_symlink "nowhere" - @mode.overwrite = true - assert_equal 3, @keg.link(@mode) - assert_predicate @keg, :linked? - end - - def test_link_overwrite_dryrun - touch @dst - @mode.overwrite = true - @mode.dry_run = true - - assert_equal 0, @keg.link(@mode) - refute_predicate @keg, :linked? - - assert_equal "#{@dst}\n", $stdout.string - end - - def test_unlink_prunes_empty_toplevel_directories - mkpath HOMEBREW_PREFIX/"lib/foo/bar" - mkpath @keg/"lib/foo/bar" - touch @keg/"lib/foo/bar/file1" - - @keg.unlink - - refute_predicate HOMEBREW_PREFIX/"lib/foo", :directory? - end - - def test_unlink_ignores_ds_store_when_pruning_empty_dirs - mkpath HOMEBREW_PREFIX/"lib/foo/bar" - touch HOMEBREW_PREFIX/"lib/foo/.DS_Store" - mkpath @keg/"lib/foo/bar" - touch @keg/"lib/foo/bar/file1" - - @keg.unlink - - refute_predicate HOMEBREW_PREFIX/"lib/foo", :directory? - refute_predicate HOMEBREW_PREFIX/"lib/foo/.DS_Store", :exist? - end - - def test_linking_creates_opt_link - refute_predicate @keg, :optlinked? - @keg.link - assert_predicate @keg, :optlinked? - end - - def test_unlinking_does_not_remove_opt_link - @keg.link - @keg.unlink - assert_predicate @keg, :optlinked? - end - - def test_existing_opt_link - @keg.opt_record.make_relative_symlink Pathname.new(@keg) - @keg.optlink - assert_predicate @keg, :optlinked? - end - - def test_existing_opt_link_directory - @keg.opt_record.mkpath - @keg.optlink - assert_predicate @keg, :optlinked? - end - - def test_existing_opt_link_file - @keg.opt_record.parent.mkpath - @keg.opt_record.write("foo") - @keg.optlink - assert_predicate @keg, :optlinked? - end - - def test_linked_keg - refute_predicate @keg, :linked? - @keg.link - assert_predicate @keg, :linked? - @keg.unlink - refute_predicate @keg, :linked? - end - - def test_unlink_preserves_broken_symlink_pointing_outside_the_keg - @keg.link - @dst.delete - @dst.make_symlink(@nonexistent) - @keg.unlink - assert_predicate @dst, :symlink? - end - - def test_unlink_preserves_broken_symlink_pointing_into_the_keg - @keg.link - @dst.resolved_path.delete - @keg.unlink - assert_predicate @dst, :symlink? - end - - def test_unlink_preserves_symlink_pointing_outside_of_keg - @keg.link - @dst.delete - @dst.make_symlink(Pathname.new("/bin/sh")) - @keg.unlink - assert_predicate @dst, :symlink? - end - - def test_unlink_preserves_real_file - @keg.link - @dst.delete - touch @dst - @keg.unlink - assert_predicate @dst, :file? - end - - def test_unlink_ignores_nonexistent_file - @keg.link - @dst.delete - assert_equal 2, @keg.unlink - end - - def test_pkgconfig_is_mkpathed - link = HOMEBREW_PREFIX.join("lib", "pkgconfig") - @keg.join("lib", "pkgconfig").mkpath - @keg.link - assert_predicate link.lstat, :directory? - end - - def test_cmake_is_mkpathed - link = HOMEBREW_PREFIX.join("lib", "cmake") - @keg.join("lib", "cmake").mkpath - @keg.link - assert_predicate link.lstat, :directory? - end - - def test_symlinks_are_linked_directly - link = HOMEBREW_PREFIX.join("lib", "pkgconfig") - - @keg.join("lib", "example").mkpath - @keg.join("lib", "pkgconfig").make_symlink "example" - @keg.link - - assert_predicate link.resolved_path, :symlink? - assert_predicate link.lstat, :symlink? - end - - def test_links_to_symlinks_are_not_removed - a = HOMEBREW_CELLAR.join("a", "1.0") - b = HOMEBREW_CELLAR.join("b", "1.0") - - a.join("lib", "example").mkpath - a.join("lib", "example2").make_symlink "example" - b.join("lib", "example2").mkpath - - a = Keg.new(a) - b = Keg.new(b) - a.link - - lib = HOMEBREW_PREFIX.join("lib") - assert_equal 2, lib.children.length - assert_raises(Keg::ConflictError) { b.link } - assert_equal 2, lib.children.length - ensure - a.unlink - a.uninstall - b.uninstall - end - - def test_removes_broken_symlinks_that_conflict_with_directories - a = HOMEBREW_CELLAR.join("a", "1.0") - a.join("lib", "foo").mkpath - - keg = Keg.new(a) - - link = HOMEBREW_PREFIX.join("lib", "foo") - link.parent.mkpath - link.make_symlink(@nonexistent) - - keg.link - ensure - keg.unlink - keg.uninstall - end -end - -class InstalledDependantsTests < LinkTestCase - def stub_formula_name(name) - f = formula(name) { url "foo-1.0" } - stub_formula_loader f - stub_formula_loader f, "homebrew/core/#{f}" - f - end - - def setup_test_keg(name, version) - f = stub_formula_name(name) - keg = super - Tab.create(f, DevelopmentTools.default_compiler, :libcxx).write - keg - end - - def setup - super - @dependent = setup_test_keg("bar", "1.0") - @keg.link - end - - def alter_tab(keg = @dependent) - tab = Tab.for_keg(keg) - yield tab - tab.write - end - - # 1.1.6 is the earliest version of Homebrew that generates correct runtime - # dependency lists in tabs. - def dependencies(deps, homebrew_version: "1.1.6") - alter_tab do |tab| - tab.homebrew_version = homebrew_version - tab.tabfile = @dependent.join("INSTALL_RECEIPT.json") - tab.runtime_dependencies = deps - end - end - - def unreliable_dependencies(deps) - # 1.1.5 is (hopefully!) the last version of Homebrew that generates - # incorrect runtime dependency lists in tabs. - dependencies(deps, homebrew_version: "1.1.5") - end - - # 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. - def test_unknown_formula - Formulary.unstub(:loader_for) - alter_tab(@keg) do |t| - t.source["tap"] = "some/tap" - t.source["path"] = nil - end - - dependencies [{ "full_name" => "some/tap/foo", "version" => "1.0" }] - assert_equal [@dependent], @keg.installed_dependents - assert_equal [[@keg], ["bar 1.0"]], Keg.find_some_installed_dependents([@keg]) - - dependencies nil - # It doesn't make sense for a keg with no formula to have any dependents, - # so that can't really be tested. - assert_nil Keg.find_some_installed_dependents([@keg]) - end - - def test_a_dependency_with_no_tap_in_tab - @tap_dep = setup_test_keg("baz", "1.0") - - alter_tab(@keg) { |t| t.source["tap"] = nil } - - dependencies nil - Formula["bar"].class.depends_on "foo" - Formula["bar"].class.depends_on "baz" - - result = Keg.find_some_installed_dependents([@keg, @tap_dep]) - assert_equal [[@keg, @tap_dep], ["bar"]], result - end - - def test_no_dependencies_anywhere - dependencies nil - assert_empty @keg.installed_dependents - assert_nil Keg.find_some_installed_dependents([@keg]) - end - - def test_missing_formula_dependency - dependencies nil - Formula["bar"].class.depends_on "foo" - assert_empty @keg.installed_dependents - assert_equal [[@keg], ["bar"]], Keg.find_some_installed_dependents([@keg]) - end - - def test_uninstalling_dependent_and_dependency - dependencies nil - Formula["bar"].class.depends_on "foo" - assert_empty @keg.installed_dependents - assert_nil Keg.find_some_installed_dependents([@keg, @dependent]) - end - - def test_renamed_dependency - dependencies nil - - stub_formula_loader Formula["foo"], "homebrew/core/foo-old" - renamed_path = HOMEBREW_CELLAR/"foo-old" - (HOMEBREW_CELLAR/"foo").rename(renamed_path) - renamed_keg = Keg.new(renamed_path.join("1.0")) - - Formula["bar"].class.depends_on "foo" - - result = Keg.find_some_installed_dependents([renamed_keg]) - assert_equal [[renamed_keg], ["bar"]], result - ensure - # Move it back to where it was so it'll be cleaned up. - (HOMEBREW_CELLAR/"foo-old").rename(HOMEBREW_CELLAR/"foo") - end - - def test_empty_dependencies_in_tab - dependencies [] - assert_empty @keg.installed_dependents - assert_nil Keg.find_some_installed_dependents([@keg]) - end - - def test_same_name_different_version_in_tab - dependencies [{ "full_name" => "foo", "version" => "1.1" }] - assert_equal [@dependent], @keg.installed_dependents - assert_equal [[@keg], ["bar 1.0"]], Keg.find_some_installed_dependents([@keg]) - end - - def test_different_name_same_version_in_tab - stub_formula_name("baz") - dependencies [{ "full_name" => "baz", "version" => @keg.version.to_s }] - assert_empty @keg.installed_dependents - assert_nil Keg.find_some_installed_dependents([@keg]) - end - - def test_same_name_and_version_in_tab - dependencies [{ "full_name" => "foo", "version" => "1.0" }] - assert_equal [@dependent], @keg.installed_dependents - assert_equal [[@keg], ["bar 1.0"]], Keg.find_some_installed_dependents([@keg]) - end - - def test_fallback_for_old_versions - unreliable_dependencies [{ "full_name" => "baz", "version" => "1.0" }] - Formula["bar"].class.depends_on "foo" - assert_empty @keg.installed_dependents - assert_equal [[@keg], ["bar"]], Keg.find_some_installed_dependents([@keg]) - end - - def test_nonoptlinked - @keg.remove_opt_record - dependencies [{ "full_name" => "foo", "version" => "1.0" }] - assert_empty @keg.installed_dependents - assert_nil Keg.find_some_installed_dependents([@keg]) - end - - def test_keg_only - @keg.unlink - Formula["foo"].class.keg_only "a good reason" - dependencies [{ "full_name" => "foo", "version" => "1.1" }] # different version - assert_equal [@dependent], @keg.installed_dependents - assert_equal [[@keg], ["bar 1.0"]], Keg.find_some_installed_dependents([@keg]) - end -end diff --git a/Library/Homebrew/test/language/go_spec.rb b/Library/Homebrew/test/language/go_spec.rb new file mode 100644 index 000000000..24db78594 --- /dev/null +++ b/Library/Homebrew/test/language/go_spec.rb @@ -0,0 +1,15 @@ +require "language/go" + +describe Language::Go do + specify "#stage_deps" do + ENV.delete("HOMEBREW_DEVELOPER") + + expect(described_class).to receive(:opoo).once + + Dir.mktmpdir do |path| + shutup do + described_class.stage_deps [], path + end + end + end +end diff --git a/Library/Homebrew/test/language/python_spec.rb b/Library/Homebrew/test/language/python_spec.rb new file mode 100644 index 000000000..c78520897 --- /dev/null +++ b/Library/Homebrew/test/language/python_spec.rb @@ -0,0 +1,106 @@ +require "language/python" +require "resource" + +describe Language::Python::Virtualenv::Virtualenv do + subject { described_class.new(formula, dir, "python") } + + let(:dir) { @dir = Pathname.new(Dir.mktmpdir) } + + let(:resource) { double("resource", stage: true) } + let(:formula_bin) { dir/"formula_bin" } + let(:formula) { double("formula", resource: resource, bin: formula_bin) } + + after(:each) { dir.rmtree unless @dir.nil? } + + describe "#create" do + it "creates a virtual environment" do + expect(formula).to receive(:resource).with("homebrew-virtualenv").and_return(resource) + subject.create + end + + specify "virtual environment creation is idempotent" do + expect(formula).to receive(:resource).with("homebrew-virtualenv").and_return(resource) + subject.create + FileUtils.mkdir_p dir/"bin" + FileUtils.touch dir/"bin/python" + subject.create + FileUtils.rm dir/"bin/python" + end + end + + describe "#pip_install" do + it "accepts a string" do + expect(formula).to receive(:system) + .with(dir/"bin/pip", "install", "-v", "--no-deps", + "--no-binary", ":all:", "--ignore-installed", "foo") + .and_return(true) + subject.pip_install "foo" + end + + it "accepts a multi-line strings" do + expect(formula).to receive(:system) + .with(dir/"bin/pip", "install", "-v", "--no-deps", + "--no-binary", ":all:", "--ignore-installed", "foo", "bar") + .and_return(true) + + subject.pip_install <<-EOS.undent + foo + bar + EOS + end + + it "accepts an array" do + expect(formula).to receive(:system) + .with(dir/"bin/pip", "install", "-v", "--no-deps", + "--no-binary", ":all:", "--ignore-installed", "foo") + .and_return(true) + + expect(formula).to receive(:system) + .with(dir/"bin/pip", "install", "-v", "--no-deps", + "--no-binary", ":all:", "--ignore-installed", "bar") + .and_return(true) + + subject.pip_install ["foo", "bar"] + end + + it "accepts a Resource" do + res = Resource.new("test") + + expect(res).to receive(:stage).and_yield + expect(formula).to receive(:system) + .with(dir/"bin/pip", "install", "-v", "--no-deps", + "--no-binary", ":all:", "--ignore-installed", Pathname.pwd) + .and_return(true) + + subject.pip_install res + end + end + + describe "#pip_install_and_link" do + let(:src_bin) { dir/"bin" } + let(:dest_bin) { formula.bin } + + it "can link scripts" do + src_bin.mkpath + + expect(src_bin/"kilroy").not_to exist + expect(dest_bin/"kilroy").not_to exist + + FileUtils.touch src_bin/"irrelevant" + bin_before = Dir.glob(src_bin/"*") + FileUtils.touch src_bin/"kilroy" + bin_after = Dir.glob(src_bin/"*") + + expect(subject).to receive(:pip_install).with("foo") + expect(Dir).to receive(:[]).with(src_bin/"*").twice.and_return(bin_before, bin_after) + + subject.pip_install_and_link "foo" + + expect(src_bin/"kilroy").to exist + expect(dest_bin/"kilroy").to exist + expect(dest_bin/"kilroy").to be_a_symlink + expect((src_bin/"kilroy").realpath).to eq((dest_bin/"kilroy").realpath) + expect(dest_bin/"irrelevant").not_to exist + end + end +end diff --git a/Library/Homebrew/test/language_go_test.rb b/Library/Homebrew/test/language_go_test.rb deleted file mode 100644 index 692a5d2cc..000000000 --- a/Library/Homebrew/test/language_go_test.rb +++ /dev/null @@ -1,17 +0,0 @@ -# -*- coding: UTF-8 -*- - -require "testing_env" -require "language/go" - -class LanguageGoTests < Homebrew::TestCase - def test_stage_deps_empty - if ARGV.homebrew_developer? - Language::Go.expects(:odie).once - else - Language::Go.expects(:opoo).once - end - mktmpdir do |path| - shutup { Language::Go.stage_deps [], path } - end - end -end diff --git a/Library/Homebrew/test/language_module_requirement_spec.rb b/Library/Homebrew/test/language_module_requirement_spec.rb new file mode 100644 index 000000000..7f2666855 --- /dev/null +++ b/Library/Homebrew/test/language_module_requirement_spec.rb @@ -0,0 +1,49 @@ +require "requirements/language_module_requirement" + +describe LanguageModuleRequirement do + specify "unique dependencies are not equal" do + x = described_class.new(:node, "less") + y = described_class.new(:node, "coffee-script") + expect(x).not_to eq(y) + expect(x.hash).not_to eq(y.hash) + end + + 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" } + + its(:message) { is_expected.to include(mod_name) } + its(:the_test) { is_expected.to include("import #{import_name}") } + end + + context "when the language is Perl" do + it "does not satisfy invalid dependencies" do + expect(described_class.new(:perl, "notapackage")).not_to be_satisfied + end + + it "satisfies valid dependencies" do + expect(described_class.new(:perl, "Env")).to be_satisfied + end + end + + context "when the language is Python", :needs_python do + it "does not satisfy invalid dependencies" do + expect(described_class.new(:python, "notapackage")).not_to be_satisfied + end + + it "satisfies valid dependencies" do + expect(described_class.new(:python, "datetime")).to be_satisfied + end + end + + context "when the language is Ruby" do + it "does not satisfy invalid dependencies" do + expect(described_class.new(:ruby, "notapackage")).not_to be_satisfied + end + + it "satisfies valid dependencies" do + expect(described_class.new(:ruby, "date")).to be_satisfied + end + end +end diff --git a/Library/Homebrew/test/language_module_requirement_test.rb b/Library/Homebrew/test/language_module_requirement_test.rb deleted file mode 100644 index dfa992287..000000000 --- a/Library/Homebrew/test/language_module_requirement_test.rb +++ /dev/null @@ -1,55 +0,0 @@ -require "testing_env" -require "requirements/language_module_requirement" - -class LanguageModuleRequirementTests < Homebrew::TestCase - parallelize_me! - - def assert_deps_fail(spec) - refute_predicate LanguageModuleRequirement.new(*spec.shift.reverse), :satisfied? - end - - def assert_deps_pass(spec) - assert_predicate LanguageModuleRequirement.new(*spec.shift.reverse), :satisfied? - end - - def test_unique_deps_are_not_eql - x = LanguageModuleRequirement.new(:node, "less") - y = LanguageModuleRequirement.new(:node, "coffee-script") - refute_eql x, y - refute_equal x.hash, y.hash - end - - def test_differing_module_and_import_name - mod_name = "foo" - import_name = "bar" - l = LanguageModuleRequirement.new(:python, mod_name, import_name) - assert_includes l.message, mod_name - assert_includes l.the_test, "import #{import_name}" - end - - def test_bad_perl_deps - assert_deps_fail "notapackage" => :perl - end - - def test_good_perl_deps - assert_deps_pass "Env" => :perl - end - - def test_bad_python_deps - needs_python - assert_deps_fail "notapackage" => :python - end - - def test_good_python_deps - needs_python - assert_deps_pass "datetime" => :python - end - - def test_bad_ruby_deps - assert_deps_fail "notapackage" => :ruby - end - - def test_good_ruby_deps - assert_deps_pass "date" => :ruby - end -end diff --git a/Library/Homebrew/test/language_python_test.rb b/Library/Homebrew/test/language_python_test.rb deleted file mode 100644 index d1e3867f7..000000000 --- a/Library/Homebrew/test/language_python_test.rb +++ /dev/null @@ -1,99 +0,0 @@ -require "testing_env" -require "language/python" -require "resource" - -class LanguagePythonTests < Homebrew::TestCase - def setup - @dir = Pathname.new(mktmpdir) - resource = stub("resource", stage: true) - formula_bin = @dir/"formula_bin" - @formula = mock("formula") do - stubs(:resource).returns(resource) - stubs(:bin).returns(formula_bin) - end - @venv = Language::Python::Virtualenv::Virtualenv.new(@formula, @dir, "python") - end - - def teardown - FileUtils.rm_rf @dir - end - - def test_virtualenv_creation - @formula.expects(:resource).with("homebrew-virtualenv").returns( - mock("resource", stage: true) - ) - @venv.create - end - - # or at least doesn't crash the second time - def test_virtualenv_creation_is_idempotent - @formula.expects(:resource).with("homebrew-virtualenv").returns( - mock("resource", stage: true) - ) - @venv.create - FileUtils.mkdir_p @dir/"bin" - FileUtils.touch @dir/"bin/python" - @venv.create - FileUtils.rm @dir/"bin/python" - end - - def test_pip_install_accepts_string - @formula.expects(:system).returns(true).with do |*params| - params.first == @dir/"bin/pip" && params.last == "foo" - end - @venv.pip_install "foo" - end - - def test_pip_install_accepts_multiline_string - @formula.expects(:system).returns(true).with do |*params| - params.first == @dir/"bin/pip" && params[-2..-1] == ["foo", "bar"] - end - @venv.pip_install <<-EOS.undent - foo - bar - EOS - end - - def test_pip_install_accepts_array - @formula.expects(:system).returns(true).with do |*params| - params.first == @dir/"bin/pip" && params.last == "foo" - end - @formula.expects(:system).returns(true).with do |*params| - params.first == @dir/"bin/pip" && params.last == "bar" - end - @venv.pip_install ["foo", "bar"] - end - - def test_pip_install_accepts_resource - res = Resource.new "test" - res.expects(:stage).yields(nil) - @formula.expects(:system).returns(true).with do |*params| - params.first == @dir/"bin/pip" && params.last == Pathname.pwd - end - @venv.pip_install res - end - - def test_pip_install_and_link_links_scripts - bin = @dir/"bin" - bin.mkpath - dest = @formula.bin - - refute_predicate bin/"kilroy", :exist? - refute_predicate dest/"kilroy", :exist? - - FileUtils.touch bin/"irrelevant" - bin_before = Dir[bin/"*"] - FileUtils.touch bin/"kilroy" - bin_after = Dir[bin/"*"] - @venv.expects(:pip_install).with("foo") - Dir.expects(:[]).twice.returns(bin_before, bin_after) - - @venv.pip_install_and_link "foo" - - assert_predicate bin/"kilroy", :exist? - assert_predicate dest/"kilroy", :exist? - assert_predicate dest/"kilroy", :symlink? - assert_equal((bin/"kilroy").realpath, (dest/"kilroy").realpath) - refute_predicate dest/"irrelevant", :exist? - end -end diff --git a/Library/Homebrew/test/leaves_test.rb b/Library/Homebrew/test/leaves_test.rb deleted file mode 100644 index f73fba1ea..000000000 --- a/Library/Homebrew/test/leaves_test.rb +++ /dev/null @@ -1,15 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestLeaves < IntegrationCommandTestCase - def test_leaves - setup_test_formula "foo" - setup_test_formula "bar" - assert_equal "", cmd("leaves") - - (HOMEBREW_CELLAR/"foo/0.1/somedir").mkpath - assert_equal "foo", cmd("leaves") - - (HOMEBREW_CELLAR/"bar/0.1/somedir").mkpath - assert_equal "bar", cmd("leaves") - end -end diff --git a/Library/Homebrew/test/link_test.rb b/Library/Homebrew/test/link_test.rb deleted file mode 100644 index 062caa0c0..000000000 --- a/Library/Homebrew/test/link_test.rb +++ /dev/null @@ -1,23 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestLink < IntegrationCommandTestCase - def test_link - assert_match "This command requires a keg argument", cmd_fail("link") - - setup_test_formula "testball1" - cmd("install", "testball1") - cmd("link", "testball1") - - cmd("unlink", "testball1") - assert_match "Would link", cmd("link", "--dry-run", "testball1") - assert_match "Would remove", - cmd("link", "--dry-run", "--overwrite", "testball1") - assert_match "Linking", cmd("link", "testball1") - - setup_test_formula "testball2", <<-EOS.undent - keg_only "just because" - EOS - cmd("install", "testball2") - assert_match "testball2 is keg-only", cmd("link", "testball2") - end -end diff --git a/Library/Homebrew/test/linkapps_test.rb b/Library/Homebrew/test/linkapps_test.rb deleted file mode 100644 index 4c5b8ec13..000000000 --- a/Library/Homebrew/test/linkapps_test.rb +++ /dev/null @@ -1,15 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestLinkapps < IntegrationCommandTestCase - def test_linkapps - home_dir = Pathname.new(mktmpdir) - (home_dir/"Applications").mkpath - - setup_test_formula "testball" - - source_dir = HOMEBREW_CELLAR/"testball/0.1/TestBall.app" - source_dir.mkpath - assert_match "Linking: #{source_dir}", - cmd("linkapps", "--local", "HOME" => home_dir) - end -end diff --git a/Library/Homebrew/test/list_test.rb b/Library/Homebrew/test/list_test.rb deleted file mode 100644 index 3c691e3ad..000000000 --- a/Library/Homebrew/test/list_test.rb +++ /dev/null @@ -1,13 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestList < IntegrationCommandTestCase - def test_list - formulae = %w[bar foo qux] - formulae.each do |f| - (HOMEBREW_CELLAR/"#{f}/1.0/somedir").mkpath - end - - assert_equal formulae.join("\n"), - cmd("list") - end -end diff --git a/Library/Homebrew/test/log_formula_test.rb b/Library/Homebrew/test/log_formula_test.rb deleted file mode 100644 index bb6a1f661..000000000 --- a/Library/Homebrew/test/log_formula_test.rb +++ /dev/null @@ -1,27 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestLogFormula < IntegrationCommandTestCase - def test_log_formula - core_tap = CoreTap.new - setup_test_formula "testball" - - core_tap.path.cd do - shutup do - system "git", "init" - system "git", "add", "--all" - system "git", "commit", "-m", "This is a test commit for Testball" - end - end - - core_tap_url = "file://#{core_tap.path}" - shallow_tap = Tap.fetch("homebrew", "shallow") - shutup do - system "git", "clone", "--depth=1", core_tap_url, shallow_tap.path - end - - assert_match "This is a test commit for Testball", - cmd("log", "#{shallow_tap}/testball") - assert_predicate shallow_tap.path/".git/shallow", :exist?, - "A shallow clone should have been created." - end -end diff --git a/Library/Homebrew/test/log_test.rb b/Library/Homebrew/test/log_test.rb deleted file mode 100644 index b2e150ccd..000000000 --- a/Library/Homebrew/test/log_test.rb +++ /dev/null @@ -1,13 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestLog < IntegrationCommandTestCase - def test_log - FileUtils.cd HOMEBREW_REPOSITORY do - shutup do - system "git", "init" - system "git", "commit", "--allow-empty", "-m", "This is a test commit" - end - end - assert_match "This is a test commit", cmd("log") - end -end diff --git a/Library/Homebrew/test/migrate_test.rb b/Library/Homebrew/test/migrate_test.rb deleted file mode 100644 index 17929d038..000000000 --- a/Library/Homebrew/test/migrate_test.rb +++ /dev/null @@ -1,18 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestMigrate < IntegrationCommandTestCase - def test_migrate - setup_test_formula "testball1" - setup_test_formula "testball2" - assert_match "Invalid usage", cmd_fail("migrate") - assert_match "No available formula with the name \"testball\"", - cmd_fail("migrate", "testball") - assert_match "testball1 doesn't replace any formula", - cmd_fail("migrate", "testball1") - - install_and_rename_coretap_formula "testball1", "testball2" - assert_match "Migrating testball1 to testball2", cmd("migrate", "testball1") - (HOMEBREW_CELLAR/"testball1").unlink - assert_match "Error: No such keg", cmd_fail("migrate", "testball1") - end -end diff --git a/Library/Homebrew/test/migrator_spec.rb b/Library/Homebrew/test/migrator_spec.rb new file mode 100644 index 000000000..90ee9d8ff --- /dev/null +++ b/Library/Homebrew/test/migrator_spec.rb @@ -0,0 +1,264 @@ +require "migrator" +require "test/support/fixtures/testball" +require "tab" +require "keg" + +describe Migrator do + subject { described_class.new(new_formula) } + + let(:new_formula) { Testball.new("newname") } + let(:old_formula) { Testball.new("oldname") } + + let(:new_keg_record) { HOMEBREW_CELLAR/"newname/0.1" } + let(:old_keg_record) { HOMEBREW_CELLAR/"oldname/0.1" } + + let(:old_tab) { Tab.empty } + + let(:keg) { Keg.new(old_keg_record) } + let(:old_pin) { HOMEBREW_PINNED_KEGS/"oldname" } + + before(:each) do |example| + allow(new_formula).to receive(:oldname).and_return("oldname") + + # do not create directories for error tests + next if example.metadata[:description].start_with?("raises an error") + + (old_keg_record/"bin").mkpath + + %w[inside bindir].each do |file| + FileUtils.touch old_keg_record/"bin/#{file}" + end + + old_tab.tabfile = HOMEBREW_CELLAR/"oldname/0.1/INSTALL_RECEIPT.json" + old_tab.source["path"] = "/oldname" + old_tab.write + + keg.link + keg.optlink + + old_pin.make_relative_symlink old_keg_record + + subject # needs to be evaluated eagerly + + (HOMEBREW_PREFIX/"bin").mkpath + end + + after(:each) do + if !old_keg_record.parent.symlink? && old_keg_record.directory? + keg.unlink + end + + if new_keg_record.directory? + new_keg = Keg.new(new_keg_record) + new_keg.unlink + end + end + + describe "::new" do + it "raises an error if there is no old name" do + expect { + described_class.new(old_formula) + }.to raise_error(Migrator::MigratorNoOldnameError) + end + + it "raises an error if there is no old path" do + expect { + described_class.new(new_formula) + }.to raise_error(Migrator::MigratorNoOldpathError) + end + + it "raises an error if the Taps differ" do + keg = HOMEBREW_CELLAR/"oldname/0.1" + keg.mkpath + tab = Tab.empty + tab.tabfile = HOMEBREW_CELLAR/"oldname/0.1/INSTALL_RECEIPT.json" + tab.source["tap"] = "homebrew/core" + tab.write + + expect { + described_class.new(new_formula) + }.to raise_error(Migrator::MigratorDifferentTapsError) + end + end + + specify "#move_to_new_directory" do + keg.unlink + shutup do + subject.move_to_new_directory + end + + expect(new_keg_record).to be_a_directory + expect(new_keg_record/"bin").to be_a_directory + expect(new_keg_record/"bin/inside").to be_a_file + expect(new_keg_record/"bin/bindir").to be_a_file + expect(old_keg_record).not_to be_a_directory + end + + specify "#backup_oldname_cellar" do + old_keg_record.parent.rmtree + (new_keg_record/"bin").mkpath + + subject.backup_oldname_cellar + + expect(old_keg_record/"bin").to be_a_directory + expect(old_keg_record/"bin").to be_a_directory + end + + specify "#repin" do + (new_keg_record/"bin").mkpath + expected_relative = new_keg_record.relative_path_from HOMEBREW_PINNED_KEGS + + subject.repin + + expect(subject.new_pin_record).to be_a_symlink + expect(subject.new_pin_record.readlink).to eq(expected_relative) + expect(subject.old_pin_record).not_to exist + end + + specify "#unlink_oldname" do + expect(HOMEBREW_LINKED_KEGS.children.count).to eq(1) + expect((HOMEBREW_PREFIX/"opt").children.count).to eq(1) + + shutup do + subject.unlink_oldname + end + + expect(HOMEBREW_LINKED_KEGS).not_to exist + expect(HOMEBREW_LIBRARY/"bin").not_to exist + end + + specify "#link_newname" do + keg.unlink + keg.uninstall + + (new_keg_record/"bin").mkpath + %w[inside bindir].each do |file| + FileUtils.touch new_keg_record/"bin"/file + end + + shutup do + subject.link_newname + end + + expect(HOMEBREW_LINKED_KEGS.children.count).to eq(1) + expect((HOMEBREW_PREFIX/"opt").children.count).to eq(1) + end + + specify "#link_oldname_opt" do + new_keg_record.mkpath + subject.link_oldname_opt + expect((HOMEBREW_PREFIX/"opt/oldname").realpath).to eq(new_keg_record.realpath) + end + + specify "#link_oldname_cellar" do + (new_keg_record/"bin").mkpath + keg.unlink + keg.uninstall + subject.link_oldname_cellar + expect((HOMEBREW_CELLAR/"oldname").realpath).to eq(new_keg_record.parent.realpath) + end + + specify "#update_tabs" do + (new_keg_record/"bin").mkpath + tab = Tab.empty + tab.tabfile = HOMEBREW_CELLAR/"newname/0.1/INSTALL_RECEIPT.json" + tab.source["path"] = "/path/that/must/be/changed/by/update_tabs" + tab.write + subject.update_tabs + expect(Tab.for_keg(new_keg_record).source["path"]).to eq(new_formula.path.to_s) + end + + specify "#migrate" do + tab = Tab.empty + tab.tabfile = HOMEBREW_CELLAR/"oldname/0.1/INSTALL_RECEIPT.json" + tab.source["path"] = old_formula.path.to_s + tab.write + + shutup do + subject.migrate + end + + expect(new_keg_record).to exist + expect(old_keg_record.parent).to be_a_symlink + expect(HOMEBREW_LINKED_KEGS/"oldname").not_to exist + expect((HOMEBREW_LINKED_KEGS/"newname").realpath).to eq(new_keg_record.realpath) + expect(old_keg_record.realpath).to eq(new_keg_record.realpath) + expect((HOMEBREW_PREFIX/"opt/oldname").realpath).to eq(new_keg_record.realpath) + expect((HOMEBREW_CELLAR/"oldname").realpath).to eq(new_keg_record.parent.realpath) + expect((HOMEBREW_PINNED_KEGS/"newname").realpath).to eq(new_keg_record.realpath) + expect(Tab.for_keg(new_keg_record).source["path"]).to eq(new_formula.path.to_s) + end + + specify "#unlinik_oldname_opt" do + new_keg_record.mkpath + old_opt_record = HOMEBREW_PREFIX/"opt/oldname" + old_opt_record.unlink if old_opt_record.symlink? + old_opt_record.make_relative_symlink(new_keg_record) + subject.unlink_oldname_opt + expect(old_opt_record).not_to be_a_symlink + end + + specify "#unlink_oldname_cellar" do + new_keg_record.mkpath + keg.unlink + keg.uninstall + old_keg_record.parent.make_relative_symlink(new_keg_record.parent) + subject.unlink_oldname_cellar + expect(old_keg_record.parent).not_to be_a_symlink + end + + specify "#backup_oldname_cellar" do + (new_keg_record/"bin").mkpath + keg.unlink + keg.uninstall + subject.backup_oldname_cellar + expect(old_keg_record.subdirs).not_to be_empty + end + + specify "#backup_old_tabs" do + tab = Tab.empty + tab.tabfile = HOMEBREW_CELLAR/"oldname/0.1/INSTALL_RECEIPT.json" + tab.source["path"] = "/should/be/the/same" + tab.write + migrator = Migrator.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 + 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 + expect(HOMEBREW_PREFIX/"opt/oldname").to exist + expect(HOMEBREW_PINNED_KEGS/"oldname").to be_a_symlink + expect(keg).to be_linked + end + + context "when cellar exists" do + it "backs up the old name" do + subject.backup_oldname + end + end + + context "when cellar is removed" do + it "backs up the old name" do + (new_keg_record/"bin").mkpath + keg.unlink + keg.uninstall + subject.backup_oldname + end + end + + context "when cellar is linked" do + it "backs up the old name" do + (new_keg_record/"bin").mkpath + keg.unlink + keg.uninstall + old_keg_record.parent.make_relative_symlink(new_keg_record.parent) + subject.backup_oldname + end + end + end +end diff --git a/Library/Homebrew/test/migrator_test.rb b/Library/Homebrew/test/migrator_test.rb deleted file mode 100644 index 8a2b6ad63..000000000 --- a/Library/Homebrew/test/migrator_test.rb +++ /dev/null @@ -1,264 +0,0 @@ -require "testing_env" -require "migrator" -require "test/support/fixtures/testball" -require "tab" -require "keg" - -class Formula - attr_writer :oldname -end - -class MigratorErrorsTests < Homebrew::TestCase - def setup - @new_f = Testball.new("newname") - @new_f.oldname = "oldname" - @old_f = Testball.new("oldname") - end - - def test_no_oldname - assert_raises(Migrator::MigratorNoOldnameError) { Migrator.new(@old_f) } - end - - def test_no_oldpath - assert_raises(Migrator::MigratorNoOldpathError) { Migrator.new(@new_f) } - end - - def test_different_taps - keg = HOMEBREW_CELLAR/"oldname/0.1" - keg.mkpath - tab = Tab.empty - tab.tabfile = HOMEBREW_CELLAR/"oldname/0.1/INSTALL_RECEIPT.json" - tab.source["tap"] = "homebrew/core" - tab.write - assert_raises(Migrator::MigratorDifferentTapsError) { Migrator.new(@new_f) } - ensure - keg.parent.rmtree - end -end - -class MigratorTests < Homebrew::TestCase - include FileUtils - - def setup - @new_f = Testball.new("newname") - @new_f.oldname = "oldname" - - @old_f = Testball.new("oldname") - - @old_keg_record = HOMEBREW_CELLAR/"oldname/0.1" - @old_keg_record.join("bin").mkpath - @new_keg_record = HOMEBREW_CELLAR/"newname/0.1" - - %w[inside bindir].each { |file| touch @old_keg_record.join("bin", file) } - - @old_tab = Tab.empty - @old_tab.tabfile = HOMEBREW_CELLAR/"oldname/0.1/INSTALL_RECEIPT.json" - @old_tab.source["path"] = "/oldname" - @old_tab.write - - @keg = Keg.new(@old_keg_record) - @keg.link - @keg.optlink - - @old_pin = HOMEBREW_PINNED_KEGS/"oldname" - @old_pin.make_relative_symlink @old_keg_record - - @migrator = Migrator.new(@new_f) - - mkpath HOMEBREW_PREFIX/"bin" - end - - def teardown - @old_pin.unlink if @old_pin.symlink? - - if @old_keg_record.parent.symlink? - @old_keg_record.parent.unlink - elsif @old_keg_record.directory? - @keg.unlink - @keg.uninstall - end - - if @new_keg_record.directory? - new_keg = Keg.new(@new_keg_record) - new_keg.unlink - new_keg.uninstall - end - - @old_keg_record.parent.rmtree if @old_keg_record.parent.directory? - @new_keg_record.parent.rmtree if @new_keg_record.parent.directory? - - rmtree HOMEBREW_PREFIX/"bin" - rmtree HOMEBREW_PREFIX/"opt" if (HOMEBREW_PREFIX/"opt").directory? - # What to do with pin? - @new_f.unpin - - HOMEBREW_LOCK_DIR.children.each(&:unlink) - end - - def test_move_cellar - @keg.unlink - shutup { @migrator.move_to_new_directory } - assert_predicate @new_keg_record, :directory? - assert_predicate @new_keg_record/"bin", :directory? - assert_predicate @new_keg_record/"bin/inside", :file? - assert_predicate @new_keg_record/"bin/bindir", :file? - refute_predicate @old_keg_record, :directory? - end - - def test_backup_cellar - @old_keg_record.parent.rmtree - @new_keg_record.join("bin").mkpath - - @migrator.backup_oldname_cellar - - assert_predicate @old_keg_record, :directory? - assert_predicate @old_keg_record/"bin", :directory? - end - - def test_repin - @new_keg_record.join("bin").mkpath - expected_relative = @new_keg_record.relative_path_from HOMEBREW_PINNED_KEGS - - @migrator.repin - - assert_predicate @migrator.new_pin_record, :symlink? - assert_equal expected_relative, @migrator.new_pin_record.readlink - refute_predicate @migrator.old_pin_record, :exist? - end - - def test_unlink_oldname - assert_equal 1, HOMEBREW_LINKED_KEGS.children.size - assert_equal 1, (HOMEBREW_PREFIX/"opt").children.size - - shutup { @migrator.unlink_oldname } - - refute_predicate HOMEBREW_LINKED_KEGS, :exist? - refute_predicate HOMEBREW_LIBRARY/"bin", :exist? - end - - def test_link_newname - @keg.unlink - @keg.uninstall - @new_keg_record.join("bin").mkpath - %w[inside bindir].each { |file| touch @new_keg_record.join("bin", file) } - - shutup { @migrator.link_newname } - - assert_equal 1, HOMEBREW_LINKED_KEGS.children.size - assert_equal 1, (HOMEBREW_PREFIX/"opt").children.size - end - - def test_link_oldname_opt - @new_keg_record.mkpath - @migrator.link_oldname_opt - assert_equal @new_keg_record.realpath, (HOMEBREW_PREFIX/"opt/oldname").realpath - end - - def test_link_oldname_cellar - @new_keg_record.join("bin").mkpath - @keg.unlink - @keg.uninstall - @migrator.link_oldname_cellar - assert_equal @new_keg_record.parent.realpath, (HOMEBREW_CELLAR/"oldname").realpath - end - - def test_update_tabs - @new_keg_record.join("bin").mkpath - tab = Tab.empty - tab.tabfile = HOMEBREW_CELLAR/"newname/0.1/INSTALL_RECEIPT.json" - tab.source["path"] = "/path/that/must/be/changed/by/update_tabs" - tab.write - @migrator.update_tabs - assert_equal @new_f.path.to_s, Tab.for_keg(@new_keg_record).source["path"] - end - - def test_migrate - tab = Tab.empty - tab.tabfile = HOMEBREW_CELLAR/"oldname/0.1/INSTALL_RECEIPT.json" - tab.source["path"] = @old_f.path.to_s - tab.write - - shutup { @migrator.migrate } - - assert_predicate @new_keg_record, :exist? - assert_predicate @old_keg_record.parent, :symlink? - refute_predicate HOMEBREW_LINKED_KEGS/"oldname", :exist? - assert_equal @new_keg_record.realpath, (HOMEBREW_LINKED_KEGS/"newname").realpath - assert_equal @new_keg_record.realpath, @old_keg_record.realpath - assert_equal @new_keg_record.realpath, (HOMEBREW_PREFIX/"opt/oldname").realpath - assert_equal @new_keg_record.parent.realpath, (HOMEBREW_CELLAR/"oldname").realpath - assert_equal @new_keg_record.realpath, (HOMEBREW_PINNED_KEGS/"newname").realpath - assert_equal @new_f.path.to_s, Tab.for_keg(@new_keg_record).source["path"] - end - - def test_unlinik_oldname_opt - @new_keg_record.mkpath - old_opt_record = HOMEBREW_PREFIX/"opt/oldname" - old_opt_record.unlink if old_opt_record.symlink? - old_opt_record.make_relative_symlink(@new_keg_record) - @migrator.unlink_oldname_opt - refute_predicate old_opt_record, :symlink? - end - - def test_unlink_oldname_cellar - @new_keg_record.mkpath - @keg.unlink - @keg.uninstall - @old_keg_record.parent.make_relative_symlink(@new_keg_record.parent) - @migrator.unlink_oldname_cellar - refute_predicate @old_keg_record.parent, :symlink? - end - - def test_backup_oldname_cellar - @new_keg_record.join("bin").mkpath - @keg.unlink - @keg.uninstall - @migrator.backup_oldname_cellar - refute_predicate @old_keg_record.subdirs, :empty? - end - - def test_backup_old_tabs - tab = Tab.empty - tab.tabfile = HOMEBREW_CELLAR/"oldname/0.1/INSTALL_RECEIPT.json" - tab.source["path"] = "/should/be/the/same" - tab.write - migrator = Migrator.new(@new_f) - tab.tabfile.delete - migrator.backup_old_tabs - assert_equal "/should/be/the/same", Tab.for_keg(@old_keg_record).source["path"] - end - - # Backup tests are divided into three groups: when oldname Cellar is deleted - # and when it still exists and when it's a symlink - - def check_after_backup - assert_predicate @old_keg_record.parent, :directory? - refute_predicate @old_keg_record.parent.subdirs, :empty? - assert_predicate HOMEBREW_LINKED_KEGS/"oldname", :exist? - assert_predicate HOMEBREW_PREFIX/"opt/oldname", :exist? - assert_predicate HOMEBREW_PINNED_KEGS/"oldname", :symlink? - assert_predicate @keg, :linked? - end - - def test_backup_cellar_exist - @migrator.backup_oldname - check_after_backup - end - - def test_backup_cellar_removed - @new_keg_record.join("bin").mkpath - @keg.unlink - @keg.uninstall - @migrator.backup_oldname - check_after_backup - end - - def test_backup_cellar_linked - @new_keg_record.join("bin").mkpath - @keg.unlink - @keg.uninstall - @old_keg_record.parent.make_relative_symlink(@new_keg_record.parent) - @migrator.backup_oldname - check_after_backup - end -end diff --git a/Library/Homebrew/test/missing_test.rb b/Library/Homebrew/test/missing_test.rb deleted file mode 100644 index 4f20d8a7a..000000000 --- a/Library/Homebrew/test/missing_test.rb +++ /dev/null @@ -1,34 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestMissing < IntegrationCommandTestCase - def setup - super - - setup_test_formula "foo" - setup_test_formula "bar" - end - - def make_prefix(name) - (HOMEBREW_CELLAR/name/"1.0").mkpath - end - - def test_missing_missing - make_prefix "bar" - - assert_match "foo", cmd("missing") - end - - def test_missing_not_missing - make_prefix "foo" - make_prefix "bar" - - assert_empty cmd("missing") - end - - def test_missing_hide - make_prefix "foo" - make_prefix "bar" - - assert_match "foo", cmd("missing", "--hide=foo") - end -end diff --git a/Library/Homebrew/test/mpi_requirement_spec.rb b/Library/Homebrew/test/mpi_requirement_spec.rb new file mode 100644 index 000000000..f32b27993 --- /dev/null +++ b/Library/Homebrew/test/mpi_requirement_spec.rb @@ -0,0 +1,14 @@ +require "requirements/mpi_requirement" + +describe MPIRequirement do + describe "::new" do + subject { described_class.new(*(wrappers + tags)) } + let(:wrappers) { [:cc, :cxx, :f77] } + let(:tags) { [:optional, "some-other-tag"] } + + it "untangles wrappers and tags" do + expect(subject.lang_list).to eq(wrappers) + expect(subject.tags).to eq(tags) + end + end +end diff --git a/Library/Homebrew/test/mpi_requirement_test.rb b/Library/Homebrew/test/mpi_requirement_test.rb deleted file mode 100644 index e0f97e8ee..000000000 --- a/Library/Homebrew/test/mpi_requirement_test.rb +++ /dev/null @@ -1,12 +0,0 @@ -require "testing_env" -require "requirements/mpi_requirement" - -class MPIRequirementTests < Homebrew::TestCase - def test_initialize_untangles_tags_and_wrapper_symbols - wrappers = [:cc, :cxx, :f77] - tags = [:optional, "some-other-tag"] - dep = MPIRequirement.new(*wrappers + tags) - assert_equal wrappers, dep.lang_list - assert_equal tags, dep.tags - end -end diff --git a/Library/Homebrew/test/options_spec.rb b/Library/Homebrew/test/options_spec.rb new file mode 100644 index 000000000..a05bb139e --- /dev/null +++ b/Library/Homebrew/test/options_spec.rb @@ -0,0 +1,148 @@ +require "options" + +describe Option do + subject { described_class.new("foo") } + + specify "#to_s" do + expect(subject.to_s).to eq("--foo") + end + + specify "equality" do + foo = Option.new("foo") + bar = Option.new("bar") + expect(subject).to eq(foo) + expect(subject).not_to eq(bar) + expect(subject).to eql(foo) + expect(subject).not_to eql(bar) + end + + specify "#description" do + expect(subject.description).to be_empty + expect(Option.new("foo", "foo").description).to eq("foo") + end + + specify "#inspect" do + expect(subject.inspect).to eq("#<Option: \"--foo\">") + end +end + +describe DeprecatedOption do + subject { described_class.new("foo", "bar") } + + specify "#old" do + expect(subject.old).to eq("foo") + end + + specify "#old_flag" do + expect(subject.old_flag).to eq("--foo") + end + + specify "#current" do + expect(subject.current).to eq("bar") + end + + specify "#current_flag" do + expect(subject.current_flag).to eq("--bar") + end + + specify "equality" do + foobar = DeprecatedOption.new("foo", "bar") + boofar = DeprecatedOption.new("boo", "far") + expect(foobar).to eq(subject) + expect(subject).to eq(foobar) + expect(boofar).not_to eq(subject) + expect(subject).not_to eq(boofar) + end +end + +describe Options do + it "removes duplicate options" do + subject << Option.new("foo") + subject << Option.new("foo") + expect(subject).to include("--foo") + expect(subject.count).to eq(1) + end + + it "preserves existing member when adding a duplicate" do + a = Option.new("foo", "bar") + b = Option.new("foo", "qux") + subject << a << b + expect(subject.count).to eq(1) + expect(subject.first).to be(a) + expect(subject.first.description).to eq(a.description) + end + + specify "#include?" do + subject << Option.new("foo") + expect(subject).to include("--foo") + expect(subject).to include("foo") + expect(subject).to include(Option.new("foo")) + end + + describe "#+" do + it "returns options" do + expect(subject + Options.new).to be_an_instance_of(Options) + end + end + + describe "#-" do + it "returns options" do + expect(subject - Options.new).to be_an_instance_of(Options) + end + end + + specify "#&" do + foo, bar, baz = %w[foo bar baz].map { |o| Option.new(o) } + options = Options.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 + subject << foo << baz + expect((subject | options).sort).to eq([foo, bar, baz].sort) + end + + specify "#*" do + subject << Option.new("aa") << Option.new("bb") << Option.new("cc") + expect((subject * "XX").split("XX").sort).to eq(%w[--aa --bb --cc]) + end + + describe "<<" do + it "returns itself" do + expect(subject << Option.new("foo")).to be subject + end + end + + specify "#as_flags" do + subject << Option.new("foo") + expect(subject.as_flags).to eq(%w[--foo]) + end + + specify "#to_a" do + option = Option.new("foo") + subject << option + expect(subject.to_a).to eq([option]) + end + + specify "#to_ary" do + option = Option.new("foo") + subject << option + expect(subject.to_ary).to eq([option]) + end + + specify "::create_with_array" do + array = %w[--foo --bar] + option1 = Option.new("foo") + option2 = Option.new("bar") + expect(Options.create(array).sort).to eq([option1, option2].sort) + end + + specify "#inspect" do + expect(subject.inspect).to eq("#<Options: []>") + subject << Option.new("foo") + expect(subject.inspect).to eq("#<Options: [#<Option: \"--foo\">]>") + end +end diff --git a/Library/Homebrew/test/options_test.rb b/Library/Homebrew/test/options_test.rb deleted file mode 100644 index e7189a604..000000000 --- a/Library/Homebrew/test/options_test.rb +++ /dev/null @@ -1,157 +0,0 @@ -require "testing_env" -require "options" -require "testing_env" - -class IntegrationCommandTestOptions < IntegrationCommandTestCase - def test_options - setup_test_formula "testball", <<-EOS.undent - depends_on "bar" => :recommended - EOS - - assert_equal "--with-foo\n\tBuild with foo\n--without-bar\n\tBuild without bar support", - cmd_output("options", "testball").chomp - end -end - -class OptionTests < Homebrew::TestCase - def setup - @option = Option.new("foo") - end - - def test_to_s - assert_equal "--foo", @option.to_s - end - - def test_equality - foo = Option.new("foo") - bar = Option.new("bar") - assert_equal foo, @option - refute_equal bar, @option - assert_eql @option, foo - refute_eql @option, bar - end - - def test_description - assert_empty @option.description - assert_equal "foo", Option.new("foo", "foo").description - end - - def test_inspect - assert_equal "#<Option: \"--foo\">", @option.inspect - end -end - -class DeprecatedOptionTests < Homebrew::TestCase - def setup - @deprecated_option = DeprecatedOption.new("foo", "bar") - end - - def test_old - assert_equal "foo", @deprecated_option.old - assert_equal "--foo", @deprecated_option.old_flag - end - - def test_current - assert_equal "bar", @deprecated_option.current - assert_equal "--bar", @deprecated_option.current_flag - end - - def test_equality - foobar = DeprecatedOption.new("foo", "bar") - boofar = DeprecatedOption.new("boo", "far") - assert_equal foobar, @deprecated_option - refute_equal boofar, @deprecated_option - assert_eql @deprecated_option, foobar - refute_eql @deprecated_option, boofar - end -end - -class OptionsTests < Homebrew::TestCase - def setup - @options = Options.new - end - - def test_no_duplicate_options - @options << Option.new("foo") - @options << Option.new("foo") - assert_includes @options, "--foo" - assert_equal 1, @options.count - end - - def test_preserves_existing_member_when_pushing_duplicate - a = Option.new("foo", "bar") - b = Option.new("foo", "qux") - @options << a << b - assert_equal 1, @options.count - assert_same a, @options.first - assert_equal a.description, @options.first.description - end - - def test_include - @options << Option.new("foo") - assert_includes @options, "--foo" - assert_includes @options, "foo" - assert_includes @options, Option.new("foo") - end - - def test_union_returns_options - assert_instance_of Options, @options + Options.new - end - - def test_difference_returns_options - assert_instance_of Options, @options - Options.new - end - - def test_shovel_returns_self - assert_same @options, @options << Option.new("foo") - end - - def test_as_flags - @options << Option.new("foo") - assert_equal %w[--foo], @options.as_flags - end - - def test_to_a - option = Option.new("foo") - @options << option - assert_equal [option], @options.to_a - end - - def test_to_ary - option = Option.new("foo") - @options << option - assert_equal [option], @options.to_ary - end - - def test_intersection - foo, bar, baz = %w[foo bar baz].map { |o| Option.new(o) } - options = Options.new << foo << bar - @options << foo << baz - assert_equal [foo], (@options & options).to_a - end - - def test_set_union - foo, bar, baz = %w[foo bar baz].map { |o| Option.new(o) } - options = Options.new << foo << bar - @options << foo << baz - assert_equal [foo, bar, baz].sort, (@options | options).sort - end - - def test_times - @options << Option.new("aa") << Option.new("bb") << Option.new("cc") - assert_equal %w[--aa --bb --cc], (@options * "XX").split("XX").sort - end - - def test_create_with_array - array = %w[--foo --bar] - option1 = Option.new("foo") - option2 = Option.new("bar") - assert_equal [option1, option2].sort, Options.create(array).sort - end - - def test_inspect - assert_equal "#<Options: []>", @options.inspect - @options << Option.new("foo") - assert_equal "#<Options: [#<Option: \"--foo\">]>", @options.inspect - end -end diff --git a/Library/Homebrew/test/os/mac/blacklist_test.rb b/Library/Homebrew/test/os/mac/blacklist_test.rb deleted file mode 100644 index 26dd84ed9..000000000 --- a/Library/Homebrew/test/os/mac/blacklist_test.rb +++ /dev/null @@ -1,12 +0,0 @@ -require "testing_env" -require "blacklist" - -class OSMacBlacklistTests < Homebrew::TestCase - def assert_blacklisted(s) - assert blacklisted?(s), "'#{s}' should be blacklisted" - end - - def test_xcode - %w[xcode Xcode].each { |s| assert_blacklisted s } - end -end diff --git a/Library/Homebrew/test/os/mac/bottle_collector_test.rb b/Library/Homebrew/test/os/mac/bottle_collector_test.rb deleted file mode 100644 index 2f88050ae..000000000 --- a/Library/Homebrew/test/os/mac/bottle_collector_test.rb +++ /dev/null @@ -1,26 +0,0 @@ -require "testing_env" -require "utils/bottles" - -class OSMacBottleCollectorTests < Homebrew::TestCase - def setup - @collector = Utils::Bottles::Collector.new - end - - def checksum_for(tag) - @collector.fetch_checksum_for(tag) - end - - def test_collector_finds_or_later_tags - @collector[:lion_or_later] = "foo" - assert_equal ["foo", :lion_or_later], checksum_for(:mountain_lion) - assert_nil checksum_for(:snow_leopard) - end - - def test_collector_finds_altivec_tags - @collector[:tiger_altivec] = "foo" - assert_equal ["foo", :tiger_altivec], checksum_for(:tiger_g4) - assert_equal ["foo", :tiger_altivec], checksum_for(:tiger_g4e) - assert_equal ["foo", :tiger_altivec], checksum_for(:tiger_g5) - assert_nil checksum_for(:tiger_g3) - end -end diff --git a/Library/Homebrew/test/os/mac/bottle_tag_test.rb b/Library/Homebrew/test/os/mac/bottle_tag_test.rb deleted file mode 100644 index 996bd4d53..000000000 --- a/Library/Homebrew/test/os/mac/bottle_tag_test.rb +++ /dev/null @@ -1,79 +0,0 @@ -require "testing_env" -require "utils/bottles" - -class OSMacBottleTagTests < Homebrew::TestCase - def test_tag_tiger_ppc - MacOS.stubs(:version).returns(MacOS::Version.new("10.4")) - Hardware::CPU.stubs(:type).returns(:ppc) - Hardware::CPU.stubs(:family).returns(:foo) - MacOS.stubs(:prefer_64_bit?).returns(false) - assert_equal :tiger_foo, Utils::Bottles.tag - end - - def test_tag_tiger_intel - MacOS.stubs(:version).returns(MacOS::Version.new("10.4")) - Hardware::CPU.stubs(:type).returns(:intel) - MacOS.stubs(:prefer_64_bit?).returns(false) - assert_equal :tiger, Utils::Bottles.tag - end - - def test_tag_tiger_ppc_64 - MacOS.stubs(:version).returns(MacOS::Version.new("10.4")) - Hardware::CPU.stubs(:type).returns(:ppc) - Hardware::CPU.stubs(:family).returns(:g5) - MacOS.stubs(:prefer_64_bit?).returns(true) - assert_equal :tiger_g5_64, Utils::Bottles.tag - end - - # Note that this will probably never be used - def test_tag_tiger_intel_64 - MacOS.stubs(:version).returns(MacOS::Version.new("10.4")) - Hardware::CPU.stubs(:type).returns(:intel) - MacOS.stubs(:prefer_64_bit?).returns(true) - assert_equal :tiger_64, Utils::Bottles.tag - end - - def test_tag_leopard_intel - MacOS.stubs(:version).returns(MacOS::Version.new("10.5")) - Hardware::CPU.stubs(:type).returns(:intel) - MacOS.stubs(:prefer_64_bit?).returns(false) - assert_equal :leopard, Utils::Bottles.tag - end - - def test_tag_leopard_ppc_64 - MacOS.stubs(:version).returns(MacOS::Version.new("10.5")) - Hardware::CPU.stubs(:type).returns(:ppc) - Hardware::CPU.stubs(:family).returns(:g5) - MacOS.stubs(:prefer_64_bit?).returns(true) - assert_equal :leopard_g5_64, Utils::Bottles.tag - end - - def test_tag_leopard_intel_64 - MacOS.stubs(:version).returns(MacOS::Version.new("10.5")) - Hardware::CPU.stubs(:type).returns(:intel) - MacOS.stubs(:prefer_64_bit?).returns(true) - assert_equal :leopard_64, Utils::Bottles.tag - end - - def test_tag_snow_leopard_32 - MacOS.stubs(:version).returns(MacOS::Version.new("10.6")) - Hardware::CPU.stubs(:is_64_bit?).returns(false) - assert_equal :snow_leopard_32, Utils::Bottles.tag - end - - def test_tag_snow_leopard_64 - MacOS.stubs(:version).returns(MacOS::Version.new("10.6")) - Hardware::CPU.stubs(:is_64_bit?).returns(true) - assert_equal :snow_leopard, Utils::Bottles.tag - end - - def test_tag_lion - MacOS.stubs(:version).returns(MacOS::Version.new("10.7")) - assert_equal :lion, Utils::Bottles.tag - end - - def test_tag_mountain_lion - MacOS.stubs(:version).returns(MacOS::Version.new("10.8")) - assert_equal :mountain_lion, Utils::Bottles.tag - end -end diff --git a/Library/Homebrew/test/os/mac/dependency_collector_spec.rb b/Library/Homebrew/test/os/mac/dependency_collector_spec.rb new file mode 100644 index 000000000..21b15cd99 --- /dev/null +++ b/Library/Homebrew/test/os/mac/dependency_collector_spec.rb @@ -0,0 +1,50 @@ +require "dependency_collector" + +RSpec::Matchers.alias_matcher :need_tar_xz_dependency, :be_tar_needs_xz_dependency + +describe DependencyCollector do + after(:each) do + described_class.clear_cache + end + + specify "#tar_needs_xz_dependency?" do + allow(MacOS).to receive(:version).and_return(MacOS::Version.new("10.9")) + expect(described_class).not_to need_tar_xz_dependency + end + + specify "LD64 pre-Leopard dependency" do + allow(MacOS).to receive(:version).and_return(MacOS::Version.new("10.4")) + expect(subject.build(:ld64)).to eq(LD64Dependency.new) + end + + specify "LD64 Leopard or newer dependency" do + allow(MacOS).to receive(:version).and_return(MacOS::Version.new("10.5")) + expect(subject.build(:ld64)).to be nil + end + + specify "ant Mavericks or newer dependency" do + allow(MacOS).to receive(:version).and_return(MacOS::Version.new("10.9")) + subject.add ant: :build + expect(subject.deps.find { |dep| dep.name == "ant" }).to eq(Dependency.new("ant", [:build])) + end + + specify "ant pre-Mavericks dependency" do + allow(MacOS).to receive(:version).and_return(MacOS::Version.new("10.7")) + subject.add ant: :build + expect(subject.deps.find { |dep| dep.name == "ant" }).to be nil + end + + specify "Resource xz pre-Mavericks dependency" do + allow(MacOS).to receive(:version).and_return(MacOS::Version.new("10.8")) + resource = Resource.new + resource.url("http://example.com/foo.tar.xz") + expect(subject.add(resource)).to eq(Dependency.new("xz", [:build])) + end + + specify "Resource xz Mavericks or newer dependency" do + allow(MacOS).to receive(:version).and_return(MacOS::Version.new("10.9")) + resource = Resource.new + resource.url("http://example.com/foo.tar.xz") + expect(subject.add(resource)).to be nil + end +end diff --git a/Library/Homebrew/test/os/mac/dependency_collector_test.rb b/Library/Homebrew/test/os/mac/dependency_collector_test.rb deleted file mode 100644 index 4fdf3ebe4..000000000 --- a/Library/Homebrew/test/os/mac/dependency_collector_test.rb +++ /dev/null @@ -1,57 +0,0 @@ -require "testing_env" -require "dependency_collector" - -class OSMacDependencyCollectorTests < Homebrew::TestCase - def find_dependency(name) - @d.deps.find { |dep| dep.name == name } - end - - def setup - @d = DependencyCollector.new - end - - def teardown - DependencyCollector.clear_cache - end - - def test_tar_needs_xz_dependency - MacOS.stubs(:version).returns(MacOS::Version.new("10.9")) - refute DependencyCollector.tar_needs_xz_dependency? - end - - def test_ld64_dep_pre_leopard - MacOS.stubs(:version).returns(MacOS::Version.new("10.4")) - assert_equal LD64Dependency.new, @d.build(:ld64) - end - - def test_ld64_dep_leopard_or_newer - MacOS.stubs(:version).returns(MacOS::Version.new("10.5")) - assert_nil @d.build(:ld64) - end - - def test_ant_dep_mavericks_or_newer - MacOS.stubs(:version).returns(MacOS::Version.new("10.9")) - @d.add ant: :build - assert_equal find_dependency("ant"), Dependency.new("ant", [:build]) - end - - def test_ant_dep_pre_mavericks - MacOS.stubs(:version).returns(MacOS::Version.new("10.7")) - @d.add ant: :build - assert_nil find_dependency("ant") - end - - def test_resource_dep_xz_pre_mavericks - MacOS.stubs(:version).returns(MacOS::Version.new("10.8")) - resource = Resource.new - resource.url("http://example.com/foo.tar.xz") - assert_equal Dependency.new("xz", [:build]), @d.add(resource) - end - - def test_resource_dep_xz_mavericks_or_newer - MacOS.stubs(:version).returns(MacOS::Version.new("10.9")) - resource = Resource.new - resource.url("http://example.com/foo.tar.xz") - assert_nil @d.add(resource) - end -end diff --git a/Library/Homebrew/test/os/mac/diagnostic_spec.rb b/Library/Homebrew/test/os/mac/diagnostic_spec.rb new file mode 100644 index 000000000..d2b38a332 --- /dev/null +++ b/Library/Homebrew/test/os/mac/diagnostic_spec.rb @@ -0,0 +1,42 @@ +require "diagnostic" + +describe Homebrew::Diagnostic::Checks do + specify "#check_for_other_package_managers" do + allow(MacOS).to receive(:macports_or_fink).and_return(["fink"]) + expect(subject.check_for_other_package_managers) + .to match("You have MacPorts or Fink installed:") + end + + specify "#check_for_unsupported_macos" do + ENV.delete("HOMEBREW_DEVELOPER") + allow(OS::Mac).to receive(:prerelease?).and_return(true) + + expect(subject.check_for_unsupported_macos) + .to match("We do not provide support for this pre-release version.") + end + + specify "#check_for_unsupported_curl_vars" do + allow(MacOS).to receive(:version).and_return(OS::Mac::Version.new("10.10")) + ENV["SSL_CERT_DIR"] = "/some/path" + + expect(subject.check_for_unsupported_curl_vars) + .to match("SSL_CERT_DIR support was removed from Apple's curl.") + end + + specify "#check_for_beta_xquartz" do + allow(MacOS::XQuartz).to receive(:version).and_return("2.7.10_beta2") + + expect(subject.check_for_beta_xquartz) + .to match("The following beta release of XQuartz is installed: 2.7.10_beta2") + end + + specify "#check_xcode_8_without_clt_on_el_capitan" do + allow(MacOS).to receive(:version).and_return(OS::Mac::Version.new("10.11")) + allow(MacOS::Xcode).to receive(:installed?).and_return(true) + allow(MacOS::Xcode).to receive(:version).and_return("8.0") + allow(MacOS::Xcode).to receive(:without_clt?).and_return(true) + + expect(subject.check_xcode_8_without_clt_on_el_capitan) + .to match("You have Xcode 8 installed without the CLT") + end +end diff --git a/Library/Homebrew/test/os/mac/diagnostic_test.rb b/Library/Homebrew/test/os/mac/diagnostic_test.rb deleted file mode 100644 index 655aa1d46..000000000 --- a/Library/Homebrew/test/os/mac/diagnostic_test.rb +++ /dev/null @@ -1,49 +0,0 @@ -require "testing_env" -require "fileutils" -require "pathname" -require "diagnostic" - -class OSMacDiagnosticChecksTest < Homebrew::TestCase - def setup - @env = ENV.to_hash - @checks = Homebrew::Diagnostic::Checks.new - end - - def teardown - ENV.replace(@env) - end - - def test_check_for_other_package_managers - MacOS.stubs(:macports_or_fink).returns ["fink"] - assert_match "You have MacPorts or Fink installed:", - @checks.check_for_other_package_managers - end - - def test_check_for_unsupported_macos - ARGV.stubs(:homebrew_developer?).returns false - OS::Mac.stubs(:prerelease?).returns true - assert_match "We do not provide support for this pre-release version.", - @checks.check_for_unsupported_macos - end - - def test_check_for_unsupported_curl_vars - MacOS.stubs(:version).returns OS::Mac::Version.new("10.10") - ENV["SSL_CERT_DIR"] = "/some/path" - - assert_match "SSL_CERT_DIR support was removed from Apple's curl.", - @checks.check_for_unsupported_curl_vars - end - - def test_check_for_beta_xquartz - MacOS::XQuartz.stubs(:version).returns("2.7.10_beta2") - assert_match "The following beta release of XQuartz is installed: 2.7.10_beta2", @checks.check_for_beta_xquartz - end - - def test_check_xcode_8_without_clt_on_el_capitan - MacOS.stubs(:version).returns OS::Mac::Version.new("10.11") - MacOS::Xcode.stubs(:installed?).returns true - MacOS::Xcode.stubs(:version).returns "8.0" - MacOS::Xcode.stubs(:without_clt?).returns true - assert_match "You have Xcode 8 installed without the CLT", @checks.check_xcode_8_without_clt_on_el_capitan - end -end diff --git a/Library/Homebrew/test/os/mac/java_requirement_spec.rb b/Library/Homebrew/test/os/mac/java_requirement_spec.rb new file mode 100644 index 000000000..f6404db92 --- /dev/null +++ b/Library/Homebrew/test/os/mac/java_requirement_spec.rb @@ -0,0 +1,34 @@ +require "requirements/java_requirement" +require "fileutils" + +describe JavaRequirement do + subject { described_class.new(%w[1.8]) } + let(:java_home) { Dir.mktmpdir } + let(:java_home_path) { Pathname.new(java_home) } + + before(:each) do + FileUtils.mkdir java_home_path/"bin" + FileUtils.touch java_home_path/"bin/java" + allow(subject).to receive(:preferred_java).and_return(java_home_path/"bin/java") + expect(subject).to be_satisfied + end + + after(:each) { java_home_path.rmtree } + + specify "Apple Java environment" do + expect(ENV).to receive(:prepend_path) + expect(ENV).to receive(:append_to_cflags) + + subject.modify_build_environment + expect(ENV["JAVA_HOME"]).to eq(java_home) + end + + specify "Oracle Java environment" do + FileUtils.mkdir java_home_path/"include" + expect(ENV).to receive(:prepend_path) + expect(ENV).to receive(:append_to_cflags).twice + + subject.modify_build_environment + expect(ENV["JAVA_HOME"]).to eq(java_home) + end +end diff --git a/Library/Homebrew/test/os/mac/keg_spec.rb b/Library/Homebrew/test/os/mac/keg_spec.rb new file mode 100644 index 000000000..562c2ba6a --- /dev/null +++ b/Library/Homebrew/test/os/mac/keg_spec.rb @@ -0,0 +1,32 @@ +require "keg" + +describe Keg do + include FileUtils + + subject { described_class.new(keg_path) } + + describe "#mach_o_files" do + let(:keg_path) { HOMEBREW_CELLAR/"a/1.0" } + + before(:each) { (keg_path/"lib").mkpath } + + after(:each) { subject.unlink } + + it "skips hardlinks" do + cp dylib_path("i386"), keg_path/"lib/i386.dylib" + ln keg_path/"lib/i386.dylib", keg_path/"lib/i386_hardlink.dylib" + + subject.link + expect(subject.mach_o_files.count).to eq(1) + end + + it "isn't confused by symlinks" do + cp dylib_path("i386"), keg_path/"lib/i386.dylib" + ln keg_path/"lib/i386.dylib", keg_path/"lib/i386_hardlink.dylib" + ln_s keg_path/"lib/i386.dylib", keg_path/"lib/i386_symlink.dylib" + + subject.link + expect(subject.mach_o_files.count).to eq(1) + end + end +end diff --git a/Library/Homebrew/test/os/mac/keg_test.rb b/Library/Homebrew/test/os/mac/keg_test.rb deleted file mode 100644 index e79cbc921..000000000 --- a/Library/Homebrew/test/os/mac/keg_test.rb +++ /dev/null @@ -1,69 +0,0 @@ -require "testing_env" -require "keg" -require "stringio" - -class OSMacLinkTests < Homebrew::TestCase - include FileUtils - - def setup - keg = HOMEBREW_CELLAR.join("foo", "1.0") - keg.join("bin").mkpath - - %w[hiworld helloworld goodbye_cruel_world].each do |file| - touch keg.join("bin", file) - end - - @keg = Keg.new(keg) - @dst = HOMEBREW_PREFIX.join("bin", "helloworld") - @nonexistent = Pathname.new("/some/nonexistent/path") - - @mode = OpenStruct.new - - @old_stdout = $stdout - $stdout = StringIO.new - - mkpath HOMEBREW_PREFIX/"bin" - mkpath HOMEBREW_PREFIX/"lib" - end - - def teardown - @keg.unlink - @keg.uninstall - - $stdout = @old_stdout - - rmtree HOMEBREW_PREFIX/"bin" - rmtree HOMEBREW_PREFIX/"lib" - end - - def test_mach_o_files_skips_hardlinks - a = HOMEBREW_CELLAR/"a/1.0" - (a/"lib").mkpath - FileUtils.cp dylib_path("i386"), a/"lib/i386.dylib" - FileUtils.ln a/"lib/i386.dylib", a/"lib/i386_link.dylib" - - keg = Keg.new(a) - keg.link - - assert_equal 1, keg.mach_o_files.size - ensure - keg.unlink - keg.uninstall - end - - def test_mach_o_files_isnt_confused_by_symlinks - a = HOMEBREW_CELLAR/"a/1.0" - (a/"lib").mkpath - FileUtils.cp dylib_path("i386"), a/"lib/i386.dylib" - FileUtils.ln a/"lib/i386.dylib", a/"lib/i386_link.dylib" - FileUtils.ln_s a/"lib/i386.dylib", a/"lib/1.dylib" - - keg = Keg.new(a) - keg.link - - assert_equal 1, keg.mach_o_files.size - ensure - keg.unlink - keg.uninstall - end -end diff --git a/Library/Homebrew/test/os/mac/language_test.rb b/Library/Homebrew/test/os/mac/language_test.rb deleted file mode 100644 index e328db5e0..000000000 --- a/Library/Homebrew/test/os/mac/language_test.rb +++ /dev/null @@ -1,19 +0,0 @@ -require "testing_env" -require "locale" -require "os/mac" - -class OSMacLanguageTests < Homebrew::TestCase - def test_languages_format - OS::Mac.languages.each do |language| - assert_nothing_raised do - Locale.parse(language) - end - end - end - - def test_language_format - assert_nothing_raised do - Locale.parse(OS::Mac.language) - end - end -end diff --git a/Library/Homebrew/test/os/mac/mach_spec.rb b/Library/Homebrew/test/os/mac/mach_spec.rb new file mode 100644 index 000000000..5c9aafcbb --- /dev/null +++ b/Library/Homebrew/test/os/mac/mach_spec.rb @@ -0,0 +1,198 @@ +describe "Mach-O Pathname tests" do + specify "fat dylib" do + pn = dylib_path("fat") + expect(pn).to be_universal + expect(pn).not_to be_i386 + expect(pn).not_to be_x86_64 + expect(pn).not_to be_ppc7400 + expect(pn).not_to be_ppc64 + expect(pn).to be_dylib + expect(pn).not_to be_mach_o_executable + expect(pn).not_to be_text_executable + expect(pn.arch).to eq(:universal) + end + + specify "i386 dylib" do + pn = dylib_path("i386") + expect(pn).not_to be_universal + expect(pn).to be_i386 + expect(pn).not_to be_x86_64 + expect(pn).not_to be_ppc7400 + expect(pn).not_to be_ppc64 + expect(pn).to be_dylib + expect(pn).not_to be_mach_o_executable + expect(pn).not_to be_text_executable + expect(pn).not_to be_mach_o_bundle + end + + specify "x86_64 dylib" do + pn = dylib_path("x86_64") + expect(pn).not_to be_universal + expect(pn).not_to be_i386 + expect(pn).to be_x86_64 + expect(pn).not_to be_ppc7400 + expect(pn).not_to be_ppc64 + expect(pn).to be_dylib + expect(pn).not_to be_mach_o_executable + expect(pn).not_to be_text_executable + expect(pn).not_to be_mach_o_bundle + end + + specify "Mach-O executable" do + pn = Pathname.new("#{TEST_FIXTURE_DIR}/mach/a.out") + expect(pn).to be_universal + expect(pn).not_to be_i386 + expect(pn).not_to be_x86_64 + expect(pn).not_to be_ppc7400 + expect(pn).not_to be_ppc64 + expect(pn).not_to be_dylib + expect(pn).to be_mach_o_executable + expect(pn).not_to be_text_executable + expect(pn).not_to be_mach_o_bundle + end + + specify "fat bundle" do + pn = bundle_path("fat") + expect(pn).to be_universal + expect(pn).not_to be_i386 + expect(pn).not_to be_x86_64 + expect(pn).not_to be_ppc7400 + expect(pn).not_to be_ppc64 + expect(pn).not_to be_dylib + expect(pn).not_to be_mach_o_executable + expect(pn).not_to be_text_executable + expect(pn).to be_mach_o_bundle + end + + specify "i386 bundle" do + pn = bundle_path("i386") + expect(pn).not_to be_universal + expect(pn).to be_i386 + expect(pn).not_to be_x86_64 + expect(pn).not_to be_ppc7400 + expect(pn).not_to be_ppc64 + expect(pn).not_to be_dylib + expect(pn).not_to be_mach_o_executable + expect(pn).not_to be_text_executable + expect(pn).to be_mach_o_bundle + end + + specify "x86_64 bundle" do + pn = bundle_path("x86_64") + expect(pn).not_to be_universal + expect(pn).not_to be_i386 + expect(pn).to be_x86_64 + expect(pn).not_to be_ppc7400 + expect(pn).not_to be_ppc64 + expect(pn).not_to be_dylib + expect(pn).not_to be_mach_o_executable + expect(pn).not_to be_text_executable + expect(pn).to be_mach_o_bundle + end + + specify "non-Mach-O" do + pn = Pathname.new("#{TEST_FIXTURE_DIR}/tarballs/testball-0.1.tbz") + expect(pn).not_to be_universal + expect(pn).not_to be_i386 + expect(pn).not_to be_x86_64 + expect(pn).not_to be_ppc7400 + expect(pn).not_to be_ppc64 + expect(pn).not_to be_dylib + expect(pn).not_to be_mach_o_executable + expect(pn).not_to be_text_executable + expect(pn).not_to be_mach_o_bundle + expect(pn.arch).to eq(:dunno) + end +end + +describe ArchitectureListExtension do + let(:archs) { [:i386, :x86_64, :ppc7400, :ppc64].extend(described_class) } + + specify "universal checks" do + expect(archs).to be_universal + expect(archs).to be_intel_universal + expect(archs).to be_ppc_universal + expect(archs).to be_cross_universal + expect(archs).to be_fat + + non_universal = [:i386].extend(described_class) + expect(non_universal).not_to be_universal + + intel_only = [:i386, :x86_64].extend(described_class) + expect(intel_only).to be_universal + expect(intel_only).not_to be_ppc_universal + expect(intel_only).not_to be_cross_universal + + ppc_only = [:ppc970, :ppc64].extend(described_class) + expect(ppc_only).to be_universal + expect(ppc_only).not_to be_intel_universal + expect(ppc_only).not_to be_cross_universal + + cross = [:ppc7400, :i386].extend(described_class) + expect(cross).to be_universal + expect(cross).not_to be_intel_universal + expect(cross).not_to be_ppc_universal + end + + specify "messaging flags" do + archs.remove_ppc! + expect(archs.length).to eq(2) + expect(archs.as_arch_flags).to match(/-arch i386/) + expect(archs.as_arch_flags).to match(/-arch x86_64/) + end + + specify "architecture flags" do + pn = dylib_path("fat") + expect(pn.archs).to be_intel_universal + expect(pn.archs.as_arch_flags).to eq("-arch x86_64 -arch i386") + expect(pn.archs.as_cmake_arch_flags).to eq("x86_64;i386") + end +end + +describe "text executables" do + let(:pn) { HOMEBREW_PREFIX/"an_executable" } + + after(:each) { pn.unlink } + + specify "simple shebang" do + pn.write "#!/bin/sh" + expect(pn).not_to be_universal + expect(pn).not_to be_i386 + expect(pn).not_to be_x86_64 + expect(pn).not_to be_ppc7400 + expect(pn).not_to be_ppc64 + expect(pn).not_to be_dylib + expect(pn).not_to be_mach_o_executable + expect(pn).to be_text_executable + expect(pn.archs).to eq([]) + expect(pn.arch).to eq(:dunno) + end + + specify "shebang with options" do + pn.write "#! /usr/bin/perl -w" + expect(pn).not_to be_universal + expect(pn).not_to be_i386 + expect(pn).not_to be_x86_64 + expect(pn).not_to be_ppc7400 + expect(pn).not_to be_ppc64 + expect(pn).not_to be_dylib + expect(pn).not_to be_mach_o_executable + expect(pn).to be_text_executable + expect(pn.archs).to eq([]) + expect(pn.arch).to eq(:dunno) + end + + specify "malformed shebang" do + pn.write " #!" + expect(pn).not_to be_universal + expect(pn).not_to be_i386 + expect(pn).not_to be_x86_64 + expect(pn).not_to be_ppc7400 + expect(pn).not_to be_ppc64 + expect(pn).not_to be_dylib + expect(pn).not_to be_mach_o_executable + expect(pn).not_to be_text_executable + expect(pn.archs).to eq([]) + expect(pn.arch).to eq(:dunno) + end +end diff --git a/Library/Homebrew/test/os/mac/mach_test.rb b/Library/Homebrew/test/os/mac/mach_test.rb deleted file mode 100644 index a42f7316b..000000000 --- a/Library/Homebrew/test/os/mac/mach_test.rb +++ /dev/null @@ -1,208 +0,0 @@ -require "testing_env" - -class MachOPathnameTests < Homebrew::TestCase - def test_fat_dylib - pn = dylib_path("fat") - assert_predicate pn, :universal? - refute_predicate pn, :i386? - refute_predicate pn, :x86_64? - refute_predicate pn, :ppc7400? - refute_predicate pn, :ppc64? - assert_predicate pn, :dylib? - refute_predicate pn, :mach_o_executable? - refute_predicate pn, :text_executable? - assert_equal :universal, pn.arch - end - - def test_i386_dylib - pn = dylib_path("i386") - refute_predicate pn, :universal? - assert_predicate pn, :i386? - refute_predicate pn, :x86_64? - refute_predicate pn, :ppc7400? - refute_predicate pn, :ppc64? - assert_predicate pn, :dylib? - refute_predicate pn, :mach_o_executable? - refute_predicate pn, :text_executable? - refute_predicate pn, :mach_o_bundle? - end - - def test_x86_64_dylib - pn = dylib_path("x86_64") - refute_predicate pn, :universal? - refute_predicate pn, :i386? - assert_predicate pn, :x86_64? - refute_predicate pn, :ppc7400? - refute_predicate pn, :ppc64? - assert_predicate pn, :dylib? - refute_predicate pn, :mach_o_executable? - refute_predicate pn, :text_executable? - refute_predicate pn, :mach_o_bundle? - end - - def test_mach_o_executable - pn = Pathname.new("#{TEST_FIXTURE_DIR}/mach/a.out") - assert_predicate pn, :universal? - refute_predicate pn, :i386? - refute_predicate pn, :x86_64? - refute_predicate pn, :ppc7400? - refute_predicate pn, :ppc64? - refute_predicate pn, :dylib? - assert_predicate pn, :mach_o_executable? - refute_predicate pn, :text_executable? - refute_predicate pn, :mach_o_bundle? - end - - def test_fat_bundle - pn = bundle_path("fat") - assert_predicate pn, :universal? - refute_predicate pn, :i386? - refute_predicate pn, :x86_64? - refute_predicate pn, :ppc7400? - refute_predicate pn, :ppc64? - refute_predicate pn, :dylib? - refute_predicate pn, :mach_o_executable? - refute_predicate pn, :text_executable? - assert_predicate pn, :mach_o_bundle? - end - - def test_i386_bundle - pn = bundle_path("i386") - refute_predicate pn, :universal? - assert_predicate pn, :i386? - refute_predicate pn, :x86_64? - refute_predicate pn, :ppc7400? - refute_predicate pn, :ppc64? - refute_predicate pn, :dylib? - refute_predicate pn, :mach_o_executable? - refute_predicate pn, :text_executable? - assert_predicate pn, :mach_o_bundle? - end - - def test_x86_64_bundle - pn = bundle_path("x86_64") - refute_predicate pn, :universal? - refute_predicate pn, :i386? - assert_predicate pn, :x86_64? - refute_predicate pn, :ppc7400? - refute_predicate pn, :ppc64? - refute_predicate pn, :dylib? - refute_predicate pn, :mach_o_executable? - refute_predicate pn, :text_executable? - assert_predicate pn, :mach_o_bundle? - end - - def test_non_mach_o - pn = Pathname.new("#{TEST_FIXTURE_DIR}/tarballs/testball-0.1.tbz") - refute_predicate pn, :universal? - refute_predicate pn, :i386? - refute_predicate pn, :x86_64? - refute_predicate pn, :ppc7400? - refute_predicate pn, :ppc64? - refute_predicate pn, :dylib? - refute_predicate pn, :mach_o_executable? - refute_predicate pn, :text_executable? - refute_predicate pn, :mach_o_bundle? - assert_equal :dunno, pn.arch - end -end - -class ArchitectureListExtensionTests < MachOPathnameTests - def setup - @archs = [:i386, :x86_64, :ppc7400, :ppc64].extend(ArchitectureListExtension) - end - - def test_architecture_list_extension_universal_checks - assert_predicate @archs, :universal? - assert_predicate @archs, :intel_universal? - assert_predicate @archs, :ppc_universal? - assert_predicate @archs, :cross_universal? - assert_predicate @archs, :fat? - - non_universal = [:i386].extend ArchitectureListExtension - refute_predicate non_universal, :universal? - - intel_only = [:i386, :x86_64].extend ArchitectureListExtension - assert_predicate intel_only, :universal? - refute_predicate intel_only, :ppc_universal? - refute_predicate intel_only, :cross_universal? - - ppc_only = [:ppc970, :ppc64].extend ArchitectureListExtension - assert_predicate ppc_only, :universal? - refute_predicate ppc_only, :intel_universal? - refute_predicate ppc_only, :cross_universal? - - cross = [:ppc7400, :i386].extend ArchitectureListExtension - assert_predicate cross, :universal? - refute_predicate cross, :intel_universal? - refute_predicate cross, :ppc_universal? - end - - def test_architecture_list_extension_massaging_flags - @archs.remove_ppc! - assert_equal 2, @archs.length - assert_match(/-arch i386/, @archs.as_arch_flags) - assert_match(/-arch x86_64/, @archs.as_arch_flags) - end - - def test_architecture_list_arch_flags_methods - pn = dylib_path("fat") - assert_predicate pn.archs, :intel_universal? - assert_equal "-arch x86_64 -arch i386", pn.archs.as_arch_flags - assert_equal "x86_64;i386", pn.archs.as_cmake_arch_flags - end -end - -class TextExecutableTests < Homebrew::TestCase - attr_reader :pn - - def setup - @pn = HOMEBREW_PREFIX.join("an_executable") - end - - def teardown - HOMEBREW_PREFIX.join("an_executable").unlink - end - - def test_simple_shebang - pn.write "#!/bin/sh" - refute_predicate pn, :universal? - refute_predicate pn, :i386? - refute_predicate pn, :x86_64? - refute_predicate pn, :ppc7400? - refute_predicate pn, :ppc64? - refute_predicate pn, :dylib? - refute_predicate pn, :mach_o_executable? - assert_predicate pn, :text_executable? - assert_equal [], pn.archs - assert_equal :dunno, pn.arch - end - - def test_shebang_with_options - pn.write "#! /usr/bin/perl -w" - refute_predicate pn, :universal? - refute_predicate pn, :i386? - refute_predicate pn, :x86_64? - refute_predicate pn, :ppc7400? - refute_predicate pn, :ppc64? - refute_predicate pn, :dylib? - refute_predicate pn, :mach_o_executable? - assert_predicate pn, :text_executable? - assert_equal [], pn.archs - assert_equal :dunno, pn.arch - end - - def test_malformed_shebang - pn.write " #!" - refute_predicate pn, :universal? - refute_predicate pn, :i386? - refute_predicate pn, :x86_64? - refute_predicate pn, :ppc7400? - refute_predicate pn, :ppc64? - refute_predicate pn, :dylib? - refute_predicate pn, :mach_o_executable? - refute_predicate pn, :text_executable? - assert_equal [], pn.archs - assert_equal :dunno, pn.arch - end -end diff --git a/Library/Homebrew/test/os/mac/version_spec.rb b/Library/Homebrew/test/os/mac/version_spec.rb new file mode 100644 index 000000000..797207b67 --- /dev/null +++ b/Library/Homebrew/test/os/mac/version_spec.rb @@ -0,0 +1,51 @@ +require "version" +require "os/mac/version" + +describe OS::Mac::Version do + subject { described_class.new("10.7") } + + specify "comparison with Symbol" do + expect(subject).to be > :snow_leopard + expect(subject).to be == :lion + expect(subject).to be === :lion # rubocop:disable Style/CaseEquality + expect(subject).to be < :mountain_lion + end + + specify "comparison with Fixnum" do + expect(subject).to be > 10 + expect(subject).to be < 11 + end + + specify "comparison with Float" do + expect(subject).to be > 10.6 + expect(subject).to be == 10.7 + expect(subject).to be === 10.7 # rubocop:disable Style/CaseEquality + expect(subject).to be < 10.8 + end + + specify "comparison with String" do + expect(subject).to be > "10.6" + expect(subject).to be == "10.7" + expect(subject).to be === "10.7" # rubocop:disable Style/CaseEquality + expect(subject).to be < "10.8" + end + + specify "comparison with Version" do + expect(subject).to be > Version.create("10.6") + expect(subject).to be == Version.create("10.7") + expect(subject).to be === Version.create("10.7") # rubocop:disable Style/CaseEquality + expect(subject).to be < Version.create("10.8") + end + + specify "#from_symbol" do + expect(described_class.from_symbol(:lion)).to eq(subject) + expect { described_class.from_symbol(:foo) } + .to raise_error(ArgumentError) + end + + specify "#pretty_name" do + expect(described_class.new("10.11").pretty_name).to eq("El Capitan") + expect(described_class.new("10.8").pretty_name).to eq("Mountain Lion") + expect(described_class.new("10.10").pretty_name).to eq("Yosemite") + end +end diff --git a/Library/Homebrew/test/os/mac/version_test.rb b/Library/Homebrew/test/os/mac/version_test.rb deleted file mode 100644 index f702c7097..000000000 --- a/Library/Homebrew/test/os/mac/version_test.rb +++ /dev/null @@ -1,53 +0,0 @@ -require "testing_env" -require "version" -require "os/mac/version" - -class OSMacVersionTests < Homebrew::TestCase - def setup - @v = MacOS::Version.new("10.7") - end - - def test_compare_with_symbol - assert_operator @v, :>, :snow_leopard - assert_operator @v, :==, :lion - assert_operator @v, :===, :lion - assert_operator @v, :<, :mountain_lion - end - - def test_compare_with_fixnum - assert_operator @v, :>, 10 - assert_operator @v, :<, 11 - end - - def test_compare_with_float - assert_operator @v, :>, 10.6 - assert_operator @v, :==, 10.7 - assert_operator @v, :===, 10.7 - assert_operator @v, :<, 10.8 - end - - def test_compare_with_string - assert_operator @v, :>, "10.6" - assert_operator @v, :==, "10.7" - assert_operator @v, :===, "10.7" - assert_operator @v, :<, "10.8" - end - - def test_compare_with_version - assert_operator @v, :>, Version.create("10.6") - assert_operator @v, :==, Version.create("10.7") - assert_operator @v, :===, Version.create("10.7") - assert_operator @v, :<, Version.create("10.8") - end - - def test_from_symbol - assert_equal @v, MacOS::Version.from_symbol(:lion) - assert_raises(ArgumentError) { MacOS::Version.from_symbol(:foo) } - end - - def test_pretty_name - assert_equal "El Capitan", MacOS::Version.new("10.11").pretty_name - assert_equal "Mountain Lion", MacOS::Version.new("10.8").pretty_name - assert_equal "Yosemite", MacOS::Version.new("10.10").pretty_name - end -end diff --git a/Library/Homebrew/test/os/mac_spec.rb b/Library/Homebrew/test/os/mac_spec.rb new file mode 100644 index 000000000..641782451 --- /dev/null +++ b/Library/Homebrew/test/os/mac_spec.rb @@ -0,0 +1,22 @@ +require "locale" +require "os/mac" + +describe OS::Mac do + describe "::languages" do + specify "all languages can be parsed by Locale::parse" do + subject.languages.each do |language| + expect { Locale.parse(language) }.not_to raise_error + end + end + end + + describe "::language" do + it "returns the first item from #languages" do + expect(subject.language).to eq(subject.languages.first) + end + + it "can be parsed by Locale::parse" do + expect { Locale.parse(subject.language) }.not_to raise_error + end + end +end diff --git a/Library/Homebrew/test/outdated_test.rb b/Library/Homebrew/test/outdated_test.rb deleted file mode 100644 index 3e7148ded..000000000 --- a/Library/Homebrew/test/outdated_test.rb +++ /dev/null @@ -1,10 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestOutdated < IntegrationCommandTestCase - def test_outdated - setup_test_formula "testball" - (HOMEBREW_CELLAR/"testball/0.0.1/foo").mkpath - - assert_equal "testball", cmd("outdated") - end -end diff --git a/Library/Homebrew/test/patch_spec.rb b/Library/Homebrew/test/patch_spec.rb new file mode 100644 index 000000000..22c103662 --- /dev/null +++ b/Library/Homebrew/test/patch_spec.rb @@ -0,0 +1,165 @@ +require "patch" + +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) } + end + + 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 + + it "raises an error for unknown values" do + expect { + described_class.create(Object.new) + }.to raise_error(ArgumentError) + + expect { + described_class.create(Object.new, Object.new) + }.to raise_error(ArgumentError) + end + end + + describe "#patch_files" do + subject { described_class.create(:p2, nil) } + + context "empty patch" do + its(:resource) { is_expected.to be_kind_of Resource::Patch } + its(:patch_files) { is_expected.to eq(subject.resource.patch_files) } + its(:patch_files) { is_expected.to eq([]) } + end + + it "returns applied patch files" do + subject.resource.apply("patch1.diff") + expect(subject.patch_files).to eq(["patch1.diff"]) + + subject.resource.apply("patch2.diff", "patch3.diff") + expect(subject.patch_files).to eq(["patch1.diff", "patch2.diff", "patch3.diff"]) + + subject.resource.apply(["patch4.diff", "patch5.diff"]) + expect(subject.patch_files.count).to eq(5) + + subject.resource.apply("patch4.diff", ["patch5.diff", "patch6.diff"], "patch7.diff") + expect(subject.patch_files.count).to eq(7) + end + end + + describe "#normalize_legacy_patches" do + it "can create a patch from a single string" do + patches = described_class.normalize_legacy_patches("http://example.com/patch.diff") + expect(patches.length).to eq(1) + expect(patches.first.strip).to eq(:p1) + end + + it "can create patches from an array" do + patches = described_class.normalize_legacy_patches( + %w[http://example.com/patch1.diff http://example.com/patch2.diff], + ) + + expect(patches.length).to eq(2) + expect(patches[0].strip).to eq(:p1) + expect(patches[1].strip).to eq(:p1) + end + + it "can create patches from a :p0 hash" do + patches = Patch.normalize_legacy_patches( + p0: "http://example.com/patch.diff", + ) + + expect(patches.length).to eq(1) + expect(patches.first.strip).to eq(:p0) + end + + it "can create patches from a :p1 hash" do + patches = Patch.normalize_legacy_patches( + p1: "http://example.com/patch.diff", + ) + + expect(patches.length).to eq(1) + expect(patches.first.strip).to eq(:p1) + end + + it "can create patches from a mixed hash" do + patches = Patch.normalize_legacy_patches( + p1: "http://example.com/patch1.diff", + p0: "http://example.com/patch0.diff", + ) + + expect(patches.length).to eq(2) + expect(patches.count { |p| p.strip == :p0 }).to eq(1) + expect(patches.count { |p| p.strip == :p1 }).to eq(1) + end + + it "can create patches from a mixed hash with array" do + patches = Patch.normalize_legacy_patches( + p1: [ + "http://example.com/patch10.diff", + "http://example.com/patch11.diff", + ], + p0: [ + "http://example.com/patch00.diff", + "http://example.com/patch01.diff", + ], + ) + + expect(patches.length).to eq(4) + expect(patches.count { |p| p.strip == :p0 }).to eq(2) + expect(patches.count { |p| p.strip == :p1 }).to eq(2) + end + + it "returns an empty array if given nil" do + expect(Patch.normalize_legacy_patches(nil)).to be_empty + end + end +end + +describe EmbeddedPatch do + describe "#new" do + subject { described_class.new(:p1) } + its(:inspect) { is_expected.to eq("#<EmbeddedPatch: :p1>") } + end +end + +describe ExternalPatch do + subject { described_class.new(:p1) { url "file:///my.patch" } } + + describe "#url" do + its(:url) { is_expected.to eq("file:///my.patch") } + end + + describe "#inspect" do + its(:inspect) { is_expected.to eq('#<ExternalPatch: :p1 "file:///my.patch">') } + end + + describe "#cached_download" do + before(:each) do + allow(subject.resource).to receive(:cached_download).and_return("/tmp/foo.tar.gz") + end + + its(:cached_download) { is_expected.to eq("/tmp/foo.tar.gz") } + end +end diff --git a/Library/Homebrew/test/patch_test.rb b/Library/Homebrew/test/patch_test.rb deleted file mode 100644 index 62624720e..000000000 --- a/Library/Homebrew/test/patch_test.rb +++ /dev/null @@ -1,154 +0,0 @@ -require "testing_env" -require "patch" - -class PatchTests < Homebrew::TestCase - def test_create_simple - patch = Patch.create(:p2, nil) - assert_kind_of ExternalPatch, patch - assert_predicate patch, :external? - assert_equal :p2, patch.strip - end - - def test_create_string - patch = Patch.create(:p0, "foo") - assert_kind_of StringPatch, patch - assert_equal :p0, patch.strip - end - - def test_create_string_without_strip - patch = Patch.create("foo", nil) - assert_kind_of StringPatch, patch - assert_equal :p1, patch.strip - end - - def test_create_data - patch = Patch.create(:p0, :DATA) - assert_kind_of DATAPatch, patch - assert_equal :p0, patch.strip - end - - def test_create_data_without_strip - patch = Patch.create(:DATA, nil) - assert_kind_of DATAPatch, patch - assert_equal :p1, patch.strip - end - - def test_raises_for_unknown_values - assert_raises(ArgumentError) { Patch.create(Object.new) } - assert_raises(ArgumentError) { Patch.create(Object.new, Object.new) } - end -end - -class LegacyPatchTests < Homebrew::TestCase - def test_patch_single_string - patches = Patch.normalize_legacy_patches("http://example.com/patch.diff") - assert_equal 1, patches.length - assert_equal :p1, patches.first.strip - end - - def test_patch_array - patches = Patch.normalize_legacy_patches( - %w[http://example.com/patch1.diff http://example.com/patch2.diff] - ) - - assert_equal 2, patches.length - assert_equal :p1, patches[0].strip - assert_equal :p1, patches[1].strip - end - - def test_p0_hash_to_string - patches = Patch.normalize_legacy_patches( - p0: "http://example.com/patch.diff" - ) - - assert_equal 1, patches.length - assert_equal :p0, patches.first.strip - end - - def test_p1_hash_to_string - patches = Patch.normalize_legacy_patches( - p1: "http://example.com/patch.diff" - ) - - assert_equal 1, patches.length - assert_equal :p1, patches.first.strip - end - - def test_mixed_hash_to_strings - patches = Patch.normalize_legacy_patches( - p1: "http://example.com/patch1.diff", - p0: "http://example.com/patch0.diff" - ) - assert_equal 2, patches.length - assert_equal 1, patches.count { |p| p.strip == :p0 } - assert_equal 1, patches.count { |p| p.strip == :p1 } - end - - def test_mixed_hash_to_arrays - patches = Patch.normalize_legacy_patches( - p1: ["http://example.com/patch10.diff", - "http://example.com/patch11.diff"], - p0: ["http://example.com/patch00.diff", - "http://example.com/patch01.diff"] - ) - - assert_equal 4, patches.length - assert_equal 2, patches.count { |p| p.strip == :p0 } - assert_equal 2, patches.count { |p| p.strip == :p1 } - end - - def test_nil - assert_empty Patch.normalize_legacy_patches(nil) - end -end - -class EmbeddedPatchTests < Homebrew::TestCase - def test_inspect - p = EmbeddedPatch.new :p1 - assert_equal "#<EmbeddedPatch: :p1>", p.inspect - end -end - -class ExternalPatchTests < Homebrew::TestCase - def setup - @p = ExternalPatch.new(:p1) { url "file:///my.patch" } - end - - def test_url - assert_equal "file:///my.patch", @p.url - end - - def test_inspect - assert_equal '#<ExternalPatch: :p1 "file:///my.patch">', @p.inspect - end - - def test_cached_download - @p.resource.stubs(:cached_download).returns "/tmp/foo.tar.gz" - assert_equal "/tmp/foo.tar.gz", @p.cached_download - end -end - -class ApplyPatchTests < Homebrew::TestCase - def test_empty_patch_files - patch = Patch.create(:p2, nil) - resource = patch.resource - patch_files = patch.patch_files - assert_kind_of Resource::Patch, resource - assert_equal patch_files, resource.patch_files - assert_equal patch_files, [] - end - - def test_resource_patch_apply_method - patch = Patch.create(:p2, nil) - resource = patch.resource - patch_files = patch.patch_files - resource.apply("patch1.diff") - assert_equal patch_files, ["patch1.diff"] - resource.apply("patch2.diff", "patch3.diff") - assert_equal patch_files, ["patch1.diff", "patch2.diff", "patch3.diff"] - resource.apply(["patch4.diff", "patch5.diff"]) - assert_equal patch_files.count, 5 - resource.apply("patch4.diff", ["patch5.diff", "patch6.diff"], "patch7.diff") - assert_equal patch_files.count, 7 - end -end diff --git a/Library/Homebrew/test/patching_spec.rb b/Library/Homebrew/test/patching_spec.rb new file mode 100644 index 000000000..dd849ca92 --- /dev/null +++ b/Library/Homebrew/test/patching_spec.rb @@ -0,0 +1,289 @@ +require "formula" + +describe "patching" do + TESTBALL_URL = "file://#{TEST_FIXTURE_DIR}/tarballs/testball-0.1.tbz".freeze + TESTBALL_PATCHES_URL = "file://#{TEST_FIXTURE_DIR}/tarballs/testball-0.1-patches.tgz".freeze + PATCH_URL_A = "file://#{TEST_FIXTURE_DIR}/patches/noop-a.diff".freeze + PATCH_URL_B = "file://#{TEST_FIXTURE_DIR}/patches/noop-b.diff".freeze + PATCH_A_CONTENTS = File.read "#{TEST_FIXTURE_DIR}/patches/noop-a.diff" + PATCH_B_CONTENTS = File.read "#{TEST_FIXTURE_DIR}/patches/noop-b.diff" + APPLY_A = "noop-a.diff".freeze + APPLY_B = "noop-b.diff".freeze + APPLY_C = "noop-c.diff".freeze + + def formula(name = "formula_name", path: Formulary.core_path(name), spec: :stable, alias_path: nil, &block) + Class.new(Formula) { + url TESTBALL_URL + sha256 TESTBALL_SHA256 + class_eval(&block) + }.new(name, path, spec, alias_path: alias_path) + end + + matcher :be_patched do + match do |formula| + shutup do + formula.brew do + formula.patch + s = File.read("libexec/NOOP") + expect(s).not_to include("NOOP"), "libexec/NOOP was not patched as expected" + expect(s).to include("ABCD"), "libexec/NOOP was not patched as expected" + end + end + end + end + + matcher :be_sequentially_patched do + match do |formula| + shutup do + formula.brew do + formula.patch + s = File.read("libexec/NOOP") + expect(s).not_to include("NOOP"), "libexec/NOOP was not patched as expected" + expect(s).not_to include("ABCD"), "libexec/NOOP was not patched as expected" + expect(s).to include("1234"), "libexec/NOOP was not patched as expected" + end + end + end + end + + matcher :miss_apply do + match do |formula| + expect { + shutup do + formula.brew do + formula.patch + end + end + }.to raise_error(MissingApplyError) + end + end + + specify "single_patch" do + expect( + formula do + def patches + PATCH_URL_A + end + end, + ).to be_patched + end + + specify "single_patch_dsl" do + expect( + formula do + patch do + url PATCH_URL_A + sha256 PATCH_A_SHA256 + end + end, + ).to be_patched + end + + specify "single_patch_dsl_with_apply" do + expect( + formula do + patch do + url TESTBALL_PATCHES_URL + sha256 TESTBALL_PATCHES_SHA256 + apply APPLY_A + end + end, + ).to be_patched + end + + specify "single_patch_dsl_with_sequential_apply" do + expect( + formula do + patch do + url TESTBALL_PATCHES_URL + sha256 TESTBALL_PATCHES_SHA256 + apply APPLY_A, APPLY_C + end + end, + ).to be_sequentially_patched + end + + specify "single_patch_dsl_with_strip" do + expect( + formula do + patch :p1 do + url PATCH_URL_A + sha256 PATCH_A_SHA256 + end + end, + ).to be_patched + end + + specify "single_patch_dsl_with_strip_with_apply" do + expect( + formula do + patch :p1 do + url TESTBALL_PATCHES_URL + sha256 TESTBALL_PATCHES_SHA256 + apply APPLY_A + end + end, + ).to be_patched + end + + specify "single_patch_dsl_with_incorrect_strip" do + expect { + shutup do + f = formula do + patch :p0 do + url PATCH_URL_A + sha256 PATCH_A_SHA256 + end + end + + f.brew { |formula, _staging| formula.patch } + end + }.to raise_error(ErrorDuringExecution) + end + + specify "single_patch_dsl_with_incorrect_strip_with_apply" do + expect { + shutup do + f = formula do + patch :p0 do + url TESTBALL_PATCHES_URL + sha256 TESTBALL_PATCHES_SHA256 + apply APPLY_A + end + end + + f.brew { |formula, _staging| formula.patch } + end + }.to raise_error(ErrorDuringExecution) + end + + specify "patch_p0_dsl" do + expect( + formula do + patch :p0 do + url PATCH_URL_B + sha256 PATCH_B_SHA256 + end + end, + ).to be_patched + end + + specify "patch_p0_dsl_with_apply" do + expect( + formula do + patch :p0 do + url TESTBALL_PATCHES_URL + sha256 TESTBALL_PATCHES_SHA256 + apply APPLY_B + end + end, + ).to be_patched + end + + specify "patch_p0" do + expect( + formula do + def patches + { p0: PATCH_URL_B } + end + end, + ).to be_patched + end + + specify "patch_array" do + expect( + formula do + def patches + [PATCH_URL_A] + end + end, + ).to be_patched + end + + specify "patch_hash" do + expect( + formula do + def patches + { p1: PATCH_URL_A } + end + end, + ).to be_patched + end + + specify "patch_hash_array" do + expect( + formula do + def patches + { p1: [PATCH_URL_A] } + end + end, + ).to be_patched + end + + specify "patch_string" do + expect(formula { patch PATCH_A_CONTENTS }).to be_patched + end + + specify "patch_string_with_strip" do + expect(formula { patch :p0, PATCH_B_CONTENTS }).to be_patched + end + + specify "patch_data_constant" do + expect( + formula("test", path: Pathname.new(__FILE__).expand_path) do + def patches + :DATA + end + end, + ).to be_patched + end + + specify "single_patch_missing_apply_fail" do + expect( + formula do + def patches + TESTBALL_PATCHES_URL + end + end, + ).to miss_apply + end + + specify "single_patch_dsl_missing_apply_fail" do + expect( + formula do + patch do + url TESTBALL_PATCHES_URL + sha256 TESTBALL_PATCHES_SHA256 + end + end, + ).to miss_apply + end + + specify "single_patch_dsl_with_apply_enoent_fail" do + expect { + shutup do + f = formula do + patch do + url TESTBALL_PATCHES_URL + sha256 TESTBALL_PATCHES_SHA256 + apply "patches/#{APPLY_A}" + end + end + + f.brew { |formula, _staging| formula.patch } + end + }.to raise_error(ErrorDuringExecution) + end +end + +__END__ +diff --git a/libexec/NOOP b/libexec/NOOP +index bfdda4c..e08d8f4 100755 +--- a/libexec/NOOP ++++ b/libexec/NOOP +@@ -1,2 +1,2 @@ + #!/bin/bash +-echo NOOP +\ No newline at end of file ++echo ABCD +\ No newline at end of file diff --git a/Library/Homebrew/test/patching_test.rb b/Library/Homebrew/test/patching_test.rb deleted file mode 100644 index ac14c8e1e..000000000 --- a/Library/Homebrew/test/patching_test.rb +++ /dev/null @@ -1,253 +0,0 @@ -require "testing_env" -require "formula" - -class PatchingTests < Homebrew::TestCase - TESTBALL_URL = "file://#{TEST_FIXTURE_DIR}/tarballs/testball-0.1.tbz".freeze - TESTBALL_PATCHES_URL = "file://#{TEST_FIXTURE_DIR}/tarballs/testball-0.1-patches.tgz".freeze - PATCH_URL_A = "file://#{TEST_FIXTURE_DIR}/patches/noop-a.diff".freeze - PATCH_URL_B = "file://#{TEST_FIXTURE_DIR}/patches/noop-b.diff".freeze - PATCH_A_CONTENTS = File.read "#{TEST_FIXTURE_DIR}/patches/noop-a.diff" - PATCH_B_CONTENTS = File.read "#{TEST_FIXTURE_DIR}/patches/noop-b.diff" - APPLY_A = "noop-a.diff".freeze - APPLY_B = "noop-b.diff".freeze - APPLY_C = "noop-c.diff".freeze - - def formula(*args, &block) - super do - url TESTBALL_URL - sha256 TESTBALL_SHA256 - class_eval(&block) - end - end - - def teardown - @_f.clear_cache - @_f.patchlist.each { |p| p.clear_cache if p.external? } - end - - def assert_patched(formula) - shutup do - formula.brew do - formula.patch - s = File.read("libexec/NOOP") - refute_includes s, "NOOP", "libexec/NOOP was not patched as expected" - assert_includes s, "ABCD", "libexec/NOOP was not patched as expected" - end - end - end - - def assert_sequentially_patched(formula) - shutup do - formula.brew do - formula.patch - s = File.read("libexec/NOOP") - refute_includes s, "NOOP", "libexec/NOOP was not patched as expected" - refute_includes s, "ABCD", "libexec/NOOP was not patched as expected" - assert_includes s, "1234", "libexec/NOOP was not patched as expected" - end - end - end - - def assert_missing_apply_fail(formula) - assert_raises(MissingApplyError) do - shutup do - formula.brew do - formula.patch - end - end - end - end - - def test_single_patch - assert_patched formula { - def patches - PATCH_URL_A - end - } - end - - def test_single_patch_dsl - assert_patched formula { - patch do - url PATCH_URL_A - sha256 PATCH_A_SHA256 - end - } - end - - def test_single_patch_dsl_with_apply - assert_patched formula { - patch do - url TESTBALL_PATCHES_URL - sha256 TESTBALL_PATCHES_SHA256 - apply APPLY_A - end - } - end - - def test_single_patch_dsl_with_sequential_apply - assert_sequentially_patched formula { - patch do - url TESTBALL_PATCHES_URL - sha256 TESTBALL_PATCHES_SHA256 - apply APPLY_A, APPLY_C - end - } - end - - def test_single_patch_dsl_with_strip - assert_patched formula { - patch :p1 do - url PATCH_URL_A - sha256 PATCH_A_SHA256 - end - } - end - - def test_single_patch_dsl_with_strip_with_apply - assert_patched formula { - patch :p1 do - url TESTBALL_PATCHES_URL - sha256 TESTBALL_PATCHES_SHA256 - apply APPLY_A - end - } - end - - def test_single_patch_dsl_with_incorrect_strip - assert_raises(ErrorDuringExecution) do - shutup do - formula do - patch :p0 do - url PATCH_URL_A - sha256 PATCH_A_SHA256 - end - end.brew { |f, _staging| f.patch } - end - end - end - - def test_single_patch_dsl_with_incorrect_strip_with_apply - assert_raises(ErrorDuringExecution) do - shutup do - formula do - patch :p0 do - url TESTBALL_PATCHES_URL - sha256 TESTBALL_PATCHES_SHA256 - apply APPLY_A - end - end.brew { |f, _staging| f.patch } - end - end - end - - def test_patch_p0_dsl - assert_patched formula { - patch :p0 do - url PATCH_URL_B - sha256 PATCH_B_SHA256 - end - } - end - - def test_patch_p0_dsl_with_apply - assert_patched formula { - patch :p0 do - url TESTBALL_PATCHES_URL - sha256 TESTBALL_PATCHES_SHA256 - apply APPLY_B - end - } - end - - def test_patch_p0 - assert_patched formula { - def patches - { p0: PATCH_URL_B } - end - } - end - - def test_patch_array - assert_patched formula { - def patches - [PATCH_URL_A] - end - } - end - - def test_patch_hash - assert_patched formula { - def patches - { p1: PATCH_URL_A } - end - } - end - - def test_patch_hash_array - assert_patched formula { - def patches - { p1: [PATCH_URL_A] } - end - } - end - - def test_patch_string - assert_patched formula { patch PATCH_A_CONTENTS } - end - - def test_patch_string_with_strip - assert_patched formula { patch :p0, PATCH_B_CONTENTS } - end - - def test_patch_data_constant - assert_patched formula("test", Pathname.new(__FILE__).expand_path) { - def patches - :DATA - end - } - end - - def test_single_patch_missing_apply_fail - assert_missing_apply_fail formula { - def patches - TESTBALL_PATCHES_URL - end - } - end - - def test_single_patch_dsl_missing_apply_fail - assert_missing_apply_fail formula { - patch do - url TESTBALL_PATCHES_URL - sha256 TESTBALL_PATCHES_SHA256 - end - } - end - - def test_single_patch_dsl_with_apply_enoent_fail - assert_raises(ErrorDuringExecution) do - shutup do - formula do - patch do - url TESTBALL_PATCHES_URL - sha256 TESTBALL_PATCHES_SHA256 - apply "patches/#{APPLY_A}" - end - end.brew { |f, _staging| f.patch } - end - end - end -end - -__END__ -diff --git a/libexec/NOOP b/libexec/NOOP -index bfdda4c..e08d8f4 100755 ---- a/libexec/NOOP -+++ b/libexec/NOOP -@@ -1,2 +1,2 @@ - #!/bin/bash --echo NOOP -\ No newline at end of file -+echo ABCD -\ No newline at end of file diff --git a/Library/Homebrew/test/pathname_spec.rb b/Library/Homebrew/test/pathname_spec.rb new file mode 100644 index 000000000..6e7dc34aa --- /dev/null +++ b/Library/Homebrew/test/pathname_spec.rb @@ -0,0 +1,300 @@ +require "tmpdir" +require "extend/pathname" +require "install_renamed" + +describe Pathname do + include FileUtils + + let(:src) { Pathname.new(Dir.mktmpdir) } + let(:dst) { Pathname.new(Dir.mktmpdir) } + let(:file) { src/"foo" } + let(:dir) { src/"bar" } + + after(:each) { rm_rf [src, dst] } + + describe DiskUsageExtension do + before(:each) do + mkdir_p dir/"a-directory" + touch [dir/".DS_Store", dir/"a-file"] + File.truncate(dir/"a-file", 1_048_576) + ln_s dir/"a-file", dir/"a-symlink" + ln dir/"a-file", dir/"a-hardlink" + end + + describe "#file_count" do + it "returns the number of files in a directory" do + expect(dir.file_count).to eq(3) + end + end + + describe "#abv" do + context "when called on a directory" do + it "returns a string with the file count and disk usage" do + expect(dir.abv).to eq("3 files, 1MB") + end + end + + context "when called on a file" do + it "returns the disk usage" do + expect((dir/"a-file").abv).to eq("1MB") + end + end + end + end + + describe "#rmdir_if_possible" do + before(:each) { 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 + expect(dir).not_to exist + end + + it "returns false and doesn't delete a directory if it contains files" do + touch dir/"foo" + expect(dir.rmdir_if_possible).to be false + expect(dir).to be_a_directory + end + + it "ignores .DS_Store files" do + touch dir/".DS_Store" + expect(dir.rmdir_if_possible).to be true + expect(dir).not_to exist + end + end + + describe "#write" do + it "creates a file and writes to it" do + expect(file).not_to exist + file.write("CONTENT") + expect(File.read(file)).to eq("CONTENT") + end + + it "raises an error if the file already exists" do + touch file + expect { file.write("CONTENT") }.to raise_error(RuntimeError) + end + end + + describe "#append_lines" do + it "appends lines to a file" do + touch file + + file.append_lines("CONTENT") + expect(File.read(file)).to eq <<-EOS.undent + CONTENT + EOS + + file.append_lines("CONTENTS") + expect(File.read(file)).to eq <<-EOS.undent + CONTENT + CONTENTS + EOS + end + + it "raises an error if the file does not exist" do + expect(file).not_to exist + expect { file.append_lines("CONTENT") }.to raise_error(RuntimeError) + end + end + + describe "#atomic_write" do + it "atomically replaces a file" do + touch file + file.atomic_write("CONTENT") + expect(File.read(file)).to eq("CONTENT") + end + + it "preserves permissions" do + File.open(file, "w", 0100777).close + file.atomic_write("CONTENT") + expect(file.stat.mode).to eq(0100777 & ~File.umask) + end + + it "preserves default permissions" do + file.atomic_write("CONTENT") + sentinel = file.parent.join("sentinel") + touch sentinel + expect(file.stat.mode).to eq(sentinel.stat.mode) + end + end + + describe "#ensure_writable" do + it "makes a file writable and restores permissions afterwards" do + touch file + chmod 0555, file + expect(file).not_to be_writable + file.ensure_writable do + expect(file).to be_writable + end + expect(file).not_to be_writable + end + end + + 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") + end + end + + describe "#stem" do + it "returns the basename without double extensions" do + expect(Pathname("foo-0.1.tar.gz").stem).to eq("foo-0.1") + expect(Pathname("foo-0.1.cpio.gz").stem).to eq("foo-0.1") + end + end + + describe "#install" do + before(:each) do + (src/"a.txt").write "This is sample file a." + (src/"b.txt").write "This is sample file b." + end + + it "raises an error if the file doesn't exist" do + expect { dst.install "non_existent_file" }.to raise_error(Errno::ENOENT) + end + + it "installs a file to a directory with its basename" do + touch file + dst.install(file) + expect(dst/file.basename).to exist + expect(file).not_to exist + end + + it "creates intermediate directories" do + touch file + expect(dir).not_to be_a_directory + dir.install(file) + expect(dir).to be_a_directory + end + + it "can install a file" do + dst.install src/"a.txt" + expect(dst/"a.txt").to exist, "a.txt was not installed" + expect(dst/"b.txt").not_to exist, "b.txt was installed." + end + + it "can install an array of files" do + dst.install [src/"a.txt", src/"b.txt"] + + expect(dst/"a.txt").to exist, "a.txt was not installed" + expect(dst/"b.txt").to exist, "b.txt was not installed" + end + + it "can install a directory" do + bin = src/"bin" + bin.mkpath + mv Dir[src/"*.txt"], bin + dst.install bin + + expect(dst/"bin/a.txt").to exist, "a.txt was not installed" + expect(dst/"bin/b.txt").to exist, "b.txt was not installed" + end + + it "supports renaming files" do + dst.install src/"a.txt" => "c.txt" + + expect(dst/"c.txt").to exist, "c.txt was not installed" + expect(dst/"a.txt").not_to exist, "a.txt was installed but not renamed" + expect(dst/"b.txt").not_to exist, "b.txt was installed" + end + + it "supports renaming multiple files" do + dst.install(src/"a.txt" => "c.txt", src/"b.txt" => "d.txt") + + expect(dst/"c.txt").to exist, "c.txt was not installed" + expect(dst/"d.txt").to exist, "d.txt was not installed" + expect(dst/"a.txt").not_to exist, "a.txt was installed but not renamed" + expect(dst/"b.txt").not_to exist, "b.txt was installed but not renamed" + end + + it "supports renaming directories" do + bin = src/"bin" + bin.mkpath + mv Dir[src/"*.txt"], bin + dst.install bin => "libexec" + + expect(dst/"bin").not_to exist, "bin was installed but not renamed" + expect(dst/"libexec/a.txt").to exist, "a.txt was not installed" + expect(dst/"libexec/b.txt").to exist, "b.txt was not installed" + end + + it "can install directories as relative symlinks" do + bin = src/"bin" + bin.mkpath + mv Dir[src/"*.txt"], bin + dst.install_symlink bin + + expect(dst/"bin").to be_a_symlink + expect(dst/"bin").to be_a_directory + expect(dst/"bin/a.txt").to exist + expect(dst/"bin/b.txt").to exist + expect((dst/"bin").readlink).to be_relative + end + + it "can install relative paths as symlinks" do + dst.install_symlink "foo" => "bar" + expect((dst/"bar").readlink).to eq(Pathname.new("foo")) + end + end + + describe InstallRenamed do + before(:each) do + dst.extend(InstallRenamed) + end + + it "renames the installed file if it already exists" do + file.write "a" + dst.install file + + file.write "b" + dst.install file + + expect(File.read(dst/file.basename)).to eq("a") + expect(File.read(dst/"#{file.basename}.default")).to eq("b") + end + + it "renames the installed directory" do + file.write "a" + dst.install src + expect(File.read(dst/src.basename/file.basename)).to eq("a") + end + + it "recursively renames directories" do + (dst/dir.basename).mkpath + (dst/dir.basename/"another_file").write "a" + dir.mkpath + (dir/"another_file").write "b" + dst.install dir + expect(File.read(dst/dir.basename/"another_file.default")).to eq("b") + end + end + + describe "#cp_path_sub" do + it "copies a file and replaces the given pattern" do + file.write "a" + file.cp_path_sub src, dst + expect(File.read(dst/file.basename)).to eq("a") + end + + it "copies a directory and replaces the given pattern" do + dir.mkpath + dir.cp_path_sub src, dst + expect(dst/dir.basename).to be_a_directory + end + end +end + +describe FileUtils do + let(:dst) { Pathname.new(Dir.mktmpdir) } + + describe "#mkdir" do + it "creates indermediate directories" do + described_class.mkdir dst/"foo/bar/baz" do + expect(dst/"foo/bar/baz").to exist, "foo/bar/baz was not created" + expect(dst/"foo/bar/baz").to be_a_directory, "foo/bar/baz was not a directory structure" + end + end + end +end diff --git a/Library/Homebrew/test/pathname_test.rb b/Library/Homebrew/test/pathname_test.rb deleted file mode 100644 index 2f6360719..000000000 --- a/Library/Homebrew/test/pathname_test.rb +++ /dev/null @@ -1,267 +0,0 @@ -require "testing_env" -require "tmpdir" -require "extend/pathname" -require "install_renamed" - -module PathnameTestExtension - include FileUtils - - def setup - @src = Pathname.new(mktmpdir) - @dst = Pathname.new(mktmpdir) - @file = @src/"foo" - @dir = @src/"bar" - end - - def teardown - rmtree(@src) - rmtree(@dst) - end -end - -class PathnameTests < Homebrew::TestCase - include PathnameTestExtension - - def test_disk_usage_extension - mkdir_p @dir/"a-directory" - touch @dir/".DS_Store" - touch @dir/"a-file" - File.truncate(@dir/"a-file", 1_048_576) - ln_s @dir/"a-file", @dir/"a-symlink" - ln @dir/"a-file", @dir/"a-hardlink" - assert_equal 3, @dir.file_count - assert_equal "3 files, 1M", @dir.abv - assert_equal "1M", (@dir/"a-file").abv - end - - def test_rmdir_if_possible - mkdir_p @dir - touch @dir/"foo" - - assert !@dir.rmdir_if_possible - assert_predicate @dir, :directory? - - rm_f @dir/"foo" - assert @dir.rmdir_if_possible - refute_predicate @dir, :exist? - end - - def test_rmdir_if_possible_ignore_ds_store - mkdir_p @dir - touch @dir/".DS_Store" - assert @dir.rmdir_if_possible - refute_predicate @dir, :exist? - end - - def test_write - @file.write("CONTENT") - assert_equal "CONTENT", File.read(@file) - end - - def test_write_does_not_overwrite - touch @file - assert_raises(RuntimeError) { @file.write("CONTENT") } - end - - def test_append_lines - touch @file - @file.append_lines("CONTENT") - assert_equal "CONTENT\n", File.read(@file) - @file.append_lines("CONTENTS") - assert_equal "CONTENT\nCONTENTS\n", File.read(@file) - end - - def test_append_lines_does_not_create - assert_raises(RuntimeError) { @file.append_lines("CONTENT") } - end - - def test_atomic_write - touch @file - @file.atomic_write("CONTENT") - assert_equal "CONTENT", File.read(@file) - end - - def test_atomic_write_preserves_permissions - File.open(@file, "w", 0100777) {} - @file.atomic_write("CONTENT") - assert_equal 0100777 & ~File.umask, @file.stat.mode - end - - def test_atomic_write_preserves_default_permissions - @file.atomic_write("CONTENT") - sentinel = @file.parent.join("sentinel") - touch sentinel - assert_equal sentinel.stat.mode, @file.stat.mode - end - - def test_ensure_writable - touch @file - chmod 0555, @file - @file.ensure_writable { assert_predicate @file, :writable? } - refute_predicate @file, :writable? - end - - def test_extname - assert_equal ".tar.gz", Pathname("foo-0.1.tar.gz").extname - assert_equal ".cpio.gz", Pathname("foo-0.1.cpio.gz").extname - end - - def test_stem - assert_equal "foo-0.1", Pathname("foo-0.1.tar.gz").stem - assert_equal "foo-0.1", Pathname("foo-0.1.cpio.gz").stem - end - - def test_install_missing_file - assert_raises(Errno::ENOENT) { @dst.install "non_existent_file" } - end - - def test_install_removes_original - touch @file - @dst.install(@file) - - assert_predicate @dst/@file.basename, :exist? - refute_predicate @file, :exist? - end - - def test_install_creates_intermediate_directories - touch @file - refute_predicate @dir, :directory? - @dir.install(@file) - assert_predicate @dir, :directory? - end - - def test_install_renamed - @dst.extend(InstallRenamed) - - @file.write "a" - @dst.install @file - @file.write "b" - @dst.install @file - - assert_equal "a", File.read(@dst/@file.basename) - assert_equal "b", File.read(@dst/"#{@file.basename}.default") - end - - def test_install_renamed_directory - @dst.extend(InstallRenamed) - @file.write "a" - @dst.install @src - assert_equal "a", File.read(@dst/@src.basename/@file.basename) - end - - def test_install_renamed_directory_recursive - @dst.extend(InstallRenamed) - (@dst/@dir.basename).mkpath - (@dst/@dir.basename/"another_file").write "a" - @dir.mkpath - (@dir/"another_file").write "b" - @dst.install @dir - assert_equal "b", File.read(@dst/@dir.basename/"another_file.default") - end - - def test_cp_path_sub_file - @file.write "a" - @file.cp_path_sub @src, @dst - assert_equal "a", File.read(@dst/"foo") - end - - def test_cp_path_sub_directory - @dir.mkpath - @dir.cp_path_sub @src, @dst - assert_predicate @dst/@dir.basename, :directory? - end -end - -class PathnameInstallTests < Homebrew::TestCase - include PathnameTestExtension - - def setup - super - (@src/"a.txt").write "This is sample file a." - (@src/"b.txt").write "This is sample file b." - end - - def test_install - @dst.install @src/"a.txt" - - assert_predicate @dst/"a.txt", :exist?, "a.txt was not installed" - refute_predicate @dst/"b.txt", :exist?, "b.txt was installed." - end - - def test_install_list - @dst.install [@src/"a.txt", @src/"b.txt"] - - assert_predicate @dst/"a.txt", :exist?, "a.txt was not installed" - assert_predicate @dst/"b.txt", :exist?, "b.txt was not installed" - end - - def test_install_glob - @dst.install Dir[@src/"*.txt"] - - assert_predicate @dst/"a.txt", :exist?, "a.txt was not installed" - assert_predicate @dst/"b.txt", :exist?, "b.txt was not installed" - end - - def test_install_directory - bin = @src/"bin" - bin.mkpath - mv Dir[@src/"*.txt"], bin - @dst.install bin - - assert_predicate @dst/"bin/a.txt", :exist?, "a.txt was not installed" - assert_predicate @dst/"bin/b.txt", :exist?, "b.txt was not installed" - end - - def test_install_rename - @dst.install @src/"a.txt" => "c.txt" - - assert_predicate @dst/"c.txt", :exist?, "c.txt was not installed" - refute_predicate @dst/"a.txt", :exist?, "a.txt was installed but not renamed" - refute_predicate @dst/"b.txt", :exist?, "b.txt was installed" - end - - def test_install_rename_more - @dst.install(@src/"a.txt" => "c.txt", @src/"b.txt" => "d.txt") - - assert_predicate @dst/"c.txt", :exist?, "c.txt was not installed" - assert_predicate @dst/"d.txt", :exist?, "d.txt was not installed" - refute_predicate @dst/"a.txt", :exist?, "a.txt was installed but not renamed" - refute_predicate @dst/"b.txt", :exist?, "b.txt was installed but not renamed" - end - - def test_install_rename_directory - bin = @src/"bin" - bin.mkpath - mv Dir[@src/"*.txt"], bin - @dst.install bin => "libexec" - - refute_predicate @dst/"bin", :exist?, "bin was installed but not renamed" - assert_predicate @dst/"libexec/a.txt", :exist?, "a.txt was not installed" - assert_predicate @dst/"libexec/b.txt", :exist?, "b.txt was not installed" - end - - def test_install_symlink - bin = @src/"bin" - bin.mkpath - mv Dir[@src/"*.txt"], bin - @dst.install_symlink bin - - assert_predicate @dst/"bin", :symlink? - assert_predicate @dst/"bin", :directory? - assert_predicate @dst/"bin/a.txt", :exist? - assert_predicate @dst/"bin/b.txt", :exist? - assert_predicate((@dst/"bin").readlink, :relative?) - end - - def test_install_relative_symlink - @dst.install_symlink "foo" => "bar" - assert_equal Pathname.new("foo"), (@dst/"bar").readlink - end - - def test_mkdir_creates_intermediate_directories - mkdir @dst/"foo/bar/baz" do - assert_predicate @dst/"foo/bar/baz", :exist?, "foo/bar/baz was not created" - assert_predicate @dst/"foo/bar/baz", :directory?, "foo/bar/baz was not a directory structure" - end - end -end diff --git a/Library/Homebrew/test/pin_unpin_test.rb b/Library/Homebrew/test/pin_unpin_test.rb deleted file mode 100644 index 65fb9e4da..000000000 --- a/Library/Homebrew/test/pin_unpin_test.rb +++ /dev/null @@ -1,18 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestPinUnpin < IntegrationCommandTestCase - def test_pin_unpin - setup_test_formula "testball" - (HOMEBREW_CELLAR/"testball/0.0.1/foo").mkpath - - cmd("pin", "testball") - cmd("upgrade") - refute((HOMEBREW_CELLAR/"testball/0.1").directory?, - "The latest version directory should NOT be created") - - cmd("unpin", "testball") - cmd("upgrade") - assert((HOMEBREW_CELLAR/"testball/0.1").directory?, - "The latest version directory should be created") - end -end diff --git a/Library/Homebrew/test/pkg_version_spec.rb b/Library/Homebrew/test/pkg_version_spec.rb new file mode 100644 index 000000000..b1cceb32c --- /dev/null +++ b/Library/Homebrew/test/pkg_version_spec.rb @@ -0,0 +1,81 @@ +require "pkg_version" + +describe PkgVersion do + describe "::parse" do + it "parses versions from a string" do + expect(described_class.parse("1.0_1")).to eq(described_class.new(Version.create("1.0"), 1)) + expect(described_class.parse("1.0_1")).to eq(described_class.new(Version.create("1.0"), 1)) + expect(described_class.parse("1.0")).to eq(described_class.new(Version.create("1.0"), 0)) + expect(described_class.parse("1.0_0")).to eq(described_class.new(Version.create("1.0"), 0)) + expect(described_class.parse("2.1.4_0")).to eq(described_class.new(Version.create("2.1.4"), 0)) + expect(described_class.parse("1.0.1e_1")).to eq(described_class.new(Version.create("1.0.1e"), 1)) + end + end + + specify "#==" do + expect(described_class.parse("1.0_0")).to be == described_class.parse("1.0") + expect(described_class.parse("1.0_1")).to be == described_class.parse("1.0_1") + end + + describe "#>" do + it "returns true if the left version is bigger than the right" do + expect(described_class.parse("1.1")).to be > described_class.parse("1.0_1") + end + + it "returns true if the left version is HEAD" do + expect(described_class.parse("HEAD")).to be > described_class.parse("1.0") + end + + it "raises an error if the other side isn't of the same class" do + expect { + described_class.new(Version.create("1.0"), 0) > Object.new + }.to raise_error(ArgumentError) + end + + it "is not compatible with Version" do + expect { + described_class.new(Version.create("1.0"), 0) > Version.create("1.0") + }.to raise_error(ArgumentError) + end + end + + describe "#<" do + it "returns true if the left version is smaller than the right" do + expect(described_class.parse("1.0_1")).to be < described_class.parse("2.0_1") + end + + it "returns true if the right version is HEAD" do + expect(described_class.parse("1.0")).to be < described_class.parse("HEAD") + end + end + + describe "#<=>" do + it "returns nil if the comparison fails" do + expect(described_class.new(Version.create("1.0"), 0) <=> Object.new).to be nil + end + end + + describe "#to_s" do + it "returns a string of the form 'version_revision'" do + expect(described_class.new(Version.create("1.0"), 0).to_s).to eq("1.0") + expect(described_class.new(Version.create("1.0"), 1).to_s).to eq("1.0_1") + expect(described_class.new(Version.create("1.0"), 0).to_s).to eq("1.0") + expect(described_class.new(Version.create("1.0"), 0).to_s).to eq("1.0") + expect(described_class.new(Version.create("HEAD"), 1).to_s).to eq("HEAD_1") + expect(described_class.new(Version.create("HEAD-ffffff"), 1).to_s).to eq("HEAD-ffffff_1") + end + end + + describe "#hash" do + let(:p1) { described_class.new(Version.create("1.0"), 1) } + let(:p2) { described_class.new(Version.create("1.0"), 1) } + let(:p3) { described_class.new(Version.create("1.1"), 1) } + let(:p4) { described_class.new(Version.create("1.0"), 0) } + + it "returns a hash based on the version and revision" do + expect(p1.hash).to eq(p2.hash) + expect(p1.hash).not_to eq(p3.hash) + expect(p1.hash).not_to eq(p4.hash) + end + end +end diff --git a/Library/Homebrew/test/pkg_version_test.rb b/Library/Homebrew/test/pkg_version_test.rb deleted file mode 100644 index ff7896f8b..000000000 --- a/Library/Homebrew/test/pkg_version_test.rb +++ /dev/null @@ -1,51 +0,0 @@ -require "testing_env" -require "pkg_version" - -class PkgVersionTests < Homebrew::TestCase - def v(version) - PkgVersion.parse(version) - end - - def test_parse - assert_equal PkgVersion.new(Version.create("1.0"), 1), PkgVersion.parse("1.0_1") - assert_equal PkgVersion.new(Version.create("1.0"), 1), PkgVersion.parse("1.0_1") - assert_equal PkgVersion.new(Version.create("1.0"), 0), PkgVersion.parse("1.0") - assert_equal PkgVersion.new(Version.create("1.0"), 0), PkgVersion.parse("1.0_0") - assert_equal PkgVersion.new(Version.create("2.1.4"), 0), PkgVersion.parse("2.1.4_0") - assert_equal PkgVersion.new(Version.create("1.0.1e"), 1), PkgVersion.parse("1.0.1e_1") - end - - def test_comparison - assert_operator v("1.0_0"), :==, v("1.0") - assert_operator v("1.0_1"), :==, v("1.0_1") - assert_operator v("1.1"), :>, v("1.0_1") - assert_operator v("1.0_0"), :==, v("1.0") - assert_operator v("1.0_1"), :<, v("2.0_1") - assert_operator v("HEAD"), :>, v("1.0") - assert_operator v("1.0"), :<, v("HEAD") - - v = PkgVersion.new(Version.create("1.0"), 0) - assert_nil v <=> Object.new - assert_raises(ArgumentError) { v > Object.new } - assert_raises(ArgumentError) { v > Version.create("1.0") } - end - - def test_to_s - assert_equal "1.0", PkgVersion.new(Version.create("1.0"), 0).to_s - assert_equal "1.0_1", PkgVersion.new(Version.create("1.0"), 1).to_s - assert_equal "1.0", PkgVersion.new(Version.create("1.0"), 0).to_s - assert_equal "1.0", PkgVersion.new(Version.create("1.0"), 0).to_s - assert_equal "HEAD_1", PkgVersion.new(Version.create("HEAD"), 1).to_s - assert_equal "HEAD-ffffff_1", PkgVersion.new(Version.create("HEAD-ffffff"), 1).to_s - end - - def test_hash - p1 = PkgVersion.new(Version.create("1.0"), 1) - p2 = PkgVersion.new(Version.create("1.0"), 1) - p3 = PkgVersion.new(Version.create("1.1"), 1) - p4 = PkgVersion.new(Version.create("1.0"), 0) - assert_equal p1.hash, p2.hash - refute_equal p1.hash, p3.hash - refute_equal p1.hash, p4.hash - end -end diff --git a/Library/Homebrew/test/prefix_formula_test.rb b/Library/Homebrew/test/prefix_formula_test.rb deleted file mode 100644 index eb5970d3e..000000000 --- a/Library/Homebrew/test/prefix_formula_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestPrefixFormula < IntegrationCommandTestCase - def test_prefix_formula - assert_match "#{HOMEBREW_CELLAR}/testball", - cmd("--prefix", testball) - end -end diff --git a/Library/Homebrew/test/prefix_test.rb b/Library/Homebrew/test/prefix_test.rb deleted file mode 100644 index a3ae75542..000000000 --- a/Library/Homebrew/test/prefix_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestPrefix < IntegrationCommandTestCase - def test_prefix - assert_equal HOMEBREW_PREFIX.to_s, - cmd("--prefix") - end -end diff --git a/Library/Homebrew/test/prune_test.rb b/Library/Homebrew/test/prune_test.rb deleted file mode 100644 index 8fa5df7b7..000000000 --- a/Library/Homebrew/test/prune_test.rb +++ /dev/null @@ -1,21 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestPrune < IntegrationCommandTestCase - def test_prune - share = (HOMEBREW_PREFIX/"share") - - (share/"pruneable/directory/here").mkpath - (share/"notpruneable/file").write "I'm here" - FileUtils.ln_s "/i/dont/exist/no/really/i/dont", share/"pruneable_symlink" - - assert_match %r{Would remove \(empty directory\): .*/pruneable/directory/here}, - cmd("prune", "--dry-run") - assert_match "Pruned 1 symbolic links and 3 directories", - cmd("prune") - refute((share/"pruneable").directory?) - assert((share/"notpruneable").directory?) - refute((share/"pruneable_symlink").symlink?) - - assert_match "Nothing pruned", cmd("prune", "--verbose") - end -end diff --git a/Library/Homebrew/test/pull_offline_test.rb b/Library/Homebrew/test/pull_offline_test.rb deleted file mode 100644 index c9d46cd74..000000000 --- a/Library/Homebrew/test/pull_offline_test.rb +++ /dev/null @@ -1,10 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestPullOffline < IntegrationCommandTestCase - def test_pull_offline - assert_match "You meant `git pull --rebase`.", cmd_fail("pull", "--rebase") - assert_match "This command requires at least one argument", cmd_fail("pull") - assert_match "Not a GitHub pull request or commit", - cmd_fail("pull", "0") - end -end diff --git a/Library/Homebrew/test/pull_test.rb b/Library/Homebrew/test/pull_test.rb deleted file mode 100644 index 445d73cb1..000000000 --- a/Library/Homebrew/test/pull_test.rb +++ /dev/null @@ -1,27 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestPull < IntegrationCommandTestCase - def test_pull - skip "Requires network connection" if ENV["HOMEBREW_NO_GITHUB_API"] - - core_tap = CoreTap.new - core_tap.path.cd do - shutup do - system "git", "init" - system "git", "checkout", "-b", "new-branch" - end - end - - assert_match "Testing URLs require `--bottle`!", - cmd_fail("pull", "https://bot.brew.sh/job/Homebrew\%20Testing/1028/") - assert_match "Current branch is new-branch", - cmd_fail("pull", "1") - assert_match "No changed formulae found to bump", - cmd_fail("pull", "--bump", "8") - assert_match "Can only bump one changed formula", - cmd_fail("pull", "--bump", - "https://api.github.com/repos/Homebrew/homebrew-core/pulls/122") - assert_match "Patch failed to apply", - cmd_fail("pull", "https://github.com/Homebrew/homebrew-core/pull/1") - end -end diff --git a/Library/Homebrew/test/readall_test.rb b/Library/Homebrew/test/readall_test.rb deleted file mode 100644 index 3eec79dd8..000000000 --- a/Library/Homebrew/test/readall_test.rb +++ /dev/null @@ -1,12 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestReadall < IntegrationCommandTestCase - def test_readall - formula_file = setup_test_formula "testball" - alias_file = CoreTap.new.alias_dir/"foobar" - alias_file.parent.mkpath - FileUtils.ln_s formula_file, alias_file - cmd("readall", "--aliases", "--syntax") - cmd("readall", "homebrew/core") - end -end diff --git a/Library/Homebrew/test/reinstall_pinned_test.rb b/Library/Homebrew/test/reinstall_pinned_test.rb deleted file mode 100644 index 80f5518ea..000000000 --- a/Library/Homebrew/test/reinstall_pinned_test.rb +++ /dev/null @@ -1,15 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestReinstallPinned < IntegrationCommandTestCase - def test_reinstall_pinned - setup_test_formula "testball" - - HOMEBREW_CELLAR.join("testball/0.1").mkpath - HOMEBREW_PINNED_KEGS.mkpath - FileUtils.ln_s HOMEBREW_CELLAR.join("testball/0.1"), HOMEBREW_PINNED_KEGS/"testball" - - assert_match "testball is pinned. You must unpin it to reinstall.", cmd("reinstall", "testball") - - HOMEBREW_PINNED_KEGS.rmtree - end -end diff --git a/Library/Homebrew/test/reinstall_test.rb b/Library/Homebrew/test/reinstall_test.rb deleted file mode 100644 index 613c06188..000000000 --- a/Library/Homebrew/test/reinstall_test.rb +++ /dev/null @@ -1,15 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestReinstall < IntegrationCommandTestCase - def test_reinstall - setup_test_formula "testball" - - cmd("install", "testball", "--with-foo") - foo_dir = HOMEBREW_CELLAR/"testball/0.1/foo" - assert foo_dir.exist? - foo_dir.rmtree - assert_match "Reinstalling testball --with-foo", - cmd("reinstall", "testball") - assert foo_dir.exist? - end -end diff --git a/Library/Homebrew/test/repository_test.rb b/Library/Homebrew/test/repository_test.rb deleted file mode 100644 index 77967a58d..000000000 --- a/Library/Homebrew/test/repository_test.rb +++ /dev/null @@ -1,10 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestRepository < IntegrationCommandTestCase - def test_repository - assert_match HOMEBREW_REPOSITORY.to_s, - cmd("--repository") - assert_match "#{HOMEBREW_LIBRARY}/Taps/foo/homebrew-bar", - cmd("--repository", "foo/bar") - end -end diff --git a/Library/Homebrew/test/requirement_spec.rb b/Library/Homebrew/test/requirement_spec.rb new file mode 100644 index 000000000..110a7ac4f --- /dev/null +++ b/Library/Homebrew/test/requirement_spec.rb @@ -0,0 +1,288 @@ +require "extend/ENV" +require "requirement" + +RSpec::Matchers.alias_matcher :have_a_default_formula, :be_a_default_formula +RSpec::Matchers.alias_matcher :be_a_build_requirement, :be_a_build + +describe Requirement do + subject { klass.new } + + let(:klass) { Class.new(described_class) } + + describe "#tags" do + subject { described_class.new(tags) } + + context "single tag" do + let(:tags) { ["bar"] } + + its(:tags) { are_expected.to eq(tags) } + end + + context "multiple tags" do + let(:tags) { ["bar", "baz"] } + + its(:tags) { are_expected.to eq(tags) } + end + + context "symbol tags" do + let(:tags) { [:build] } + + its(:tags) { are_expected.to eq(tags) } + end + + context "symbol and string tags" do + let(:tags) { [:build, "bar"] } + + its(:tags) { are_expected.to eq(tags) } + end + end + + describe "#fatal?" do + context "#fatal true is specified" do + let(:klass) do + Class.new(described_class) do + fatal true + end + end + + it { is_expected.to be_fatal } + end + + context "#fatal is ommitted" do + it { is_expected.not_to be_fatal } + end + end + + describe "#satisfied?" do + context "#satisfy with block and build_env returns true" do + let(:klass) do + Class.new(described_class) do + satisfy(build_env: false) do + true + end + end + end + + it { is_expected.to be_satisfied } + end + + context "#satisfy with block and build_env returns false" do + let(:klass) do + Class.new(described_class) do + satisfy(build_env: false) do + false + end + end + end + + it { is_expected.not_to be_satisfied } + end + + context "#satisfy returns true" do + let(:klass) do + Class.new(described_class) do + satisfy true + end + end + + it { is_expected.to be_satisfied } + end + + context "#satisfy returns false" do + let(:klass) do + Class.new(described_class) do + satisfy false + end + end + + it { is_expected.not_to be_satisfied } + end + + context "#satisfy with block returning true and without :build_env" do + let(:klass) do + Class.new(described_class) do + satisfy do + true + end + end + end + + it "sets up build environment" do + expect(ENV).to receive(:with_build_environment).and_call_original + subject.satisfied? + end + end + + context "#satisfy with block returning true and :build_env set to false" do + let(:klass) do + Class.new(described_class) do + satisfy(build_env: false) do + true + end + end + end + + it "skips setting up build environment" do + expect(ENV).not_to receive(:with_build_environment) + subject.satisfied? + end + end + + context "#satisfy with block returning path and without :build_env" do + let(:klass) do + Class.new(described_class) do + satisfy do + Pathname.new("/foo/bar/baz") + end + end + end + + it "infers path from #satisfy result" do + expect(ENV).to receive(:append_path).with("PATH", Pathname.new("/foo/bar")) + subject.satisfied? + subject.modify_build_environment + end + end + end + + describe "#build?" do + context "#build true is specified" do + let(:klass) do + Class.new(described_class) do + build true + end + end + + it { is_expected.to be_a_build_requirement } + end + + context "#build ommitted" do + it { is_expected.not_to be_a_build_requirement } + end + end + + describe "#name and #option_names" do + let(:const) { :FooRequirement } + let(:klass) { self.class.const_get(const) } + + before(:each) do + self.class.const_set(const, Class.new(described_class)) + end + + after(:each) do + self.class.send(:remove_const, const) + end + + its(:name) { is_expected.to eq("foo") } + its(:option_names) { are_expected.to eq(["foo"]) } + end + + describe "#default_formula?" do + context "#default_formula specified" do + let(:klass) do + Class.new(described_class) do + default_formula "foo" + end + end + + it { is_expected.to have_a_default_formula } + end + + context "#default_formula ommitted" do + it { is_expected.not_to have_a_default_formula } + end + end + + describe "#to_dependency" do + let(:klass) do + Class.new(described_class) do + default_formula "foo" + end + end + + it "returns a Dependency for its default Formula" do + expect(subject.to_dependency).to eq(Dependency.new("foo")) + end + + context "#modify_build_environment" do + context "with error" do + let(:klass) do + Class.new(described_class) do + class ModifyBuildEnvironmentError < StandardError; end + + default_formula "foo" + + satisfy do + true + end + + env do + raise ModifyBuildEnvironmentError + end + end + end + + it "raises an error" do + expect { + subject.to_dependency.modify_build_environment + }.to raise_error(klass.const_get(:ModifyBuildEnvironmentError)) + end + end + end + end + + describe "#modify_build_environment" do + context "without env proc" do + let(:klass) { Class.new(described_class) } + + it "returns nil" do + expect(subject.modify_build_environment).to be nil + end + end + end + + describe "#eql? and #==" do + subject { described_class.new } + + it "returns true if the names and tags are equal" do + other = described_class.new + + expect(subject).to eql(other) + expect(subject).to eq(other) + end + + it "returns false if names differ" do + other = described_class.new + allow(other).to receive(:name).and_return("foo") + expect(subject).not_to eql(other) + expect(subject).not_to eq(other) + end + + it "returns false if tags differ" do + other = described_class.new([:optional]) + + expect(subject).not_to eql(other) + expect(subject).not_to eq(other) + end + end + + describe "#hash" do + subject { described_class.new } + + it "is equal if names and tags are equal" do + other = described_class.new + expect(subject.hash).to eq(other.hash) + end + + it "differs if names differ" do + other = described_class.new + allow(other).to receive(:name).and_return("foo") + expect(subject.hash).not_to eq(other.hash) + end + + it "differs if tags differ" do + other = described_class.new([:optional]) + expect(subject.hash).not_to eq(other.hash) + end + end +end diff --git a/Library/Homebrew/test/requirement_test.rb b/Library/Homebrew/test/requirement_test.rb deleted file mode 100644 index 580d42bfa..000000000 --- a/Library/Homebrew/test/requirement_test.rb +++ /dev/null @@ -1,152 +0,0 @@ -require "testing_env" -require "requirement" - -class RequirementTests < Homebrew::TestCase - class TestRequirement < Requirement; end - - def test_accepts_single_tag - dep = Requirement.new(%w[bar]) - assert_equal %w[bar], dep.tags - end - - def test_accepts_multiple_tags - dep = Requirement.new(%w[bar baz]) - assert_equal %w[bar baz].sort, dep.tags.sort - end - - def test_option_names - dep = TestRequirement.new - assert_equal %w[test], dep.option_names - end - - def test_preserves_symbol_tags - dep = Requirement.new([:build]) - assert_equal [:build], dep.tags - end - - def test_accepts_symbol_and_string_tags - dep = Requirement.new([:build, "bar"]) - assert_equal [:build, "bar"], dep.tags - end - - def test_dsl_fatal - req = Class.new(Requirement) { fatal true }.new - assert_predicate req, :fatal? - end - - def test_satisfy_true - req = Class.new(Requirement) do - satisfy(build_env: false) { true } - end.new - assert_predicate req, :satisfied? - end - - def test_satisfy_false - req = Class.new(Requirement) do - satisfy(build_env: false) { false } - end.new - refute_predicate req, :satisfied? - end - - def test_satisfy_with_boolean - req = Class.new(Requirement) do - satisfy true - end.new - assert_predicate req, :satisfied? - end - - def test_satisfy_sets_up_build_env_by_default - req = Class.new(Requirement) do - satisfy { true } - end.new - - ENV.expects(:with_build_environment).yields.returns(true) - - assert_predicate req, :satisfied? - end - - def test_satisfy_build_env_can_be_disabled - req = Class.new(Requirement) do - satisfy(build_env: false) { true } - end.new - - ENV.expects(:with_build_environment).never - - assert_predicate req, :satisfied? - end - - def test_infers_path_from_satisfy_result - which_path = Pathname.new("/foo/bar/baz") - req = Class.new(Requirement) do - satisfy { which_path } - end.new - - ENV.expects(:with_build_environment).yields.returns(which_path) - ENV.expects(:append_path).with("PATH", which_path.parent) - - req.satisfied? - req.modify_build_environment - end - - def test_dsl_build - req = Class.new(Requirement) { build true }.new - assert_predicate req, :build? - end - - def test_infer_name_from_class - const = :FooRequirement - klass = self.class - - klass.const_set(const, Class.new(Requirement)) - - begin - assert_equal "foo", klass.const_get(const).new.name - ensure - klass.send(:remove_const, const) - end - end - - def test_dsl_default_formula - req = Class.new(Requirement) { default_formula "foo" }.new - assert_predicate req, :default_formula? - end - - def test_to_dependency - req = Class.new(Requirement) { default_formula "foo" }.new - assert_equal Dependency.new("foo"), req.to_dependency - end - - def test_to_dependency_calls_requirement_modify_build_environment - error = Class.new(StandardError) - - req = Class.new(Requirement) do - default_formula "foo" - satisfy { true } - env { raise error } - end.new - - assert_raises(error) do - req.to_dependency.modify_build_environment - end - end - - def test_modify_build_environment_without_env_proc - assert_nil Class.new(Requirement).new.modify_build_environment - end - - def test_eql - a = Requirement.new - b = Requirement.new - assert_equal a, b - assert_eql a, b - assert_equal a.hash, b.hash - end - - def test_not_eql - a = Requirement.new([:optional]) - b = Requirement.new - refute_equal a, b - refute_eql a, b - refute_equal a.hash, b.hash - end -end diff --git a/Library/Homebrew/test/resource_spec.rb b/Library/Homebrew/test/resource_spec.rb new file mode 100644 index 000000000..6a0419538 --- /dev/null +++ b/Library/Homebrew/test/resource_spec.rb @@ -0,0 +1,147 @@ +require "resource" + +describe Resource do + subject { described_class.new("test") } + + describe "#url" do + it "sets the URL" do + subject.url("foo") + expect(subject.url).to eq("foo") + end + + it "can set the URL with specifications" do + subject.url("foo", branch: "master") + expect(subject.url).to eq("foo") + expect(subject.specs).to eq(branch: "master") + end + + it "can set the URL with a custom download strategy class" do + strategy = Class.new(AbstractDownloadStrategy) + subject.url("foo", using: strategy) + expect(subject.url).to eq("foo") + expect(subject.download_strategy).to eq(strategy) + end + + it "can set the URL with specifications and a custom download strategy class" do + strategy = Class.new(AbstractDownloadStrategy) + subject.url("foo", using: strategy, branch: "master") + expect(subject.url).to eq("foo") + expect(subject.specs).to eq(branch: "master") + expect(subject.download_strategy).to eq(strategy) + end + + it "can set the URL with a custom download strategy symbol" do + subject.url("foo", using: :git) + expect(subject.url).to eq("foo") + expect(subject.download_strategy).to eq(GitDownloadStrategy) + end + + it "raises an error if the download strategy class is unkown" do + expect { subject.url("foo", using: Class.new) }.to raise_error(TypeError) + end + + it "does not mutate the specifications hash" do + specs = { using: :git, branch: "master" } + subject.url("foo", specs) + expect(subject.specs).to eq(branch: "master") + expect(subject.using).to eq(:git) + expect(specs).to eq(using: :git, branch: "master") + end + end + + describe "#version" do + it "sets the version" do + subject.version("1.0") + expect(subject.version).to eq(Version.parse("1.0")) + expect(subject.version).not_to be_detected_from_url + end + + it "can detect the version from a URL" do + subject.url("http://example.com/foo-1.0.tar.gz") + expect(subject.version).to eq(Version.parse("1.0")) + expect(subject.version).to be_detected_from_url + end + + it "can set the version with a scheme" do + klass = Class.new(Version) + subject.version klass.new("1.0") + expect(subject.version).to eq(Version.parse("1.0")) + expect(subject.version).to be_a(klass) + end + + it "can set the version from a tag" do + subject.url("http://example.com/foo-1.0.tar.gz", tag: "v1.0.2") + expect(subject.version).to eq(Version.parse("1.0.2")) + expect(subject.version).to be_detected_from_url + end + + it "rejects non-string versions" do + expect { subject.version(1) }.to raise_error(TypeError) + expect { subject.version(2.0) }.to raise_error(TypeError) + expect { subject.version(Object.new) }.to raise_error(TypeError) + end + + it "returns nil if unset" do + expect(subject.version).to be nil + end + end + + describe "#mirrors" do + it "is empty by defaults" do + expect(subject.mirrors).to be_empty + end + + it "returns an array of mirrors added with #mirror" do + subject.mirror("foo") + subject.mirror("bar") + expect(subject.mirrors).to eq(%w[foo bar]) + end + end + + describe "#checksum" do + it "returns nil if unset" do + expect(subject.checksum).to be nil + end + + it "returns the checksum set with #sha256" do + subject.sha256(TEST_SHA256) + expect(subject.checksum).to eq(Checksum.new(:sha256, TEST_SHA256)) + end + end + + describe "#download_strategy" do + it "returns the download strategy" do + strategy = Object.new + expect(DownloadStrategyDetector) + .to receive(:detect).with("foo", nil).and_return(strategy) + subject.url("foo") + expect(subject.download_strategy).to eq(strategy) + end + end + + specify "#verify_download_integrity_missing" do + fn = Pathname.new("test") + + allow(fn).to receive(:file?).and_return(true) + expect(fn).to receive(:verify_checksum).and_raise(ChecksumMissingError) + expect(fn).to receive(:sha256) + + shutup do + subject.verify_download_integrity(fn) + end + end + + specify "#verify_download_integrity_mismatch" do + fn = double(file?: true) + checksum = subject.sha256(TEST_SHA256) + + expect(fn).to receive(:verify_checksum).with(checksum) + .and_raise(ChecksumMismatchError.new(fn, checksum, Object.new)) + + shutup do + expect { + subject.verify_download_integrity(fn) + }.to raise_error(ChecksumMismatchError) + end + end +end diff --git a/Library/Homebrew/test/resource_test.rb b/Library/Homebrew/test/resource_test.rb deleted file mode 100644 index c1b526cb2..000000000 --- a/Library/Homebrew/test/resource_test.rb +++ /dev/null @@ -1,132 +0,0 @@ -require "testing_env" -require "resource" - -class ResourceTests < Homebrew::TestCase - def setup - @resource = Resource.new("test") - end - - def test_url - @resource.url("foo") - assert_equal "foo", @resource.url - end - - def test_url_with_specs - @resource.url("foo", branch: "master") - assert_equal "foo", @resource.url - assert_equal({ branch: "master" }, @resource.specs) - end - - def test_url_with_custom_download_strategy_class - strategy = Class.new(AbstractDownloadStrategy) - @resource.url("foo", using: strategy) - assert_equal "foo", @resource.url - assert_equal strategy, @resource.download_strategy - end - - def test_url_with_specs_and_download_strategy - strategy = Class.new(AbstractDownloadStrategy) - @resource.url("foo", using: strategy, branch: "master") - assert_equal "foo", @resource.url - assert_equal({ branch: "master" }, @resource.specs) - assert_equal strategy, @resource.download_strategy - end - - def test_url_with_custom_download_strategy_symbol - @resource.url("foo", using: :git) - assert_equal "foo", @resource.url - assert_equal GitDownloadStrategy, @resource.download_strategy - end - - def test_raises_for_unknown_download_strategy_class - assert_raises(TypeError) { @resource.url("foo", using: Class.new) } - end - - def test_does_not_mutate_specs_hash - specs = { using: :git, branch: "master" } - @resource.url("foo", specs) - assert_equal({ branch: "master" }, @resource.specs) - assert_equal(:git, @resource.using) - assert_equal({ using: :git, branch: "master" }, specs) - end - - def test_version - @resource.version("1.0") - assert_version_equal "1.0", @resource.version - refute_predicate @resource.version, :detected_from_url? - end - - def test_version_from_url - @resource.url("http://example.com/foo-1.0.tar.gz") - assert_version_equal "1.0", @resource.version - assert_predicate @resource.version, :detected_from_url? - end - - def test_version_with_scheme - klass = Class.new(Version) - @resource.version klass.new("1.0") - assert_version_equal "1.0", @resource.version - assert_instance_of klass, @resource.version - end - - def test_version_from_tag - @resource.url("http://example.com/foo-1.0.tar.gz", tag: "v1.0.2") - assert_version_equal "1.0.2", @resource.version - assert_predicate @resource.version, :detected_from_url? - end - - def test_rejects_non_string_versions - assert_raises(TypeError) { @resource.version(1) } - assert_raises(TypeError) { @resource.version(2.0) } - assert_raises(TypeError) { @resource.version(Object.new) } - end - - def test_version_when_url_is_not_set - assert_nil @resource.version - end - - def test_mirrors - assert_empty @resource.mirrors - @resource.mirror("foo") - @resource.mirror("bar") - assert_equal %w[foo bar], @resource.mirrors - end - - def test_checksum_setters - assert_nil @resource.checksum - @resource.sha256(TEST_SHA256) - assert_equal Checksum.new(:sha256, TEST_SHA256), @resource.checksum - end - - def test_download_strategy - strategy = Object.new - DownloadStrategyDetector - .expects(:detect).with("foo", nil).returns(strategy) - @resource.url("foo") - assert_equal strategy, @resource.download_strategy - end - - def test_verify_download_integrity_missing - fn = Pathname.new("test") - - fn.stubs(file?: true) - fn.expects(:verify_checksum).raises(ChecksumMissingError) - fn.expects(:sha256) - - shutup { @resource.verify_download_integrity(fn) } - end - - def test_verify_download_integrity_mismatch - fn = stub(file?: true) - checksum = @resource.sha256(TEST_SHA256) - - fn.expects(:verify_checksum).with(checksum) - .raises(ChecksumMismatchError.new(fn, checksum, Object.new)) - - shutup do - assert_raises(ChecksumMismatchError) do - @resource.verify_download_integrity(fn) - end - end - end -end diff --git a/Library/Homebrew/test/sandbox_test.rb b/Library/Homebrew/test/sandbox_test.rb index 2a062cb10..a633defce 100644 --- a/Library/Homebrew/test/sandbox_test.rb +++ b/Library/Homebrew/test/sandbox_test.rb @@ -3,26 +3,23 @@ require "sandbox" class SandboxTest < Homebrew::TestCase def setup + super skip "sandbox not implemented" unless Sandbox.available? @sandbox = Sandbox.new @dir = Pathname.new(mktmpdir) @file = @dir/"foo" end - def teardown - @dir.rmtree - end - def test_formula? f = formula { url "foo-1.0" } f2 = formula { url "bar-1.0" } f2.stubs(:tap).returns(Tap.fetch("test/tap")) - ARGV.stubs(:sandbox?).returns true + ENV["HOMEBREW_SANDBOX"] = "1" assert Sandbox.formula?(f), "Formulae should be sandboxed if --sandbox was passed." - ARGV.stubs(:sandbox?).returns false + ENV.delete("HOMEBREW_SANDBOX") assert Sandbox.formula?(f), "Formulae should be sandboxed if in a sandboxed tap." refute Sandbox.formula?(f2), @@ -30,7 +27,7 @@ class SandboxTest < Homebrew::TestCase end def test_test? - ARGV.stubs(:no_sandbox?).returns false + ENV.delete("HOMEBREW_NO_SANDBOX") assert Sandbox.test?, "Tests should be sandboxed unless --no-sandbox was passed." end @@ -50,7 +47,7 @@ class SandboxTest < Homebrew::TestCase def test_complains_on_failure Utils.expects(popen_read: "foo") - ARGV.stubs(verbose?: true) + ENV["HOMEBREW_VERBOSE"] = "1" out, _err = capture_io do assert_raises(ErrorDuringExecution) { @sandbox.exec "false" } end @@ -64,7 +61,7 @@ class SandboxTest < Homebrew::TestCase bar EOS Utils.expects(popen_read: with_bogus_error) - ARGV.stubs(verbose?: true) + ENV["HOMEBREW_VERBOSE"] = "1" out, _err = capture_io do assert_raises(ErrorDuringExecution) { @sandbox.exec "false" } end diff --git a/Library/Homebrew/test/search_remote_tap_test.rb b/Library/Homebrew/test/search_remote_tap_test.rb deleted file mode 100644 index 9dd9ee654..000000000 --- a/Library/Homebrew/test/search_remote_tap_test.rb +++ /dev/null @@ -1,19 +0,0 @@ -require "testing_env" -require "cmd/search" - -class SearchRemoteTapTests < Homebrew::TestCase - def test_search_remote_tap - json_response = { - "tree" => [ - { - "path" => "Formula/not-a-formula.rb", - "type" => "blob", - }, - ], - } - - GitHub.stubs(:open).yields(json_response) - - assert_equal ["homebrew/not-a-tap/not-a-formula"], Homebrew.search_tap("homebrew", "not-a-tap", "not-a-formula") - end -end diff --git a/Library/Homebrew/test/search_test.rb b/Library/Homebrew/test/search_test.rb deleted file mode 100644 index 70b6f01fb..000000000 --- a/Library/Homebrew/test/search_test.rb +++ /dev/null @@ -1,30 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestSearch < IntegrationCommandTestCase - def test_search - setup_test_formula "testball" - desc_cache = HOMEBREW_CACHE/"desc_cache.json" - refute_predicate desc_cache, :exist?, "Cached file should not exist" - - assert_match "testball", cmd("search") - assert_match "testball", cmd("search", "testball") - assert_match "testball", cmd("search", "homebrew/homebrew-core/testball") - assert_match "testball", cmd("search", "--desc", "Some test") - - flags = { - "macports" => "https://www.macports.org/ports.php?by=name&substr=testball", - "fink" => "http://pdb.finkproject.org/pdb/browse.php?summary=testball", - "debian" => "https://packages.debian.org/search?keywords=testball&searchon=names&suite=all§ion=all", - "opensuse" => "https://software.opensuse.org/search?q=testball", - "fedora" => "https://admin.fedoraproject.org/pkgdb/packages/%2Atestball%2A/", - "ubuntu" => "http://packages.ubuntu.com/search?keywords=testball&searchon=names&suite=all§ion=all", - } - - flags.each do |flag, url| - assert_equal url, cmd("search", "--#{flag}", - "testball", "HOMEBREW_BROWSER" => "echo") - end - - assert_predicate desc_cache, :exist?, "Cached file should exist" - end -end diff --git a/Library/Homebrew/test/services_test.rb b/Library/Homebrew/test/services_test.rb deleted file mode 100644 index 280aeb9f4..000000000 --- a/Library/Homebrew/test/services_test.rb +++ /dev/null @@ -1,11 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestServices < IntegrationCommandTestCase - def test_services - needs_test_cmd_taps - needs_macos - setup_remote_tap("homebrew/services") - assert_equal "Warning: No services available to control with `brew services`", - cmd("services", "list") - end -end diff --git a/Library/Homebrew/test/sh_test.rb b/Library/Homebrew/test/sh_test.rb deleted file mode 100644 index 48fcdc54a..000000000 --- a/Library/Homebrew/test/sh_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestSh < IntegrationCommandTestCase - def test_sh - assert_match "Your shell has been configured", - cmd("sh", "SHELL" => which("true")) - end -end diff --git a/Library/Homebrew/test/shell_test.rb b/Library/Homebrew/test/shell_test.rb deleted file mode 100644 index 877acb5c8..000000000 --- a/Library/Homebrew/test/shell_test.rb +++ /dev/null @@ -1,59 +0,0 @@ -require "testing_env" -require "utils/shell" - -class ShellSmokeTest < Homebrew::TestCase - def test_path_to_shell - # raw command name - assert_equal :bash, Utils::Shell.path_to_shell("bash") - # full path - assert_equal :bash, Utils::Shell.path_to_shell("/bin/bash") - # versions - assert_equal :zsh, Utils::Shell.path_to_shell("zsh-5.2") - # strip newline too - assert_equal :zsh, Utils::Shell.path_to_shell("zsh-5.2\n") - end - - def test_path_to_shell_failure - assert_equal nil, Utils::Shell.path_to_shell("") - assert_equal nil, Utils::Shell.path_to_shell("@@@@@@") - assert_equal nil, Utils::Shell.path_to_shell("invalid_shell-4.2") - end - - def test_sh_quote - assert_equal "''", Utils::Shell.sh_quote("") - assert_equal "\\\\", Utils::Shell.sh_quote("\\") - assert_equal "'\n'", Utils::Shell.sh_quote("\n") - assert_equal "\\$", Utils::Shell.sh_quote("$") - assert_equal "word", Utils::Shell.sh_quote("word") - end - - def test_csh_quote - assert_equal "''", Utils::Shell.csh_quote("") - assert_equal "\\\\", Utils::Shell.csh_quote("\\") - # note this test is different than for sh - assert_equal "'\\\n'", Utils::Shell.csh_quote("\n") - assert_equal "\\$", Utils::Shell.csh_quote("$") - assert_equal "word", Utils::Shell.csh_quote("word") - end - - def prepend_path_shell(shell, path, fragment) - original_shell = ENV["SHELL"] - ENV["SHELL"] = shell - - prepend_message = Utils::Shell.prepend_path_in_shell_profile(path) - assert( - prepend_message.start_with?(fragment), - "#{shell}: expected #{prepend_message} to match #{fragment}" - ) - - ENV["SHELL"] = original_shell - end - - def test_prepend_path_in_shell_profile - prepend_path_shell "/bin/tcsh", "/path", "echo 'setenv PATH /path" - - prepend_path_shell "/bin/bash", "/path", "echo 'export PATH=\"/path" - - prepend_path_shell "/usr/local/bin/fish", "/path", "echo 'set -g fish_user_paths \"/path\" $fish_user_paths' >>" - end -end diff --git a/Library/Homebrew/test/software_spec_spec.rb b/Library/Homebrew/test/software_spec_spec.rb new file mode 100644 index 000000000..5fd4f598a --- /dev/null +++ b/Library/Homebrew/test/software_spec_spec.rb @@ -0,0 +1,184 @@ +require "software_spec" + +RSpec::Matchers.alias_matcher :have_defined_resource, :be_resource_defined +RSpec::Matchers.alias_matcher :have_defined_option, :be_option_defined + +describe SoftwareSpec do + let(:owner) { double(name: "some_name", full_name: "some_name", tap: "homebrew/core") } + + describe "#resource" do + it "defines a resource" do + subject.resource("foo") { url "foo-1.0" } + expect(subject).to have_defined_resource("foo") + end + + it "sets itself to be the resource's owner" do + subject.resource("foo") { url "foo-1.0" } + subject.owner = owner + subject.resources.each_value do |r| + expect(r.owner).to eq(subject) + end + end + + it "receives the owner's version if it has no own version" do + subject.url("foo-42") + subject.resource("bar") { url "bar" } + subject.owner = owner + + expect(subject.resource("bar").version).to eq("42") + end + + it "raises an error when duplicate resources are defined" do + subject.resource("foo") { url "foo-1.0" } + expect { + subject.resource("foo") { url "foo-1.0" } + }.to raise_error(DuplicateResourceError) + end + + it "raises an error when accessing missing resources" do + subject.owner = owner + expect { + subject.resource("foo") + }.to raise_error(ResourceMissingError) + end + end + + describe "#owner" do + it "sets the owner" do + subject.owner = owner + expect(subject.owner).to eq(owner) + end + + it "sets the name" do + subject.owner = owner + expect(subject.name).to eq(owner.name) + end + end + + describe "#option" do + it "defines an option" do + subject.option("foo") + expect(subject).to have_defined_option("foo") + end + + it "raises an error when it begins with dashes" do + expect { + subject.option("--foo") + }.to raise_error(ArgumentError) + end + + it "raises an error when name is empty" do + expect { + subject.option("") + }.to raise_error(ArgumentError) + end + + it "special cases the cxx11 option" do + subject.option(:cxx11) + expect(subject).to have_defined_option("c++11") + expect(subject).not_to have_defined_option("cxx11") + end + + it "supports options with descriptions" do + subject.option("bar", "description") + expect(subject.options.first.description).to eq("description") + end + + it "defaults to an empty string when no description is given" do + subject.option("foo") + expect(subject.options.first.description).to eq("") + end + end + + describe "#deprecated_option" do + it "allows specifying deprecated options" do + subject.deprecated_option("foo" => "bar") + expect(subject.deprecated_options).not_to be_empty + expect(subject.deprecated_options.first.old).to eq("foo") + expect(subject.deprecated_options.first.current).to eq("bar") + end + + it "allows specifying deprecated options as a Hash from an Array/String to an Array/String" do + subject.deprecated_option(["foo1", "foo2"] => "bar1", "foo3" => ["bar2", "bar3"]) + expect(subject.deprecated_options).to include(DeprecatedOption.new("foo1", "bar1")) + expect(subject.deprecated_options).to include(DeprecatedOption.new("foo2", "bar1")) + expect(subject.deprecated_options).to include(DeprecatedOption.new("foo3", "bar2")) + expect(subject.deprecated_options).to include(DeprecatedOption.new("foo3", "bar3")) + end + + it "raises an error when empty" do + expect { + subject.deprecated_option({}) + }.to raise_error(ArgumentError) + end + end + + describe "#depends_on" do + it "allows specifying dependencies" do + subject.depends_on("foo") + expect(subject.deps.first.name).to eq("foo") + end + + it "allows specifying optional dependencies" do + subject.depends_on "foo" => :optional + expect(subject).to have_defined_option("with-foo") + end + + it "allows specifying recommended dependencies" do + subject.depends_on "bar" => :recommended + expect(subject).to have_defined_option("without-bar") + end + end + + specify "explicit options override defaupt depends_on option description" do + subject.option("with-foo", "blah") + subject.depends_on("foo" => :optional) + expect(subject.options.first.description).to eq("blah") + end + + describe "#patch" do + it "adds a patch" do + subject.patch(:p1, :DATA) + expect(subject.patches.count).to eq(1) + expect(subject.patches.first.strip).to eq(:p1) + end + end +end + +describe HeadSoftwareSpec do + specify "#version" do + expect(subject.version).to eq(Version.create("HEAD")) + end + + specify "#verify_download_integrity" do + expect(subject.verify_download_integrity(Object.new)).to be nil + end +end + +describe BottleSpecification do + specify "#sha256" do + checksums = { + snow_leopard_32: "deadbeef" * 8, + snow_leopard: "faceb00c" * 8, + lion: "baadf00d" * 8, + mountain_lion: "8badf00d" * 8, + } + + checksums.each_pair do |cat, digest| + subject.sha256(digest => cat) + end + + checksums.each_pair do |cat, digest| + checksum, = subject.checksum_for(cat) + expect(Checksum.new(:sha256, digest)).to eq(checksum) + end + end + + %w[root_url prefix cellar rebuild].each do |method| + specify "##{method}" do + object = Object.new + subject.public_send(method, object) + expect(subject.public_send(method)).to eq(object) + end + end +end diff --git a/Library/Homebrew/test/software_spec_test.rb b/Library/Homebrew/test/software_spec_test.rb deleted file mode 100644 index d9226f8c3..000000000 --- a/Library/Homebrew/test/software_spec_test.rb +++ /dev/null @@ -1,181 +0,0 @@ -require "testing_env" -require "software_spec" - -class SoftwareSpecTests < Homebrew::TestCase - def setup - @spec = SoftwareSpec.new - end - - def test_resource - @spec.resource("foo") { url "foo-1.0" } - assert @spec.resource_defined?("foo") - end - - def test_raises_when_duplicate_resources_are_defined - @spec.resource("foo") { url "foo-1.0" } - assert_raises(DuplicateResourceError) do - @spec.resource("foo") { url "foo-1.0" } - end - end - - def test_raises_when_accessing_missing_resources - @spec.owner = Class.new do - def name - "test" - end - - def full_name - "test" - end - - def tap - "homebrew/core" - end - end.new - assert_raises(ResourceMissingError) { @spec.resource("foo") } - end - - def test_set_owner - owner = stub name: "some_name", - full_name: "some_name", - tap: "homebrew/core" - @spec.owner = owner - assert_equal owner, @spec.owner - end - - def test_resource_owner - @spec.resource("foo") { url "foo-1.0" } - @spec.owner = stub name: "some_name", - full_name: "some_name", - tap: "homebrew/core" - assert_equal "some_name", @spec.name - @spec.resources.each_value { |r| assert_equal @spec, r.owner } - end - - def test_resource_without_version_receives_owners_version - @spec.url("foo-42") - @spec.resource("bar") { url "bar" } - @spec.owner = stub name: "some_name", - full_name: "some_name", - tap: "homebrew/core" - assert_version_equal "42", @spec.resource("bar").version - end - - def test_option - @spec.option("foo") - assert @spec.option_defined?("foo") - end - - def test_option_raises_when_begins_with_dashes - assert_raises(ArgumentError) { @spec.option("--foo") } - end - - def test_option_raises_when_name_empty - assert_raises(ArgumentError) { @spec.option("") } - end - - def test_cxx11_option_special_case - @spec.option(:cxx11) - assert @spec.option_defined?("c++11") - refute @spec.option_defined?("cxx11") - end - - def test_option_description - @spec.option("bar", "description") - assert_equal "description", @spec.options.first.description - end - - def test_option_description_defaults_to_empty_string - @spec.option("foo") - assert_equal "", @spec.options.first.description - end - - def test_deprecated_option - @spec.deprecated_option("foo" => "bar") - refute_empty @spec.deprecated_options - assert_equal "foo", @spec.deprecated_options.first.old - assert_equal "bar", @spec.deprecated_options.first.current - end - - def test_deprecated_options - @spec.deprecated_option(["foo1", "foo2"] => "bar1", "foo3" => ["bar2", "bar3"]) - assert_includes @spec.deprecated_options, DeprecatedOption.new("foo1", "bar1") - assert_includes @spec.deprecated_options, DeprecatedOption.new("foo2", "bar1") - assert_includes @spec.deprecated_options, DeprecatedOption.new("foo3", "bar2") - assert_includes @spec.deprecated_options, DeprecatedOption.new("foo3", "bar3") - end - - def test_deprecated_option_raises_when_empty - assert_raises(ArgumentError) { @spec.deprecated_option({}) } - end - - def test_depends_on - @spec.depends_on("foo") - assert_equal "foo", @spec.deps.first.name - end - - def test_dependency_option_integration - @spec.depends_on "foo" => :optional - @spec.depends_on "bar" => :recommended - assert @spec.option_defined?("with-foo") - assert @spec.option_defined?("without-bar") - end - - def test_explicit_options_override_default_dep_option_description - @spec.option("with-foo", "blah") - @spec.depends_on("foo" => :optional) - assert_equal "blah", @spec.options.first.description - end - - def test_patch - @spec.patch :p1, :DATA - assert_equal 1, @spec.patches.length - assert_equal :p1, @spec.patches.first.strip - end -end - -class HeadSoftwareSpecTests < Homebrew::TestCase - def setup - @spec = HeadSoftwareSpec.new - end - - def test_version - assert_version_equal "HEAD", @spec.version - end - - def test_verify_download_integrity - assert_nil @spec.verify_download_integrity(Object.new) - end -end - -class BottleSpecificationTests < Homebrew::TestCase - def setup - @spec = BottleSpecification.new - end - - def test_checksum_setters - checksums = { - snow_leopard_32: "deadbeef"*8, - snow_leopard: "faceb00c"*8, - lion: "baadf00d"*8, - mountain_lion: "8badf00d"*8, - } - - checksums.each_pair do |cat, digest| - @spec.sha256(digest => cat) - end - - checksums.each_pair do |cat, digest| - checksum, = @spec.checksum_for(cat) - assert_equal Checksum.new(:sha256, digest), checksum - end - end - - def test_other_setters - double = Object.new - %w[root_url prefix cellar rebuild].each do |method| - @spec.send(method, double) - assert_equal double, @spec.send(method) - end - end -end diff --git a/Library/Homebrew/test/spec_helper.rb b/Library/Homebrew/test/spec_helper.rb new file mode 100644 index 000000000..9a4dbe026 --- /dev/null +++ b/Library/Homebrew/test/spec_helper.rb @@ -0,0 +1,101 @@ +require "find" +require "pathname" +require "rspec/its" +require "rspec/wait" +require "set" + +if ENV["HOMEBREW_TESTS_COVERAGE"] + require "simplecov" +end + +$LOAD_PATH.unshift(File.expand_path("#{ENV["HOMEBREW_LIBRARY"]}/Homebrew")) +$LOAD_PATH.unshift(File.expand_path("#{ENV["HOMEBREW_LIBRARY"]}/Homebrew/test/support/lib")) + +require "global" +require "tap" + +require "test/support/helper/shutup" +require "test/support/helper/fixtures" +require "test/support/helper/formula" +require "test/support/helper/spec/shared_context/integration_test" + +TEST_DIRECTORIES = [ + CoreTap.instance.path/"Formula", + HOMEBREW_CACHE, + HOMEBREW_CACHE_FORMULA, + HOMEBREW_CELLAR, + HOMEBREW_LOCK_DIR, + HOMEBREW_LOGS, + HOMEBREW_TEMP, +].freeze + +RSpec.configure do |config| + config.order = :random + config.include(Test::Helper::Shutup) + config.include(Test::Helper::Fixtures) + config.include(Test::Helper::Formula) + config.before(:each) do |example| + if example.metadata[:needs_macos] + skip "Not on macOS." unless OS.mac? + end + + if example.metadata[:needs_official_cmd_taps] + skip "Needs official command Taps." unless ENV["HOMEBREW_TEST_OFFICIAL_CMD_TAPS"] + end + + if example.metadata[:needs_python] + skip "Python not installed." unless which("python") + end + end + config.around(:each) do |example| + begin + TEST_DIRECTORIES.each(&:mkpath) + + @__homebrew_failed = Homebrew.failed? + + @__files_before_test = Find.find(TEST_TMPDIR).map { |f| f.sub(TEST_TMPDIR, "") } + + @__argv = ARGV.dup + @__env = ENV.to_hash # dup doesn't work on ENV + + example.run + ensure + ARGV.replace(@__argv) + ENV.replace(@__env) + + Tab.clear_cache + + FileUtils.rm_rf [ + TEST_DIRECTORIES.map(&:children), + HOMEBREW_LINKED_KEGS, + HOMEBREW_PINNED_KEGS, + HOMEBREW_PREFIX/".git", + HOMEBREW_PREFIX/"bin", + HOMEBREW_PREFIX/"share", + HOMEBREW_PREFIX/"opt", + HOMEBREW_PREFIX/"Caskroom", + HOMEBREW_LIBRARY/"Taps/caskroom", + HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-bundle", + HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-foo", + HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-services", + HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-shallow", + HOMEBREW_REPOSITORY/".git", + CoreTap.instance.path/".git", + CoreTap.instance.alias_dir, + CoreTap.instance.path/"formula_renames.json", + ] + + files_after_test = Find.find(TEST_TMPDIR).map { |f| f.sub(TEST_TMPDIR, "") } + + diff = Set.new(@__files_before_test) ^ Set.new(files_after_test) + expect(diff).to be_empty, <<-EOS.undent + file leak detected: + #{diff.map { |f| " #{f}" }.join("\n")} + EOS + + Homebrew.failed = @__homebrew_failed + end + end +end + +RSpec::Matchers.alias_matcher :have_failed, :be_failed diff --git a/Library/Homebrew/test/stdlib_test.rb b/Library/Homebrew/test/stdlib_test.rb deleted file mode 100644 index 3babfd58a..000000000 --- a/Library/Homebrew/test/stdlib_test.rb +++ /dev/null @@ -1,62 +0,0 @@ -require "testing_env" -require "formula" -require "cxxstdlib" - -class CxxStdlibTests < Homebrew::TestCase - def setup - @clang = CxxStdlib.create(:libstdcxx, :clang) - @gcc = CxxStdlib.create(:libstdcxx, :gcc) - @gcc40 = CxxStdlib.create(:libstdcxx, :gcc_4_0) - @gcc42 = CxxStdlib.create(:libstdcxx, :gcc_4_2) - @gcc48 = CxxStdlib.create(:libstdcxx, "gcc-4.8") - @gcc49 = CxxStdlib.create(:libstdcxx, "gcc-4.9") - @lcxx = CxxStdlib.create(:libcxx, :clang) - @purec = CxxStdlib.create(nil, :clang) - end - - def test_apple_libstdcxx_intercompatibility - assert @clang.compatible_with?(@gcc) - assert @clang.compatible_with?(@gcc42) - end - - def test_compatibility_same_compilers_and_type - assert @gcc.compatible_with?(@gcc) - assert @gcc48.compatible_with?(@gcc48) - assert @clang.compatible_with?(@clang) - end - - def test_apple_gnu_libstdcxx_incompatibility - assert !@clang.compatible_with?(@gcc48) - assert !@gcc48.compatible_with?(@clang) - end - - def test_gnu_cross_version_incompatibility - assert !@gcc48.compatible_with?(@gcc49) - assert !@gcc49.compatible_with?(@gcc48) - end - - def test_libstdcxx_libcxx_incompatibility - assert !@clang.compatible_with?(@lcxx) - assert !@lcxx.compatible_with?(@clang) - end - - def test_apple_compiler_reporting - assert_predicate @clang, :apple_compiler? - assert_predicate @gcc, :apple_compiler? - assert_predicate @gcc42, :apple_compiler? - refute_predicate @gcc48, :apple_compiler? - end - - def test_type_string_formatting - assert_equal "libstdc++", @clang.type_string - assert_equal "libc++", @lcxx.type_string - end - - def test_compatibility_for_non_cxx_software - assert @purec.compatible_with?(@clang) - assert @clang.compatible_with?(@purec) - assert @purec.compatible_with?(@purec) - assert @purec.compatible_with?(@gcc48) - assert @gcc48.compatible_with?(@purec) - end -end diff --git a/Library/Homebrew/test/string_spec.rb b/Library/Homebrew/test/string_spec.rb new file mode 100644 index 000000000..d1b820b66 --- /dev/null +++ b/Library/Homebrew/test/string_spec.rb @@ -0,0 +1,49 @@ +require "extend/string" + +describe String do + describe "#undent" do + it "removes leading whitespace, taking the first line as reference" do + string = <<-EOS.undent + hi +........my friend over + there + EOS + + expect(string).to eq("hi\n........my friend over\n there\n") + end + + it "removes nothing if the text is not indented" do + string = <<-EOS.undent +hi +I'm not indented + EOS + + expect(string).to eq("hi\nI'm not indented\n") + end + + it "can be nested" do + nested_string = <<-EOS.undent + goodbye + EOS + + string = <<-EOS.undent + hello + #{nested_string} + EOS + + expect(string).to eq("hello\ngoodbye\n\n") + end + end +end + +describe StringInreplaceExtension do + subject { string.extend(described_class) } + let(:string) { "foobar" } + + describe "#sub!" do + it "adds an error to #errors when no replacement was made" do + subject.sub! "not here", "test" + expect(subject.errors).to eq(['expected replacement of "not here" with "test"']) + end + end +end diff --git a/Library/Homebrew/test/string_test.rb b/Library/Homebrew/test/string_test.rb deleted file mode 100644 index 497c4badb..000000000 --- a/Library/Homebrew/test/string_test.rb +++ /dev/null @@ -1,40 +0,0 @@ -require "testing_env" -require "extend/string" - -class StringTest < Homebrew::TestCase - def test_undent - undented = <<-EOS.undent - hi -....my friend over - there - EOS - assert_equal "hi\n....my friend over\nthere\n", undented - end - - def test_undent_not_indented - undented = <<-EOS.undent -hi -I'm not indented - EOS - assert_equal "hi\nI'm not indented\n", undented - end - - def test_undent_nested - nest = <<-EOS.undent - goodbye - EOS - - undented = <<-EOS.undent - hello - #{nest} - EOS - - assert_equal "hello\ngoodbye\n\n", undented - end - - def test_inreplace_sub_failure - s = "foobar".extend StringInreplaceExtension - s.sub! "not here", "test" - assert_equal ['expected replacement of "not here" with "test"'], s.errors - end -end diff --git a/Library/Homebrew/cask/spec/support/Casks/appcast-checkpoint-sha256-for-empty-string.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/appcast-checkpoint-sha256-for-empty-string.rb index f40f244f2..4e74d728d 100644 --- a/Library/Homebrew/cask/spec/support/Casks/appcast-checkpoint-sha256-for-empty-string.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/appcast-checkpoint-sha256-for-empty-string.rb @@ -1,4 +1,4 @@ -test_cask 'appcast-checkpoint-sha256-for-empty-string' do +cask 'appcast-checkpoint-sha256-for-empty-string' do appcast 'http://localhost/appcast.xml', checkpoint: 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' end diff --git a/Library/Homebrew/cask/spec/support/Casks/appcast-invalid-checkpoint.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/appcast-invalid-checkpoint.rb index e182c2389..8b6934148 100644 --- a/Library/Homebrew/cask/spec/support/Casks/appcast-invalid-checkpoint.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/appcast-invalid-checkpoint.rb @@ -1,4 +1,4 @@ -test_cask 'appcast-invalid-checkpoint' do +cask 'appcast-invalid-checkpoint' do appcast 'http://localhost/appcast.xml', checkpoint: 'not a valid shasum' end diff --git a/Library/Homebrew/cask/spec/support/Casks/appcast-missing-checkpoint.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/appcast-missing-checkpoint.rb index 5ab2c0665..fefdbcb3a 100644 --- a/Library/Homebrew/cask/spec/support/Casks/appcast-missing-checkpoint.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/appcast-missing-checkpoint.rb @@ -1,3 +1,3 @@ -test_cask 'appcast-missing-checkpoint' do +cask 'appcast-missing-checkpoint' do appcast 'http://localhost/appcast.xml' end diff --git a/Library/Homebrew/cask/spec/support/Casks/appcast-valid-checkpoint.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/appcast-valid-checkpoint.rb index 96d7edbba..84c9ca512 100644 --- a/Library/Homebrew/cask/spec/support/Casks/appcast-valid-checkpoint.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/appcast-valid-checkpoint.rb @@ -1,4 +1,4 @@ -test_cask 'appcast-valid-checkpoint' do +cask 'appcast-valid-checkpoint' do appcast 'http://localhost/appcast.xml', checkpoint: 'd5b2dfbef7ea28c25f7a77cd7fa14d013d82b626db1d82e00e25822464ba19e2' end diff --git a/Library/Homebrew/cask/test/support/Casks/appdir-interpolation.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/appdir-interpolation.rb index fdc09ef5a..e4b3e79e6 100644 --- a/Library/Homebrew/cask/test/support/Casks/appdir-interpolation.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/appdir-interpolation.rb @@ -1,4 +1,4 @@ -test_cask 'appdir-interpolation' do +cask 'appdir-interpolation' do version '2.61' sha256 'e44ffa103fbf83f55c8d0b1bea309a43b2880798dae8620b1ee8da5e1095ec68' diff --git a/Library/Homebrew/cask/test/support/Casks/auto-updates.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/auto-updates.rb index 0fcdb991a..1cada2561 100644 --- a/Library/Homebrew/cask/test/support/Casks/auto-updates.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/auto-updates.rb @@ -1,4 +1,4 @@ -test_cask 'auto-updates' do +cask 'auto-updates' do version '2.61' sha256 'e44ffa103fbf83f55c8d0b1bea309a43b2880798dae8620b1ee8da5e1095ec68' diff --git a/Library/Homebrew/cask/test/support/Casks/bad-checksum.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/bad-checksum.rb index 79e5f24c9..254ee59fd 100644 --- a/Library/Homebrew/cask/test/support/Casks/bad-checksum.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/bad-checksum.rb @@ -1,4 +1,4 @@ -test_cask 'bad-checksum' do +cask 'bad-checksum' do version '1.2.3' sha256 'badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadb' diff --git a/Library/Homebrew/cask/test/support/Casks/basic-cask.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/basic-cask.rb index d3aaa283e..ff1d90003 100644 --- a/Library/Homebrew/cask/test/support/Casks/basic-cask.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/basic-cask.rb @@ -1,4 +1,4 @@ -test_cask 'basic-cask' do +cask 'basic-cask' do version '1.2.3' sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' diff --git a/Library/Homebrew/cask/spec/support/Casks/booby-trap.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/booby-trap.rb index 21bd97952..21bd97952 100644 --- a/Library/Homebrew/cask/spec/support/Casks/booby-trap.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/booby-trap.rb diff --git a/Library/Homebrew/cask/test/support/Casks/container-7z.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/container-7z.rb index 7dd01eee4..5b043a75e 100644 --- a/Library/Homebrew/cask/test/support/Casks/container-7z.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/container-7z.rb @@ -1,4 +1,4 @@ -test_cask 'container-7z' do +cask 'container-7z' do version '1.2.3' sha256 '3f9542ace85ed5f88549e2d0ea82210f8ddc87e0defbb78469d3aed719b3c964' diff --git a/Library/Homebrew/cask/test/support/Casks/container-air.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/container-air.rb index c310e0a6f..5aaf3d53e 100644 --- a/Library/Homebrew/cask/test/support/Casks/container-air.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/container-air.rb @@ -1,4 +1,4 @@ -test_cask 'container-air' do +cask 'container-air' do version '0.1' sha256 '554472e163f8a028629b12b468e29acda9f16b223dff74fcd218bba73cc2365a' diff --git a/Library/Homebrew/cask/test/support/Casks/container-bzip2.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/container-bzip2.rb index 9d9bdff98..60f834b7f 100644 --- a/Library/Homebrew/cask/test/support/Casks/container-bzip2.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/container-bzip2.rb @@ -1,4 +1,4 @@ -test_cask 'container-bzip2' do +cask 'container-bzip2' do version '1.2.3' sha256 'eaf67b3a62cb9275f96e45d05c70b94bef9ef1dae344083e93eda6b0b388a61c' diff --git a/Library/Homebrew/cask/test/support/Casks/container-cab.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/container-cab.rb index ebc7a544e..e57131567 100644 --- a/Library/Homebrew/cask/test/support/Casks/container-cab.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/container-cab.rb @@ -1,4 +1,4 @@ -test_cask 'container-cab' do +cask 'container-cab' do version '1.2.3' sha256 'c267f5cebb14814c8e612a8b7d2bda02aec913f869509b6f1d3883427c0f552b' diff --git a/Library/Homebrew/cask/test/support/Casks/container-dmg.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/container-dmg.rb index d63596f42..e9974b5d2 100644 --- a/Library/Homebrew/cask/test/support/Casks/container-dmg.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/container-dmg.rb @@ -1,4 +1,4 @@ -test_cask 'container-dmg' do +cask 'container-dmg' do version '1.2.3' sha256 '74d89d4fa5cef175cf43666ce11fefa3741aa1522114042ac75e656be37141a1' diff --git a/Library/Homebrew/cask/test/support/Casks/container-gzip.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/container-gzip.rb index c2ab00384..0bfc4108f 100644 --- a/Library/Homebrew/cask/test/support/Casks/container-gzip.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/container-gzip.rb @@ -1,4 +1,4 @@ -test_cask 'container-gzip' do +cask 'container-gzip' do version '1.2.3' sha256 'fa4ebb5246583c4b6e62e1df4e3b71b4e38a1d7d91c025665827195d36214b20' diff --git a/Library/Homebrew/cask/test/support/Casks/container-lzma.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/container-lzma.rb index d5f708523..92d2c253e 100644 --- a/Library/Homebrew/cask/test/support/Casks/container-lzma.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/container-lzma.rb @@ -1,4 +1,4 @@ -test_cask 'container-lzma' do +cask 'container-lzma' do version '1.2.3' sha256 '9d7edb32d02ab9bd9749a5bde8756595ea4cfcb1da02ca11c30fb591d4c1ed85' diff --git a/Library/Homebrew/cask/test/support/Casks/container-pkg.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/container-pkg.rb index 959caaa08..2ff4cca1e 100644 --- a/Library/Homebrew/cask/test/support/Casks/container-pkg.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/container-pkg.rb @@ -1,4 +1,4 @@ -test_cask 'container-pkg' do +cask 'container-pkg' do version '1.2.3' sha256 '611c50c8a2a2098951d2cd0fd54787ed81b92cd97b4b08bd7cba17f1e1d8e40b' diff --git a/Library/Homebrew/cask/test/support/Casks/container-rar.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/container-rar.rb index 7186577a2..33ea670d1 100644 --- a/Library/Homebrew/cask/test/support/Casks/container-rar.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/container-rar.rb @@ -1,4 +1,4 @@ -test_cask 'container-rar' do +cask 'container-rar' do version '1.2.3' sha256 '419af7864c0e1f125515c49b08bd22e0f7de39f5285897c440fe03c714871763' diff --git a/Library/Homebrew/cask/test/support/Casks/container-sit.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/container-sit.rb index 3a0faad97..5715795a7 100644 --- a/Library/Homebrew/cask/test/support/Casks/container-sit.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/container-sit.rb @@ -1,4 +1,4 @@ -test_cask 'container-sit' do +cask 'container-sit' do version '1.2.3' sha256 '0d21a64dce625044345c8ecca888e5439feaf254dac7f884917028a744f93cf3' diff --git a/Library/Homebrew/cask/test/support/Casks/container-tar-gz.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/container-tar-gz.rb index 58e1d82fd..e32931c89 100644 --- a/Library/Homebrew/cask/test/support/Casks/container-tar-gz.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/container-tar-gz.rb @@ -1,4 +1,4 @@ -test_cask 'container-tar-gz' do +cask 'container-tar-gz' do version '1.2.3' sha256 'fab685fabf73d5a9382581ce8698fce9408f5feaa49fa10d9bc6c510493300f5' diff --git a/Library/Homebrew/cask/test/support/Casks/container-xar.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/container-xar.rb index 35e01d0a8..82a751d5d 100644 --- a/Library/Homebrew/cask/test/support/Casks/container-xar.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/container-xar.rb @@ -1,4 +1,4 @@ -test_cask 'container-xar' do +cask 'container-xar' do version '1.2.3' sha256 '5bb8e09a6fc630ebeaf266b1fd2d15e2ae7d32d7e4da6668a8093426fa1ba509' diff --git a/Library/Homebrew/cask/test/support/Casks/container-xz.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/container-xz.rb index b27e908ae..3f844af04 100644 --- a/Library/Homebrew/cask/test/support/Casks/container-xz.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/container-xz.rb @@ -1,4 +1,4 @@ -test_cask 'container-xz' do +cask 'container-xz' do version '1.2.3' sha256 '839263f474edde1d54a9101606e6f0dc9d963acc93f6dcc5af8d10ebc3187c02' diff --git a/Library/Homebrew/cask/spec/support/Casks/generic-artifact-absolute-target.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/generic-artifact-absolute-target.rb index 475fb055f..a1844a9c9 100644 --- a/Library/Homebrew/cask/spec/support/Casks/generic-artifact-absolute-target.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/generic-artifact-absolute-target.rb @@ -1,3 +1,3 @@ -test_cask 'generic-artifact-absolute-target' do +cask 'generic-artifact-absolute-target' do artifact 'Caffeine.app', target: "#{Hbc.appdir}/Caffeine.app" end diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/generic-artifact-no-target.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/generic-artifact-no-target.rb new file mode 100644 index 000000000..a3e65caab --- /dev/null +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/generic-artifact-no-target.rb @@ -0,0 +1,3 @@ +cask 'generic-artifact-no-target' do + artifact 'Caffeine.app' +end diff --git a/Library/Homebrew/cask/spec/support/Casks/generic-artifact-relative-target.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/generic-artifact-relative-target.rb index f97441751..eb521e35a 100644 --- a/Library/Homebrew/cask/spec/support/Casks/generic-artifact-relative-target.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/generic-artifact-relative-target.rb @@ -1,3 +1,3 @@ -test_cask 'generic-artifact-relative-target' do +cask 'generic-artifact-relative-target' do artifact 'Caffeine.app', target: 'Caffeine.app' end diff --git a/Library/Homebrew/cask/spec/support/Casks/invalid-sha256.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid-sha256.rb index aac00f495..2804da7c3 100644 --- a/Library/Homebrew/cask/spec/support/Casks/invalid-sha256.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid-sha256.rb @@ -1,4 +1,4 @@ -test_cask 'invalid-sha256' do +cask 'invalid-sha256' do version '1.2.3' sha256 'not a valid shasum' end diff --git a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-appcast-multiple.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-appcast-multiple.rb index db2621074..37634f619 100644 --- a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-appcast-multiple.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-appcast-multiple.rb @@ -1,4 +1,4 @@ -test_cask 'invalid-appcast-multiple' do +cask 'invalid-appcast-multiple' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-appcast-url.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-appcast-url.rb index b4c11b1be..7b51ffb53 100644 --- a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-appcast-url.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-appcast-url.rb @@ -1,4 +1,4 @@ -test_cask 'invalid-appcast-url' do +cask 'invalid-appcast-url' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-conflicts-with-key.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-conflicts-with-key.rb index d39d124b0..b066139ce 100644 --- a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-conflicts-with-key.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-conflicts-with-key.rb @@ -1,4 +1,4 @@ -test_cask 'invalid-conflicts-with-key' do +cask 'invalid-conflicts-with-key' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-depends-on-arch-value.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-depends-on-arch-value.rb index b0c919a9b..b21912a6e 100644 --- a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-depends-on-arch-value.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-depends-on-arch-value.rb @@ -1,4 +1,4 @@ -test_cask 'invalid-depends-on-arch-value' do +cask 'invalid-depends-on-arch-value' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-depends-on-key.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-depends-on-key.rb index 05304e806..24a912893 100644 --- a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-depends-on-key.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-depends-on-key.rb @@ -1,4 +1,4 @@ -test_cask 'invalid-depends-on-key' do +cask 'invalid-depends-on-key' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-depends-on-macos-bad-release.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-depends-on-macos-bad-release.rb index 183dd5d91..723ceacbb 100644 --- a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-depends-on-macos-bad-release.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-depends-on-macos-bad-release.rb @@ -1,4 +1,4 @@ -test_cask 'invalid-depends-on-macos-bad-release' do +cask 'invalid-depends-on-macos-bad-release' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-depends-on-macos-conflicting-forms.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-depends-on-macos-conflicting-forms.rb index b1f763d76..689e24b67 100644 --- a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-depends-on-macos-conflicting-forms.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-depends-on-macos-conflicting-forms.rb @@ -1,4 +1,4 @@ -test_cask 'invalid-depends-on-macos-conflicting-forms' do +cask 'invalid-depends-on-macos-conflicting-forms' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-depends-on-x11-value.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-depends-on-x11-value.rb index eefd3ac40..5c3faec35 100644 --- a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-depends-on-x11-value.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-depends-on-x11-value.rb @@ -1,4 +1,4 @@ -test_cask 'invalid-depends-on-x11-value' do +cask 'invalid-depends-on-x11-value' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-gpg-conflicting-keys.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-gpg-conflicting-keys.rb index bf14d372b..baf124b7a 100644 --- a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-gpg-conflicting-keys.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-gpg-conflicting-keys.rb @@ -1,4 +1,4 @@ -test_cask 'invalid-gpg-conflicting-keys' do +cask 'invalid-gpg-conflicting-keys' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-gpg-key-id.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-gpg-key-id.rb index 626e02a47..386593b06 100644 --- a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-gpg-key-id.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-gpg-key-id.rb @@ -1,4 +1,4 @@ -test_cask 'invalid-gpg-key-id' do +cask 'invalid-gpg-key-id' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-gpg-key-url.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-gpg-key-url.rb index 77d41ed6b..4108380d2 100644 --- a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-gpg-key-url.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-gpg-key-url.rb @@ -1,4 +1,4 @@ -test_cask 'invalid-gpg-key-url' do +cask 'invalid-gpg-key-url' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-gpg-missing-key.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-gpg-missing-key.rb index 460bcd532..3375801c9 100644 --- a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-gpg-missing-key.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-gpg-missing-key.rb @@ -1,4 +1,4 @@ -test_cask 'invalid-gpg-missing-key' do +cask 'invalid-gpg-missing-key' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-gpg-multiple-stanzas.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-gpg-multiple-stanzas.rb index 8abc89486..b420f74d5 100644 --- a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-gpg-multiple-stanzas.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-gpg-multiple-stanzas.rb @@ -1,4 +1,4 @@ -test_cask 'invalid-gpg-multiple-stanzas' do +cask 'invalid-gpg-multiple-stanzas' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-gpg-parameter.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-gpg-parameter.rb index f1abc9225..40f6a9dae 100644 --- a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-gpg-parameter.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-gpg-parameter.rb @@ -1,4 +1,4 @@ -test_cask 'invalid-gpg-parameter' do +cask 'invalid-gpg-parameter' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-gpg-signature-url.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-gpg-signature-url.rb index 1b9e7362f..43cc27b08 100644 --- a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-gpg-signature-url.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-gpg-signature-url.rb @@ -1,4 +1,4 @@ -test_cask 'invalid-gpg-signature-url' do +cask 'invalid-gpg-signature-url' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-gpg-type.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-gpg-type.rb index 266047617..a369ef875 100644 --- a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-gpg-type.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-gpg-type.rb @@ -1,4 +1,4 @@ -test_cask 'invalid-gpg-type' do +cask 'invalid-gpg-type' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-header-format.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-header-format.rb index a8159c979..c8c613767 100644 --- a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-header-format.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-header-format.rb @@ -1,4 +1,4 @@ -test_cask => 'invalid-header-format' do +cask => 'invalid-header-format' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-header-token-mismatch.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-header-token-mismatch.rb new file mode 100644 index 000000000..af15a13ef --- /dev/null +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-header-token-mismatch.rb @@ -0,0 +1,9 @@ +cask 'invalid-header-token-mismatch-this-text-does-not-belong' do + version '1.2.3' + sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' + + url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip" + homepage 'http://example.com/local-caffeine' + + app 'Caffeine.app' +end diff --git a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-header-version.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-header-version.rb index 47851c0e0..7e37e61df 100644 --- a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-header-version.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-header-version.rb @@ -1,4 +1,4 @@ -test_cask 'invalid-header-version' do +cask 'invalid-header-version' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-stage-only-conflict.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-stage-only-conflict.rb index 84510ac24..5a0ccadf6 100644 --- a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-stage-only-conflict.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-stage-only-conflict.rb @@ -1,4 +1,4 @@ -test_cask 'invalid-stage-only-conflict' do +cask 'invalid-stage-only-conflict' do version '2.61' sha256 'e44ffa103fbf83f55c8d0b1bea309a43b2880798dae8620b1ee8da5e1095ec68' diff --git a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-two-homepage.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-two-homepage.rb index d4e5ff4a9..5170a9c0f 100644 --- a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-two-homepage.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-two-homepage.rb @@ -1,4 +1,4 @@ -test_cask 'invalid-two-homepage' do +cask 'invalid-two-homepage' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-two-url.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-two-url.rb index 49e470788..f548400a4 100644 --- a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-two-url.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-two-url.rb @@ -1,4 +1,4 @@ -test_cask 'invalid-two-url' do +cask 'invalid-two-url' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-two-version.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-two-version.rb index c9fe37772..fbffa8a1e 100644 --- a/Library/Homebrew/cask/test/support/Casks/invalid/invalid-two-version.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-two-version.rb @@ -1,4 +1,4 @@ -test_cask 'invalid-two-version' do +cask 'invalid-two-version' do version '1.2.3' version '2.0' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/local-caffeine.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/local-caffeine.rb index 2be9b4397..934d22463 100644 --- a/Library/Homebrew/cask/test/support/Casks/local-caffeine.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/local-caffeine.rb @@ -1,4 +1,4 @@ -test_cask 'local-caffeine' do +cask 'local-caffeine' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/local-transmission.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/local-transmission.rb index f5244d0a5..6709ac12e 100644 --- a/Library/Homebrew/cask/test/support/Casks/local-transmission.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/local-transmission.rb @@ -1,4 +1,4 @@ -test_cask 'local-transmission' do +cask 'local-transmission' do version '2.61' sha256 'e44ffa103fbf83f55c8d0b1bea309a43b2880798dae8620b1ee8da5e1095ec68' diff --git a/Library/Homebrew/cask/test/support/Casks/missing-checksum.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/missing-checksum.rb index 5e1886a57..907b1375f 100644 --- a/Library/Homebrew/cask/test/support/Casks/missing-checksum.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/missing-checksum.rb @@ -1,4 +1,4 @@ -test_cask 'missing-checksum' do +cask 'missing-checksum' do version '1.2.3' url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip" diff --git a/Library/Homebrew/cask/spec/support/Casks/missing-homepage.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/missing-homepage.rb index ff924541d..cf06d6c33 100644 --- a/Library/Homebrew/cask/spec/support/Casks/missing-homepage.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/missing-homepage.rb @@ -1,4 +1,4 @@ -test_cask 'missing-homepage' do +cask 'missing-homepage' do version '1.2.3' url 'http://localhost/something.dmg' diff --git a/Library/Homebrew/cask/spec/support/Casks/missing-name.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/missing-name.rb index a5265b379..0801f4abb 100644 --- a/Library/Homebrew/cask/spec/support/Casks/missing-name.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/missing-name.rb @@ -1,4 +1,4 @@ -test_cask 'missing-name' do +cask 'missing-name' do version '1.2.3' url 'http://localhost/something.dmg' diff --git a/Library/Homebrew/cask/spec/support/Casks/missing-sha256.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/missing-sha256.rb index 7f8027907..e6e6d9d20 100644 --- a/Library/Homebrew/cask/spec/support/Casks/missing-sha256.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/missing-sha256.rb @@ -1,4 +1,4 @@ -test_cask 'missing-sha256' do +cask 'missing-sha256' do version '1.2.3' url 'http://localhost/something.dmg' diff --git a/Library/Homebrew/cask/spec/support/Casks/missing-url.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/missing-url.rb index 1b3e76b9c..0bfaec332 100644 --- a/Library/Homebrew/cask/spec/support/Casks/missing-url.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/missing-url.rb @@ -1,4 +1,4 @@ -test_cask 'missing-url' do +cask 'missing-url' do version '1.2.3' homepage 'http://example.com' diff --git a/Library/Homebrew/cask/spec/support/Casks/missing-version.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/missing-version.rb index da2160bce..88e13d8bb 100644 --- a/Library/Homebrew/cask/spec/support/Casks/missing-version.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/missing-version.rb @@ -1,4 +1,4 @@ -test_cask 'missing-version' do +cask 'missing-version' do url 'http://localhost/something.dmg' homepage 'http://example.com' end diff --git a/Library/Homebrew/cask/test/support/Casks/naked-executable.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/naked-executable.rb index 619c7a5fb..2f4e30dc1 100644 --- a/Library/Homebrew/cask/test/support/Casks/naked-executable.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/naked-executable.rb @@ -1,4 +1,4 @@ -test_cask 'naked-executable' do +cask 'naked-executable' do version '1.2.3' sha256 '306c6ca7407560340797866e077e053627ad409277d1b9da58106fce4cf717cb' diff --git a/Library/Homebrew/cask/test/support/Casks/nested-app.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/nested-app.rb index 526c7414a..6061f7bff 100644 --- a/Library/Homebrew/cask/test/support/Casks/nested-app.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/nested-app.rb @@ -1,4 +1,4 @@ -test_cask 'nested-app' do +cask 'nested-app' do version '1.2.3' sha256 '1866dfa833b123bb8fe7fa7185ebf24d28d300d0643d75798bc23730af734216' diff --git a/Library/Homebrew/cask/test/support/Casks/no-checksum.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/no-checksum.rb index d9ba354f5..1e06c6168 100644 --- a/Library/Homebrew/cask/test/support/Casks/no-checksum.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/no-checksum.rb @@ -1,4 +1,4 @@ -test_cask 'no-checksum' do +cask 'no-checksum' do version '1.2.3' sha256 :no_check diff --git a/Library/Homebrew/cask/test/support/Casks/no-dsl-version.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/no-dsl-version.rb index ee557b1e4..3bafa171d 100644 --- a/Library/Homebrew/cask/test/support/Casks/no-dsl-version.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/no-dsl-version.rb @@ -1,4 +1,4 @@ -test_cask 'no-dsl-version' do +cask 'no-dsl-version' do version '1.2.3' sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' diff --git a/Library/Homebrew/cask/spec/support/Casks/osdn-correct-url-format.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/osdn-correct-url-format.rb index da6ff0fcd..7e60fc179 100644 --- a/Library/Homebrew/cask/spec/support/Casks/osdn-correct-url-format.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/osdn-correct-url-format.rb @@ -1,4 +1,4 @@ -test_cask 'osdn-correct-url-format' do +cask 'osdn-correct-url-format' do version '1.2.3' url 'http://user.dl.osdn.jp/something/id/Something-1.2.3.dmg' diff --git a/Library/Homebrew/cask/spec/support/Casks/osdn-incorrect-url-format.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/osdn-incorrect-url-format.rb index 8400159a1..68b4ecd4c 100644 --- a/Library/Homebrew/cask/spec/support/Casks/osdn-incorrect-url-format.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/osdn-incorrect-url-format.rb @@ -1,4 +1,4 @@ -test_cask 'osdn-incorrect-url-format' do +cask 'osdn-incorrect-url-format' do version '1.2.3' url 'http://osdn.jp/projects/something/files/Something-1.2.3.dmg/download' diff --git a/Library/Homebrew/cask/spec/support/Casks/sha256-for-empty-string.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/sha256-for-empty-string.rb index b97764071..0bf3ee9b5 100644 --- a/Library/Homebrew/cask/spec/support/Casks/sha256-for-empty-string.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/sha256-for-empty-string.rb @@ -1,4 +1,4 @@ -test_cask 'sha256-for-empty-string' do +cask 'sha256-for-empty-string' do version '1.2.3' sha256 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' end diff --git a/Library/Homebrew/cask/spec/support/Casks/sourceforge-correct-url-format.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/sourceforge-correct-url-format.rb index 41ef73500..439eb8998 100644 --- a/Library/Homebrew/cask/spec/support/Casks/sourceforge-correct-url-format.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/sourceforge-correct-url-format.rb @@ -1,4 +1,4 @@ -test_cask 'sourceforge-correct-url-format' do +cask 'sourceforge-correct-url-format' do version '1.2.3' url 'https://downloads.sourceforge.net/something/Something-1.2.3.dmg' diff --git a/Library/Homebrew/cask/spec/support/Casks/sourceforge-incorrect-url-format.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/sourceforge-incorrect-url-format.rb index 27b5490b7..39ac52414 100644 --- a/Library/Homebrew/cask/spec/support/Casks/sourceforge-incorrect-url-format.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/sourceforge-incorrect-url-format.rb @@ -1,4 +1,4 @@ -test_cask 'sourceforge-incorrect-url-format' do +cask 'sourceforge-incorrect-url-format' do version '1.2.3' url 'http://sourceforge.net/projects/something/files/Something-1.2.3.dmg/download' diff --git a/Library/Homebrew/cask/spec/support/Casks/sourceforge-version-latest-correct-url-format.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/sourceforge-version-latest-correct-url-format.rb index d9546c5e1..07b068f70 100644 --- a/Library/Homebrew/cask/spec/support/Casks/sourceforge-version-latest-correct-url-format.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/sourceforge-version-latest-correct-url-format.rb @@ -1,4 +1,4 @@ -test_cask 'sourceforge-version-latest-correct-url-format' do +cask 'sourceforge-version-latest-correct-url-format' do version :latest url 'https://sourceforge.net/projects/something/files/latest/download' diff --git a/Library/Homebrew/cask/test/support/Casks/stage-only.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/stage-only.rb index b52b5d3d2..941e2084f 100644 --- a/Library/Homebrew/cask/test/support/Casks/stage-only.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/stage-only.rb @@ -1,4 +1,4 @@ -test_cask 'stage-only' do +cask 'stage-only' do version '2.61' sha256 'e44ffa103fbf83f55c8d0b1bea309a43b2880798dae8620b1ee8da5e1095ec68' diff --git a/Library/Homebrew/cask/test/support/Casks/test-opera-mail.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/test-opera-mail.rb index afc8387c7..3e2c76e67 100644 --- a/Library/Homebrew/cask/test/support/Casks/test-opera-mail.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/test-opera-mail.rb @@ -1,4 +1,4 @@ -test_cask 'test-opera-mail' do +cask 'test-opera-mail' do version '1.0' sha256 'afd192e308f8ea8ddb3d426fd6663d97078570417ee78b8e1fa15f515ae3d677' diff --git a/Library/Homebrew/cask/test/support/Casks/test-opera.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/test-opera.rb index ec32828f7..7ca0157d9 100644 --- a/Library/Homebrew/cask/test/support/Casks/test-opera.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/test-opera.rb @@ -1,4 +1,4 @@ -test_cask 'test-opera' do +cask 'test-opera' do version '19.0.1326.47' sha256 '7b91f20ab754f7b3fef8dc346e0393917e11676b74c8f577408841619f76040a' diff --git a/Library/Homebrew/cask/spec/support/Casks/version-latest-string.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/version-latest-string.rb index 3b4723f45..6bd090c28 100644 --- a/Library/Homebrew/cask/spec/support/Casks/version-latest-string.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/version-latest-string.rb @@ -1,4 +1,4 @@ -test_cask 'version-latest-string' do +cask 'version-latest-string' do version 'latest' sha256 :no_check end diff --git a/Library/Homebrew/cask/spec/support/Casks/version-latest-with-checksum.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/version-latest-with-checksum.rb index 884ddff90..040cfc76e 100644 --- a/Library/Homebrew/cask/spec/support/Casks/version-latest-with-checksum.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/version-latest-with-checksum.rb @@ -1,4 +1,4 @@ -test_cask 'version-latest-with-checksum' do +cask 'version-latest-with-checksum' do version :latest sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' end diff --git a/Library/Homebrew/cask/test/support/Casks/with-accessibility-access.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-accessibility-access.rb index 1aa7bc8f7..4c1c9897a 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-accessibility-access.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-accessibility-access.rb @@ -1,4 +1,4 @@ -test_cask 'with-accessibility-access' do +cask 'with-accessibility-access' do version '1.2.3' sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' diff --git a/Library/Homebrew/cask/test/support/Casks/with-alt-target.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-alt-target.rb index b75ff320c..7a6d75a9c 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-alt-target.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-alt-target.rb @@ -1,4 +1,4 @@ -test_cask 'with-alt-target' do +cask 'with-alt-target' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/with-appcast.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-appcast.rb index f99f7a93c..fc57e5e65 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-appcast.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-appcast.rb @@ -1,4 +1,4 @@ -test_cask 'with-appcast' do +cask 'with-appcast' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/spec/support/Casks/with-binary.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-binary.rb index d8cede7aa..38be2e772 100644 --- a/Library/Homebrew/cask/spec/support/Casks/with-binary.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-binary.rb @@ -1,4 +1,4 @@ -test_cask 'with-binary' do +cask 'with-binary' do version '1.2.3' sha256 'd5b2dfbef7ea28c25f7a77cd7fa14d013d82b626db1d82e00e25822464ba19e2' diff --git a/Library/Homebrew/cask/test/support/Casks/with-caveats.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-caveats.rb index 30d3a49b3..d5d90114a 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-caveats.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-caveats.rb @@ -1,4 +1,4 @@ -test_cask 'with-caveats' do +cask 'with-caveats' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/with-choices.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-choices.rb index 1871efab3..640a3bbb3 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-choices.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-choices.rb @@ -1,4 +1,4 @@ -test_cask 'with-choices' do +cask 'with-choices' do version '1.2.3' sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' diff --git a/Library/Homebrew/cask/test/support/Casks/with-conditional-caveats.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-conditional-caveats.rb index d8a3836b8..e3c666834 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-conditional-caveats.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-conditional-caveats.rb @@ -1,4 +1,4 @@ -test_cask 'with-conditional-caveats' do +cask 'with-conditional-caveats' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/with-conflicts-with.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-conflicts-with.rb index a20d932ba..ab3631743 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-conflicts-with.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-conflicts-with.rb @@ -1,4 +1,4 @@ -test_cask 'with-conflicts-with' do +cask 'with-conflicts-with' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/with-depends-on-arch.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-arch.rb index e0c4e3fa7..9fe0d043b 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-depends-on-arch.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-arch.rb @@ -1,4 +1,4 @@ -test_cask 'with-depends-on-arch' do +cask 'with-depends-on-arch' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/with-depends-on-cask-cyclic-helper.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-cask-cyclic-helper.rb index 327fc4000..3a90295e5 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-depends-on-cask-cyclic-helper.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-cask-cyclic-helper.rb @@ -1,4 +1,4 @@ -test_cask 'with-depends-on-cask-cyclic-helper' do +cask 'with-depends-on-cask-cyclic-helper' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/with-depends-on-cask-cyclic.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-cask-cyclic.rb index f74d860bf..776351568 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-depends-on-cask-cyclic.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-cask-cyclic.rb @@ -1,4 +1,4 @@ -test_cask 'with-depends-on-cask-cyclic' do +cask 'with-depends-on-cask-cyclic' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/with-depends-on-cask-multiple.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-cask-multiple.rb index bb69b7506..74e1c2747 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-depends-on-cask-multiple.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-cask-multiple.rb @@ -1,4 +1,4 @@ -test_cask 'with-depends-on-cask-multiple' do +cask 'with-depends-on-cask-multiple' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/with-depends-on-cask.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-cask.rb index 05a180560..52daec865 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-depends-on-cask.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-cask.rb @@ -1,4 +1,4 @@ -test_cask 'with-depends-on-cask' do +cask 'with-depends-on-cask' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/with-depends-on-formula-multiple.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-formula-multiple.rb index c99d2dee1..07d7bb86a 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-depends-on-formula-multiple.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-formula-multiple.rb @@ -1,4 +1,4 @@ -test_cask 'with-depends-on-formula-multiple' do +cask 'with-depends-on-formula-multiple' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/with-depends-on-formula.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-formula.rb index b0339e68c..ac980f890 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-depends-on-formula.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-formula.rb @@ -1,4 +1,4 @@ -test_cask 'with-depends-on-formula' do +cask 'with-depends-on-formula' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/with-depends-on-macos-array.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-macos-array.rb index cae16704c..7fb1a9016 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-depends-on-macos-array.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-macos-array.rb @@ -1,4 +1,4 @@ -test_cask 'with-depends-on-macos-array' do +cask 'with-depends-on-macos-array' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/with-depends-on-macos-comparison.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-macos-comparison.rb index 7f14dd84f..1483bcf74 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-depends-on-macos-comparison.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-macos-comparison.rb @@ -1,4 +1,4 @@ -test_cask 'with-depends-on-macos-comparison' do +cask 'with-depends-on-macos-comparison' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/with-depends-on-macos-failure.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-macos-failure.rb index ecefff362..483d75814 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-depends-on-macos-failure.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-macos-failure.rb @@ -1,4 +1,4 @@ -test_cask 'with-depends-on-macos-failure' do +cask 'with-depends-on-macos-failure' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/with-depends-on-macos-string.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-macos-string.rb index 6e370d46a..887771fe2 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-depends-on-macos-string.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-macos-string.rb @@ -1,4 +1,4 @@ -test_cask 'with-depends-on-macos-string' do +cask 'with-depends-on-macos-string' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/with-depends-on-macos-symbol.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-macos-symbol.rb index 7f11b6e64..e5aa05d23 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-depends-on-macos-symbol.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-macos-symbol.rb @@ -1,4 +1,4 @@ -test_cask 'with-depends-on-macos-symbol' do +cask 'with-depends-on-macos-symbol' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/with-depends-on-x11-false.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-x11-false.rb index fc84f2daa..d5107edc5 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-depends-on-x11-false.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-x11-false.rb @@ -1,4 +1,4 @@ -test_cask 'with-depends-on-x11-false' do +cask 'with-depends-on-x11-false' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/with-depends-on-x11.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-x11.rb index b1a7bad2b..bcb781637 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-depends-on-x11.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-depends-on-x11.rb @@ -1,4 +1,4 @@ -test_cask 'with-depends-on-x11' do +cask 'with-depends-on-x11' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/with-dsl-version.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-dsl-version.rb index c16343c4b..15f0319c5 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-dsl-version.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-dsl-version.rb @@ -1,4 +1,4 @@ -test_cask :v1 => 'with-dsl-version' do +cask :v1 => 'with-dsl-version' do version '1.2.3' sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' diff --git a/Library/Homebrew/cask/spec/support/Casks/with-embedded-binary.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-embedded-binary.rb index 107c6cbe2..5987bbfe6 100644 --- a/Library/Homebrew/cask/spec/support/Casks/with-embedded-binary.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-embedded-binary.rb @@ -1,4 +1,4 @@ -test_cask 'with-embedded-binary' do +cask 'with-embedded-binary' do version '1.2.3' sha256 'fe052d3e77d92676775fd916ddb8942e72a565b844ea7f6d055474c99bb4e47b' diff --git a/Library/Homebrew/cask/test/support/Casks/with-generic-artifact-no-target.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-generic-artifact-no-target.rb index a7d347fb5..f7f1ddc22 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-generic-artifact-no-target.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-generic-artifact-no-target.rb @@ -1,4 +1,4 @@ -test_cask 'with-generic-artifact-no-target' do +cask 'with-generic-artifact-no-target' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/with-generic-artifact.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-generic-artifact.rb index e718b994b..d6ce0ce8d 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-generic-artifact.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-generic-artifact.rb @@ -1,4 +1,4 @@ -test_cask 'with-generic-artifact' do +cask 'with-generic-artifact' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/with-gpg-key-url.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-gpg-key-url.rb index 6aa735e1f..fc0c9ddfc 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-gpg-key-url.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-gpg-key-url.rb @@ -1,4 +1,4 @@ -test_cask 'with-gpg-key-url' do +cask 'with-gpg-key-url' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/with-gpg.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-gpg.rb index 1f7042515..e07546b94 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-gpg.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-gpg.rb @@ -1,4 +1,4 @@ -test_cask 'with-gpg' do +cask 'with-gpg' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/with-installable.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-installable.rb index d1105b50e..8416f3f88 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-installable.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-installable.rb @@ -1,4 +1,4 @@ -test_cask 'with-installable' do +cask 'with-installable' do version '1.2.3' sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' @@ -11,10 +11,11 @@ test_cask 'with-installable' do quit: 'my.fancy.package.app', login_item: 'Fancy', delete: [ - '/permissible/absolute/path', - '~/permissible/path/with/tilde', + "#{TEST_TMPDIR}/absolute_path", + '~/path_with_tilde', + "#{TEST_TMPDIR}/glob_path*", 'impermissible/relative/path', '/another/impermissible/../relative/path', ], - rmdir: "#{TEST_FIXTURE_DIR}/cask/empty_directory" + rmdir: "#{TEST_TMPDIR}/empty_directory_path" end diff --git a/Library/Homebrew/cask/test/support/Casks/with-installer-manual.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-installer-manual.rb index 92e2e09df..a857b6900 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-installer-manual.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-installer-manual.rb @@ -1,4 +1,4 @@ -test_cask 'with-installer-manual' do +cask 'with-installer-manual' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/with-installer-script.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-installer-script.rb index 5e98eab48..b32d131e0 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-installer-script.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-installer-script.rb @@ -1,4 +1,4 @@ -test_cask 'with-installer-script' do +cask 'with-installer-script' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/with-macosx-dir.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-macosx-dir.rb index 837627119..505e9f5a7 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-macosx-dir.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-macosx-dir.rb @@ -1,4 +1,4 @@ -test_cask 'with-macosx-dir' do +cask 'with-macosx-dir' do version '1.2.3' sha256 '5633c3a0f2e572cbf021507dec78c50998b398c343232bdfc7e26221d0a5db4d' diff --git a/Library/Homebrew/cask/test/support/Casks/with-pkgutil-zap.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-pkgutil-zap.rb index 8bb42c447..d86d47126 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-pkgutil-zap.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-pkgutil-zap.rb @@ -1,4 +1,4 @@ -test_cask 'with-pkgutil-zap' do +cask 'with-pkgutil-zap' do version '1.2.3' sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' diff --git a/Library/Homebrew/cask/test/support/Casks/with-suite.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-suite.rb index c36151d52..88158e10d 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-suite.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-suite.rb @@ -1,4 +1,4 @@ -test_cask 'with-suite' do +cask 'with-suite' do version '1.2.3' sha256 'd95dcc12d4e5be0bc3cb9793c4b7e7f69a25f0b3c7418494b0c883957e6eeae4' diff --git a/Library/Homebrew/cask/test/support/Casks/with-two-apps-correct.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-two-apps-correct.rb index 8eb68d88a..3963d7790 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-two-apps-correct.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-two-apps-correct.rb @@ -1,4 +1,4 @@ -test_cask 'with-two-apps-correct' do +cask 'with-two-apps-correct' do version '1.2.3' sha256 '3178fbfd1ea5d87a2a0662a4eb599ebc9a03888e73f37538d9f3f6ee69d2368e' diff --git a/Library/Homebrew/cask/test/support/Casks/with-two-apps-incorrect.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-two-apps-incorrect.rb index 6bd316dfe..c3ca473bd 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-two-apps-incorrect.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-two-apps-incorrect.rb @@ -1,4 +1,4 @@ -test_cask 'with-two-apps-incorrect' do +cask 'with-two-apps-incorrect' do version '1.2.3' sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94' diff --git a/Library/Homebrew/cask/test/support/Casks/with-two-apps-subdir.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-two-apps-subdir.rb index 202423691..879e6e4ce 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-two-apps-subdir.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-two-apps-subdir.rb @@ -1,4 +1,4 @@ -test_cask 'with-two-apps-subdir' do +cask 'with-two-apps-subdir' do version '1.2.3' sha256 'd687c22a21c02bd8f07da9302c8292b93a04df9a929e3f04d09aea6c76f75c65' diff --git a/Library/Homebrew/cask/test/support/Casks/with-uninstall-delete.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-uninstall-delete.rb index 203f18405..c7d2e4767 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-uninstall-delete.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-uninstall-delete.rb @@ -1,4 +1,4 @@ -test_cask 'with-uninstall-delete' do +cask 'with-uninstall-delete' do version '1.2.3' sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' @@ -8,8 +8,9 @@ test_cask 'with-uninstall-delete' do pkg 'Fancy.pkg' uninstall delete: [ - '/permissible/absolute/path', - '~/permissible/path/with/tilde', + "#{TEST_TMPDIR}/absolute_path", + '~/path_with_tilde', + "#{TEST_TMPDIR}/glob_path*", 'impermissible/relative/path', '/another/impermissible/../relative/path', ] diff --git a/Library/Homebrew/cask/test/support/Casks/with-uninstall-early-script.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-uninstall-early-script.rb index a26abab1c..a9cec5b97 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-uninstall-early-script.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-uninstall-early-script.rb @@ -1,4 +1,4 @@ -test_cask 'with-uninstall-early-script' do +cask 'with-uninstall-early-script' do version '1.2.3' sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' diff --git a/Library/Homebrew/cask/test/support/Casks/with-uninstall-kext.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-uninstall-kext.rb index fa54c7e1f..9b27a1f36 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-uninstall-kext.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-uninstall-kext.rb @@ -1,4 +1,4 @@ -test_cask 'with-uninstall-kext' do +cask 'with-uninstall-kext' do version '1.2.3' sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' diff --git a/Library/Homebrew/cask/test/support/Casks/with-uninstall-launchctl.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-uninstall-launchctl.rb index 51ad45a09..e5aa2b2d7 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-uninstall-launchctl.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-uninstall-launchctl.rb @@ -1,4 +1,4 @@ -test_cask 'with-uninstall-launchctl' do +cask 'with-uninstall-launchctl' do version '1.2.3' sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' diff --git a/Library/Homebrew/cask/test/support/Casks/with-uninstall-login-item.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-uninstall-login-item.rb index 26dca6f1a..46f1f9704 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-uninstall-login-item.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-uninstall-login-item.rb @@ -1,4 +1,4 @@ -test_cask 'with-uninstall-login-item' do +cask 'with-uninstall-login-item' do version '1.2.3' sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' diff --git a/Library/Homebrew/cask/test/support/Casks/with-uninstall-pkgutil.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-uninstall-pkgutil.rb index db77a460b..00157322d 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-uninstall-pkgutil.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-uninstall-pkgutil.rb @@ -1,4 +1,4 @@ -test_cask 'with-uninstall-pkgutil' do +cask 'with-uninstall-pkgutil' do version '1.2.3' sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' diff --git a/Library/Homebrew/cask/test/support/Casks/with-uninstall-quit.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-uninstall-quit.rb index 19337b18a..7f9515578 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-uninstall-quit.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-uninstall-quit.rb @@ -1,4 +1,4 @@ -test_cask 'with-uninstall-quit' do +cask 'with-uninstall-quit' do version '1.2.3' sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/with-uninstall-rmdir.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-uninstall-rmdir.rb new file mode 100644 index 000000000..8ded5b835 --- /dev/null +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-uninstall-rmdir.rb @@ -0,0 +1,11 @@ +cask 'with-uninstall-rmdir' do + version '1.2.3' + sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' + + url "file://#{TEST_FIXTURE_DIR}/cask/MyFancyPkg.zip" + homepage 'http://example.com/fancy-pkg' + + pkg 'MyFancyPkg/Fancy.pkg' + + uninstall rmdir: "#{TEST_TMPDIR}/empty_directory_path" +end diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/with-uninstall-script-app.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-uninstall-script-app.rb new file mode 100644 index 000000000..f5f3ae5dd --- /dev/null +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-uninstall-script-app.rb @@ -0,0 +1,21 @@ +cask 'with-uninstall-script-app' do + version '1.2.3' + sha256 '5633c3a0f2e572cbf021507dec78c50998b398c343232bdfc7e26221d0a5db4d' + + url "file://#{TEST_FIXTURE_DIR}/cask/MyFancyApp.zip" + homepage 'http://example.com/MyFancyApp' + + app 'MyFancyApp/MyFancyApp.app' + + postflight do + IO.write "#{appdir}/MyFancyApp.app/uninstall.sh", <<-EOS.undent + #!/bin/sh + /bin/rm -r "#{appdir}/MyFancyApp.app" + EOS + end + + uninstall script: { + executable: "#{appdir}/MyFancyApp.app/uninstall.sh", + sudo: false + } +end diff --git a/Library/Homebrew/cask/test/support/Casks/with-uninstall-script.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-uninstall-script.rb index d2e0d6167..3e2dd0bb9 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-uninstall-script.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-uninstall-script.rb @@ -1,4 +1,4 @@ -test_cask 'with-uninstall-script' do +cask 'with-uninstall-script' do version '1.2.3' sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' diff --git a/Library/Homebrew/cask/test/support/Casks/with-uninstall-signal.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-uninstall-signal.rb index cc32b888a..850055c3c 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-uninstall-signal.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-uninstall-signal.rb @@ -1,4 +1,4 @@ -test_cask 'with-uninstall-signal' do +cask 'with-uninstall-signal' do version '1.2.3' sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' diff --git a/Library/Homebrew/cask/test/support/Casks/with-uninstall-trash.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-uninstall-trash.rb index 4fe58a19a..b085b3e32 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-uninstall-trash.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-uninstall-trash.rb @@ -1,4 +1,4 @@ -test_cask 'with-uninstall-trash' do +cask 'with-uninstall-trash' do version '1.2.3' sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' @@ -8,8 +8,9 @@ test_cask 'with-uninstall-trash' do pkg 'Fancy.pkg' uninstall trash: [ - '/permissible/absolute/path', - '~/permissible/path/with/tilde', + "#{TEST_TMPDIR}/absolute_path", + '~/path_with_tilde', + "#{TEST_TMPDIR}/glob_path*", 'impermissible/relative/path', '/another/impermissible/../relative/path', ] diff --git a/Library/Homebrew/cask/test/support/Casks/with-zap-delete.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-zap-delete.rb index c76a9acb0..d81a387f9 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-zap-delete.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-zap-delete.rb @@ -1,4 +1,4 @@ -test_cask 'with-zap-delete' do +cask 'with-zap-delete' do version '1.2.3' sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' @@ -8,8 +8,9 @@ test_cask 'with-zap-delete' do pkg 'Fancy.pkg' zap delete: [ - '/permissible/absolute/path', - '~/permissible/path/with/tilde', + "#{TEST_TMPDIR}/absolute_path", + '~/path_with_tilde', + "#{TEST_TMPDIR}/glob_path*", 'impermissible/relative/path', '/another/impermissible/../relative/path', ] diff --git a/Library/Homebrew/cask/test/support/Casks/with-zap-early-script.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-zap-early-script.rb index d35c1809e..9375d2cc7 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-zap-early-script.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-zap-early-script.rb @@ -1,4 +1,4 @@ -test_cask 'with-zap-early-script' do +cask 'with-zap-early-script' do version '1.2.3' sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' diff --git a/Library/Homebrew/cask/test/support/Casks/with-zap-kext.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-zap-kext.rb index 463fe8133..e9c29f619 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-zap-kext.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-zap-kext.rb @@ -1,4 +1,4 @@ -test_cask 'with-zap-kext' do +cask 'with-zap-kext' do version '1.2.3' sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' diff --git a/Library/Homebrew/cask/test/support/Casks/with-zap-launchctl.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-zap-launchctl.rb index aab285672..6d17ccfb0 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-zap-launchctl.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-zap-launchctl.rb @@ -1,4 +1,4 @@ -test_cask 'with-zap-launchctl' do +cask 'with-zap-launchctl' do version '1.2.3' sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' diff --git a/Library/Homebrew/cask/test/support/Casks/with-zap-login-item.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-zap-login-item.rb index d7ba9a65b..2715892ef 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-zap-login-item.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-zap-login-item.rb @@ -1,4 +1,4 @@ -test_cask 'with-zap-login-item' do +cask 'with-zap-login-item' do version '1.2.3' sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' diff --git a/Library/Homebrew/cask/test/support/Casks/with-zap-pkgutil.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-zap-pkgutil.rb index 17a667000..c7f08b76d 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-zap-pkgutil.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-zap-pkgutil.rb @@ -1,4 +1,4 @@ -test_cask 'with-zap-pkgutil' do +cask 'with-zap-pkgutil' do version '1.2.3' sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' diff --git a/Library/Homebrew/cask/test/support/Casks/with-zap-quit.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-zap-quit.rb index 21f824ae9..4e4ab3a85 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-zap-quit.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-zap-quit.rb @@ -1,4 +1,4 @@ -test_cask 'with-zap-quit' do +cask 'with-zap-quit' do version '1.2.3' sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/with-zap-rmdir.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-zap-rmdir.rb new file mode 100644 index 000000000..a67c4ca9a --- /dev/null +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-zap-rmdir.rb @@ -0,0 +1,11 @@ +cask 'with-zap-rmdir' do + version '1.2.3' + sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' + + url "file://#{TEST_FIXTURE_DIR}/cask/MyFancyPkg.zip" + homepage 'http://example.com/fancy-pkg' + + pkg 'MyFancyPkg/Fancy.pkg' + + zap rmdir: "#{TEST_TMPDIR}/empty_directory_path" +end diff --git a/Library/Homebrew/cask/test/support/Casks/with-zap-script.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-zap-script.rb index f8646a267..5e033301a 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-zap-script.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-zap-script.rb @@ -1,4 +1,4 @@ -test_cask 'with-zap-script' do +cask 'with-zap-script' do version '1.2.3' sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' diff --git a/Library/Homebrew/cask/test/support/Casks/with-zap-signal.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-zap-signal.rb index 5accd8337..47870cf05 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-zap-signal.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-zap-signal.rb @@ -1,4 +1,4 @@ -test_cask 'with-zap-signal' do +cask 'with-zap-signal' do version '1.2.3' sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' diff --git a/Library/Homebrew/cask/test/support/Casks/with-zap-trash.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-zap-trash.rb index aef4e0eab..ea2bc2a01 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-zap-trash.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-zap-trash.rb @@ -1,4 +1,4 @@ -test_cask 'with-zap-trash' do +cask 'with-zap-trash' do version '1.2.3' sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' @@ -8,8 +8,9 @@ test_cask 'with-zap-trash' do pkg 'Fancy.pkg' zap trash: [ - '/permissible/absolute/path', - '~/permissible/path/with/tilde', + "#{TEST_TMPDIR}/absolute_path", + '~/path_with_tilde', + "#{TEST_TMPDIR}/glob_path*", 'impermissible/relative/path', '/another/impermissible/../relative/path', ] diff --git a/Library/Homebrew/cask/test/support/Casks/with-zap.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-zap.rb index 056c90671..275516fba 100644 --- a/Library/Homebrew/cask/test/support/Casks/with-zap.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-zap.rb @@ -1,4 +1,4 @@ -test_cask 'with-zap' do +cask 'with-zap' do version '1.2.3' sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b' diff --git a/Library/Homebrew/test/support/fixtures/cask/empty_directory/.gitignore b/Library/Homebrew/test/support/fixtures/cask/empty_directory/.gitignore deleted file mode 100644 index e69de29bb..000000000 --- a/Library/Homebrew/test/support/fixtures/cask/empty_directory/.gitignore +++ /dev/null diff --git a/Library/Homebrew/test/support/helper/env.rb b/Library/Homebrew/test/support/helper/env.rb deleted file mode 100644 index 904a1d4c7..000000000 --- a/Library/Homebrew/test/support/helper/env.rb +++ /dev/null @@ -1,15 +0,0 @@ -module Test - module Helper - module Env - def with_environment(partial_env) - old = ENV.to_hash - ENV.update partial_env - begin - yield - ensure - ENV.replace old - end - end - end - end -end diff --git a/Library/Homebrew/test/support/helper/fixtures.rb b/Library/Homebrew/test/support/helper/fixtures.rb new file mode 100644 index 000000000..716fe2008 --- /dev/null +++ b/Library/Homebrew/test/support/helper/fixtures.rb @@ -0,0 +1,13 @@ +module Test + module Helper + module Fixtures + def dylib_path(name) + Pathname.new("#{TEST_FIXTURE_DIR}/mach/#{name}.dylib") + end + + def bundle_path(name) + Pathname.new("#{TEST_FIXTURE_DIR}/mach/#{name}.bundle") + end + end + end +end diff --git a/Library/Homebrew/test/support/helper/formula.rb b/Library/Homebrew/test/support/helper/formula.rb new file mode 100644 index 000000000..7f55f4b66 --- /dev/null +++ b/Library/Homebrew/test/support/helper/formula.rb @@ -0,0 +1,19 @@ +require "formulary" + +module Test + module Helper + module Formula + def formula(name = "formula_name", path: Formulary.core_path(name), spec: :stable, alias_path: nil, &block) + Class.new(::Formula, &block).new(name, path, spec, alias_path: alias_path) + end + + # Use a stubbed {Formulary::FormulaLoader} to make a given formula be found + # when loading from {Formulary} with `ref`. + def stub_formula_loader(formula, ref = formula.full_name) + loader = double(get_formula: formula) + allow(Formulary).to receive(:loader_for).with(ref, from: :keg).and_return(loader) + allow(Formulary).to receive(:loader_for).with(ref, from: nil).and_return(loader) + end + end + end +end diff --git a/Library/Homebrew/test/support/helper/fs_leak_logger.rb b/Library/Homebrew/test/support/helper/fs_leak_logger.rb index 774ccda04..3fbb148fa 100644 --- a/Library/Homebrew/test/support/helper/fs_leak_logger.rb +++ b/Library/Homebrew/test/support/helper/fs_leak_logger.rb @@ -9,13 +9,13 @@ module Test klass.make_my_diffs_pretty! end - def before_setup + def setup @__files_before_test = [] Find.find(TEST_TMPDIR) { |f| @__files_before_test << f.sub(TEST_TMPDIR, "") } super end - def after_teardown + def teardown super files_after_test = [] Find.find(TEST_TMPDIR) { |f| files_after_test << f.sub(TEST_TMPDIR, "") } diff --git a/Library/Homebrew/test/support/helper/integration_command_test_case.rb b/Library/Homebrew/test/support/helper/integration_command_test_case.rb index b79fdd6e0..7ba094645 100644 --- a/Library/Homebrew/test/support/helper/integration_command_test_case.rb +++ b/Library/Homebrew/test/support/helper/integration_command_test_case.rb @@ -3,43 +3,16 @@ require "fileutils" require "pathname" require "formula" require "test/support/helper/test_case" +require "open3" class IntegrationCommandTestCase < Homebrew::TestCase def setup + super @cmd_id_index = 0 # Assign unique IDs to invocations of `cmd_output`. (HOMEBREW_PREFIX/"bin").mkpath FileUtils.touch HOMEBREW_PREFIX/"bin/brew" end - def teardown - coretap = CoreTap.new - paths_to_delete = [ - HOMEBREW_LINKED_KEGS, - HOMEBREW_PINNED_KEGS, - HOMEBREW_CELLAR.children, - HOMEBREW_CACHE.children, - HOMEBREW_LOCK_DIR.children, - HOMEBREW_LOGS.children, - HOMEBREW_TEMP.children, - HOMEBREW_PREFIX/".git", - HOMEBREW_PREFIX/"bin", - HOMEBREW_PREFIX/"share", - HOMEBREW_PREFIX/"opt", - HOMEBREW_PREFIX/"Caskroom", - HOMEBREW_LIBRARY/"Taps/caskroom", - HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-bundle", - HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-foo", - HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-services", - HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-shallow", - HOMEBREW_REPOSITORY/".git", - coretap.path/".git", - coretap.alias_dir, - coretap.formula_dir.children, - coretap.path/"formula_renames.json", - ].flatten - FileUtils.rm_rf paths_to_delete - end - def needs_test_cmd_taps return if ENV["HOMEBREW_TEST_OFFICIAL_CMD_TAPS"] skip "HOMEBREW_TEST_OFFICIAL_CMD_TAPS is not set" @@ -56,66 +29,46 @@ class IntegrationCommandTestCase < Homebrew::TestCase end def cmd_output(*args) - # 1.8-compatible way of writing def cmd_output(*args, **env) env = args.last.is_a?(Hash) ? args.pop : {} - cmd_args = %W[ - -W0 - -I#{HOMEBREW_LIBRARY_PATH}/test/support/lib - -I#{HOMEBREW_LIBRARY_PATH} - -rconfig + + env.merge!( + "HOMEBREW_BREW_FILE" => HOMEBREW_PREFIX/"bin/brew", + "HOMEBREW_INTEGRATION_TEST" => cmd_id_from_args(args), + "HOMEBREW_TEST_TMPDIR" => TEST_TMPDIR, + "HOMEBREW_DEVELOPER" => ENV["HOMEBREW_DEVELOPER"], + ) + + ruby_args = [ + "-W0", + "-I", "#{HOMEBREW_LIBRARY_PATH}/test/support/lib", + "-I", HOMEBREW_LIBRARY_PATH.to_s, + "-rconfig" ] - if ENV["HOMEBREW_TESTS_COVERAGE"] - # This is needed only because we currently use a patched version of - # simplecov, and gems installed through git are not available without - # requiring bundler/setup first. See also the comment in test/Gemfile. - # Remove this line when we'll switch back to a stable simplecov release. - cmd_args << "-rbundler/setup" - cmd_args << "-rsimplecov" - end - cmd_args << "-rtest/support/helper/integration_mocks" - cmd_args << (HOMEBREW_LIBRARY_PATH/"brew.rb").resolved_path.to_s - cmd_args += args - developer = ENV["HOMEBREW_DEVELOPER"] - Bundler.with_original_env do - ENV["HOMEBREW_BREW_FILE"] = HOMEBREW_PREFIX/"bin/brew" - ENV["HOMEBREW_INTEGRATION_TEST"] = cmd_id_from_args(args) - ENV["HOMEBREW_TEST_TMPDIR"] = TEST_TMPDIR - ENV["HOMEBREW_DEVELOPER"] = developer - env.each_pair do |k, v| - ENV[k] = v - end + ruby_args << "-rsimplecov" if ENV["HOMEBREW_TESTS_COVERAGE"] + ruby_args << "-rtest/support/helper/integration_mocks" + ruby_args << (HOMEBREW_LIBRARY_PATH/"brew.rb").resolved_path.to_s - read, write = IO.pipe - begin - pid = fork do - read.close - $stdout.reopen(write) - $stderr.reopen(write) - write.close - exec RUBY_PATH, *cmd_args - end - write.close - read.read.chomp - ensure - Process.wait(pid) - read.close - end + Bundler.with_original_env do + output, status = Open3.capture2e(env, RUBY_PATH, *ruby_args, *args) + [output.chomp, status] end end def cmd(*args) - output = cmd_output(*args) - status = $?.exitstatus - puts "\n'brew #{args.join " "}' output: #{output}" if status.nonzero? - assert_equal 0, status + output, status = cmd_output(*args) + assert status.success?, <<-EOS.undent + `brew #{args.join " "}` exited with non-zero status! + #{output} + EOS output end def cmd_fail(*args) - output = cmd_output(*args) - status = $?.exitstatus - $stderr.puts "\n'brew #{args.join " "}'" if status.zero? - refute_equal 0, status + output, status = cmd_output(*args) + refute status.success?, <<-EOS.undent + `brew #{args.join " "}` exited with zero status! + #{output} + EOS output end diff --git a/Library/Homebrew/test/support/helper/lifecycle_enforcer.rb b/Library/Homebrew/test/support/helper/lifecycle_enforcer.rb new file mode 100644 index 000000000..413f8b11e --- /dev/null +++ b/Library/Homebrew/test/support/helper/lifecycle_enforcer.rb @@ -0,0 +1,22 @@ +module Test + module Helper + module LifecycleEnforcer + def setup + @__setup_called = true + super + end + + def teardown + @__teardown_called = true + super + end + + def after_teardown + assert @__setup_called, "Expected setup to call `super` but didn't" + assert @__teardown_called, "Expected teardown to call `super` but didn't" + + super + end + end + end +end 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 new file mode 100644 index 000000000..2eb98826a --- /dev/null +++ b/Library/Homebrew/test/support/helper/spec/shared_context/integration_test.rb @@ -0,0 +1,176 @@ +require "rspec" +require "open3" + +RSpec::Matchers.define_negated_matcher :not_to_output, :output +RSpec::Matchers.define_negated_matcher :be_a_failure, :be_a_success + +RSpec.shared_context "integration test" do + extend RSpec::Matchers::DSL + + matcher :be_a_success do + match do |actual| + status = actual.is_a?(Proc) ? actual.call : actual + status.respond_to?(:success?) && status.success? + end + + def supports_block_expectations? + true + end + + # It needs to be nested like this: + # + # expect { + # expect { + # # command + # }.to be_a_success + # }.to output(something).to_stdout + # + # rather than this: + # + # expect { + # expect { + # # command + # }.to output(something).to_stdout + # }.to be_a_success + # + def expects_call_stack_jump? + true + end + end + + before(:each) do + (HOMEBREW_PREFIX/"bin").mkpath + FileUtils.touch HOMEBREW_PREFIX/"bin/brew" + end + + after(:each) do + FileUtils.rm HOMEBREW_PREFIX/"bin/brew" + FileUtils.rmdir HOMEBREW_PREFIX/"bin" + end + + # Generate unique ID to be able to + # properly merge coverage results. + def command_id_from_args(args) + @command_count ||= 0 + pretty_args = args.join(" ").gsub(TEST_TMPDIR, "@TMPDIR@") + file_and_line = caller[1].sub(/(.*\d+):.*/, '\1') + .sub("#{HOMEBREW_LIBRARY_PATH}/test/", "") + "#{file_and_line}:brew #{pretty_args}:#{@command_count += 1}" + end + + # Runs a `brew` command with the test configuration + # and with coverage reporting enabled. + def brew(*args) + env = args.last.is_a?(Hash) ? args.pop : {} + + # Avoid warnings when HOMEBREW_PREFIX/bin is not in PATH. + path = [ + env["PATH"], + (HOMEBREW_PREFIX/"bin").realpath.to_s, + ENV["PATH"], + ].compact.join(File::PATH_SEPARATOR) + + env.merge!( + "PATH" => path, + "HOMEBREW_BREW_FILE" => HOMEBREW_PREFIX/"bin/brew", + "HOMEBREW_INTEGRATION_TEST" => command_id_from_args(args), + "HOMEBREW_TEST_TMPDIR" => TEST_TMPDIR, + "HOMEBREW_DEVELOPER" => ENV["HOMEBREW_DEVELOPER"], + ) + + ruby_args = [ + "-W0", + "-I", "#{HOMEBREW_LIBRARY_PATH}/test/support/lib", + "-I", HOMEBREW_LIBRARY_PATH.to_s, + "-rconfig" + ] + ruby_args << "-rsimplecov" if ENV["HOMEBREW_TESTS_COVERAGE"] + ruby_args << "-rtest/support/helper/integration_mocks" + ruby_args << (HOMEBREW_LIBRARY_PATH/"brew.rb").resolved_path.to_s + + Bundler.with_original_env do + stdout, stderr, status = Open3.capture3(env, RUBY_PATH, *ruby_args, *args) + $stdout.print stdout + $stderr.print stderr + status + end + end + + def setup_test_formula(name, content = nil) + case name + when /^testball/ + content = <<-EOS.undent + desc "Some test" + homepage "https://example.com/#{name}" + url "file://#{TEST_FIXTURE_DIR}/tarballs/testball-0.1.tbz" + sha256 "#{TESTBALL_SHA256}" + + option "with-foo", "Build with foo" + + def install + (prefix/"foo"/"test").write("test") if build.with? "foo" + prefix.install Dir["*"] + (buildpath/"test.c").write \ + "#include <stdio.h>\\nint main(){return printf(\\"test\\");}" + bin.mkpath + system ENV.cc, "test.c", "-o", bin/"test" + end + + #{content} + + # something here + EOS + when "foo" + content = <<-EOS.undent + url "https://example.com/#{name}-1.0" + EOS + when "bar" + content = <<-EOS.undent + url "https://example.com/#{name}-1.0" + depends_on "foo" + EOS + end + + Formulary.core_path(name).tap do |formula_path| + formula_path.write <<-EOS.undent + class #{Formulary.class_s(name)} < Formula + #{content} + end + EOS + end + end + + def setup_remote_tap(name) + Tap.fetch(name).tap do |tap| + tap.install(full_clone: false, quiet: true) unless tap.installed? + end + end + + def install_and_rename_coretap_formula(old_name, new_name) + shutup do + CoreTap.instance.path.cd do |tap_path| + system "git", "init" + system "git", "add", "--all" + system "git", "commit", "-m", + "#{old_name.capitalize} has not yet been renamed" + + brew "install", old_name + + (tap_path/"Formula/#{old_name}.rb").unlink + (tap_path/"formula_renames.json").write JSON.generate(old_name => new_name) + + system "git", "add", "--all" + system "git", "commit", "-m", + "#{old_name.capitalize} has been renamed to #{new_name.capitalize}" + end + end + end + + def testball + "#{TEST_FIXTURE_DIR}/testball.rb" + end +end + +RSpec.configure do |config| + config.include_context "integration test", :integration_test +end diff --git a/Library/Homebrew/test/support/helper/test_case.rb b/Library/Homebrew/test/support/helper/test_case.rb index 60c91e7bb..568beb947 100644 --- a/Library/Homebrew/test/support/helper/test_case.rb +++ b/Library/Homebrew/test/support/helper/test_case.rb @@ -1,16 +1,66 @@ +require "formulary" +require "tap" + module Homebrew class TestCase < ::Minitest::Test - require "test/support/helper/env" require "test/support/helper/fs_leak_logger" + require "test/support/helper/lifecycle_enforcer" require "test/support/helper/shutup" require "test/support/helper/version_assertions" - include Test::Helper::Env include Test::Helper::FSLeakLogger + include Test::Helper::LifecycleEnforcer include Test::Helper::Shutup include Test::Helper::VersionAssertions - TEST_SHA1 = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef".freeze - TEST_SHA256 = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef".freeze + TEST_DIRECTORIES = [ + CoreTap.instance.path/"Formula", + HOMEBREW_CACHE, + HOMEBREW_CACHE_FORMULA, + HOMEBREW_CELLAR, + HOMEBREW_LOCK_DIR, + HOMEBREW_LOGS, + HOMEBREW_TEMP, + ].freeze + + def setup + # These directories need to be created before + # `FSLeakLogger` is called with `super`. + TEST_DIRECTORIES.each(&:mkpath) + + super + + @__argv = ARGV.dup + @__env = ENV.to_hash # dup doesn't work on ENV + end + + def teardown + ARGV.replace(@__argv) + ENV.replace(@__env) + + Tab.clear_cache + + FileUtils.rm_rf [ + TEST_DIRECTORIES.map(&:children), + HOMEBREW_LINKED_KEGS, + HOMEBREW_PINNED_KEGS, + HOMEBREW_PREFIX/".git", + HOMEBREW_PREFIX/"bin", + HOMEBREW_PREFIX/"share", + HOMEBREW_PREFIX/"opt", + HOMEBREW_PREFIX/"Caskroom", + HOMEBREW_LIBRARY/"Taps/caskroom", + HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-bundle", + HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-foo", + HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-services", + HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-shallow", + HOMEBREW_REPOSITORY/".git", + CoreTap.instance.path/".git", + CoreTap.instance.alias_dir, + CoreTap.instance.path/"formula_renames.json", + ] + + super + end def formula(name = "formula_name", path = Formulary.core_path(name), spec = :stable, alias_path: nil, &block) @_f = Class.new(Formula, &block).new(name, path, spec, alias_path: alias_path) diff --git a/Library/Homebrew/test/support/lib/config.rb b/Library/Homebrew/test/support/lib/config.rb index f6fdb4ecb..3a0a76722 100644 --- a/Library/Homebrew/test/support/lib/config.rb +++ b/Library/Homebrew/test/support/lib/config.rb @@ -2,6 +2,8 @@ unless ENV["HOMEBREW_BREW_FILE"] raise "HOMEBREW_BREW_FILE was not exported! Please call bin/brew directly!" end +require "constants" + require "tmpdir" require "pathname" @@ -38,3 +40,6 @@ TESTBALL_SHA256 = "91e3f7930c98d7ccfb288e115ed52d06b0e5bc16fec7dce8bdda865300270 TESTBALL_PATCHES_SHA256 = "799c2d551ac5c3a5759bea7796631a7906a6a24435b52261a317133a0bfb34d9".freeze PATCH_A_SHA256 = "83404f4936d3257e65f176c4ffb5a5b8d6edd644a21c8d8dcc73e22a6d28fcfa".freeze PATCH_B_SHA256 = "57958271bb802a59452d0816e0670d16c8b70bdf6530bcf6f78726489ad89b90".freeze + +TEST_SHA1 = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef".freeze +TEST_SHA256 = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef".freeze diff --git a/Library/Homebrew/test/switch_test.rb b/Library/Homebrew/test/switch_test.rb deleted file mode 100644 index af1926c39..000000000 --- a/Library/Homebrew/test/switch_test.rb +++ /dev/null @@ -1,20 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestSwitch < IntegrationCommandTestCase - def test_switch - assert_match "Usage: brew switch <name> <version>", cmd_fail("switch") - assert_match "testball not found", cmd_fail("switch", "testball", "0.1") - - setup_test_formula "testball", <<-EOS.undent - keg_only "just because" - EOS - - cmd("install", "testball") - testball_rack = HOMEBREW_CELLAR/"testball" - FileUtils.cp_r testball_rack/"0.1", testball_rack/"0.2" - - cmd("switch", "testball", "0.2") - assert_match "testball does not have a version \"0.3\"", - cmd_fail("switch", "testball", "0.3") - end -end diff --git a/Library/Homebrew/test/tab_spec.rb b/Library/Homebrew/test/tab_spec.rb new file mode 100644 index 000000000..01dbeb67c --- /dev/null +++ b/Library/Homebrew/test/tab_spec.rb @@ -0,0 +1,341 @@ +require "tab" +require "formula" + +RSpec::Matchers.alias_matcher :be_built_with, :be_with + +describe Tab do + matcher :be_poured_from_bottle do + match do |actual| + actual.poured_from_bottle == true + end + end + + matcher :be_built_as_bottle do + match do |actual| + actual.built_as_bottle == true + end + end + + subject { + described_class.new( + "homebrew_version" => HOMEBREW_VERSION, + "used_options" => used_options.as_flags, + "unused_options" => unused_options.as_flags, + "built_as_bottle" => false, + "poured_from_bottle" => true, + "changed_files" => [], + "time" => time, + "source_modified_time" => 0, + "HEAD" => TEST_SHA1, + "compiler" => "clang", + "stdlib" => "libcxx", + "runtime_dependencies" => [], + "source" => { + "tap" => CoreTap.instance.to_s, + "path" => CoreTap.instance.path.to_s, + "spec" => "stable", + "versions" => { + "stable" => "0.10", + "devel" => "0.14", + "head" => "HEAD-1111111", + }, + }, + ) + } + 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]) } + + let(:f) { formula { url "foo-1.0" } } + let(:f_tab_path) { f.prefix/"INSTALL_RECEIPT.json" } + let(:f_tab_content) { (TEST_FIXTURE_DIR/"receipt.json").read } + + specify "defaults" do + tab = described_class.empty + + expect(tab.homebrew_version).to eq(HOMEBREW_VERSION) + expect(tab.unused_options).to be_empty + expect(tab.used_options).to be_empty + expect(tab.changed_files).to be nil + expect(tab).not_to be_built_as_bottle + expect(tab).not_to be_poured_from_bottle + expect(tab).to be_stable + expect(tab).not_to be_devel + expect(tab).not_to be_head + 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.stable_version).to be nil + expect(tab.devel_version).to be nil + expect(tab.head_version).to be nil + expect(tab.cxxstdlib.compiler).to eq(DevelopmentTools.default_compiler) + expect(tab.cxxstdlib.type).to be nil + expect(tab.source["path"]).to be nil + end + + specify "#include?" do + expect(subject).to include("with-foo") + expect(subject).to include("without-bar") + end + + specify "#with?" do + expect(subject).to be_built_with("foo") + expect(subject).to be_built_with("qux") + expect(subject).not_to be_built_with("bar") + expect(subject).not_to be_built_with("baz") + end + + specify "#universal?" do + tab = described_class.new(used_options: %w[--universal]) + expect(tab).to be_universal + end + + specify "#parsed_homebrew_version" do + tab = described_class.new + expect(tab.parsed_homebrew_version).to be Version::NULL + + tab = described_class.new(homebrew_version: "1.2.3") + expect(tab.parsed_homebrew_version).to eq("1.2.3") + expect(tab.parsed_homebrew_version).to be < "1.2.3-1-g12789abdf" + expect(tab.parsed_homebrew_version).to be_kind_of(Version) + + tab.homebrew_version = "1.2.4-567-g12789abdf" + expect(tab.parsed_homebrew_version).to be > "1.2.4" + expect(tab.parsed_homebrew_version).to be > "1.2.4-566-g21789abdf" + expect(tab.parsed_homebrew_version).to be < "1.2.4-568-g01789abdf" + + tab = described_class.new(homebrew_version: "2.0.0-134-gabcdefabc-dirty") + expect(tab.parsed_homebrew_version).to be > "2.0.0" + expect(tab.parsed_homebrew_version).to be > "2.0.0-133-g21789abdf" + expect(tab.parsed_homebrew_version).to be < "2.0.0-135-g01789abdf" + end + + specify "#runtime_dependencies" do + tab = described_class.new + expect(tab.runtime_dependencies).to be nil + + tab.homebrew_version = "1.1.6" + expect(tab.runtime_dependencies).to be nil + + tab.runtime_dependencies = [] + expect(tab.runtime_dependencies).not_to be nil + + tab.homebrew_version = "1.1.5" + expect(tab.runtime_dependencies).to be nil + + tab.homebrew_version = "1.1.7" + expect(tab.runtime_dependencies).not_to be nil + + tab.homebrew_version = "1.1.10" + expect(tab.runtime_dependencies).not_to be nil + + tab.runtime_dependencies = [{ "full_name" => "foo", "version" => "1.0" }] + expect(tab.runtime_dependencies).not_to be nil + end + + specify "#cxxstdlib" do + expect(subject.cxxstdlib.compiler).to eq(:clang) + expect(subject.cxxstdlib.type).to eq(:libcxx) + end + + specify "other attributes" do + expect(subject.HEAD).to eq(TEST_SHA1) + expect(subject.tap.name).to eq("homebrew/core") + expect(subject.time).to eq(time) + expect(subject).not_to be_built_as_bottle + expect(subject).to be_poured_from_bottle + end + + describe "::from_file" do + it "parses a Tab from a file" do + path = Pathname.new("#{TEST_FIXTURE_DIR}/receipt.json") + tab = described_class.from_file(path) + source_path = "/usr/local/Library/Taps/homebrew/homebrew-core/Formula/foo.rb" + runtime_dependencies = [{ "full_name" => "foo", "version" => "1.0" }] + changed_files = %w[INSTALL_RECEIPT.json bin/foo] + + expect(tab.used_options.sort).to eq(used_options.sort) + expect(tab.unused_options.sort).to eq(unused_options.sort) + expect(tab.changed_files).to eq(changed_files) + expect(tab).not_to be_built_as_bottle + expect(tab).to be_poured_from_bottle + expect(tab).to be_stable + expect(tab).not_to be_devel + expect(tab).not_to be_head + expect(tab.tap.name).to eq("homebrew/core") + expect(tab.spec).to eq(:stable) + expect(tab.time).to eq(Time.at(1_403_827_774).to_i) + expect(tab.HEAD).to eq(TEST_SHA1) + expect(tab.cxxstdlib.compiler).to eq(:clang) + expect(tab.cxxstdlib.type).to eq(:libcxx) + expect(tab.runtime_dependencies).to eq(runtime_dependencies) + expect(tab.stable_version.to_s).to eq("2.14") + expect(tab.devel_version.to_s).to eq("2.15") + expect(tab.head_version.to_s).to eq("HEAD-0000000") + expect(tab.source["path"]).to eq(source_path) + end + + it "can parse an old Tab file" do + path = Pathname.new("#{TEST_FIXTURE_DIR}/receipt_old.json") + tab = described_class.from_file(path) + + expect(tab.used_options.sort).to eq(used_options.sort) + expect(tab.unused_options.sort).to eq(unused_options.sort) + expect(tab).not_to be_built_as_bottle + expect(tab).to be_poured_from_bottle + expect(tab).to be_stable + expect(tab).not_to be_devel + expect(tab).not_to be_head + expect(tab.tap.name).to eq("homebrew/core") + expect(tab.spec).to eq(:stable) + expect(tab.time).to eq(Time.at(1_403_827_774).to_i) + expect(tab.HEAD).to eq(TEST_SHA1) + expect(tab.cxxstdlib.compiler).to eq(:clang) + expect(tab.cxxstdlib.type).to eq(:libcxx) + expect(tab.runtime_dependencies).to be nil + end + end + + describe "::create" do + it "creates a Tab" do + f = formula do + url "foo-1.0" + depends_on "bar" + depends_on "user/repo/from_tap" + depends_on "baz" => :build + end + + tap = Tap.new("user", "repo") + from_tap = formula("from_tap", path: tap.path/"Formula/from_tap.rb") do + url "from_tap-1.0" + end + stub_formula_loader from_tap + + stub_formula_loader formula("bar") { url "bar-2.0" } + stub_formula_loader formula("baz") { url "baz-3.0" } + + compiler = DevelopmentTools.default_compiler + stdlib = :libcxx + tab = described_class.create(f, compiler, stdlib) + + runtime_dependencies = [ + { "full_name" => "bar", "version" => "2.0" }, + { "full_name" => "user/repo/from_tap", "version" => "1.0" }, + ] + + expect(tab.runtime_dependencies).to eq(runtime_dependencies) + expect(tab.source["path"]).to eq(f.path.to_s) + end + + it "can create a Tab from an alias" do + alias_path = CoreTap.instance.alias_dir/"bar" + f = formula(alias_path: alias_path) { url "foo-1.0" } + compiler = DevelopmentTools.default_compiler + stdlib = :libcxx + tab = described_class.create(f, compiler, stdlib) + + expect(tab.source["path"]).to eq(f.alias_path.to_s) + end + end + + describe "::for_keg" do + subject { described_class.for_keg(f.prefix) } + + it "creates a Tab for a given Keg" do + f.prefix.mkpath + f_tab_path.write f_tab_content + + expect(subject.tabfile).to eq(f_tab_path) + end + + it "can create a Tab for a non-existant Keg" do + f.prefix.mkpath + + expect(subject.tabfile).to be nil + end + end + + describe "::for_formula" do + it "creates a Tab for a given Formula" do + tab = described_class.for_formula(f) + expect(tab.source["path"]).to eq(f.path.to_s) + end + + it "can create a Tab for for a Formula from an alias" do + alias_path = CoreTap.instance.alias_dir/"bar" + f = formula(alias_path: alias_path) { url "foo-1.0" } + + tab = described_class.for_formula(f) + expect(tab.source["path"]).to eq(alias_path.to_s) + end + + it "creates a Tab for a given Formula" do + f.prefix.mkpath + f_tab_path.write f_tab_content + + tab = described_class.for_formula(f) + expect(tab.tabfile).to eq(f_tab_path) + end + + it "can create a Tab for a non-existant Formula" do + f.prefix.mkpath + + tab = described_class.for_formula(f) + expect(tab.tabfile).to be nil + end + + it "can create a Tab for a Formula with multiple Kegs" do + f.prefix.mkpath + f_tab_path.write f_tab_content + + f2 = formula { url "foo-2.0" } + f2.prefix.mkpath + + expect(f2.rack).to eq(f.rack) + expect(f.installed_prefixes.length).to eq(2) + + tab = described_class.for_formula(f) + expect(tab.tabfile).to eq(f_tab_path) + end + + it "can create a Tab for a Formula with an outdated Kegs" do + f_tab_path.write f_tab_content + + f2 = formula { url "foo-2.0" } + + expect(f2.rack).to eq(f.rack) + expect(f.installed_prefixes.length).to eq(1) + + tab = described_class.for_formula(f) + expect(tab.tabfile).to eq(f_tab_path) + end + end + + specify "#to_json" do + tab = described_class.new(JSON.parse(subject.to_json)) + expect(tab.used_options.sort).to eq(subject.used_options.sort) + expect(tab.unused_options.sort).to eq(subject.unused_options.sort) + expect(tab.built_as_bottle).to eq(subject.built_as_bottle) + expect(tab.poured_from_bottle).to eq(subject.poured_from_bottle) + expect(tab.changed_files).to eq(subject.changed_files) + expect(tab.tap).to eq(subject.tap) + expect(tab.spec).to eq(subject.spec) + expect(tab.time).to eq(subject.time) + expect(tab.HEAD).to eq(subject.HEAD) + expect(tab.compiler).to eq(subject.compiler) + expect(tab.stdlib).to eq(subject.stdlib) + expect(tab.runtime_dependencies).to eq(subject.runtime_dependencies) + expect(tab.stable_version).to eq(subject.stable_version) + expect(tab.devel_version).to eq(subject.devel_version) + expect(tab.head_version).to eq(subject.head_version) + expect(tab.source["path"]).to eq(subject.source["path"]) + end + + specify "::remap_deprecated_options" do + deprecated_options = [DeprecatedOption.new("with-foo", "with-foo-new")] + remapped_options = described_class.remap_deprecated_options(deprecated_options, subject.used_options) + expect(remapped_options).to include(Option.new("without-bar")) + expect(remapped_options).to include(Option.new("with-foo-new")) + end +end diff --git a/Library/Homebrew/test/tab_test.rb b/Library/Homebrew/test/tab_test.rb deleted file mode 100644 index f9824ba2a..000000000 --- a/Library/Homebrew/test/tab_test.rb +++ /dev/null @@ -1,315 +0,0 @@ -require "testing_env" -require "tab" -require "formula" - -class TabTests < Homebrew::TestCase - def setup - @used = Options.create(%w[--with-foo --without-bar]) - @unused = Options.create(%w[--with-baz --without-qux]) - - @tab = Tab.new("used_options" => @used.as_flags, - "unused_options" => @unused.as_flags, - "built_as_bottle" => false, - "poured_from_bottle" => true, - "changed_files" => [], - "time" => nil, - "source_modified_time" => 0, - "HEAD" => TEST_SHA1, - "compiler" => "clang", - "stdlib" => "libcxx", - "runtime_dependencies" => [], - "source" => { - "tap" => "homebrew/core", - "path" => nil, - "spec" => "stable", - "versions" => { - "stable" => "0.10", - "devel" => "0.14", - "head" => "HEAD-1111111", - }, - }) - end - - def test_defaults - tab = Tab.empty - - assert_equal HOMEBREW_VERSION, tab.homebrew_version - assert_empty tab.unused_options - assert_empty tab.used_options - assert_nil tab.changed_files - refute_predicate tab, :built_as_bottle - refute_predicate tab, :poured_from_bottle - assert_predicate tab, :stable? - refute_predicate tab, :devel? - refute_predicate tab, :head? - assert_nil tab.tap - assert_nil tab.time - assert_nil tab.HEAD - assert_empty tab.runtime_dependencies - assert_nil tab.stable_version - assert_nil tab.devel_version - assert_nil tab.head_version - assert_equal DevelopmentTools.default_compiler, tab.cxxstdlib.compiler - assert_nil tab.cxxstdlib.type - assert_nil tab.source["path"] - end - - def test_include? - assert_includes @tab, "with-foo" - assert_includes @tab, "without-bar" - end - - def test_with? - assert @tab.with?("foo") - assert @tab.with?("qux") - refute @tab.with?("bar") - refute @tab.with?("baz") - end - - def test_universal? - tab = Tab.new(used_options: %w[--universal]) - assert_predicate tab, :universal? - end - - def test_parsed_homebrew_version - tab = Tab.new - assert_same Version::NULL, tab.parsed_homebrew_version - - tab = Tab.new(homebrew_version: "1.2.3") - assert_equal "1.2.3", tab.parsed_homebrew_version - assert tab.parsed_homebrew_version < "1.2.3-1-g12789abdf" - assert_kind_of Version, tab.parsed_homebrew_version - - tab.homebrew_version = "1.2.4-567-g12789abdf" - assert tab.parsed_homebrew_version > "1.2.4" - assert tab.parsed_homebrew_version > "1.2.4-566-g21789abdf" - assert tab.parsed_homebrew_version < "1.2.4-568-g01789abdf" - - tab = Tab.new(homebrew_version: "2.0.0-134-gabcdefabc-dirty") - assert tab.parsed_homebrew_version > "2.0.0" - assert tab.parsed_homebrew_version > "2.0.0-133-g21789abdf" - assert tab.parsed_homebrew_version < "2.0.0-135-g01789abdf" - end - - def test_runtime_dependencies - tab = Tab.new - assert_nil tab.runtime_dependencies - - tab.homebrew_version = "1.1.6" - assert_nil tab.runtime_dependencies - - tab.runtime_dependencies = [] - refute_nil tab.runtime_dependencies - - tab.homebrew_version = "1.1.5" - assert_nil tab.runtime_dependencies - - tab.homebrew_version = "1.1.7" - refute_nil tab.runtime_dependencies - - tab.homebrew_version = "1.1.10" - refute_nil tab.runtime_dependencies - - tab.runtime_dependencies = [{ "full_name" => "foo", "version" => "1.0" }] - refute_nil tab.runtime_dependencies - end - - def test_cxxstdlib - assert_equal :clang, @tab.cxxstdlib.compiler - assert_equal :libcxx, @tab.cxxstdlib.type - end - - def test_other_attributes - assert_equal TEST_SHA1, @tab.HEAD - assert_equal "homebrew/core", @tab.tap.name - assert_nil @tab.time - refute_predicate @tab, :built_as_bottle - assert_predicate @tab, :poured_from_bottle - end - - def test_from_old_version_file - path = Pathname.new("#{TEST_FIXTURE_DIR}/receipt_old.json") - tab = Tab.from_file(path) - - assert_equal @used.sort, tab.used_options.sort - assert_equal @unused.sort, tab.unused_options.sort - refute_predicate tab, :built_as_bottle - assert_predicate tab, :poured_from_bottle - assert_predicate tab, :stable? - refute_predicate tab, :devel? - refute_predicate tab, :head? - assert_equal "homebrew/core", tab.tap.name - assert_equal :stable, tab.spec - refute_nil tab.time - assert_equal TEST_SHA1, tab.HEAD - assert_equal :clang, tab.cxxstdlib.compiler - assert_equal :libcxx, tab.cxxstdlib.type - assert_nil tab.runtime_dependencies - end - - def test_from_file - path = Pathname.new("#{TEST_FIXTURE_DIR}/receipt.json") - tab = Tab.from_file(path) - source_path = "/usr/local/Library/Taps/homebrew/homebrew-core/Formula/foo.rb" - runtime_dependencies = [{ "full_name" => "foo", "version" => "1.0" }] - changed_files = %w[INSTALL_RECEIPT.json bin/foo] - - assert_equal @used.sort, tab.used_options.sort - assert_equal @unused.sort, tab.unused_options.sort - assert_equal changed_files, tab.changed_files - refute_predicate tab, :built_as_bottle - assert_predicate tab, :poured_from_bottle - assert_predicate tab, :stable? - refute_predicate tab, :devel? - refute_predicate tab, :head? - assert_equal "homebrew/core", tab.tap.name - assert_equal :stable, tab.spec - refute_nil tab.time - assert_equal TEST_SHA1, tab.HEAD - assert_equal :clang, tab.cxxstdlib.compiler - assert_equal :libcxx, tab.cxxstdlib.type - assert_equal runtime_dependencies, tab.runtime_dependencies - assert_equal "2.14", tab.stable_version.to_s - assert_equal "2.15", tab.devel_version.to_s - assert_equal "HEAD-0000000", tab.head_version.to_s - assert_equal source_path, tab.source["path"] - end - - def test_create - f = formula do - url "foo-1.0" - depends_on "bar" - depends_on "user/repo/from_tap" - depends_on "baz" => :build - end - - tap = Tap.new("user", "repo") - from_tap = formula("from_tap", tap.path/"Formula/from_tap.rb") do - url "from_tap-1.0" - end - stub_formula_loader from_tap - - stub_formula_loader formula("bar") { url "bar-2.0" } - stub_formula_loader formula("baz") { url "baz-3.0" } - - compiler = DevelopmentTools.default_compiler - stdlib = :libcxx - tab = Tab.create(f, compiler, stdlib) - - runtime_dependencies = [ - { "full_name" => "bar", "version" => "2.0" }, - { "full_name" => "user/repo/from_tap", "version" => "1.0" }, - ] - - assert_equal runtime_dependencies, tab.runtime_dependencies - assert_equal f.path.to_s, tab.source["path"] - end - - def test_create_from_alias - alias_path = CoreTap.instance.alias_dir/"bar" - f = formula(alias_path: alias_path) { url "foo-1.0" } - compiler = DevelopmentTools.default_compiler - stdlib = :libcxx - tab = Tab.create(f, compiler, stdlib) - - assert_equal f.alias_path.to_s, tab.source["path"] - end - - def test_for_formula - f = formula { url "foo-1.0" } - tab = Tab.for_formula(f) - - assert_equal f.path.to_s, tab.source["path"] - end - - def test_for_formula_from_alias - alias_path = CoreTap.instance.alias_dir/"bar" - f = formula(alias_path: alias_path) { url "foo-1.0" } - tab = Tab.for_formula(f) - - assert_equal alias_path.to_s, tab.source["path"] - end - - def test_to_json - tab = Tab.new(JSON.parse(@tab.to_json)) - assert_equal @tab.used_options.sort, tab.used_options.sort - assert_equal @tab.unused_options.sort, tab.unused_options.sort - assert_equal @tab.built_as_bottle, tab.built_as_bottle - assert_equal @tab.poured_from_bottle, tab.poured_from_bottle - assert_equal @tab.changed_files, tab.changed_files - assert_equal @tab.tap, tab.tap - assert_equal @tab.spec, tab.spec - assert_equal @tab.time, tab.time - assert_equal @tab.HEAD, tab.HEAD - assert_equal @tab.compiler, tab.compiler - assert_equal @tab.stdlib, tab.stdlib - assert_equal @tab.runtime_dependencies, tab.runtime_dependencies - assert_equal @tab.stable_version, tab.stable_version - assert_equal @tab.devel_version, tab.devel_version - assert_equal @tab.head_version, tab.head_version - assert_equal @tab.source["path"], tab.source["path"] - end - - def test_remap_deprecated_options - deprecated_options = [DeprecatedOption.new("with-foo", "with-foo-new")] - remapped_options = Tab.remap_deprecated_options(deprecated_options, @tab.used_options) - assert_includes remapped_options, Option.new("without-bar") - assert_includes remapped_options, Option.new("with-foo-new") - end -end - -class TabLoadingTests < Homebrew::TestCase - def setup - @f = formula { url "foo-1.0" } - @f.prefix.mkpath - @path = @f.prefix.join(Tab::FILENAME) - @path.write TEST_FIXTURE_DIR.join("receipt.json").read - end - - def teardown - @f.rack.rmtree - end - - def test_for_keg - tab = Tab.for_keg(@f.prefix) - assert_equal @path, tab.tabfile - end - - def test_for_keg_nonexistent_path - @path.unlink - tab = Tab.for_keg(@f.prefix) - assert_nil tab.tabfile - end - - def test_for_formula - tab = Tab.for_formula(@f) - assert_equal @path, tab.tabfile - end - - def test_for_formula_nonexistent_path - @path.unlink - tab = Tab.for_formula(@f) - assert_nil tab.tabfile - end - - def test_for_formula_multiple_kegs - f2 = formula { url "foo-2.0" } - f2.prefix.mkpath - - assert_equal @f.rack, f2.rack - assert_equal 2, @f.installed_prefixes.length - - tab = Tab.for_formula(@f) - assert_equal @path, tab.tabfile - end - - def test_for_formula_outdated_keg - f2 = formula { url "foo-2.0" } - - assert_equal @f.rack, f2.rack - assert_equal 1, @f.installed_prefixes.length - - tab = Tab.for_formula(f2) - assert_equal @path, tab.tabfile - end -end diff --git a/Library/Homebrew/test/tap_new_test.rb b/Library/Homebrew/test/tap_new_test.rb deleted file mode 100644 index 261a334f0..000000000 --- a/Library/Homebrew/test/tap_new_test.rb +++ /dev/null @@ -1,9 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestTapNew < IntegrationCommandTestCase - def test_tap_readme - assert_equal "", cmd("tap-new", "homebrew/foo", "--verbose") - readme = HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-foo/README.md" - assert readme.exist?, "The README should be created" - end -end diff --git a/Library/Homebrew/test/tap_test.rb b/Library/Homebrew/test/tap_test.rb index 7114cdf22..729fc8198 100644 --- a/Library/Homebrew/test/tap_test.rb +++ b/Library/Homebrew/test/tap_test.rb @@ -1,39 +1,10 @@ require "testing_env" -require "testing_env" - -class IntegrationCommandTestTap < IntegrationCommandTestCase - def test_tap - path = Tap::TAP_DIRECTORY/"homebrew/homebrew-foo" - path.mkpath - path.cd do - shutup do - system "git", "init" - system "git", "remote", "add", "origin", "https://github.com/Homebrew/homebrew-foo" - FileUtils.touch "readme" - system "git", "add", "--all" - system "git", "commit", "-m", "init" - end - end - - assert_match "homebrew/foo", cmd("tap") - assert_match "homebrew/science", cmd("tap", "--list-official") - assert_match "2 taps", cmd("tap-info") - assert_match "https://github.com/Homebrew/homebrew-foo", cmd("tap-info", "homebrew/foo") - assert_match "https://github.com/Homebrew/homebrew-foo", cmd("tap-info", "--json=v1", "--installed") - assert_match "Pinned homebrew/foo", cmd("tap-pin", "homebrew/foo") - assert_match "homebrew/foo", cmd("tap", "--list-pinned") - assert_match "Unpinned homebrew/foo", cmd("tap-unpin", "homebrew/foo") - assert_match "Tapped", cmd("tap", "homebrew/bar", path/".git") - assert_match "Untapped", cmd("untap", "homebrew/bar") - assert_equal "", cmd("tap", "homebrew/bar", path/".git", "-q", "--full") - assert_match "Untapped", cmd("untap", "homebrew/bar") - end -end class TapTest < Homebrew::TestCase include FileUtils def setup + super @path = Tap::TAP_DIRECTORY/"homebrew/homebrew-foo" @path.mkpath @tap = Tap.new("Homebrew", "foo") @@ -65,13 +36,6 @@ class TapTest < Homebrew::TestCase end def setup_git_repo - env = ENV.to_hash - %w[AUTHOR COMMITTER].each do |role| - ENV["GIT_#{role}_NAME"] = "brew tests" - ENV["GIT_#{role}_EMAIL"] = "brew-tests@localhost" - ENV["GIT_#{role}_DATE"] = "Thu May 21 00:04:11 2009 +0100" - end - @path.cd do shutup do system "git", "init" @@ -80,12 +44,6 @@ class TapTest < Homebrew::TestCase system "git", "commit", "-m", "init" end end - ensure - ENV.replace(env) - end - - def teardown - @path.rmtree end def test_fetch @@ -171,8 +129,6 @@ class TapTest < Homebrew::TestCase end end refute_predicate services_tap, :private? - ensure - services_tap.path.rmtree if services_tap end def test_remote_not_git_repo @@ -189,10 +145,10 @@ class TapTest < Homebrew::TestCase touch @path/"README" setup_git_repo - assert_equal "e1893a6bd191ba895c71b652ff8376a6114c7fa7", @tap.git_head - assert_equal "e189", @tap.git_short_head - assert_match "years ago", @tap.git_last_commit - assert_equal "2009-05-21", @tap.git_last_commit_date + assert_equal "0453e16c8e3fac73104da50927a86221ca0740c2", @tap.git_head + assert_equal "0453", @tap.git_short_head + assert_match(/\A\d+ .+ ago\Z/, @tap.git_last_commit) + assert_equal "2017-01-22", @tap.git_last_commit_date end def test_private_remote @@ -256,8 +212,6 @@ class TapTest < Homebrew::TestCase refute_predicate tap, :installed? refute_predicate HOMEBREW_PREFIX/"share/man/man1/brew-tap-cmd.1", :exist? refute_predicate HOMEBREW_PREFIX/"share/man/man1", :exist? - ensure - (HOMEBREW_PREFIX/"share").rmtree if (HOMEBREW_PREFIX/"share").exist? end def test_pin_and_unpin @@ -285,6 +239,7 @@ class CoreTapTest < Homebrew::TestCase include FileUtils def setup + super @repo = CoreTap.new end @@ -322,8 +277,5 @@ class CoreTapTest < Homebrew::TestCase assert_equal ["bar"], @repo.aliases assert_equal @repo.alias_table, "bar" => "foo" assert_equal @repo.alias_reverse_table, "foo" => ["bar"] - ensure - @formula_file.unlink - @repo.alias_dir.rmtree end end diff --git a/Library/Homebrew/test/test_formula_test.rb b/Library/Homebrew/test/test_formula_test.rb deleted file mode 100644 index 5ad2db9e9..000000000 --- a/Library/Homebrew/test/test_formula_test.rb +++ /dev/null @@ -1,30 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestTestFormula < IntegrationCommandTestCase - def test_test_formula - assert_match "This command requires a formula argument", cmd_fail("test") - assert_match "Testing requires the latest version of testball", - cmd_fail("test", testball) - - cmd("install", testball) - assert_match "testball defines no test", cmd_fail("test", testball) - - setup_test_formula "testball_copy", <<-EOS.undent - head "https://github.com/example/testball2.git" - - devel do - url "file://#{TEST_FIXTURE_DIR}/tarballs/testball-0.1.tbz" - sha256 "#{TESTBALL_SHA256}" - end - - keg_only "just because" - - test do - end - EOS - - cmd("install", "testball_copy") - assert_match "Testing testball_copy", cmd("test", "--HEAD", "testball_copy") - assert_match "Testing testball_copy", cmd("test", "--devel", "testball_copy") - end -end diff --git a/Library/Homebrew/test/testing_env.rb b/Library/Homebrew/test/testing_env.rb index e2ba2e4e4..999fa1013 100644 --- a/Library/Homebrew/test/testing_env.rb +++ b/Library/Homebrew/test/testing_env.rb @@ -1,21 +1,18 @@ -$:.unshift File.expand_path("../..", __FILE__) -$:.unshift File.expand_path("../support/lib", __FILE__) - -require "simplecov" if ENV["HOMEBREW_TESTS_COVERAGE"] -require "global" -require "formulary" - -# Test environment setup -(HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-core/Formula").mkpath -%w[cache formula_cache locks cellar logs temp].each { |d| HOMEBREW_PREFIX.parent.join(d).mkpath } - begin require "minitest/autorun" - require "parallel_tests/test/runtime_logger" + require "minitest/reporters" + Minitest::Reporters.use! Minitest::Reporters::DefaultReporter.new(color: true) require "mocha/setup" + require "parallel_tests/test/runtime_logger" + require "simplecov" if ENV["HOMEBREW_TESTS_COVERAGE"] rescue LoadError - abort "Run `bundle install` or install the mocha and minitest gems before running the tests" + abort "Run `bundle install` before running the tests." end +$LOAD_PATH.unshift(File.expand_path("#{ENV["HOMEBREW_LIBRARY"]}/Homebrew")) +$LOAD_PATH.unshift(File.expand_path("#{ENV["HOMEBREW_LIBRARY"]}/Homebrew/test/support/lib")) + +require "global" + require "test/support/helper/test_case" require "test/support/helper/integration_command_test_case" diff --git a/Library/Homebrew/test/uninstall_test.rb b/Library/Homebrew/test/uninstall_test.rb index 597e77e40..a9230ffac 100644 --- a/Library/Homebrew/test/uninstall_test.rb +++ b/Library/Homebrew/test/uninstall_test.rb @@ -3,6 +3,8 @@ require "cmd/uninstall" class UninstallTests < Homebrew::TestCase def setup + super + @dependency = formula("dependency") { url "f-1" } @dependent = formula("dependent") do url "f-1" @@ -28,10 +30,7 @@ class UninstallTests < Homebrew::TestCase def teardown Homebrew.failed = false - [@dependency, @dependent].each do |f| - f.installed_kegs.each(&:remove_opt_record) - f.rack.rmtree - end + super end def handle_unsatisfied_dependents @@ -59,14 +58,5 @@ class UninstallTests < Homebrew::TestCase assert_empty handle_unsatisfied_dependents refute_predicate Homebrew, :failed? end - ensure - ARGV.delete("--ignore-dependencies") - end -end - -class IntegrationCommandTestUninstall < IntegrationCommandTestCase - def test_uninstall - cmd("install", testball) - assert_match "Uninstalling testball", cmd("uninstall", "--force", testball) end end diff --git a/Library/Homebrew/test/unlink_test.rb b/Library/Homebrew/test/unlink_test.rb deleted file mode 100644 index 6d5cefc67..000000000 --- a/Library/Homebrew/test/unlink_test.rb +++ /dev/null @@ -1,10 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestUnlink < IntegrationCommandTestCase - def test_unlink - setup_test_formula "testball" - - cmd("install", "testball") - assert_match "Would remove", cmd("unlink", "--dry-run", "testball") - end -end diff --git a/Library/Homebrew/test/unlinkapps_test.rb b/Library/Homebrew/test/unlinkapps_test.rb deleted file mode 100644 index 9d9672199..000000000 --- a/Library/Homebrew/test/unlinkapps_test.rb +++ /dev/null @@ -1,19 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestUnlinkapps < IntegrationCommandTestCase - def test_unlinkapps - home_dir = Pathname.new(mktmpdir) - apps_dir = home_dir/"Applications" - apps_dir.mkpath - - setup_test_formula "testball" - - source_app = (HOMEBREW_CELLAR/"testball/0.1/TestBall.app") - source_app.mkpath - - FileUtils.ln_s source_app, "#{apps_dir}/TestBall.app" - - assert_match "Unlinking: #{apps_dir}/TestBall.app", - cmd("unlinkapps", "--local", "HOME" => home_dir) - end -end diff --git a/Library/Homebrew/test/unpack_test.rb b/Library/Homebrew/test/unpack_test.rb deleted file mode 100644 index bbff6ad1c..000000000 --- a/Library/Homebrew/test/unpack_test.rb +++ /dev/null @@ -1,13 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestUnpack < IntegrationCommandTestCase - def test_unpack - setup_test_formula "testball" - - mktmpdir do |path| - cmd "unpack", "testball", "--destdir=#{path}" - assert File.directory?("#{path}/testball-0.1"), - "The tarball should be unpacked" - end - end -end diff --git a/Library/Homebrew/test/update_report_test.rb b/Library/Homebrew/test/update_report_test.rb deleted file mode 100644 index 6b6cec6ce..000000000 --- a/Library/Homebrew/test/update_report_test.rb +++ /dev/null @@ -1,134 +0,0 @@ -require "testing_env" -require "cmd/update-report" -require "formula_versions" -require "yaml" - -class ReportTests < Homebrew::TestCase - class ReporterMock < ::Reporter - attr_accessor :diff - - def initialize(tap) - @tap = tap - ENV["HOMEBREW_UPDATE_BEFORE#{repo_var}"] = "12345678" - ENV["HOMEBREW_UPDATE_AFTER#{repo_var}"] = "abcdef12" - super(tap) - end - end - - def fixture(name) - self.class.fixture_data[name] || "" - end - - def self.fixture_data - @fixture_data ||= YAML.load_file("#{TEST_FIXTURE_DIR}/updater_fixture.yaml") - end - - def setup - @tap = CoreTap.new - @reporter = ReporterMock.new(@tap) - @hub = ReporterHub.new - end - - def perform_update(fixture_name = "") - Formulary.stubs(:factory).returns(stub(pkg_version: "1.0")) - FormulaVersions.stubs(:new).returns(stub(formula_at_revision: "2.0")) - @reporter.diff = fixture(fixture_name) - @hub.add(@reporter) if @reporter.updated? - end - - def test_update_report_without_revision_var - ENV.delete_if { |k, _v| k.start_with? "HOMEBREW_UPDATE" } - assert_raises(Reporter::ReporterRevisionUnsetError) { Reporter.new(@tap) } - end - - def test_update_homebrew_without_any_changes - perform_update - assert_empty @hub - end - - def test_update_homebrew_without_formulae_changes - perform_update("update_git_diff_output_without_formulae_changes") - assert_empty @hub.select_formula(:M) - assert_empty @hub.select_formula(:A) - assert_empty @hub.select_formula(:D) - end - - def test_update_homebrew_with_formulae_changes - perform_update("update_git_diff_output_with_formulae_changes") - assert_equal %w[xar yajl], @hub.select_formula(:M) - assert_equal %w[antiword bash-completion ddrescue dict lua], @hub.select_formula(:A) - end - - def test_update_homebrew_with_removed_formulae - perform_update("update_git_diff_output_with_removed_formulae") - assert_equal %w[libgsasl], @hub.select_formula(:D) - end - - def test_update_homebrew_with_changed_filetype - perform_update("update_git_diff_output_with_changed_filetype") - assert_equal %w[elixir], @hub.select_formula(:M) - assert_equal %w[libbson], @hub.select_formula(:A) - assert_equal %w[libgsasl], @hub.select_formula(:D) - end - - def test_update_homebrew_with_formula_rename - @tap.stubs(:formula_renames).returns("cv" => "progress") - perform_update("update_git_diff_output_with_formula_rename") - assert_empty @hub.select_formula(:A) - assert_empty @hub.select_formula(:D) - assert_equal [["cv", "progress"]], @hub.select_formula(:R) - end - - def test_update_homebrew_with_restructured_tap - tap = Tap.new("foo", "bar") - @reporter = ReporterMock.new(tap) - tap.path.join("Formula").mkpath - - perform_update("update_git_diff_output_with_restructured_tap") - assert_empty @hub.select_formula(:A) - assert_empty @hub.select_formula(:D) - assert_empty @hub.select_formula(:R) - ensure - tap.path.parent.rmtree - end - - def test_update_homebrew_with_formula_rename_and_restructuring - tap = Tap.new("foo", "bar") - @reporter = ReporterMock.new(tap) - tap.path.join("Formula").mkpath - tap.stubs(:formula_renames).returns("xchat" => "xchat2") - - perform_update("update_git_diff_output_with_formula_rename_and_restructuring") - assert_empty @hub.select_formula(:A) - assert_empty @hub.select_formula(:D) - assert_equal [%w[foo/bar/xchat foo/bar/xchat2]], @hub.select_formula(:R) - ensure - tap.path.parent.rmtree - end - - def test_update_homebrew_simulate_homebrew_php_restructuring - tap = Tap.new("foo", "bar") - @reporter = ReporterMock.new(tap) - tap.path.join("Formula").mkpath - - perform_update("update_git_diff_simulate_homebrew_php_restructuring") - assert_empty @hub.select_formula(:A) - assert_empty @hub.select_formula(:D) - assert_empty @hub.select_formula(:R) - ensure - tap.path.parent.rmtree - end - - def test_update_homebrew_with_tap_formulae_changes - tap = Tap.new("foo", "bar") - @reporter = ReporterMock.new(tap) - tap.path.join("Formula").mkpath - - perform_update("update_git_diff_output_with_tap_formulae_changes") - assert_equal %w[foo/bar/lua], @hub.select_formula(:A) - assert_equal %w[foo/bar/git], @hub.select_formula(:M) - assert_empty @hub.select_formula(:D) - ensure - tap.path.parent.rmtree - end -end diff --git a/Library/Homebrew/test/upgrade_test.rb b/Library/Homebrew/test/upgrade_test.rb deleted file mode 100644 index f3f5dccc7..000000000 --- a/Library/Homebrew/test/upgrade_test.rb +++ /dev/null @@ -1,12 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestUpgrade < IntegrationCommandTestCase - def test_upgrade - setup_test_formula "testball" - (HOMEBREW_CELLAR/"testball/0.0.1/foo").mkpath - - cmd("upgrade") - assert((HOMEBREW_CELLAR/"testball/0.1").directory?, - "The latest version directory should be created") - end -end diff --git a/Library/Homebrew/test/uses_test.rb b/Library/Homebrew/test/uses_test.rb deleted file mode 100644 index 1fad0da28..000000000 --- a/Library/Homebrew/test/uses_test.rb +++ /dev/null @@ -1,16 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestUses < IntegrationCommandTestCase - def test_uses - setup_test_formula "foo" - setup_test_formula "bar" - setup_test_formula "baz", <<-EOS.undent - url "https://example.com/baz-1.0" - depends_on "bar" - EOS - - assert_equal "", cmd("uses", "baz") - assert_equal "baz", cmd("uses", "bar") - assert_match(/(bar\nbaz|baz\nbar)/, cmd("uses", "--recursive", "foo")) - end -end diff --git a/Library/Homebrew/test/utils/bottles/bintray_spec.rb b/Library/Homebrew/test/utils/bottles/bintray_spec.rb new file mode 100644 index 000000000..a7dfc00ea --- /dev/null +++ b/Library/Homebrew/test/utils/bottles/bintray_spec.rb @@ -0,0 +1,18 @@ +require "utils/bottles" + +describe Utils::Bottles::Bintray do + describe "::package" do + it "converts a Formula name to a package name" do + expect(described_class.package("openssl@1.1")).to eq("openssl:1.1") + expect(described_class.package("gtk+")).to eq("gtkx") + expect(described_class.package("llvm")).to eq("llvm") + end + end + + describe "::repository" do + it "returns the repository for a given Tap" do + expect(described_class.repository(Tap.new("homebrew", "bintray-test"))) + .to eq("bottles-bintray-test") + end + end +end diff --git a/Library/Homebrew/test/utils/bottles/bottles_spec.rb b/Library/Homebrew/test/utils/bottles/bottles_spec.rb new file mode 100644 index 000000000..8b54b0b34 --- /dev/null +++ b/Library/Homebrew/test/utils/bottles/bottles_spec.rb @@ -0,0 +1,80 @@ +require "utils/bottles" + +describe Utils::Bottles do + describe "#tag", :needs_macos do + it "returns :tiger_foo on Tiger PowerPC" do + allow(MacOS).to receive(:version).and_return(MacOS::Version.new("10.4")) + allow(Hardware::CPU).to receive(:type).and_return(:ppc) + allow(Hardware::CPU).to receive(:family).and_return(:foo) + allow(MacOS).to receive(:prefer_64_bit?).and_return(false) + expect(described_class.tag).to eq(:tiger_foo) + end + + it "returns :tiger on Tiger Intel" do + allow(MacOS).to receive(:version).and_return(MacOS::Version.new("10.4")) + allow(Hardware::CPU).to receive(:type).and_return(:intel) + allow(MacOS).to receive(:prefer_64_bit?).and_return(false) + expect(described_class.tag).to eq(:tiger) + end + + it "returns :tiger_g5_64 on Tiger PowerPC 64-bit" do + allow(MacOS).to receive(:version).and_return(MacOS::Version.new("10.4")) + allow(Hardware::CPU).to receive(:type).and_return(:ppc) + allow(Hardware::CPU).to receive(:family).and_return(:g5) + allow(MacOS).to receive(:prefer_64_bit?).and_return(true) + expect(described_class.tag).to eq(:tiger_g5_64) + end + + # Note that this will probably never be used + it "returns :tiger_64 on Tiger Intel 64-bit" do + allow(MacOS).to receive(:version).and_return(MacOS::Version.new("10.4")) + allow(Hardware::CPU).to receive(:type).and_return(:intel) + allow(MacOS).to receive(:prefer_64_bit?).and_return(true) + expect(described_class.tag).to eq(:tiger_64) + end + + it "returns :leopard on Leopard Intel" do + allow(MacOS).to receive(:version).and_return(MacOS::Version.new("10.5")) + allow(Hardware::CPU).to receive(:type).and_return(:intel) + allow(MacOS).to receive(:prefer_64_bit?).and_return(false) + expect(described_class.tag).to eq(:leopard) + end + + it "returns :leopard_g5_64 on Leopard PowerPC 64-bit" do + allow(MacOS).to receive(:version).and_return(MacOS::Version.new("10.5")) + allow(Hardware::CPU).to receive(:type).and_return(:ppc) + allow(Hardware::CPU).to receive(:family).and_return(:g5) + allow(MacOS).to receive(:prefer_64_bit?).and_return(true) + expect(described_class.tag).to eq(:leopard_g5_64) + end + + it "returns :leopard_64 on Leopard Intel 64-bit" do + allow(MacOS).to receive(:version).and_return(MacOS::Version.new("10.5")) + allow(Hardware::CPU).to receive(:type).and_return(:intel) + allow(MacOS).to receive(:prefer_64_bit?).and_return(true) + expect(described_class.tag).to eq(:leopard_64) + end + + it "returns :snow_leopard_32 on Snow Leopard 32-bit" do + allow(MacOS).to receive(:version).and_return(MacOS::Version.new("10.6")) + allow(Hardware::CPU).to receive(:is_64_bit?).and_return(false) + expect(described_class.tag).to eq(:snow_leopard_32) + end + + it "returns :snow_leopard on Snow Leopard 64-bit" do + allow(MacOS).to receive(:version).and_return(MacOS::Version.new("10.6")) + allow(Hardware::CPU).to receive(:is_64_bit?).and_return(true) + expect(described_class.tag).to eq(:snow_leopard) + end + + it "returns :lion on Lion" do + allow(MacOS).to receive(:version).and_return(MacOS::Version.new("10.7")) + expect(described_class.tag).to eq(:lion) + end + + it "returns :mountain_lion on Mountain Lion" do + allow(MacOS).to receive(:version).and_return(MacOS::Version.new("10.8")) + expect(described_class.tag).to eq(:mountain_lion) + end + end +end diff --git a/Library/Homebrew/test/utils/bottles/collector_spec.rb b/Library/Homebrew/test/utils/bottles/collector_spec.rb new file mode 100644 index 000000000..08484e545 --- /dev/null +++ b/Library/Homebrew/test/utils/bottles/collector_spec.rb @@ -0,0 +1,45 @@ +require "utils/bottles" + +describe Utils::Bottles::Collector do + describe "#fetch_checksum_for" do + it "returns passed tags" do + subject[:lion] = "foo" + subject[:mountain_lion] = "bar" + expect(subject.fetch_checksum_for(:mountain_lion)).to eq(["bar", :mountain_lion]) + end + + it "returns nil if empty" do + expect(subject.fetch_checksum_for(:foo)).to be nil + end + + it "returns nil when there is no match" do + subject[:lion] = "foo" + expect(subject.fetch_checksum_for(:foo)).to be nil + end + + it "returns nil when there is no match and later tag is present" do + subject[:lion_or_later] = "foo" + expect(subject.fetch_checksum_for(:foo)).to be nil + end + + it "prefers exact matches" do + subject[:lion_or_later] = "foo" + subject[:mountain_lion] = "bar" + expect(subject.fetch_checksum_for(:mountain_lion)).to eq(["bar", :mountain_lion]) + end + + it "finds '_or_later' tags", :needs_macos do + subject[:lion_or_later] = "foo" + expect(subject.fetch_checksum_for(:mountain_lion)).to eq(["foo", :lion_or_later]) + expect(subject.fetch_checksum_for(:snow_leopard)).to be nil + end + + it "finds '_altivec' tags", :needs_macos do + subject[:tiger_altivec] = "foo" + expect(subject.fetch_checksum_for(:tiger_g4)).to eq(["foo", :tiger_altivec]) + expect(subject.fetch_checksum_for(:tiger_g4e)).to eq(["foo", :tiger_altivec]) + expect(subject.fetch_checksum_for(:tiger_g5)).to eq(["foo", :tiger_altivec]) + expect(subject.fetch_checksum_for(:tiger_g3)).to be nil + end + end +end diff --git a/Library/Homebrew/test/utils/popen_spec.rb b/Library/Homebrew/test/utils/popen_spec.rb new file mode 100644 index 000000000..e3704a876 --- /dev/null +++ b/Library/Homebrew/test/utils/popen_spec.rb @@ -0,0 +1,28 @@ +require "utils/popen" + +describe Utils do + describe "::popen_read" do + it "reads the standard output of a given command" do + expect(subject.popen_read("sh", "-c", "echo success").chomp).to eq("success") + expect($?).to be_a_success + end + + it "can be given a block to manually read from the pipe" do + expect( + subject.popen_read("sh", "-c", "echo success") do |pipe| + pipe.read.chomp + end, + ).to eq("success") + expect($?).to be_a_success + end + end + + describe "::popen_write" do + it "with supports writing to a command's standard input" do + subject.popen_write("grep", "-q", "success") do |pipe| + pipe.write("success\n") + end + expect($?).to be_a_success + end + end +end diff --git a/Library/Homebrew/test/utils/shell_spec.rb b/Library/Homebrew/test/utils/shell_spec.rb new file mode 100644 index 000000000..c44bd8253 --- /dev/null +++ b/Library/Homebrew/test/utils/shell_spec.rb @@ -0,0 +1,93 @@ +require "utils/shell" + +describe Utils::Shell do + describe "::shell_profile" do + it "returns ~/.bash_profile by default" do + ENV["SHELL"] = "/bin/another_shell" + expect(subject.shell_profile).to eq("~/.bash_profile") + end + + it "returns ~/.bash_profile for Sh" do + ENV["SHELL"] = "/bin/another_shell" + expect(subject.shell_profile).to eq("~/.bash_profile") + end + + it "returns ~/.bash_profile for Bash" do + ENV["SHELL"] = "/bin/bash" + expect(subject.shell_profile).to eq("~/.bash_profile") + end + + it "returns ~/.zshrc for Zsh" do + ENV["SHELL"] = "/bin/zsh" + expect(subject.shell_profile).to eq("~/.zshrc") + end + + it "returns ~/.kshrc for Ksh" do + ENV["SHELL"] = "/bin/ksh" + expect(subject.shell_profile).to eq("~/.kshrc") + end + end + + describe "::path_to_shell" do + it "supports a raw command name" do + expect(subject.path_to_shell("bash")).to eq(:bash) + end + + it "supports full paths" do + expect(subject.path_to_shell("/bin/bash")).to eq(:bash) + end + + it "supports versions" do + expect(subject.path_to_shell("zsh-5.2")).to eq(:zsh) + end + + it "strips newlines" do + expect(subject.path_to_shell("zsh-5.2\n")).to eq(:zsh) + end + + it "returns nil when input is invalid" do + expect(subject.path_to_shell("")).to be nil + expect(subject.path_to_shell("@@@@@@")).to be nil + expect(subject.path_to_shell("invalid_shell-4.2")).to be nil + end + end + + specify "::sh_quote" do + expect(subject.sh_quote("")).to eq("''") + expect(subject.sh_quote("\\")).to eq("\\\\") + expect(subject.sh_quote("\n")).to eq("'\n'") + expect(subject.sh_quote("$")).to eq("\\$") + expect(subject.sh_quote("word")).to eq("word") + end + + specify "::csh_quote" do + expect(subject.csh_quote("")).to eq("''") + expect(subject.csh_quote("\\")).to eq("\\\\") + # note this test is different than for sh + expect(subject.csh_quote("\n")).to eq("'\\\n'") + expect(subject.csh_quote("$")).to eq("\\$") + expect(subject.csh_quote("word")).to eq("word") + end + + describe "::prepend_path_in_shell_profile" do + let(:path) { "/my/path" } + + it "supports Tcsh" do + ENV["SHELL"] = "/bin/tcsh" + expect(subject.prepend_path_in_shell_profile(path)) + .to start_with("echo 'setenv PATH #{path}:$") + end + + it "supports Bash" do + ENV["SHELL"] = "/bin/bash" + expect(subject.prepend_path_in_shell_profile(path)) + .to start_with("echo 'export PATH=\"#{path}:$") + end + + it "supports Fish" do + ENV["SHELL"] = "/usr/local/bin/fish" + expect(subject.prepend_path_in_shell_profile(path)) + .to start_with("echo 'set -g fish_user_paths \"#{path}\" $fish_user_paths' >>") + end + end +end diff --git a/Library/Homebrew/test/utils/tty_spec.rb b/Library/Homebrew/test/utils/tty_spec.rb new file mode 100644 index 000000000..3ba89b6fd --- /dev/null +++ b/Library/Homebrew/test/utils/tty_spec.rb @@ -0,0 +1,67 @@ +require "utils" + +describe Tty do + describe "::strip_ansi" do + it "removes ANSI escape codes from a string" do + expect(subject.strip_ansi("\033\[36;7mhello\033\[0m")).to eq("hello") + end + end + + describe "::width" do + it "returns an Integer" do + expect(subject.width).to be_kind_of(Integer) + end + + it "cannot be negative" do + expect(subject.width).to be >= 0 + end + end + + describe "::truncate" do + it "truncates the text to the terminal width, minus 4, to account for '==> '" do + allow(subject).to receive(:width).and_return(15) + + expect(subject.truncate("foobar something very long")).to eq("foobar some") + expect(subject.truncate("truncate")).to eq("truncate") + end + + it "doesn't truncate the text if the terminal is unsupported, i.e. the width is 0" do + allow(subject).to receive(:width).and_return(0) + expect(subject.truncate("foobar something very long")).to eq("foobar something very long") + end + end + + context "when $stdout is not a TTY" do + before(:each) do + allow($stdout).to receive(:tty?).and_return(false) + end + + it "returns an empty string for all colors" do + expect(subject.to_s).to eq("") + expect(subject.red.to_s).to eq("") + expect(subject.green.to_s).to eq("") + expect(subject.yellow.to_s).to eq("") + expect(subject.blue.to_s).to eq("") + expect(subject.magenta.to_s).to eq("") + expect(subject.cyan.to_s).to eq("") + expect(subject.default.to_s).to eq("") + end + end + + context "when $stdout is a TTY" do + before(:each) do + allow($stdout).to receive(:tty?).and_return(true) + end + + it "returns an empty string for all colors" do + expect(subject.to_s).to eq("") + expect(subject.red.to_s).to eq("\033[31m") + expect(subject.green.to_s).to eq("\033[32m") + expect(subject.yellow.to_s).to eq("\033[33m") + expect(subject.blue.to_s).to eq("\033[34m") + expect(subject.magenta.to_s).to eq("\033[35m") + expect(subject.cyan.to_s).to eq("\033[36m") + expect(subject.default.to_s).to eq("\033[39m") + end + end +end diff --git a/Library/Homebrew/test/utils/tty_test.rb b/Library/Homebrew/test/utils/tty_test.rb deleted file mode 100644 index 09f092cbd..000000000 --- a/Library/Homebrew/test/utils/tty_test.rb +++ /dev/null @@ -1,46 +0,0 @@ -require "testing_env" -require "utils" - -class TtyTests < Homebrew::TestCase - def test_strip_ansi - assert_equal "hello", Tty.strip_ansi("\033\[36;7mhello\033\[0m") - end - - def test_width - assert_kind_of Integer, Tty.width - end - - def test_truncate - Tty.stubs(:width).returns 15 - assert_equal "foobar some", Tty.truncate("foobar something very long") - assert_equal "truncate", Tty.truncate("truncate") - - # When the terminal is unsupported, we report 0 width - Tty.stubs(:width).returns 0 - assert_equal "foobar something very long", Tty.truncate("foobar something very long") - end - - def test_no_tty_formatting - $stdout.stubs(:tty?).returns false - assert_equal "", Tty.to_s - assert_equal "", Tty.red.to_s - assert_equal "", Tty.green.to_s - assert_equal "", Tty.yellow.to_s - assert_equal "", Tty.blue.to_s - assert_equal "", Tty.magenta.to_s - assert_equal "", Tty.cyan.to_s - assert_equal "", Tty.default.to_s - end - - def test_formatting - $stdout.stubs(:tty?).returns(true) - assert_equal "", Tty.to_s - assert_equal "\033[31m", Tty.red.to_s - assert_equal "\033[32m", Tty.green.to_s - assert_equal "\033[33m", Tty.yellow.to_s - assert_equal "\033[34m", Tty.blue.to_s - assert_equal "\033[35m", Tty.magenta.to_s - assert_equal "\033[36m", Tty.cyan.to_s - assert_equal "\033[39m", Tty.default.to_s - end -end diff --git a/Library/Homebrew/test/utils_spec.rb b/Library/Homebrew/test/utils_spec.rb new file mode 100644 index 000000000..b3fdedcb9 --- /dev/null +++ b/Library/Homebrew/test/utils_spec.rb @@ -0,0 +1,277 @@ +require "utils" + +describe "globally-scoped helper methods" do + let(:dir) { @dir = Pathname.new(Dir.mktmpdir) } + + after(:each) { dir.rmtree unless @dir.nil? } + + def esc(code) + /(\e\[\d+m)*\e\[#{code}m/ + end + + describe "#ofail" do + it "sets Homebrew.failed to true" do + expect { + ofail "foo" + }.to output("Error: foo\n").to_stderr + + expect(Homebrew).to have_failed + end + end + + describe "#odie" do + it "exits with 1" do + expect(self).to receive(:exit).and_return(1) + expect { + odie "foo" + }.to output("Error: foo\n").to_stderr + end + end + + describe "#pretty_installed" do + subject { pretty_installed("foo") } + + context "when $stdout is a TTY" do + before(:each) { allow($stdout).to receive(:tty?).and_return(true) } + + context "with HOMEBREW_NO_EMOJI unset" do + before(:each) { ENV.delete("HOMEBREW_NO_EMOJI") } + + it "returns a string with a colored checkmark" do + expect(subject) + .to match(/#{esc 1}foo #{esc 32}✔#{esc 0}/) + end + end + + context "with HOMEBREW_NO_EMOJI set" do + before(:each) { ENV["HOMEBREW_NO_EMOJI"] = "1" } + + it "returns a string with colored info" do + expect(subject) + .to match(/#{esc 1}foo \(installed\)#{esc 0}/) + end + end + end + + context "when $stdout is not a TTY" do + before(:each) { allow($stdout).to receive(:tty?).and_return(false) } + + it "returns plain text" do + expect(subject).to eq("foo") + end + end + end + + describe "#pretty_uninstalled" do + subject { pretty_uninstalled("foo") } + + context "when $stdout is a TTY" do + before(:each) { allow($stdout).to receive(:tty?).and_return(true) } + + context "with HOMEBREW_NO_EMOJI unset" do + before(:each) { ENV.delete("HOMEBREW_NO_EMOJI") } + + it "returns a string with a colored checkmark" do + expect(subject) + .to match(/#{esc 1}foo #{esc 31}✘#{esc 0}/) + end + end + + context "with HOMEBREW_NO_EMOJI set" do + before(:each) { ENV["HOMEBREW_NO_EMOJI"] = "1" } + + it "returns a string with colored info" do + expect(subject) + .to match(/#{esc 1}foo \(uninstalled\)#{esc 0}/) + end + end + end + + context "when $stdout is not a TTY" do + before(:each) { allow($stdout).to receive(:tty?).and_return(false) } + + it "returns plain text" do + expect(subject).to eq("foo") + end + end + end + + describe "#interactive_shell" do + let(:shell) { dir/"myshell" } + + it "starts an interactive shell session" do + IO.write shell, <<-EOS.undent + #!/bin/sh + echo called > "#{dir}/called" + EOS + + FileUtils.chmod 0755, shell + + ENV["SHELL"] = shell + + expect { interactive_shell }.not_to raise_error + expect(dir/"called").to exist + end + end + + describe "#with_custom_locale" do + it "temporarily overrides the system locale" do + ENV["LC_ALL"] = "en_US.UTF-8" + + with_custom_locale("C") do + expect(ENV["LC_ALL"]).to eq("C") + end + + expect(ENV["LC_ALL"]).to eq("en_US.UTF-8") + end + end + + describe "#run_as_not_developer" do + it "temporarily unsets HOMEBREW_DEVELOPER" do + ENV["HOMEBREW_DEVELOPER"] = "foo" + + run_as_not_developer do + expect(ENV["HOMEBREW_DEVELOPER"]).to be nil + end + + expect(ENV["HOMEBREW_DEVELOPER"]).to eq("foo") + end + end + + describe "#which" do + let(:cmd) { dir/"foo" } + + before(:each) { FileUtils.touch cmd } + + it "returns the first executable that is found" do + cmd.chmod 0744 + expect(which(File.basename(cmd), File.dirname(cmd))).to eq(cmd) + end + + it "skips non-executables" do + expect(which(File.basename(cmd), File.dirname(cmd))).to be nil + end + + it "skips malformed path and doesn't fail" do + # 'which' should not fail if a path is malformed + # see https://github.com/Homebrew/legacy-homebrew/issues/32789 for an example + cmd.chmod 0744 + + # ~~ will fail because ~foo resolves to foo's home and there is no '~' user + path = ["~~", File.dirname(cmd)].join(File::PATH_SEPARATOR) + expect(which(File.basename(cmd), path)).to eq(cmd) + end + end + + describe "#which_all" do + let(:cmd1) { dir/"foo" } + let(:cmd2) { dir/"bar/foo" } + let(:cmd3) { dir/"bar/baz/foo" } + + before(:each) do + (dir/"bar/baz").mkpath + + FileUtils.touch cmd2 + + [cmd1, cmd3].each do |cmd| + FileUtils.touch cmd + cmd.chmod 0744 + end + end + + it "returns an array of all executables that are found" do + path = [ + "#{dir}/bar/baz", + "#{dir}/baz:#{dir}", + "~baduserpath", + ].join(File::PATH_SEPARATOR) + expect(which_all("foo", path)).to eq([cmd3, cmd1]) + end + end + + specify "#which_editor" do + ENV["HOMEBREW_EDITOR"] = "vemate" + expect(which_editor).to eq("vemate") + end + + specify "#gzip" do + Dir.mktmpdir do |path| + path = Pathname.new(path) + somefile = path/"somefile" + FileUtils.touch somefile + expect(gzip(somefile)[0].to_s).to eq("#{somefile}.gz") + expect(Pathname.new("#{somefile}.gz")).to exist + end + end + + specify "#capture_stderr" do + err = capture_stderr do + $stderr.print "test" + end + + expect(err).to eq("test") + end + + describe "#pretty_duration" do + it "converts seconds to a human-readable string" do + expect(pretty_duration(1)).to eq("1 second") + expect(pretty_duration(2.5)).to eq("2 seconds") + expect(pretty_duration(42)).to eq("42 seconds") + expect(pretty_duration(240)).to eq("4 minutes") + expect(pretty_duration(252.45)).to eq("4 minutes 12 seconds") + end + end + + specify "#plural" do + expect(plural(1)).to eq("") + expect(plural(0)).to eq("s") + expect(plural(42)).to eq("s") + expect(plural(42, "")).to eq("") + end + + specify "#disk_usage_readable" do + expect(disk_usage_readable(1)).to eq("1B") + expect(disk_usage_readable(1000)).to eq("1000B") + expect(disk_usage_readable(1024)).to eq("1KB") + expect(disk_usage_readable(1025)).to eq("1KB") + expect(disk_usage_readable(4_404_020)).to eq("4.2MB") + expect(disk_usage_readable(4_509_715_660)).to eq("4.2GB") + end + + describe "#number_readable" do + it "returns a string with thousands separators" do + expect(number_readable(1)).to eq("1") + expect(number_readable(1_000)).to eq("1,000") + expect(number_readable(1_000_000)).to eq("1,000,000") + end + end + + specify "#truncate_text_to_approximate_size" do + glue = "\n[...snip...]\n" # hard-coded copy from truncate_text_to_approximate_size + n = 20 + long_s = "x" * 40 + + s = truncate_text_to_approximate_size(long_s, n) + expect(s.length).to eq(n) + expect(s).to match(/^x+#{Regexp.escape(glue)}x+$/) + + s = truncate_text_to_approximate_size(long_s, n, front_weight: 0.0) + expect(s).to eq(glue + ("x" * (n - glue.length))) + + s = truncate_text_to_approximate_size(long_s, n, front_weight: 1.0) + expect(s).to eq(("x" * (n - glue.length)) + glue) + end + + describe "#odeprecated" do + it "raises a MethodDeprecatedError" do + ENV.delete("HOMEBREW_DEVELOPER") + expect { + odeprecated( + "method", "replacement", + caller: ["#{HOMEBREW_LIBRARY}/Taps/homebrew/homebrew-core/"], + disable: true + ) + }.to raise_error(MethodDeprecatedError, %r{method.*replacement.*homebrew/homebrew-core.*homebrew/core}m) + end + end +end diff --git a/Library/Homebrew/test/utils_test.rb b/Library/Homebrew/test/utils_test.rb deleted file mode 100644 index d7c25683d..000000000 --- a/Library/Homebrew/test/utils_test.rb +++ /dev/null @@ -1,235 +0,0 @@ -require "testing_env" -require "utils" -require "tempfile" -require "utils/shell" - -class UtilTests < Homebrew::TestCase - def setup - @dir = Pathname.new(mktmpdir) - @env = ENV.to_hash - end - - def teardown - @dir.rmtree - ENV.replace @env - end - - def test_ofail - shutup { ofail "foo" } - assert Homebrew.failed? - ensure - Homebrew.failed = false - end - - def test_odie - expects(:exit).returns 1 - shutup { odie "foo" } - end - - def test_pretty_installed - $stdout.stubs(:tty?).returns false - assert_equal "foo", pretty_installed("foo") - end - - def test_pretty_uninstalled - $stdout.stubs(:tty?).returns false - assert_equal "foo", pretty_uninstalled("foo") - end - - def test_interactive_shell - mktmpdir do |path| - shell = "#{path}/myshell" - File.open(shell, "w") do |file| - file.write "#!/bin/sh\necho called > #{path}/called\n" - end - FileUtils.chmod 0755, shell - ENV["SHELL"] = shell - assert_nothing_raised { interactive_shell } - assert File.exist? "#{path}/called" - end - end - - def test_with_custom_locale - ENV["LC_ALL"] = "en_US.UTF-8" - with_custom_locale("C") do - assert_equal "C", ENV["LC_ALL"] - end - assert_equal "en_US.UTF-8", ENV["LC_ALL"] - end - - def test_run_as_not_developer - ENV["HOMEBREW_DEVELOPER"] = "foo" - run_as_not_developer do - assert_nil ENV["HOMEBREW_DEVELOPER"] - end - assert_equal "foo", ENV["HOMEBREW_DEVELOPER"] - end - - def test_put_columns_empty - out, err = capture_io do - puts Formatter.columns([]) - end - - assert_equal out, "\n" - assert_equal err, "" - end - - def test_which - cmd = @dir/"foo" - FileUtils.touch cmd - cmd.chmod 0744 - assert_equal Pathname.new(cmd), - which(File.basename(cmd), File.dirname(cmd)) - end - - def test_which_skip_non_executables - cmd = @dir/"foo" - FileUtils.touch cmd - assert_nil which(File.basename(cmd), File.dirname(cmd)) - end - - def test_which_skip_malformed_path - # 'which' should not fail if a path is malformed - # see https://github.com/Homebrew/legacy-homebrew/issues/32789 for an example - cmd = @dir/"foo" - FileUtils.touch cmd - cmd.chmod 0744 - - # ~~ will fail because ~foo resolves to foo's home and there is no '~' user - # here - assert_equal Pathname.new(cmd), - which(File.basename(cmd), "~~#{File::PATH_SEPARATOR}#{File.dirname(cmd)}") - end - - def test_which_all - (@dir/"bar/baz").mkpath - cmd1 = @dir/"foo" - cmd2 = @dir/"bar/foo" - cmd3 = @dir/"bar/baz/foo" - FileUtils.touch cmd2 - [cmd1, cmd3].each do |cmd| - FileUtils.touch cmd - cmd.chmod 0744 - end - assert_equal [cmd3, cmd1], - which_all("foo", "#{@dir}/bar/baz:#{@dir}/baz:#{@dir}:~baduserpath") - end - - def test_which_editor - ENV["HOMEBREW_EDITOR"] = "vemate" - assert_equal "vemate", which_editor - end - - def test_gzip - mktmpdir do |path| - somefile = "#{path}/somefile" - FileUtils.touch somefile - assert_equal "#{somefile}.gz", - gzip(somefile)[0].to_s - assert File.exist?("#{somefile}.gz") - end - end - - def test_capture_stderr - assert_equal "test\n", capture_stderr { $stderr.puts "test" } - end - - def test_shell_profile - ENV["SHELL"] = "/bin/sh" - assert_equal "~/.bash_profile", Utils::Shell.shell_profile - ENV["SHELL"] = "/bin/bash" - assert_equal "~/.bash_profile", Utils::Shell.shell_profile - ENV["SHELL"] = "/bin/another_shell" - assert_equal "~/.bash_profile", Utils::Shell.shell_profile - ENV["SHELL"] = "/bin/zsh" - assert_equal "~/.zshrc", Utils::Shell.shell_profile - ENV["SHELL"] = "/bin/ksh" - assert_equal "~/.kshrc", Utils::Shell.shell_profile - end - - def test_popen_read - out = Utils.popen_read("sh", "-c", "echo success").chomp - assert_equal "success", out - assert_predicate $?, :success? - end - - def test_popen_read_with_block - out = Utils.popen_read("sh", "-c", "echo success") do |pipe| - pipe.read.chomp - end - assert_equal "success", out - assert_predicate $?, :success? - end - - def test_popen_write_with_block - Utils.popen_write("grep", "-q", "success") do |pipe| - pipe.write("success\n") - end - assert_predicate $?, :success? - end - - def test_pretty_duration - assert_equal "1 second", pretty_duration(1) - assert_equal "2 seconds", pretty_duration(2.5) - assert_equal "42 seconds", pretty_duration(42) - assert_equal "4 minutes", pretty_duration(240) - assert_equal "4 minutes 12 seconds", pretty_duration(252.45) - end - - def test_plural - assert_equal "", plural(1) - assert_equal "s", plural(0) - assert_equal "s", plural(42) - assert_equal "", plural(42, "") - end - - def test_disk_usage_readable - assert_equal "1B", disk_usage_readable(1) - assert_equal "1000B", disk_usage_readable(1000) - assert_equal "1K", disk_usage_readable(1024) - assert_equal "1K", disk_usage_readable(1025) - assert_equal "4.2M", disk_usage_readable(4_404_020) - assert_equal "4.2G", disk_usage_readable(4_509_715_660) - end - - def test_number_readable - assert_equal "1", number_readable(1) - assert_equal "1,000", number_readable(1_000) - assert_equal "1,000,000", number_readable(1_000_000) - end - - def test_truncate_text_to_approximate_size - glue = "\n[...snip...]\n" # hard-coded copy from truncate_text_to_approximate_size - n = 20 - long_s = "x" * 40 - s = truncate_text_to_approximate_size(long_s, n) - assert_equal n, s.length - assert_match(/^x+#{Regexp.escape(glue)}x+$/, s) - s = truncate_text_to_approximate_size(long_s, n, front_weight: 0.0) - assert_equal glue + ("x" * (n - glue.length)), s - s = truncate_text_to_approximate_size(long_s, n, front_weight: 1.0) - assert_equal(("x" * (n - glue.length)) + glue, s) - end - - def test_odeprecated - ARGV.stubs(:homebrew_developer?).returns false - e = assert_raises(MethodDeprecatedError) do - odeprecated("method", "replacement", - caller: ["#{HOMEBREW_LIBRARY}/Taps/homebrew/homebrew-core/"], - disable: true) - end - assert_match "method", e.message - assert_match "replacement", e.message - assert_match "homebrew/homebrew-core", e.message - assert_match "homebrew/core", e.message - end - - def test_bottles_bintray - assert_equal "openssl:1.1", Utils::Bottles::Bintray.package("openssl@1.1") - assert_equal "gtkx", Utils::Bottles::Bintray.package("gtk+") - assert_equal "llvm", Utils::Bottles::Bintray.package("llvm") - - tap = Tap.new("homebrew", "bintray-test") - assert_equal "bottles-bintray-test", Utils::Bottles::Bintray.repository(tap) - end -end diff --git a/Library/Homebrew/test/version_test.rb b/Library/Homebrew/test/version_test.rb deleted file mode 100644 index e7ffbc4f6..000000000 --- a/Library/Homebrew/test/version_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -require "testing_env" - -class IntegrationCommandTestVersion < IntegrationCommandTestCase - def test_version - assert_match HOMEBREW_VERSION.to_s, - cmd("--version") - end -end diff --git a/Library/Homebrew/test/versions_test.rb b/Library/Homebrew/test/versions_test.rb index a6e922178..b6814b1d1 100644 --- a/Library/Homebrew/test/versions_test.rb +++ b/Library/Homebrew/test/versions_test.rb @@ -185,8 +185,6 @@ class VersionParsingTests < Homebrew::TestCase d = HOMEBREW_CELLAR/"foo-0.1.9" d.mkpath assert_equal version("0.1.9"), d.version - ensure - d.unlink end def test_no_version diff --git a/Library/Homebrew/test/x11_requirement_spec.rb b/Library/Homebrew/test/x11_requirement_spec.rb new file mode 100644 index 000000000..f60c8bffe --- /dev/null +++ b/Library/Homebrew/test/x11_requirement_spec.rb @@ -0,0 +1,36 @@ +require "requirements/x11_requirement" + +describe X11Requirement do + let(:default_name) { "x11" } + + describe "#name" do + it "defaults to x11" do + expect(subject.name).to eq(default_name) + end + end + + describe "#eql?" do + it "returns true if the names are equal" do + other = described_class.new(default_name) + expect(subject).to eql(other) + end + + it "and returns false if the names differ" do + other = described_class.new("foo") + expect(subject).not_to eql(other) + end + + it "returns false if the minimum version differs" do + other = described_class.new(default_name, ["2.5"]) + expect(subject).not_to eql(other) + end + end + + describe "#modify_build_environment" do + it "calls ENV#x11" do + allow(subject).to receive(:satisfied?).and_return(true) + expect(ENV).to receive(:x11) + subject.modify_build_environment + end + end +end diff --git a/Library/Homebrew/test/x11_requirement_test.rb b/Library/Homebrew/test/x11_requirement_test.rb deleted file mode 100644 index b82a59e53..000000000 --- a/Library/Homebrew/test/x11_requirement_test.rb +++ /dev/null @@ -1,31 +0,0 @@ -require "testing_env" -require "requirements/x11_requirement" - -class X11RequirementTests < Homebrew::TestCase - def test_eql_instances_are_eql - x = X11Requirement.new - y = X11Requirement.new - assert_eql x, y - assert_equal x.hash, y.hash - end - - def test_not_eql_when_hashes_differ - x = X11Requirement.new("foo") - y = X11Requirement.new - refute_eql x, y - refute_equal x.hash, y.hash - end - - def test_different_min_version - x = X11Requirement.new - y = X11Requirement.new("x11", %w[2.5]) - refute_eql x, y - end - - def test_x_env - x = X11Requirement.new - x.stubs(:satisfied?).returns(true) - ENV.expects(:x11) - x.modify_build_environment - end -end diff --git a/Library/Homebrew/utils.rb b/Library/Homebrew/utils.rb index 614d50eea..56ddfd611 100644 --- a/Library/Homebrew/utils.rb +++ b/Library/Homebrew/utils.rb @@ -10,6 +10,7 @@ require "utils/github" require "utils/hash" require "utils/inreplace" require "utils/popen" +require "utils/svn" require "utils/tty" require "time" @@ -106,7 +107,7 @@ def pretty_installed(f) if !$stdout.tty? f.to_s elsif Emoji.enabled? - "#{Tty.bold}#{f} #{Formatter.success(Emoji.tick)}#{Tty.reset}" + "#{Tty.bold}#{f} #{Formatter.success("✔")}#{Tty.reset}" else Formatter.success("#{Tty.bold}#{f} (installed)#{Tty.reset}") end @@ -116,7 +117,7 @@ def pretty_uninstalled(f) if !$stdout.tty? f.to_s elsif Emoji.enabled? - "#{Tty.bold}#{f} #{Formatter.error(Emoji.cross)}#{Tty.reset}" + "#{Tty.bold}#{f} #{Formatter.error("✘")}#{Tty.reset}" else Formatter.error("#{Tty.bold}#{f} (uninstalled)#{Tty.reset}") end @@ -421,13 +422,13 @@ end def disk_usage_readable(size_in_bytes) if size_in_bytes >= 1_073_741_824 size = size_in_bytes.to_f / 1_073_741_824 - unit = "G" + unit = "GB" elsif size_in_bytes >= 1_048_576 size = size_in_bytes.to_f / 1_048_576 - unit = "M" + unit = "MB" elsif size_in_bytes >= 1_024 size = size_in_bytes.to_f / 1_024 - unit = "K" + unit = "KB" else size = size_in_bytes unit = "B" diff --git a/Library/Homebrew/utils/git.rb b/Library/Homebrew/utils/git.rb index dfe47f890..1b4d24894 100644 --- a/Library/Homebrew/utils/git.rb +++ b/Library/Homebrew/utils/git.rb @@ -40,4 +40,9 @@ module Utils @git_path = nil @git_version = nil end + + def self.git_remote_exists(url) + return true unless git_available? + quiet_system "git", "ls-remote", url + end end diff --git a/Library/Homebrew/utils/svn.rb b/Library/Homebrew/utils/svn.rb new file mode 100644 index 000000000..fb49ac2e9 --- /dev/null +++ b/Library/Homebrew/utils/svn.rb @@ -0,0 +1,11 @@ +module Utils + def self.svn_available? + return @svn if instance_variable_defined?(:@svn) + @svn = quiet_system HOMEBREW_SHIMS_PATH/"scm/svn", "--version" + end + + def self.svn_remote_exists(url) + return true unless svn_available? + quiet_system "svn", "ls", url, "--depth", "empty" + end +end diff --git a/Library/Homebrew/version.rb b/Library/Homebrew/version.rb index 0f3cbb773..77f270dd9 100644 --- a/Library/Homebrew/version.rb +++ b/Library/Homebrew/version.rb @@ -164,7 +164,7 @@ class Version RCToken::PATTERN, PatchToken::PATTERN, NumericToken::PATTERN, - StringToken::PATTERN + StringToken::PATTERN, ) class FromURL < Version @@ -1,5 +1,5 @@ # Homebrew -Features, usage and installation instructions are [summarised on the homepage](http://brew.sh). Terminology (e.g. the difference between a Cellar, Tap, Cask and so forth) is [explained here](docs/Formula-Cookbook.md#homebrew-terminology). +Features, usage and installation instructions are [summarised on the homepage](https://brew.sh). Terminology (e.g. the difference between a Cellar, Tap, Cask and so forth) is [explained here](docs/Formula-Cookbook.md#homebrew-terminology). ## Update Bug If Homebrew was updated on Aug 10-11th 2016 and `brew update` always says `Already up-to-date.` you need to run: @@ -13,7 +13,7 @@ cd "$(brew --repo)" && git fetch && git reset --hard origin/master && brew updat 3. Or use `brew search --desc <keyword>` to browse packages from the command line. ## More Documentation -`brew help`, `man brew` or check [our documentation](https://brew.sh/brew/). +`brew help`, `man brew` or check [our documentation](http://docs.brew.sh/). ## Troubleshooting First, please run `brew update` and `brew doctor`. @@ -40,9 +40,9 @@ This is our PGP key which is valid until May 24, 2017. ## Who Are You? Homebrew's lead maintainer is [Mike McQuaid](https://github.com/mikemcquaid). -Homebrew's current maintainers are [Misty De Meo](https://github.com/mistydemeo), [Andrew Janke](https://github.com/apjanke), [Xu Cheng](https://github.com/xu-cheng), [Tomasz Pajor](https://github.com/nijikon), [Josh Hagins](https://github.com/jawshooah), [Baptiste Fontaine](https://github.com/bfontaine), [Markus Reiter](https://github.com/reitermarkus), [ilovezfs](https://github.com/ilovezfs), [Tom Schoonjans](https://github.com/tschoonj), [Uladzislau Shablinski](https://github.com/vladshablinsky), [Tim Smith](https://github.com/tdsmith) and [Alex Dunn](https://github.com/dunn). +Homebrew's current maintainers are [Alyssa Ross](https://github.com/alyssais), [Andrew Janke](https://github.com/apjanke), [Baptiste Fontaine](https://github.com/bfontaine), [Alex Dunn](https://github.com/dunn), [FX Coudert](https://github.com/fxcoudert), [ilovezfs](https://github.com/ilovezfs), [Josh Hagins](https://github.com/jawshooah), [JCount](https://github.com/jcount), [Misty De Meo](https://github.com/mistydemeo), [Tomasz Pajor](https://github.com/nijikon), [Markus Reiter](https://github.com/reitermarkus), [Tim Smith](https://github.com/tdsmith), [Tom Schoonjans](https://github.com/tschoonj), [Uladzislau Shablinski](https://github.com/vladshablinsky) and [William Woodruff](https://github.com/woodruffw). -Former maintainers with significant contributions include [Martin Afanasjew](https://github.com/UniqMartin), [Dominyk Tiller](https://github.com/DomT4), [Brett Koonce](https://github.com/asparagui), [Jack Nagel](https://github.com/jacknagel), [Adam Vandenberg](https://github.com/adamv) and Homebrew's creator: [Max Howell](https://github.com/mxcl). +Former maintainers with significant contributions include [Xu Cheng](https://github.com/xu-cheng), [Martin Afanasjew](https://github.com/UniqMartin), [Dominyk Tiller](https://github.com/DomT4), [Brett Koonce](https://github.com/asparagui), [Jack Nagel](https://github.com/jacknagel), [Adam Vandenberg](https://github.com/adamv) and Homebrew's creator: [Max Howell](https://github.com/mxcl). ## Community - [discourse.brew.sh (forum)](http://discourse.brew.sh) @@ -61,15 +61,23 @@ Please consider a regular donation through Patreon: [](https://www.patreon.com/homebrew) ## Sponsors -Our CI infrastructure was paid for by [our Kickstarter supporters](http://docs.brew.sh/Kickstarter-Supporters.html). +Our Xserve ESXi boxes for CI are hosted by [MacStadium](https://www.macstadium.com). -Our CI infrastructure is hosted by [The Positive Internet Company](http://www.positive-internet.com). +[](https://www.macstadium.com) -Our bottles (binary packages) are hosted by Bintray. +Our Mac Minis for CI were paid for by [our Kickstarter supporters](http://docs.brew.sh/Kickstarter-Supporters.html). + +Our Mac Minis for CI are hosted by [The Positive Internet Company](http://www.positive-internet.com). + +Our bottles (binary packages) are hosted by [Bintray](https://bintray.com/homebrew). [](https://bintray.com/homebrew) -Secure password storage and syncing provided by [1Password for Teams](https://1password.com/teams/) by AgileBits +[Our website](https://brew.sh) is hosted by [Netlify](https://www.netlify.com). + +[](https://www.netlify.com) + +Secure password storage and syncing provided by [1Password for Teams](https://1password.com/teams/) by [AgileBits](https://agilebits.com) [](https://agilebits.com) diff --git a/completions/zsh/_brew b/completions/zsh/_brew index 2d8e1b42b..04cf56f70 100644 --- a/completions/zsh/_brew +++ b/completions/zsh/_brew @@ -88,6 +88,7 @@ __brew_common_commands() { 'doctor:audits your installation for common issues' 'edit:edit a formula' 'fetch:download formula resources to the cache' + 'formula:the path for a formula' 'gist-logs:generate a gist of the full build logs' 'home:visit the homepage of a formula or the brew project' 'info:information about a formula' @@ -366,6 +367,11 @@ _brew_fetch() { '*:formula:__brew_formulae' } +# brew formula formula: +_brew_formula() { + __brew_formulae +} + # brew gist-logs [--new-issue|-n] formula _brew_gist_logs() { _arguments \ @@ -678,7 +684,7 @@ _brew_test_bot() { } # brew tests [-v] [--coverage] [--generic] [--no-compat] -# [--only=test_script/test_method] [--seed seed] [--trace] [--online] +# [--only=test_script:test_method] [--seed seed] [--trace] [--online] # [--official-cmd-taps]: _brew_tests() { _arguments \ diff --git a/docs/Acceptable-Formulae.md b/docs/Acceptable-Formulae.md index 9f4fb45db..24dd7a7c4 100644 --- a/docs/Acceptable-Formulae.md +++ b/docs/Acceptable-Formulae.md @@ -38,7 +38,7 @@ There are exceptions: | emacs, vim | [Too popular to move to dupes](https://github.com/Homebrew/homebrew/pull/21594#issuecomment-21968819) | | subversion | Originally added for 10.5, but people want the latest version | | libcurl | Some formulae require a newer version than macOS provides | -| openssl | macOS's openssl is deprecated & outdated. | +| openssl | macOS's openssl is deprecated & outdated | | libxml2 | Historically, macOS's libxml2 has been buggy | We also maintain [a tap](https://github.com/Homebrew/homebrew-dupes) that @@ -74,7 +74,7 @@ due to upstream changes and we can’t provide [bottles](Bottles.md) for them. ### Bindings First check that there is not already a binding available via [`gem`](https://rubygems.org/) or [`pip`](http://www.pip-installer.org/) -etc.. +etc. If not, then put bindings in the formula they bind to. This is more useful to people. Just install the stuff! Having to faff around with diff --git a/docs/Brew-Test-Bot-For-Core-Contributors.md b/docs/Brew-Test-Bot-For-Core-Contributors.md index f4c9a0ec6..3ed86c706 100644 --- a/docs/Brew-Test-Bot-For-Core-Contributors.md +++ b/docs/Brew-Test-Bot-For-Core-Contributors.md @@ -4,13 +4,13 @@ If a build has run and passed on `brew test-bot` then it can be used to quickly There are two types of Jenkins jobs you will interact with: -## [Homebrew Pull Requests](https://bot.brew.sh/job/Homebrew%20Core%20Pull%20Requests/) +## [Homebrew Core Pull Requests](https://bot.brew.sh/job/Homebrew%20Core/) This job automatically builds any pull requests submitted to Homebrew/homebrew-core. On success or failure it updates the pull request status (see more details on the [main Brew Test Bot documentation page](Brew-Test-Bot.md)). On a successful build it automatically uploads bottles. ## [Homebrew Testing](https://bot.brew.sh/job/Homebrew%20Testing/) -This job is manually triggered to run [`brew test-bot`](https://github.com/Homebrew/brew/blob/master/Library/Homebrew/dev-cmd/test-bot.rb) with user-specified parameters. On a successful build it automatically uploads bottles. +This job is manually triggered to run [`brew test-bot`](https://github.com/Homebrew/homebrew-test-bot/blob/master/cmd/brew-test-bot.rb) with user-specified parameters. On a successful build it automatically uploads bottles. -You can manually start this job with parameters to run [`brew test-bot`](https://github.com/Homebrew/brew/blob/master/Library/Homebrew/dev-cmd/test-bot.rb) with the same parameters. It's often useful to pass a pull request URL, a commit URL, a commit SHA-1 and/or formula names to have `brew-test-bot` test them, report the results and produce bottles. +You can manually start this job with parameters to run [`brew test-bot`](https://github.com/Homebrew/homebrew-test-bot/blob/master/cmd/brew-test-bot.rb) with the same parameters. It's often useful to pass a pull request URL, a commit URL, a commit SHA-1 and/or formula names to have `brew-test-bot` test them, report the results and produce bottles. ## Bottling To pull and bottle a pull request with `brew pull`: diff --git a/docs/Brew-Test-Bot.md b/docs/Brew-Test-Bot.md index db39327fa..484fa3275 100644 --- a/docs/Brew-Test-Bot.md +++ b/docs/Brew-Test-Bot.md @@ -3,9 +3,9 @@ `brew test-bot` is the name for the automated review and testing system funded by [our Kickstarter in 2013](https://www.kickstarter.com/projects/homebrew/brew-test-bot). -It comprises of four Mac Minis running in a data centre in England which host +It comprises four Mac Minis running in a data centre in England which host [a Jenkins instance at https://bot.brew.sh](https://bot.brew.sh) and run the -[`brew test-bot.rb`](https://github.com/Homebrew/brew/blob/master/Library/Homebrew/dev-cmd/test-bot.rb) +[`brew test-bot.rb`](https://github.com/Homebrew/homebrew-test-bot/blob/master/cmd/brew-test-bot.rb) Ruby script to perform automated testing of commits to the master branch, pull requests and custom builds requested by maintainers. @@ -15,7 +15,7 @@ The bot automatically builds pull requests and updates their status depending on the result of the job. For example, a job which has been queued but not yet started will have a -section in the pull-request that looks like this: +section in the pull request that looks like this:  diff --git a/docs/Common-Issues.md b/docs/Common-Issues.md index 8da622ab4..e8b48751d 100644 --- a/docs/Common-Issues.md +++ b/docs/Common-Issues.md @@ -7,8 +7,7 @@ You need to have the Xcode Command Line Utilities installed (and updated): run ` (In OS X prior to 10.9, the "Command Line Tools" package can alternatively be installed from within Xcode. `⌘,` will get you to preferences. Visit the "Downloads" tab and hit the install button next to "Command Line Tools".) ### Ruby `bad interpreter: /usr/bin/ruby^M: no such file or directory` -You cloned with git, and your git configuration is set to use Windows line endings. See this page: https://help.github.com/articles/dealing-with-line-endings - +You cloned with git, and your git configuration is set to use Windows line endings. See this page: <https://help.github.com/articles/dealing-with-line-endings> ### Ruby `bad interpreter: /usr/bin/ruby` You don't have a `/usr/bin/ruby` or it is not executable. It's not recommended to let this persist, you'd be surprised how many .apps, tools and scripts expect your macOS provided files and directories to be *unmodified* since macOS was installed. diff --git a/docs/External-Commands.md b/docs/External-Commands.md index 59622bd3a..e2dafdce8 100644 --- a/docs/External-Commands.md +++ b/docs/External-Commands.md @@ -47,15 +47,15 @@ brew tap youtux/livecheck ``` ### brew-gem -Install any gem package into a self-contained Homebrew cellar location: [https://github.com/sportngin/brew-gem](https://github.com/sportngin/brew-gem). +Install any gem package into a self-contained Homebrew cellar location: <https://github.com/sportngin/brew-gem> Note this can also be installed with `brew install brew-gem`. ### brew-growl -Get Growl notifications for Homebrew https://github.com/secondplanet/brew-growl +Get Growl notifications for Homebrew: <https://github.com/secondplanet/homebrew-growl> ### brew-services -Simple support to start formulae using launchctl, has out of the box support for any formula which defines `startup_plist` (e.g. mysql, postgres, redis u.v.m.): [https://github.com/Homebrew/homebrew-services](https://github.com/Homebrew/homebrew-services) +Simple support to start formulae using launchctl, has out of the box support for any formula which defines `startup_plist` (e.g. mysql, postgres, redis u.v.m.): <https://github.com/Homebrew/homebrew-services> Install using: ```sh diff --git a/docs/FAQ.md b/docs/FAQ.md index 7a32cf926..7527289dc 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -81,13 +81,12 @@ including how to set this across reboots. If you’re pre-Mountain Lion, alternative](https://developer.apple.com/legacy/library/qa/qa1067/_index.html). ## How do I contribute to Homebrew? -Read [CONTRIBUTING.md](/CONTRIBUTING.md). +Read [CONTRIBUTING.md](https://github.com/Homebrew/brew/blob/master/CONTRIBUTING.md). ## Why do you compile everything? Homebrew provides pre-compiled versions for many formulae. These pre-compiled versions are referred to as **bottles** and are available -at: -[https://bintray.com/homebrew/bottles](https://bintray.com/homebrew/bottles). +at <https://bintray.com/homebrew/bottles>. If available, bottled binaries will be used by default except under the following conditions: diff --git a/docs/Formula-Cookbook.md b/docs/Formula-Cookbook.md index bb3ad33dc..6b4678f90 100644 --- a/docs/Formula-Cookbook.md +++ b/docs/Formula-Cookbook.md @@ -288,13 +288,13 @@ Name the formula like the project markets the product. So it’s `pkg-config`, n The only exception is stuff like “Apache Ant”. Apache sticks “Apache” in front of everything, but we use the formula name `ant`. We only include the prefix in cases like *GNUplot* (because it’s part of the name) and *GNU Go* (because everyone calls it “GNU go”—nobody just calls it “Go”). The word “Go” is too common and there are too many implementations of it. -If you’re not sure about the name check the homepage, and check the Wikipedia page and [what Debian call it](https://www.debian.org/distrib/packages). +If you’re not sure about the name check the homepage, and check the Wikipedia page and [what Debian calls it](https://www.debian.org/distrib/packages). -Where Homebrew already has a formula called `foo` we typically do not accept requests to replace that formula with something else also named `foo`. This is to avoid both confusing and surprising users’ expectation. +Where Homebrew already has a formula called `foo` we typically do not accept requests to replace that formula with something else also named `foo`. This is to avoid both confusing and surprising users’ expectations. When two formulae share an upstream name, e.g. [`AESCrypt`](https://github.com/Homebrew/homebrew-core/blob/master/Formula/aescrypt.rb) and [`AESCrypt`](https://github.com/Homebrew/homebrew-core/blob/master/Formula/aescrypt-packetizer.rb) the newer formula must typically adapt the name to avoid conflict with the current formula. -If you’re *still* not sure, just commit. We’ll apply some arbitrary rule and make a decision :wink:. +If you’re *still* not sure, just commit. We’ll apply some arbitrary rule and make a decision 😉. When importing classes, Homebrew will require the formula and then create an instance of the class. It does this by assuming the formula name can be directly converted to the class name using a `regexp`. The rules are simple: @@ -359,6 +359,7 @@ Now, please [open a pull request](http://docs.brew.sh/How-To-Open-a-Homebrew-Pul * Keep merge commits out of the pull request # Convenience Tools + ## Messaging Three commands are provided for displaying informational messages to the user: @@ -783,6 +784,8 @@ The symlinks created by `install_symlink` are guaranteed to be relative. `ln_s` For example, Ruby 1.9’s gems should be installed to `var/lib/ruby/` so that gems don’t need to be reinstalled when upgrading Ruby. You can usually do this with symlink trickery, or *better* a configure option. +Another example would be configuration files that should not be overwritten on package upgrades. If after installation you find that to-be-persisted configuration files are not copied but instead *symlinked* into `/usr/local/etc/` from the Cellar, this can often be rectified by passing an appropriate argument to the package’s configure script. That argument will vary depending on a given package’s configure script and/or Makefile, but one example might be: `--sysconfdir=#{etc}` + ### launchd plist files Homebrew provides two Formula methods for launchd plist files. [`plist_name`](http://www.rubydoc.info/github/Homebrew/brew/master/Formula#plist_name-instance_method) will return e.g. `homebrew.mxcl.<formula>` and [`plist_path`](http://www.rubydoc.info/github/Homebrew/brew/master/Formula#plist_path-instance_method) will return e.g. `/usr/local/Cellar/foo/0.1/homebrew.mxcl.foo.plist`. diff --git a/docs/Gems,-Eggs-and-Perl-Modules.md b/docs/Gems,-Eggs-and-Perl-Modules.md index 770d770f6..f86124f66 100644 --- a/docs/Gems,-Eggs-and-Perl-Modules.md +++ b/docs/Gems,-Eggs-and-Perl-Modules.md @@ -81,7 +81,7 @@ or use this: **However all versions of RubyGems before 1.3.6 are buggy** and ignore the above setting. Sadly a fresh install of Snow Leopard comes with -1.3.5. Currently the only known way to get round this is to upgrade +1.3.5. Currently the only known way to get around this is to upgrade rubygems as root: `sudo gem update --system` diff --git a/docs/Homebrew-and-Python.md b/docs/Homebrew-and-Python.md index e2f59c322..2e9e643b5 100644 --- a/docs/Homebrew-and-Python.md +++ b/docs/Homebrew-and-Python.md @@ -58,7 +58,7 @@ Homebrew builds bindings against the first `python` (and `python-config`) in you **Warning!** Python may crash (see [Common Issues](Common-Issues.md)) if you `import <module>` from a brewed Python if you ran `brew install <formula_with_python_bindings>` against the system Python. If you decide to switch to the brewed Python, then reinstall all formulae with python bindings (e.g. `pyside`, `wxwidgets`, `pygtk`, `pygobject`, `opencv`, `vtk` and `boost-python`). ## Policy for non-brewed Python bindings -These should be installed via `pip install <x>`. To discover, you can use `pip search` or <https://pypi.python.org/pypi>. (**Note:** System Python does not provide `pip`. Follow the instructions at https://pip.readthedocs.org/en/stable/installing/#install-pip to install it for your system Python if you would like it.) +These should be installed via `pip install <x>`. To discover, you can use `pip search` or <https://pypi.python.org/pypi>. (**Note:** System Python does not provide `pip`. Follow the instructions at <https://pip.readthedocs.io/en/stable/installing/#install-pip> to install it for your system Python if you would like it.) ## Brewed Python modules diff --git a/docs/How-To-Open-a-Homebrew-Pull-Request.md b/docs/How-To-Open-a-Homebrew-Pull-Request.md index ef6091e2c..104fc2829 100644 --- a/docs/How-To-Open-a-Homebrew-Pull-Request.md +++ b/docs/How-To-Open-a-Homebrew-Pull-Request.md @@ -25,7 +25,7 @@ Depending on the change you want to make, you need to send the pull request to t 3. Add your pushable forked repository with `git remote add <YOUR_USERNAME> https://github.com/<YOUR_USERNAME>/homebrew-core.git` * `<YOUR_USERNAME>` is your GitHub username, not your local machine username. -For formulae in central taps other than `homebrew/core`, such as `homebrew/science` or `homebrew/games`, substitute that tap's name for `homebrew/core` in each step, and alter the GitHub repository URLs as necessary. +For formulae in central taps other than `homebrew/core`, such as `homebrew/science` or `homebrew/nginx`, substitute that tap's name for `homebrew/core` in each step, and alter the GitHub repository URLs as necessary. ## Create your pull request from a new branch @@ -43,7 +43,7 @@ To make a new branch and submit it for review, create a GitHub pull request with 4. `brew audit --strict <CHANGED_FORMULA>` 6. Make a separate commit for each changed formula with `git add` and `git commit`. 7. Upload your new commits to the branch on your fork with `git push --set-upstream <YOUR_USERNAME> <YOUR_BRANCH_NAME>`. -8. Go to the relevant repository (e.g. https://github.com/Homebrew/brew, https://github.com/Homebrew/homebrew-core, etc.) and create a pull request to request review and merging of the commits in your pushed branch. Explain why the change is needed and, if fixing a bug, how to reproduce the bug. Make sure you have done each step in the checklist that appears in your new PR. +8. Go to the relevant repository (e.g. <https://github.com/Homebrew/brew>, <https://github.com/Homebrew/homebrew-core>, etc.) and create a pull request to request review and merging of the commits in your pushed branch. Explain why the change is needed and, if fixing a bug, how to reproduce the bug. Make sure you have done each step in the checklist that appears in your new PR. * Please note that our preferred commit message format for simple version updates is "`<FORMULA_NAME> <NEW_VERSION>`", e.g. "`source-highlight 3.1.8`". `devel` version updates should have the commit message suffixed with `(devel)`, e.g. "`nginx 1.9.1 (devel)`". If updating both stable and `devel`, the format should be a concatenation of these two forms, e.g. "`x264 r2699, r2705 (devel)`". 9. Await feedback or a merge from Homebrew's maintainers. We typically respond to all PRs within a couple days, but it may take up to a week, depending on the maintainers' workload. 10. Thank you! diff --git a/docs/Installation.md b/docs/Installation.md index dbe8b9917..4780e76ef 100644 --- a/docs/Installation.md +++ b/docs/Installation.md @@ -1,7 +1,7 @@ # Installation The suggested and easiest way to install Homebrew is on the -[homepage](http://brew.sh). +[homepage](https://brew.sh). The standard script installs Homebrew to `/usr/local` so that [you don’t need sudo](FAQ.md) when you @@ -55,5 +55,5 @@ Apple Developer account on older versions of Mac OS X. Sign up for free [here](https://developer.apple.com/register/index.action). <a name="4"><sup>4</sup></a> The one-liner installation method found on -[brew.sh](http://brew.sh) requires a Bourne-compatible shell (e.g. bash or +[brew.sh](https://brew.sh) requires a Bourne-compatible shell (e.g. bash or zsh). Notably, fish, tcsh and csh will not work. diff --git a/docs/Interesting-Taps-&-Forks.md b/docs/Interesting-Taps-&-Forks.md index a5c609441..de9b8809e 100644 --- a/docs/Interesting-Taps-&-Forks.md +++ b/docs/Interesting-Taps-&-Forks.md @@ -1,7 +1,7 @@ # Interesting Taps & Forks A Tap is homebrew-speak for a git repository containing extra formulae. -Homebrew has the capability to add (and remove) multiple taps to your local installation with the `brew tap` and `brew untap` command. Type `man brew` in your Terminal. The main repository https://github.com/Homebrew/homebrew-core, often called `homebrew/core`, is always built-in. +Homebrew has the capability to add (and remove) multiple taps to your local installation with the `brew tap` and `brew untap` command. Type `man brew` in your Terminal. The main repository <https://github.com/Homebrew/homebrew-core>, often called `homebrew/core`, is always built-in. ## Main Taps diff --git a/docs/Node-for-Formula-Authors.md b/docs/Node-for-Formula-Authors.md index c78668a58..83516da93 100644 --- a/docs/Node-for-Formula-Authors.md +++ b/docs/Node-for-Formula-Authors.md @@ -14,9 +14,9 @@ where `libexec` is the destination prefix (usually the `libexec` variable). # Download URL -If the Node module is also available on the npm registry, we prefer npm hosted release tarballs over GitHub (or elsewhere) hosted source tarballs. The advantages of these tarballs are that they doesn't include the files from the `.npmignore` (such as tests) resulting in a smaller download size and that a possibly transpilation step is already done (e.g. no need to compile CoffeeScript files as a build step). +If the Node module is also available on the npm registry, we prefer npm hosted release tarballs over GitHub (or elsewhere) hosted source tarballs. The advantages of these tarballs are that they don't include the files from the `.npmignore` (such as tests) resulting in a smaller download size and that any possible transpilation step is already done (e.g. no need to compile CoffeeScript files as a build step). -The npm registry URLs have usually the format of: +The npm registry URLs usually have the format of: ``` https://registry.npmjs.org/<name>/-/<name>-<version>.tgz @@ -26,33 +26,33 @@ Alternatively you could curl the JSON at `https://registry.npmjs.org/<name>` and # Dependencies -Node modules, which are compatible with the latest Node version should declare a dependencies on the `node` formula. +Node modules which are compatible with the latest Node version should declare a dependency on the `node` formula. ```ruby depends_on "node" ``` -If your formula requires to be executed with an older Node version you must vendor this older Node version as done in the [`kibana` formula](https://github.com/Homebrew/homebrew-core/blob/c6202f91a129e2f994d904f299a308cc6fbd58e5/Formula/kibana.rb). +If your formula requires being executed with an older Node version you must vendor this older Node version as done in the [`kibana` formula](https://github.com/Homebrew/homebrew-core/blob/c6202f91a129e2f994d904f299a308cc6fbd58e5/Formula/kibana.rb). ### Special requirements for native addons -If your node module is a native addon or has a native addon somewhere in it's dependency tree you have to declare an additional dependency. Since the compilation of the native addon results in a invocation of `node-gyp` we need an additional build time dependency on `:python` (because gyp depends on Python 2.7). +If your node module is a native addon or has a native addon somewhere in its dependency tree you have to declare an additional dependency. Since the compilation of the native addon results in a invocation of `node-gyp` we need an additional build time dependency on `:python` (because gyp depends on Python 2.7). ```ruby depends_on :python => :build ``` -Please also note, that such a formula would only be compatible with the same Node major version it originally was compiled with. This means that we need to revision every formula with a Node native addon with every major version bump of the `node` formula. To make sure we don't overlook your formula on a Node major version bump, write a meaningful test which would fail in such a case (invoked with an ABI incompatible Node version). +Please also note that such a formula would only be compatible with the same Node major version it originally was compiled with. This means that we need to revision every formula with a Node native addon with every major version bump of the `node` formula. To make sure we don't overlook your formula on a Node major version bump, write a meaningful test which would fail in such a case (invoked with an ABI incompatible Node version). # Installation Node modules should be installed to `libexec`. This prevents the Node modules from contaminating the global `node_modules`, which is important so that npm doesn't try to manage Homebrew-installed Node modules. -In the following we distinguish between 2 type of Node module using formulae: +In the following we distinguish between two types of Node modules using formulae: * formulae for standard Node modules compatible with npm's global module format which should use [`std_npm_install_args`](#installing-global-style-modules-with-std_npm_install_args-to-libexec) (like [`azure-cli`](https://github.com/Homebrew/homebrew-core/blob/d93fe9ba3bcc9071b699c8da4e7d733518d3337e/Formula/azure-cli.rb) or [`autocode`](https://github.com/Homebrew/homebrew-core/blob/1a670a6269e1e07f86683c2d164977c9bd8a3fb6/Formula/autocode.rb)) and -* formulae were the `npm install` step is only one of multiple not exclusively Node related install steps (not compatible with npm's global module format) which have to use [`local_npm_install_args`](#installing-module-dependencies-locally-with-local_npm_install_args) (like [`elixirscript`](https://github.com/Homebrew/homebrew-core/blob/ec1e40d37e81af63122a354f0101c377f6a4e66d/Formula/elixirscript.rb) or [`kibana`](https://github.com/Homebrew/homebrew-core/blob/c6202f91a129e2f994d904f299a308cc6fbd58e5/Formula/kibana.rb)) +* formulae where the `npm install` step is only one of multiple not exclusively Node related install steps (not compatible with npm's global module format) which have to use [`local_npm_install_args`](#installing-module-dependencies-locally-with-local_npm_install_args) (like [`elixirscript`](https://github.com/Homebrew/homebrew-core/blob/ec1e40d37e81af63122a354f0101c377f6a4e66d/Formula/elixirscript.rb) or [`kibana`](https://github.com/Homebrew/homebrew-core/blob/c6202f91a129e2f994d904f299a308cc6fbd58e5/Formula/kibana.rb)) -Both methods have in common, that they are setting the correct environment for using npm inside Homebrew up and returning the arguments for invoking `npm install` for their specific use cases. This includes fixing an important edge case with the npm cache (Caused by Homebrew's redirection of `$HOME` during the build and test process) by using our own custom `npm_cache` inside `HOMEBREW_CACHE`, which would otherwise result in very long build times and high disk space usage. +Both methods have in common that they are setting the correct environment for using npm inside Homebrew and are returning the arguments for invoking `npm install` for their specific use cases. This includes fixing an important edge case with the npm cache (caused by Homebrew's redirection of `$HOME` during the build and test process) by using our own custom `npm_cache` inside `HOMEBREW_CACHE`, which would otherwise result in very long build times and high disk space usage. To use them you have to require the Node language module at the beginning of your formula file with: @@ -62,13 +62,13 @@ require "language/node" ### Installing global style modules with `std_npm_install_args` to libexec -In your formula's `install` method, simply cd to the top level of your Node module if necessary and than use `system` to invoke `npm install` with `Language::Node.std_npm_install_args` like: +In your formula's `install` method, simply cd to the top level of your Node module if necessary and then use `system` to invoke `npm install` with `Language::Node.std_npm_install_args` like: ```ruby system "npm", "install", *Language::Node.std_npm_install_args(libexec) ``` -This will install your Node module in npm's global module style with a custom prefix to `libexec`. All your modules executable will be automatically resolved by npm into `libexec/"bin"` for you, which is not symlinked into Homebrew's prefix. We need to make sure these are installed. Do this with we need to symlink all executables to `bin` with: +This will install your Node module in npm's global module style with a custom prefix to `libexec`. All your modules' executables will be automatically resolved by npm into `libexec/"bin"` for you, which is not symlinked into Homebrew's prefix. We need to make sure these are installed. To do this we need to symlink all executables to `bin` with: ```ruby bin.install_symlink Dir["#{libexec}/bin/*"] @@ -76,13 +76,13 @@ bin.install_symlink Dir["#{libexec}/bin/*"] ### Installing module dependencies locally with `local_npm_install_args` -In your formula's `install` method, do any installation steps which need to be done before the `npm install` step and than cd to the top level of the included Node module. Then, use `system` with `Language::Node.local_npm_install_args` to invoke `npm install` like: +In your formula's `install` method, do any installation steps which need to be done before the `npm install` step and then cd to the top level of the included Node module. Then, use `system` with `Language::Node.local_npm_install_args` to invoke `npm install` like: ```ruby system "npm", "install", *Language::Node.local_npm_install_args ``` -This will install all of your Node modules dependencies to your local build path. You can now continue with your build steps and take care of the installation into the Homebrew `prefix` by your own, following the [general Homebrew formula instructions](https://github.com/Homebrew/brew/blob/master/docs/Formula-Cookbook.md). +This will install all of your Node modules dependencies to your local build path. You can now continue with your build steps and take care of the installation into the Homebrew `prefix` on your own, following the [general Homebrew formula instructions](https://github.com/Homebrew/brew/blob/master/docs/Formula-Cookbook.md). # Example diff --git a/docs/Prose-Style-Guidelines.md b/docs/Prose-Style-Guidelines.md index 1d8e2b0fc..7da21d355 100644 --- a/docs/Prose-Style-Guidelines.md +++ b/docs/Prose-Style-Guidelines.md @@ -44,8 +44,8 @@ We prefer: * More generally, parallel list item structure * Capitalize all list items if you want, even if they're not complete sentences; just be consistent within each list, and preferably, throughout the whole page * Use a subordinate list item instead of dropping a multi-sentence paragraph-long item into a list of sentence fragments -* Prefer Markdown over other markup formats unless their specific features are needed. -* GitHub flavored Markdown. GitHub's implementation is the standard, period. +* Prefer Markdown over other markup formats unless their specific features are needed + * GitHub Flavored Markdown. GitHub's implementation is the standard, period. ### Typographical conventions diff --git a/docs/Python-for-Formula-Authors.md b/docs/Python-for-Formula-Authors.md index 93830a6c7..0867e8dd8 100644 --- a/docs/Python-for-Formula-Authors.md +++ b/docs/Python-for-Formula-Authors.md @@ -4,7 +4,7 @@ This document explains how to successfully use Python in a Homebrew formula. Homebrew draws a distinction between Python **applications** and Python **libraries**. The difference is that users generally do not care that applications are written in Python; it is unusual that a user would expect to be able to `import foo` after installing an application. Examples of applications are `ansible` and `jrnl`. -Python libraries exist to be imported from other Python modules; they are often dependencies of Python applications. They are usually no more than incidentally useful from a Terminal.app command line. Examples of libraries are `py2cairo` and the bindings that are installed by `protobuf --with-python`. +Python libraries exist to be imported by other Python modules; they are often dependencies of Python applications. They are usually no more than incidentally useful from a Terminal.app command line. Examples of libraries are `py2cairo` and the bindings that are installed by `protobuf --with-python`. Bindings are a special case of libraries that allow Python code to interact with a library or application implemented in another language. @@ -22,7 +22,7 @@ where `prefix` is the destination prefix (usually `libexec` or `prefix`). # Python module dependencies -In general, applications should unconditionally bundle all of their dependencies and libraries should install any unsatisfied dependencies; these strategies are discussed in depth in the following sections. +In general, applications should unconditionally bundle all of their dependencies and libraries and should install any unsatisfied dependencies; these strategies are discussed in depth in the following sections. In the rare instance that this proves impractical, you can specify a Python module as an external dependency using the syntax: @@ -49,9 +49,9 @@ Applications that are compatible with Python 2 **should** use the Apple-provided ```ruby depends_on :python if MacOS.version <= :snow_leopard ``` -No explicit Python dependency is needed on recent OS versions since /usr/bin is always in `PATH` for Homebrew formulæ; on Leopard and older, the python in `PATH` is used if it's at least version 2.7, or else Homebrew's python is installed. +No explicit Python dependency is needed on recent OS versions since /usr/bin is always in `PATH` for Homebrew formulae; on Leopard and older, the python in `PATH` is used if it's at least version 2.7, or else Homebrew's python is installed. -Formulæ for apps that require Python 3 **should** declare an unconditional dependency on `:python3`, which will cause the formula to use the first python3 discovered in `PATH` at install time (or install Homebrew's if there isn't one). These apps **must** work with the current Homebrew python3 formula. +Formulae for apps that require Python 3 **should** declare an unconditional dependency on `:python3`, which will cause the formula to use the first python3 discovered in `PATH` at install time (or install Homebrew's if there isn't one). These apps **must** work with the current Homebrew python3 formula. ## Installing @@ -183,7 +183,7 @@ Sometimes we have to `inreplace` a `Makefile` to use our prefix for the python b Libraries **should** declare a dependency on `:python` or `:python3` as appropriate, which will respectively cause the formula to use the first python or python3 discovered in `PATH` at install time. If a library supports both Python 2.x and Python 3.x, the `:python` dependency **should** be `:recommended` (i.e. built by default) and the :python3 dependency should be `:optional`. Python 2.x libraries **must** function when they are installed against either the system Python or Homebrew Python. -Formulæ that declare a dependency on `:python` will always be bottled against Homebrew's python, since we cannot in general build binary packages that can be imported from both Pythons. Users can add `--build-from-source` after `brew install` to compile against whichever python is in `PATH`. +Formulae that declare a dependency on `:python` will always be bottled against Homebrew's python, since we cannot in general build binary packages that can be imported from both Pythons. Users can add `--build-from-source` after `brew install` to compile against whichever python is in `PATH`. ## Installing @@ -213,7 +213,7 @@ Distribute (not to be confused with distutils) is an obsolete fork of setuptools ## What is `--single-version-externally-managed`? -`--single-version-externally-managed` ("SVEM") is a setuptools-only [argument to setup.py install](https://pythonhosted.org/setuptools/setuptools.html#install-run-easy-install-or-old-style-installation). The primary effect of SVEM is to use distutils to perform the install instead of using setuptools' `easy_install`. +`--single-version-externally-managed` ("SVEM") is a setuptools-only [argument to setup.py install](http://setuptools.readthedocs.io/en/latest/setuptools.html?#install-run-easy-install-or-old-style-installation). The primary effect of SVEM is to use distutils to perform the install instead of using setuptools' `easy_install`. `easy_install` does a few things that we need to avoid: diff --git a/docs/Querying-Brew.md b/docs/Querying-Brew.md index 6d37cb588..c5a2d9aeb 100644 --- a/docs/Querying-Brew.md +++ b/docs/Querying-Brew.md @@ -31,9 +31,9 @@ The schema itself is not currently documented outside of the code that generates ## Examples -_The top-level element of the JSON is always an array, so the `map` operator is used to act on the data._ +_The top-level element of the JSON output is always an array, so the `map` operator is used to act on the data._ -### Prety-print a single formula's info +### Pretty-print a single formula's info `brew info --json=v1 tig | jq .` @@ -63,6 +63,6 @@ To find the names of normal (not keg-only) formulae that are installed, but not ## Concluding remarks -Using the JSON output, queries can be made against Homebrew with less risk of being broken due to Homebrew code changes, and without needing to understand Homebrew's ruby internals. +Using the JSON output, queries can be made against Homebrew with less risk of being broken due to Homebrew code changes, and without needing to understand Homebrew's Ruby internals. -If the JSON does not provide some information that it ought to, please submit request, preferably with a patch to add the desired information. +If the JSON output does not provide some information that it ought to, please submit a request, preferably with a patch to add the desired information. diff --git a/docs/Tips-N'-Tricks.md b/docs/Tips-N'-Tricks.md index 8f67c9ca8..e6e18ca9e 100644 --- a/docs/Tips-N'-Tricks.md +++ b/docs/Tips-N'-Tricks.md @@ -5,7 +5,7 @@ The supported method of installing specific versions of some formulae is to see if there is a versions formula like e.g. `gcc@6` available. If the version you’re looking for isn’t available, consider [opening a pull request](How-To-Open-a-Homebrew-Pull-Request.md)! -### Installing directly from pull-requests +### Installing directly from pull requests You can [browse pull requests](https://github.com/Homebrew/homebrew-core/pulls) and install through the direct link. For example Python 3.3.0 pull request [Homebrew/homebrew#15199](https://github.com/Homebrew/homebrew/pull/15199) diff --git a/docs/Versions.md b/docs/Versions.md index 9e679db7d..6c6438144 100644 --- a/docs/Versions.md +++ b/docs/Versions.md @@ -1,6 +1,6 @@ # Versions -Now that [Homebrew/versions](https://github.com/homebrew/homebrew-versions) has been deprecated [Homebrew/core](https://github.com/homebrew/homebrew-core) supports multiple versions of formulae with a new naming format. +Now that [Homebrew/versions](https://github.com/homebrew/homebrew-versions) has been deprecated, [Homebrew/core](https://github.com/homebrew/homebrew-core) supports multiple versions of formulae with a new naming format. In [Homebrew/versions](https://github.com/homebrew/homebrew-versions) the formula for GCC 6 was named `gcc6.rb` and began `class Gcc6 < Formula`. In [Homebrew/core](https://github.com/homebrew/homebrew-core) this same formula is named `gcc@6.rb` and begins `class GccAT6 < Formula`. @@ -11,6 +11,6 @@ Versioned formulae we include must meet the following standards: * Versioned formulae should differ in major/minor (not patch) versions from the current stable release. This is because patch versions indicate bug or security updates and we want to ensure you apply security updates. * Formulae that depend on versioned formulae must not depend on the same formulae at two different versions twice in their recursive dependencies. For example, if you depend on `openssl@1.0` and `foo`, and `foo` depends on `openssl` then you must instead use `openssl`. -* Versioned formulae should strive to be linked at the same time as their non-versioned counterpart (without patching). If this is not possible, favour either `conflicts_with` or `keg_only` depending on whether users expect to have multiple versions installed at once or not. +* Versioned formulae should only be linkable at the same time as their non-versioned counterpart if the upstream project provides support for e.g. suffixed binaries. If this is not possible, use `keg_only :versioned_formula` to allow users to have multiple versions installed at once. You should create your own [tap](https://github.com/Homebrew/brew/blob/master/docs/How-to-Create-and-Maintain-a-Tap.md) for formulae you or your organisation wishes to control the versioning of or those that do not meet the above standards. diff --git a/docs/brew-tap.md b/docs/brew-tap.md index 15f8c7936..cfa0870d8 100644 --- a/docs/brew-tap.md +++ b/docs/brew-tap.md @@ -73,7 +73,7 @@ If you need a formula to be installed from a particular tap, you can use fully qualified names to refer to them. For example, you can create a tap for an alternative `vim` formula. Without -pinning it, the behavior will be +pinning it, the behaviour will be ```bash brew install vim # installs from homebrew/core diff --git a/docs/brew.1.html b/docs/brew.1.html index 2e036eb55..ff2d6105c 100644 --- a/docs/brew.1.html +++ b/docs/brew.1.html @@ -25,7 +25,7 @@ didn't include with macOS.</p> <dt><code>uninstall</code> <var>formula</var></dt><dd><p>Uninstall <var>formula</var>.</p></dd> <dt class="flush"><code>update</code></dt><dd><p>Fetch the newest version of Homebrew from GitHub using <code>git</code>(1).</p></dd> <dt class="flush"><code>list</code></dt><dd><p>List all installed formulae.</p></dd> -<dt><code>search</code> <var>text</var>|<code>/</code><var>text</var><code>/</code></dt><dd><p>Perform a substring search of formula names for <var>text</var>. If <var>text</var> is +<dt><code>search</code> (<var>text</var>|<code>/</code><var>text</var><code>/</code>)</dt><dd><p>Perform a substring search of formula names for <var>text</var>. If <var>text</var> is surrounded with slashes, then it is interpreted as a regular expression. The search for <var>text</var> is extended online to some popular taps. If no search term is given, all locally available formulae are listed.</p></dd> @@ -48,7 +48,7 @@ cellar. In addition, old downloads from the Homebrew download-cache are deleted. <p>If <code>--dry-run</code> or <code>-n</code> is passed, show what would be removed, but do not actually remove anything.</p> -<p>If <code>-s</code> is passed, scrubs the cache, removing downloads for even the latest +<p>If <code>-s</code> is passed, scrub the cache, removing downloads for even the latest versions of formulae. Note downloads for any installed formulae will still not be deleted. If you want to delete those too: <code>rm -rf $(brew --cache)</code></p></dd> <dt><code>command</code> <var>cmd</var></dt><dd><p>Display the path to the file which is used when invoking <code>brew</code> <var>cmd</var>.</p></dd> @@ -93,10 +93,9 @@ dependencies of that formula.</p> <p>The <var>filters</var> placeholder is any combination of options <code>--include-build</code>, <code>--include-optional</code>, and <code>--skip-recommended</code> as documented above.</p></dd> <dt><code>desc</code> <var>formula</var></dt><dd><p>Display <var>formula</var>'s name and one-line description.</p></dd> -<dt><code>desc</code> [<code>-s</code>|<code>-n</code>|<code>-d</code>] <var>pattern</var></dt><dd><p>Search both name and description (<code>-s</code>), just the names (<code>-n</code>), or just the -descriptions (<code>-d</code>) for <code><pattern></code>. <code><pattern></code> is by default interpreted -as a literal string; if flanked by slashes, it is instead interpreted as a -regular expression. Formula descriptions are cached; the cache is created on +<dt><code>desc</code> [<code>-s</code>|<code>-n</code>|<code>-d</code>] (<var>text</var>|<code>/</code><var>text</var><code>/</code>)</dt><dd><p>Search both name and description (<code>-s</code>), just the names (<code>-n</code>), or just the +descriptions (<code>-d</code>) for <var>text</var>. If <var>text</var> is flanked by slashes, it is interpreted +as a regular expression. Formula descriptions are cached; the cache is created on the first search, making that search slower than subsequent ones.</p></dd> <dt><code>diy</code> [<code>--name=</code><var>name</var>] [<code>--version=</code><var>version</var>]</dt><dd><p>Automatically determine the installation prefix for non-Homebrew software.</p> @@ -144,14 +143,14 @@ GitHub repository as well as creating the Gist.</p> <dt><code>info</code> <var>formula</var></dt><dd><p>Display information about <var>formula</var>.</p></dd> <dt><code>info</code> <code>--github</code> <var>formula</var></dt><dd><p>Open a browser to the GitHub History page for formula <var>formula</var>.</p> -<p>To view formula history locally: <code>brew log -p <formula></code>.</p></dd> +<p>To view formula history locally: <code>brew log -p <formula></code></p></dd> <dt><code>info</code> <code>--json=</code><var>version</var> (<code>--all</code>|<code>--installed</code>|<var>formulae</var>)</dt><dd><p>Print a JSON representation of <var>formulae</var>. Currently the only accepted value for <var>version</var> is <code>v1</code>.</p> <p>Pass <code>--all</code> to get information on all formulae, or <code>--installed</code> to get information on all installed formulae.</p> -<p>See the docs for examples of using the JSON: +<p>See the docs for examples of using the JSON output: <a href="http://docs.brew.sh/Querying-Brew.html" data-bare-link="true">http://docs.brew.sh/Querying-Brew.html</a></p></dd> <dt><code>install</code> [<code>--debug</code>] [<code>--env=</code><var>std</var>|<var>super</var>] [<code>--ignore-dependencies</code>] [<code>--only-dependencies</code>] [<code>--cc=</code><var>compiler</var>] [<code>--build-from-source</code>] [<code>--devel</code>|<code>--HEAD</code>] [<code>--keep-tmp</code>] <var>formula</var></dt><dd><p>Install <var>formula</var>.</p> @@ -265,7 +264,7 @@ spaces.</p> <p>If <code>--all</code> is passed, show options for all formulae.</p> <p>If <code>--installed</code> is passed, show options for all installed formulae.</p></dd> -<dt><code>outdated</code> [<code>--quiet</code>|<code>--verbose</code>|<code>--json=v1</code>] [<code>--fetch-HEAD</code>]</dt><dd><p>Show formulae that have an updated version available.</p> +<dt><code>outdated</code> [<code>--quiet</code>|<code>--verbose</code>|<code>--json=</code><var>version</var>] [<code>--fetch-HEAD</code>]</dt><dd><p>Show formulae that have an updated version available.</p> <p>By default, version information is displayed in interactive shells, and suppressed otherwise.</p> @@ -295,7 +294,7 @@ actually remove anything.</p></dd> <dt><code>reinstall</code> <var>formula</var></dt><dd><p>Uninstall and then install <var>formula</var>.</p></dd> <dt><code>search</code>, <code>-S</code></dt><dd><p>Display all locally available formulae for brewing (including tapped ones). No online search is performed if called without arguments.</p></dd> -<dt><code>search</code> [<code>--desc</code>] <var>text</var>|<code>/</code><var>text</var><code>/</code></dt><dd><p>Perform a substring search of formula names for <var>text</var>. If <var>text</var> is +<dt><code>search</code> [<code>--desc</code>] (<var>text</var>|<code>/</code><var>text</var><code>/</code>)</dt><dd><p>Perform a substring search of formula names for <var>text</var>. If <var>text</var> is surrounded with slashes, then it is interpreted as a regular expression. The search for <var>text</var> is extended online to some popular taps.</p> @@ -353,7 +352,7 @@ for <var>version</var> is <code>v1</code>.</p> <p>Pass <code>--installed</code> to get information on installed taps.</p> -<p>See the docs for examples of using the JSON: +<p>See the docs for examples of using the JSON output: <a href="http://docs.brew.sh/Querying-Brew.html" data-bare-link="true">http://docs.brew.sh/Querying-Brew.html</a></p></dd> <dt><code>tap-pin</code> <var>tap</var></dt><dd><p>Pin <var>tap</var>, prioritizing its formulae over core when formula names are supplied by the user. See also <code>tap-unpin</code>.</p></dd> @@ -367,7 +366,7 @@ installed, delete all installed versions.</p> formulae depending on <var>formula</var> would still be installed.</p></dd> <dt><code>unlink</code> [<code>--dry-run</code>] <var>formula</var></dt><dd><p>Remove symlinks for <var>formula</var> from the Homebrew prefix. This can be useful for temporarily disabling a formula: -<code>brew unlink foo && commands && brew link foo</code>.</p> +<code>brew unlink <formula> && <commands> && brew link <formula></code></p> <p>If <code>--dry-run</code> or <code>-n</code> is passed, Homebrew will list all files which would be unlinked, but will not actually unlink or delete any files.</p></dd> @@ -387,7 +386,7 @@ directory instead of the system directory.</p> would be removed, but will not actually delete any files.</p></dd> <dt><code>unpack</code> [<code>--git</code>|<code>--patch</code>] [<code>--destdir=</code><var>path</var>] <var>formulae</var></dt><dd><p>Unpack the source files for <var>formulae</var> into subdirectories of the current working directory. If <code>--destdir=</code><var>path</var> is given, the subdirectories will -be created in the directory named by <code><path></code> instead.</p> +be created in the directory named by <var>path</var> instead.</p> <p>If <code>--patch</code> is passed, patches for <var>formulae</var> will be applied to the unpacked source.</p> @@ -398,7 +397,7 @@ source. This is useful for creating patches for the software.</p></dd> <code>pin</code>.</p></dd> <dt><code>untap</code> <var>tap</var></dt><dd><p>Remove a tapped repository.</p></dd> <dt><code>update</code> [<code>--merge</code>] [<code>--force</code>]</dt><dd><p>Fetch the newest version of Homebrew and all formulae from GitHub using -<code>git</code>(1).</p> +<code>git</code>(1) and perform any necessary migrations.</p> <p>If <code>--merge</code> is specified then <code>git merge</code> is used to include updates (rather than <code>git rebase</code>).</p> @@ -431,8 +430,8 @@ or recommended dependency. To include the <code>:build</code> type dependencies, <code>--include-build</code>. Similarly, pass <code>--include-optional</code> to include <code>:optional</code> dependencies. To skip <code>:recommended</code> type dependencies, pass <code>--skip-recommended</code>.</p> -<p>By default, <code>uses</code> shows usages of <code>formula</code> by stable builds. To find -cases where <code>formula</code> is used by development or HEAD build, pass +<p>By default, <code>uses</code> shows usages of <var>formulae</var> by stable builds. To find +cases where <var>formulae</var> is used by development or HEAD build, pass <code>--devel</code> or <code>--HEAD</code>.</p></dd> <dt class="flush"><code>--cache</code></dt><dd><p>Display Homebrew's download cache. See also <code>HOMEBREW_CACHE</code>.</p></dd> <dt><code>--cache</code> <var>formula</var></dt><dd><p>Display the file or directory used to cache <var>formula</var>.</p></dd> @@ -453,7 +452,7 @@ the <code>prefix</code> and <code>repository</code> are the same directory.</p>< <h2 id="DEVELOPER-COMMANDS">DEVELOPER COMMANDS</h2> <dl> -<dt><code>audit</code> [<code>--strict</code>] [<code>--online</code>] [<code>--new-formula</code>] [<code>--display-cop-names</code>] [<code>--display-filename</code>] [<var>formulae</var>]</dt><dd><p>Check <var>formulae</var> for Homebrew coding style violations. This should be +<dt><code>audit</code> [<code>--strict</code>] [<code>--fix</code>] [<code>--online</code>] [<code>--new-formula</code>] [<code>--display-cop-names</code>] [<code>--display-filename</code>] [<var>formulae</var>]</dt><dd><p>Check <var>formulae</var> for Homebrew coding style violations. This should be run before submitting a new formula.</p> <p>If no <var>formulae</var> are provided, all of them are checked.</p> @@ -461,6 +460,9 @@ run before submitting a new formula.</p> <p>If <code>--strict</code> is passed, additional checks are run, including RuboCop style checks.</p> +<p>If <code>--fix</code> is passed, style violations will be +automatically fixed using RuboCop's <code>--auto-correct</code> feature.</p> + <p>If <code>--online</code> is passed, additional slower checks that require a network connection are run.</p> @@ -476,15 +478,12 @@ name of the file or formula being audited, to make the output easy to grep.</p> <p><code>audit</code> exits with a non-zero status if any errors are found. This is useful, for instance, for implementing pre-commit hooks.</p></dd> -<dt><code>bottle</code> [<code>--verbose</code>] [<code>--no-rebuild</code>] [<code>--keep-old</code>] [<code>--skip-relocation</code>] [<code>--root-url=<root_url></code>] [<code>--force-core-tap</code>]:</dt><dd><p></p></dd> -<dt><code>bottle</code> <code>--merge</code> [<code>--no-commit</code>] [<code>--keep-old</code>] [<code>--write</code>]:</dt><dd><p></p> - -<p>Generate a bottle (binary package) from a formula installed with +<dt><code>bottle</code> [<code>--verbose</code>] [<code>--no-rebuild</code>] [<code>--keep-old</code>] [<code>--skip-relocation</code>] [<code>--root-url=</code><var>URL</var>] [<code>--force-core-tap</code>]:</dt><dd><p></p></dd> +<dt><code>bottle</code> <code>--merge</code> [<code>--no-commit</code>] [<code>--keep-old</code>] [<code>--write</code>]</dt><dd><p>Generate a bottle (binary package) from a formula installed with <code>--build-bottle</code>.</p></dd> -<dt><code>bump-formula-pr</code> [<code>--devel</code>] [<code>--dry-run</code>] [<code>--audit</code>|<code>--strict</code>] [<code>--message=</code><var>message</var>] <code>--url=</code><var>url</var> <code>--sha256=</code><var>sha-256</var> <var>formula</var>:</dt><dd><p></p></dd> -<dt><code>bump-formula-pr</code> [<code>--devel</code>] [<code>--dry-run</code>] [<code>--audit</code>|<code>--strict</code>] [<code>--message=</code><var>message</var>] <code>--tag=</code><var>tag</var> <code>--revision=</code><var>revision</var> <var>formula</var></dt><dd><p>Creates a pull request to update the formula with a new url or a new tag.</p> +<dt><code>bump-formula-pr</code> [<code>--devel</code>] [<code>--dry-run</code> [<code>--write</code>]] [<code>--audit</code>|<code>--strict</code>] [<code>--mirror=</code><var>URL</var>] [<code>--version=</code><var>version</var>] [<code>--message=</code><var>message</var>] (<code>--url=</code><var>URL</var> <code>--sha256=</code><var>sha-256</var>|<code>--tag=</code><var>tag</var> <code>--revision=</code><var>revision</var>) <var>formula</var></dt><dd><p>Creates a pull request to update the formula with a new URL or a new tag.</p> -<p>If a <var>url</var> is specified, the <var>sha-256</var> checksum of the new download must +<p>If a <var>URL</var> is specified, the <var>sha-256</var> checksum of the new download must also be specified. A best effort to determine the <var>sha-256</var> and <var>formula</var> name will be made if either or both values are not supplied by the user.</p> @@ -503,25 +502,24 @@ making the expected file modifications but not taking any git actions.</p> <p>If <code>--strict</code> is passed, run <code>brew audit --strict</code> before opening the PR.</p> -<p>If <code>--mirror=</code><var>url</var> is passed, use the value as a mirror url.</p> +<p>If <code>--mirror=</code><var>URL</var> is passed, use the value as a mirror URL.</p> <p>If <code>--version=</code><var>version</var> is passed, use the value to override the value -parsed from the url or tag. Note that <code>--version=0</code> can be used to delete +parsed from the URL or tag. Note that <code>--version=0</code> can be used to delete an existing <code>version</code> override from a formula if it has become redundant.</p> <p>If <code>--message=</code><var>message</var> is passed, append <var>message</var> to the default PR message.</p> <p>Note that this command cannot be used to transition a formula from a -url-and-sha256 style specification into a tag-and-revision style +URL-and-sha256 style specification into a tag-and-revision style specification, nor vice versa. It must use whichever style specification the preexisting formula already uses.</p></dd> <dt><code>create</code> <var>URL</var> [<code>--autotools</code>|<code>--cmake</code>|<code>--meson</code>] [<code>--no-fetch</code>] [<code>--set-name</code> <var>name</var>] [<code>--set-version</code> <var>version</var>] [<code>--tap</code> <var>user</var><code>/</code><var>repo</var>]</dt><dd><p>Generate a formula for the downloadable file at <var>URL</var> and open it in the editor. Homebrew will attempt to automatically derive the formula name and version, but if it fails, you'll have to make your own template. The <code>wget</code> -formula serves as a simple example. For the complete API have a look at</p> - -<p><a href="http://www.rubydoc.info/github/Homebrew/brew/master/Formula" data-bare-link="true">http://www.rubydoc.info/github/Homebrew/brew/master/Formula</a></p> +formula serves as a simple example. For the complete API have a look at +<a href="http://www.rubydoc.info/github/Homebrew/brew/master/Formula" data-bare-link="true">http://www.rubydoc.info/github/Homebrew/brew/master/Formula</a>.</p> <p>If <code>--autotools</code> is passed, create a basic template for an Autotools-style build. If <code>--cmake</code> is passed, create a basic template for a CMake-style build. @@ -537,7 +535,8 @@ you to explicitly set the name and version of the package you are creating.</p> the specified tap.</p></dd> <dt class="flush"><code>edit</code></dt><dd><p>Open all of Homebrew for editing.</p></dd> <dt><code>edit</code> <var>formula</var></dt><dd><p>Open <var>formula</var> in the editor.</p></dd> -<dt><code>linkage</code> [<code>--test</code>] [<code>--reverse</code>] <var>formula-name</var></dt><dd><p>Checks the library links of an installed formula.</p> +<dt><code>formula</code> <var>formula</var></dt><dd><p>Display the path where <var>formula</var> is located.</p></dd> +<dt><code>linkage</code> [<code>--test</code>] [<code>--reverse</code>] <var>formula</var></dt><dd><p>Checks the library links of an installed formula.</p> <p>Only works on installed formulae. An error is raised if it is run on uninstalled formulae.</p> @@ -554,44 +553,47 @@ status code if changes are detected in the manpage outputs. This can be used for CI to be notified when the manpages are out of date. Additionally, the date used in new manpages will match those in the existing manpages (to allow comparison without factoring in the date).</p></dd> -</dl> +<dt><code>pull</code> [<code>--bottle</code>] [<code>--bump</code>] [<code>--clean</code>] [<code>--ignore-whitespace</code>] [<code>--resolve</code>] [<code>--branch-okay</code>] [<code>--no-pbcopy</code>] [<code>--no-publish</code>] <var>patch-source</var> [<var>patch-source</var>]</dt><dd><p>Gets a patch from a GitHub commit or pull request and applies it to Homebrew. +Optionally, installs the formulae changed by the patch.</p> +<p>Each <var>patch-source</var> may be one of:</p> -<p> <code>pull</code> [<code>--bottle</code>] [<code>--bump</code>] [<code>--clean</code>] [<code>--ignore-whitespace</code>] [<code>--resolve</code>] [<code>--branch-okay</code>] [<code>--no-pbcopy</code>] [<code>--no-publish</code>] <var>patch-source</var> [<var>patch-source</var>]</p> +<p> ~ The ID number of a PR (pull request) in the homebrew/core GitHub + repository</p> -<pre><code>Gets a patch from a GitHub commit or pull request and applies it to Homebrew. -Optionally, installs the formulae changed by the patch. - -Each <patch-source> may be one of: - * The ID number of a PR (Pull Request) in the homebrew/core GitHub - repository - * The URL of a PR on GitHub, using either the web page or API URL +<p> ~ The URL of a PR on GitHub, using either the web page or API URL formats. In this form, the PR may be on Homebrew/brew, - Homebrew/homebrew-core or any tap. - * The URL of a commit on GitHub - * A "http://bot.brew.sh/job/..." string specifying a testing job ID -</code></pre> + Homebrew/homebrew-core or any tap.</p> -<p> If <code>--bottle</code> was passed, handle bottles, pulling the bottle-update - commit and publishing files on Bintray. - If <code>--bump</code> was passed, for one-formula PRs, automatically reword - commit message to our preferred format. - If <code>--clean</code> was passed, do not rewrite or otherwise modify the - commits found in the pulled PR. - If <code>--ignore-whitespace</code> was passed, silently ignore whitespace - discrepancies when applying diffs. - If <code>--resolve</code> was passed, when a patch fails to apply, leave in - progress and allow user to - resolve, instead of aborting. - If <code>--branch-okay</code> was passed, do not warn if pulling to a branch - besides master (useful for testing). - If <code>--no-pbcopy</code> was passed, do not copy anything to the system - If <code>--no-publish</code> was passed, do not publish bottles to Bintray.</p> +<p> ~ The URL of a commit on GitHub</p> -<dl> -<dt><code>release-notes</code> [<var>previous_tag</var>] [<var>end_ref</var>]</dt><dd><p>Output the merged pull requests on Homebrew/brew between two Git refs. -If no <code>previous_tag</code> is provided it defaults to the newest tag. -If no <code>end_ref</code> is provided it defaults to <code>origin/master</code>.</p> +<p> ~ A "http://bot.brew.sh/job/..." string specifying a testing job ID</p> + +<p>If <code>--bottle</code> is passed, handle bottles, pulling the bottle-update +commit and publishing files on Bintray.</p> + +<p>If <code>--bump</code> is passed, for one-formula PRs, automatically reword +commit message to our preferred format.</p> + +<p>If <code>--clean</code> is passed, do not rewrite or otherwise modify the +commits found in the pulled PR.</p> + +<p>If <code>--ignore-whitespace</code> is passed, silently ignore whitespace +discrepancies when applying diffs.</p> + +<p>If <code>--resolve</code> is passed, when a patch fails to apply, leave in +progress and allow user to resolve, instead of aborting.</p> + +<p>If <code>--branch-okay</code> is passed, do not warn if pulling to a branch +besides master (useful for testing).</p> + +<p>If <code>--no-pbcopy</code> is passed, do not copy anything to the system +clipboard.</p> + +<p>If <code>--no-publish</code> is passed, do not publish bottles to Bintray.</p></dd> +<dt><code>release-notes</code> [<code>--markdown</code>] [<var>previous_tag</var>] [<var>end_ref</var>]</dt><dd><p>Output the merged pull requests on Homebrew/brew between two Git refs. +If no <var>previous_tag</var> is provided it defaults to the newest tag. +If no <var>end_ref</var> is provided it defaults to <code>origin/master</code>.</p> <p>If <code>--markdown</code> is passed, output as a Markdown list.</p></dd> <dt><code>tap-new</code> <var>user</var><code>/</code><var>repo</var></dt><dd><p>Generate the template files for a new tap.</p></dd> @@ -610,17 +612,17 @@ launched with access to IRB or a shell inside the temporary test directory.</p> not deleted.</p> <p>Example: <code>brew install jruby && brew test jruby</code></p></dd> -<dt><code>tests</code> [<code>-v</code>] [<code>--coverage</code>] [<code>--generic</code>] [<code>--no-compat</code>] [<code>--only=</code><test_script/test_method>] [<code>--seed</code> <var>seed</var>] [<code>--trace</code>] [<code>--online</code>] [<code>--official-cmd-taps</code>]</dt><dd><p>Run Homebrew's unit and integration tests.</p></dd> -<dt><code>update-test</code> [<code>--commit=<commit></code>] [<code>--before=<date></code>] [<code>--keep-tmp</code>]</dt><dd><p>Runs a test of <code>brew update</code> with a new repository clone.</p> +<dt><code>tests</code> [<code>-v</code>] [<code>--coverage</code>] [<code>--generic</code>] [<code>--no-compat</code>] [<code>--only=</code><var>test_script</var><code>:</code><var>test_method</var>] [<code>--seed</code> <var>seed</var>] [<code>--trace</code>] [<code>--online</code>] [<code>--official-cmd-taps</code>]</dt><dd><p>Run Homebrew's unit and integration tests.</p></dd> +<dt><code>update-test</code> [<code>--commit=</code><var>commit</var>] [<code>--before=</code><var>date</var>] [<code>--keep-tmp</code>]</dt><dd><p>Runs a test of <code>brew update</code> with a new repository clone.</p> <p>If no arguments are passed, use <code>origin/master</code> as the start commit.</p> -<p>If <code>--commit=<commit></code> is passed, use <code><commit></code> as the start commit.</p> +<p>If <code>--commit=</code><var>commit</var> is passed, use <var>commit</var> as the start commit.</p> -<p>If <code>--before=<date></code> is passed, use the commit at <code><date></code> as the +<p>If <code>--before=</code><var>date</var> is passed, use the commit at <var>date</var> as the start commit.</p> -<p>If <code>--to-tag</code> is passed, set HOMEBREW_UPDATE_TO_TAG to test updating +<p>If <code>--to-tag</code> is passed, set <code>HOMEBREW_UPDATE_TO_TAG</code> to test updating between tags.</p> <p>If <code>--keep-tmp</code> is passed, retain the temporary directory containing @@ -738,7 +740,7 @@ successful build.</p> to insecure HTTP.</p> <p>While ensuring your downloads are fully secure, this is likely -to cause from-source Sourceforge, some GNU & GNOME based +to cause from-source SourceForge, some GNU & GNOME based formulae to fail to download.</p></dd> <dt><code>HOMEBREW_NO_GITHUB_API</code></dt><dd><p>If set, Homebrew will not use the GitHub API for e.g searches or fetching relevant issues on a failed install.</p></dd> @@ -787,9 +789,9 @@ your shell profile, or you can use it before a brew command:</p> <p>Homebrew's lead maintainer is Mike McQuaid.</p> -<p>Homebrew's current maintainers are Misty De Meo, Andrew Janke, Xu Cheng, Tomasz Pajor, Josh Hagins, Baptiste Fontaine, Markus Reiter, ilovezfs, Tom Schoonjans, Uladzislau Shablinski, Tim Smith and Alex Dunn.</p> +<p>Homebrew's current maintainers are Alyssa Ross, Andrew Janke, Baptiste Fontaine, Alex Dunn, FX Coudert, ilovezfs, Josh Hagins, JCount, Misty De Meo, Tomasz Pajor, Markus Reiter, Tim Smith, Tom Schoonjans, Uladzislau Shablinski and William Woodruff.</p> -<p>Former maintainers with significant contributions include Martin Afanasjew, Dominyk Tiller, Brett Koonce, Jack Nagel, Adam Vandenberg and Homebrew's creator: Max Howell.</p> +<p>Former maintainers with significant contributions include Xu Cheng, Martin Afanasjew, Dominyk Tiller, Brett Koonce, Jack Nagel, Adam Vandenberg and Homebrew's creator: Max Howell.</p> <h2 id="BUGS">BUGS</h2> diff --git a/manpages/brew-cask.1 b/manpages/brew-cask.1 index 63aad2c56..d42feb6c0 100644 --- a/manpages/brew-cask.1 +++ b/manpages/brew-cask.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BREW\-CASK" "1" "January 2017" "Homebrew" "brew-cask" +.TH "BREW\-CASK" "1" "February 2017" "Homebrew" "brew-cask" . .SH "NAME" \fBbrew\-cask\fR \- a friendly binary installer for macOS @@ -34,68 +34,84 @@ The tokens returned by \fBsearch\fR are suitable as arguments for most other com . .SH "COMMANDS" . -.IP "\(bu" 4 -\fBaudit\fR [ \fItoken\fR \.\.\. ]: Check the given Casks for installability\. If no tokens are given on the command line, all Casks are audited\. +.TP +\fBaudit\fR [ \fItoken\fR \.\.\. ] +Check the given Casks for installability\. If no tokens are given on the command line, all Casks are audited\. . -.IP "\(bu" 4 -\fBcat\fR \fItoken\fR [ \fItoken\fR \.\.\. ]: Dump the given Cask definition file to the standard output\. +.TP +\fBcat\fR \fItoken\fR [ \fItoken\fR \.\.\. ] +Dump the given Cask definition file to the standard output\. . -.IP "\(bu" 4 -\fBcleanup\fR [\-\-outdated]: Clean up cached downloads and tracker symlinks\. With \fB\-\-outdated\fR, only clean up cached downloads older than 10 days old\. +.TP +\fBcleanup\fR [\-\-outdated] +Clean up cached downloads and tracker symlinks\. With \fB\-\-outdated\fR, only clean up cached downloads older than 10 days old\. . -.IP "\(bu" 4 -\fBcreate\fR \fItoken\fR: Generate a Cask definition file for the Cask identified by \fItoken\fR and open a template for it in your favorite editor\. +.TP +\fBcreate\fR \fItoken\fR +Generate a Cask definition file for the Cask identified by \fItoken\fR and open a template for it in your favorite editor\. . -.IP "\(bu" 4 -\fBdoctor\fR or \fBdr\fR: Check for configuration issues\. Can be useful to upload as a gist for developers along with a bug report\. +.TP +\fBdoctor\fR or \fBdr\fR +Check for configuration issues\. Can be useful to upload as a gist for developers along with a bug report\. . -.IP "\(bu" 4 -\fBedit\fR \fItoken\fR: Open the given Cask definition file for editing\. +.TP +\fBedit\fR \fItoken\fR +Open the given Cask definition file for editing\. . -.IP "\(bu" 4 -\fBfetch\fR [\-\-force] \fItoken\fR [ \fItoken\fR \.\.\. ]: Download remote application files for the given Cask to the local cache\. With \fB\-\-force\fR, force re\-download even if the files are already cached\. +.TP +\fBfetch\fR [\-\-force] \fItoken\fR [ \fItoken\fR \.\.\. ] +Download remote application files for the given Cask to the local cache\. With \fB\-\-force\fR, force re\-download even if the files are already cached\. . -.IP "\(bu" 4 -\fBhome\fR or \fBhomepage\fR [ \fItoken\fR \.\.\. ]: Display the homepage associated with a given Cask in a browser\. +.TP +\fBhome\fR or \fBhomepage\fR [ \fItoken\fR \.\.\. ] +Display the homepage associated with a given Cask in a browser\. . .IP With no arguments, display the project page \fIhttp://caskroom\.io\fR\. . -.IP "\(bu" 4 -\fBinfo\fR or \fBabv\fR \fItoken\fR [ \fItoken\fR \.\.\. ]: Display information about the given Cask\. +.TP +\fBinfo\fR or \fBabv\fR \fItoken\fR [ \fItoken\fR \.\.\. ] +Display information about the given Cask\. . -.IP "\(bu" 4 -\fBinstall\fR [\-\-force] [\-\-skip\-cask\-deps] [\-\-require\-sha] \fItoken\fR [ \fItoken\fR \.\.\. ]: Install the given Cask\. With \fB\-\-force\fR, re\-install even if the Cask appears to be already present\. With \fB\-\-skip\-cask\-deps\fR, skip any Cask dependencies\. \fB\-\-require\-sha\fR will abort installation if the Cask does not have a checksum defined\. +.TP +\fBinstall\fR [\-\-force] [\-\-skip\-cask\-deps] [\-\-require\-sha] \fItoken\fR [ \fItoken\fR \.\.\. ] +Install the given Cask\. With \fB\-\-force\fR, re\-install even if the Cask appears to be already present\. With \fB\-\-skip\-cask\-deps\fR, skip any Cask dependencies\. \fB\-\-require\-sha\fR will abort installation if the Cask does not have a checksum defined\. . .IP \fItoken\fR is usually the ID of a Cask as returned by \fBbrew cask search\fR, but see \fIOTHER WAYS TO SPECIFY A CASK\fR for variations\. . -.IP "\(bu" 4 -\fBlist\fR or \fBls\fR [\-1] [\-\-versions] [ \fItoken\fR \.\.\. ]: Without any arguments, list all installed Casks\. With \fB\-1\fR, always format the output in a single column\. With \fB\-\-versions\fR, show all installed versions\. +.TP +\fBlist\fR or \fBls\fR [\-1] [\-\-versions] [ \fItoken\fR \.\.\. ] +Without any arguments, list all installed Casks\. With \fB\-1\fR, always format the output in a single column\. With \fB\-\-versions\fR, show all installed versions\. . .IP If \fItoken\fR is given, summarize the staged files associated with the given Cask\. . -.IP "\(bu" 4 -\fBreinstall\fR \fItoken\fR [ \fItoken\fR \.\.\.] Reinstall the given Cask\. +.TP +\fBreinstall\fR \fItoken\fR [ \fItoken\fR \.\.\. ] +Reinstall the given Cask\. . -.IP "\(bu" 4 -\fBsearch\fR or \fB\-S\fR [\fItext\fR | /\fIregexp\fR/]: Without argument, display all Casks available for install, otherwise perform a substring search of known Cask tokens for \fItext\fR or, if the text is delimited by slashes (/\fIregexp\fR/), it is interpreted as a Ruby regular expression\. +.TP +\fBsearch\fR or \fB\-S\fR [\fItext\fR | /\fIregexp\fR/] +Without an argument, display all Casks available for install; otherwise perform a substring search of known Cask tokens for \fItext\fR or, if the text is delimited by slashes (/\fIregexp\fR/), it is interpreted as a Ruby regular expression\. . -.IP "\(bu" 4 -\fBstyle\fR [\-\-fix] [ \fItoken\fR \.\.\. ]: Check the given Casks for correct style using RuboCop Cask \fIhttps://github\.com/caskroom/rubocop\-cask\fR\. If no tokens are given on the command line, all Casks are checked\. With \fB\-\-fix\fR, auto\-correct any style errors if possible\. +.TP +\fBstyle\fR [\-\-fix] [ \fItoken\fR \.\.\. ] +Check the given Casks for correct style using RuboCop Cask \fIhttps://github\.com/caskroom/rubocop\-cask\fR\. If no tokens are given on the command line, all Casks are checked\. With \fB\-\-fix\fR, auto\-correct any style errors if possible\. . -.IP "\(bu" 4 -\fBuninstall\fR or \fBrm\fR or \fBremove\fR [\-\-force] \fItoken\fR [ \fItoken\fR \.\.\. ]: Uninstall the given Cask\. With \fB\-\-force\fR, uninstall even if the Cask does not appear to be present\. +.TP +\fBuninstall\fR or \fBrm\fR or \fBremove\fR [\-\-force] \fItoken\fR [ \fItoken\fR \.\.\. ] +Uninstall the given Cask\. With \fB\-\-force\fR, uninstall even if the Cask does not appear to be present\. . -.IP "\(bu" 4 -\fBzap\fR \fItoken\fR [ \fItoken\fR \.\.\. ]: Unconditionally remove \fIall\fR files associated with the given Cask\. +.TP +\fBzap\fR \fItoken\fR [ \fItoken\fR \.\.\. ] +Unconditionally remove \fIall\fR files associated with the given Cask\. . .IP Implicitly performs all actions associated with \fBuninstall\fR, even if the Cask does not appear to be currently installed\. . .IP -Removes all staged versions of the Cask distribution found under \fB<Caskroom_path>/<token>\fR\. +Removes all staged versions of the Cask distribution found under \fB<Caskroom_path>/\fR\fItoken\fR\. . .IP If the Cask definition contains a \fBzap\fR stanza, performs additional \fBzap\fR actions as defined there, such as removing local preference files\. \fBzap\fR actions are variable, depending on the level of detail defined by the Cask author\. @@ -103,10 +119,21 @@ If the Cask definition contains a \fBzap\fR stanza, performs additional \fBzap\f .IP \fB\fBzap\fR may remove files which are shared between applications\.\fR . -.IP "" 0 +.SH "INTERNAL COMMANDS" +. +.TP +\fB_appcast_checkpoint\fR [\-\-calculate] [ \fItoken\fR \.\.\. | \fIURL\fR \.\.\. ] +Given a \fItoken\fR, returns the current appcast checkpoint, or calculates the appcast checkpoint if the \fB\-\-calculate\fR flag is specified\. +. +.IP +Given a \fIURL\fR, calculates the appcast checkpoint for it\. +. +.TP +\fB_stanza\fR \fIstanza_name\fR [ \-\-table | \-\-yaml | \-\-inspect | \-\-quiet ] [ \fItoken\fR \.\.\. ] +Given a \fIstanza_name\fR and a \fItoken\fR, returns the current stanza for a given Cask\. If no \fItoken\fR is given, then data for all Casks is returned\. . .SH "OPTIONS" -To make these options persistent, see the ENVIRONMENT section, below\. +To make these options persistent, see the \fIENVIRONMENT\fR section, below\. . .P Some of these (such as \fB\-\-prefpanedir\fR) may be subject to removal in a future version\. @@ -125,7 +152,7 @@ Abort Cask installation if the Cask does not have a checksum defined\. . .TP \fB\-\-caskroom=<path>\fR -Location of the Caskroom, where all binaries are stored\. The default value is: \fB$(brew \-\-prefix)/Caskroom\fR\. +Set location of the Caskroom, where all binaries are stored\. The default value is \fB$(brew \-\-prefix)/Caskroom\fR\. . .TP \fB\-\-verbose\fR @@ -221,7 +248,7 @@ brew update Most Homebrew\-Cask commands can accept a Cask token as an argument\. As described above, the argument can take the form of: . .IP "\(bu" 4 -A token as returned by \fBbrew cask search\fR, \fIeg\fR \fBgoogle\-chrome\fR +A token as returned by \fBbrew cask search\fR, e\.g\. \fBgoogle\-chrome\fR . .IP "" 0 . @@ -229,13 +256,13 @@ A token as returned by \fBbrew cask search\fR, \fIeg\fR \fBgoogle\-chrome\fR Homebrew\-Cask also accepts three other forms in place of plain tokens: . .IP "\(bu" 4 -A fully\-qualified token which includes the Tap name, \fIeg\fR \fBcaskroom/fonts/font\-symbola\fR +A fully\-qualified token which includes the Tap name, e\.g\. \fBcaskroom/fonts/font\-symbola\fR . .IP "\(bu" 4 -A fully\-qualified pathname to a Cask file, \fIeg\fR \fB/usr/local/Library/Taps/caskroom/homebrew\-cask/Casks/google\-chrome\.rb\fR +A fully\-qualified pathname to a Cask file, e\.g\. \fB/usr/local/Library/Taps/caskroom/homebrew\-cask/Casks/google\-chrome\.rb\fR . .IP "\(bu" 4 -A \fBcurl\fR\-retrievable URI to a Cask file, \fIeg\fR \fBhttps://raw\.githubusercontent\.com/caskroom/homebrew\-cask/f25b6babcd398abf48e33af3d887b2d00de1d661/Casks/google\-chrome\.rb\fR +A \fBcurl\fR\-retrievable URI to a Cask file, e\.g\. \fBhttps://raw\.githubusercontent\.com/caskroom/homebrew\-cask/f25b6babcd398abf48e33af3d887b2d00de1d661/Casks/google\-chrome\.rb\fR . .IP "" 0 . @@ -246,14 +273,25 @@ Homebrew\-Cask respects many of the environment variables used by the parent com Environment variables specific to Homebrew\-Cask: . .TP -HOMEBREW_CASK_OPTS -This variable may contain any arguments normally used as options on the command\-line\. This is particularly useful to make options persistent\. For example, you might add to your \.bash_profile or \.zshenv something like: \fBexport HOMEBREW_CASK_OPTS=\'\-\-appdir=/Applications \-\-caskroom=/etc/Caskroom\'\fR\. +\fBHOMEBREW_CASK_OPTS\fR +This variable may contain any arguments normally used as options on the command\-line\. This is particularly useful to make options persistent\. For example, you might add to your \.bash_profile or \.zshenv something like: +. +.IP "" 4 +. +.nf + + export HOMEBREW_CASK_OPTS=\'\-\-appdir=/Applications \-\-caskroom=/etc/Caskroom\' +. +.fi +. +.IP "" 0 + . .SH "SEE ALSO" -The Homebrew\-Cask home page: \fIhttp://caskroom\.io\fR\. +The Homebrew\-Cask home page: \fIhttp://caskroom\.io\fR . .P -The Homebrew\-Cask GitHub page: \fIhttps://github\.com/caskroom/homebrew\-cask\fR\. +The Homebrew\-Cask GitHub page: \fIhttps://github\.com/caskroom/homebrew\-cask\fR . .P \fBbrew\fR(1), \fBcurl\fR(1) @@ -265,7 +303,7 @@ Paul Hinze and Contributors\. Man page format based on \fBbrew\.1\.md\fR from Homebrew\. . .SH "BUGS" -We still have bugs — and we are busy fixing them! If you have a problem, don’t be shy about reporting it on our GitHub issues page \fIhttps://github\.com/caskroom/homebrew\-cask/issues?state=open\fR\. +We still have bugs \- and we are busy fixing them! If you have a problem, don\'t be shy about reporting it on our GitHub issues page \fIhttps://github\.com/caskroom/homebrew\-cask/issues?state=open\fR\. . .P When reporting bugs, remember that Homebrew\-Cask is an independent project from Homebrew\. Do your best to direct bug reports to the appropriate project\. If your command\-line started with \fBbrew cask\fR, bring the bug to us first! diff --git a/manpages/brew.1 b/manpages/brew.1 index f122337fb..0899007b5 100644 --- a/manpages/brew.1 +++ b/manpages/brew.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BREW" "1" "January 2017" "Homebrew" "brew" +.TH "BREW" "1" "February 2017" "Homebrew" "brew" . .SH "NAME" \fBbrew\fR \- The missing package manager for macOS @@ -38,7 +38,7 @@ Fetch the newest version of Homebrew from GitHub using \fBgit\fR(1)\. List all installed formulae\. . .TP -\fBsearch\fR \fItext\fR|\fB/\fR\fItext\fR\fB/\fR +\fBsearch\fR (\fItext\fR|\fB/\fR\fItext\fR\fB/\fR) Perform a substring search of formula names for \fItext\fR\. If \fItext\fR is surrounded with slashes, then it is interpreted as a regular expression\. The search for \fItext\fR is extended online to some popular taps\. If no search term is given, all locally available formulae are listed\. . .SH "COMMANDS" @@ -70,7 +70,7 @@ If \fB\-\-prune=\fR\fIdays\fR is specified, remove all cache files older than \f If \fB\-\-dry\-run\fR or \fB\-n\fR is passed, show what would be removed, but do not actually remove anything\. . .IP -If \fB\-s\fR is passed, scrubs the cache, removing downloads for even the latest versions of formulae\. Note downloads for any installed formulae will still not be deleted\. If you want to delete those too: \fBrm \-rf $(brew \-\-cache)\fR +If \fB\-s\fR is passed, scrub the cache, removing downloads for even the latest versions of formulae\. Note downloads for any installed formulae will still not be deleted\. If you want to delete those too: \fBrm \-rf $(brew \-\-cache)\fR . .TP \fBcommand\fR \fIcmd\fR @@ -131,8 +131,8 @@ The \fIfilters\fR placeholder is any combination of options \fB\-\-include\-buil Display \fIformula\fR\'s name and one\-line description\. . .TP -\fBdesc\fR [\fB\-s\fR|\fB\-n\fR|\fB\-d\fR] \fIpattern\fR -Search both name and description (\fB\-s\fR), just the names (\fB\-n\fR), or just the descriptions (\fB\-d\fR) for \fB<pattern>\fR\. \fB<pattern>\fR is by default interpreted as a literal string; if flanked by slashes, it is instead interpreted as a regular expression\. Formula descriptions are cached; the cache is created on the first search, making that search slower than subsequent ones\. +\fBdesc\fR [\fB\-s\fR|\fB\-n\fR|\fB\-d\fR] (\fItext\fR|\fB/\fR\fItext\fR\fB/\fR) +Search both name and description (\fB\-s\fR), just the names (\fB\-n\fR), or just the descriptions (\fB\-d\fR) for \fItext\fR\. If \fItext\fR is flanked by slashes, it is interpreted as a regular expression\. Formula descriptions are cached; the cache is created on the first search, making that search slower than subsequent ones\. . .TP \fBdiy\fR [\fB\-\-name=\fR\fIname\fR] [\fB\-\-version=\fR\fIversion\fR] @@ -203,7 +203,7 @@ Display information about \fIformula\fR\. Open a browser to the GitHub History page for formula \fIformula\fR\. . .IP -To view formula history locally: \fBbrew log \-p <formula>\fR\. +To view formula history locally: \fBbrew log \-p <formula>\fR . .TP \fBinfo\fR \fB\-\-json=\fR\fIversion\fR (\fB\-\-all\fR|\fB\-\-installed\fR|\fIformulae\fR) @@ -213,7 +213,7 @@ Print a JSON representation of \fIformulae\fR\. Currently the only accepted valu Pass \fB\-\-all\fR to get information on all formulae, or \fB\-\-installed\fR to get information on all installed formulae\. . .IP -See the docs for examples of using the JSON: \fIhttp://docs\.brew\.sh/Querying\-Brew\.html\fR +See the docs for examples of using the JSON output: \fIhttp://docs\.brew\.sh/Querying\-Brew\.html\fR . .TP \fBinstall\fR [\fB\-\-debug\fR] [\fB\-\-env=\fR\fIstd\fR|\fIsuper\fR] [\fB\-\-ignore\-dependencies\fR] [\fB\-\-only\-dependencies\fR] [\fB\-\-cc=\fR\fIcompiler\fR] [\fB\-\-build\-from\-source\fR] [\fB\-\-devel\fR|\fB\-\-HEAD\fR] [\fB\-\-keep\-tmp\fR] \fIformula\fR @@ -352,7 +352,7 @@ If \fB\-\-all\fR is passed, show options for all formulae\. If \fB\-\-installed\fR is passed, show options for all installed formulae\. . .TP -\fBoutdated\fR [\fB\-\-quiet\fR|\fB\-\-verbose\fR|\fB\-\-json=v1\fR] [\fB\-\-fetch\-HEAD\fR] +\fBoutdated\fR [\fB\-\-quiet\fR|\fB\-\-verbose\fR|\fB\-\-json=\fR\fIversion\fR] [\fB\-\-fetch\-HEAD\fR] Show formulae that have an updated version available\. . .IP @@ -394,7 +394,7 @@ Uninstall and then install \fIformula\fR\. Display all locally available formulae for brewing (including tapped ones)\. No online search is performed if called without arguments\. . .TP -\fBsearch\fR [\fB\-\-desc\fR] \fItext\fR|\fB/\fR\fItext\fR\fB/\fR +\fBsearch\fR [\fB\-\-desc\fR] (\fItext\fR|\fB/\fR\fItext\fR\fB/\fR) Perform a substring search of formula names for \fItext\fR\. If \fItext\fR is surrounded with slashes, then it is interpreted as a regular expression\. The search for \fItext\fR is extended online to some popular taps\. . .IP @@ -479,7 +479,7 @@ Print a JSON representation of \fItaps\fR\. Currently the only accepted value fo Pass \fB\-\-installed\fR to get information on installed taps\. . .IP -See the docs for examples of using the JSON: \fIhttp://docs\.brew\.sh/Querying\-Brew\.html\fR +See the docs for examples of using the JSON output: \fIhttp://docs\.brew\.sh/Querying\-Brew\.html\fR . .TP \fBtap\-pin\fR \fItap\fR @@ -501,7 +501,7 @@ If \fB\-\-ignore\-dependencies\fR is passed, uninstalling won\'t fail, even if f . .TP \fBunlink\fR [\fB\-\-dry\-run\fR] \fIformula\fR -Remove symlinks for \fIformula\fR from the Homebrew prefix\. This can be useful for temporarily disabling a formula: \fBbrew unlink foo && commands && brew link foo\fR\. +Remove symlinks for \fIformula\fR from the Homebrew prefix\. This can be useful for temporarily disabling a formula: \fBbrew unlink <formula> && <commands> && brew link <formula>\fR . .IP If \fB\-\-dry\-run\fR or \fB\-n\fR is passed, Homebrew will list all files which would be unlinked, but will not actually unlink or delete any files\. @@ -524,7 +524,7 @@ If \fB\-\-dry\-run\fR or \fB\-n\fR is passed, Homebrew will list all symlinks wh . .TP \fBunpack\fR [\fB\-\-git\fR|\fB\-\-patch\fR] [\fB\-\-destdir=\fR\fIpath\fR] \fIformulae\fR -Unpack the source files for \fIformulae\fR into subdirectories of the current working directory\. If \fB\-\-destdir=\fR\fIpath\fR is given, the subdirectories will be created in the directory named by \fB<path>\fR instead\. +Unpack the source files for \fIformulae\fR into subdirectories of the current working directory\. If \fB\-\-destdir=\fR\fIpath\fR is given, the subdirectories will be created in the directory named by \fIpath\fR instead\. . .IP If \fB\-\-patch\fR is passed, patches for \fIformulae\fR will be applied to the unpacked source\. @@ -542,7 +542,7 @@ Remove a tapped repository\. . .TP \fBupdate\fR [\fB\-\-merge\fR] [\fB\-\-force\fR] -Fetch the newest version of Homebrew and all formulae from GitHub using \fBgit\fR(1)\. +Fetch the newest version of Homebrew and all formulae from GitHub using \fBgit\fR(1) and perform any necessary migrations\. . .IP If \fB\-\-merge\fR is specified then \fBgit merge\fR is used to include updates (rather than \fBgit rebase\fR)\. @@ -580,7 +580,7 @@ If \fB\-\-installed\fR is passed, only list installed formulae\. 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\. . .IP -By default, \fBuses\fR shows usages of \fBformula\fR by stable builds\. To find cases where \fBformula\fR is used by development or HEAD build, pass \fB\-\-devel\fR or \fB\-\-HEAD\fR\. +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\. . .TP \fB\-\-cache\fR @@ -625,7 +625,7 @@ Print the version number of Homebrew to standard output and exit\. .SH "DEVELOPER COMMANDS" . .TP -\fBaudit\fR [\fB\-\-strict\fR] [\fB\-\-online\fR] [\fB\-\-new\-formula\fR] [\fB\-\-display\-cop\-names\fR] [\fB\-\-display\-filename\fR] [\fIformulae\fR] +\fBaudit\fR [\fB\-\-strict\fR] [\fB\-\-fix\fR] [\fB\-\-online\fR] [\fB\-\-new\-formula\fR] [\fB\-\-display\-cop\-names\fR] [\fB\-\-display\-filename\fR] [\fIformulae\fR] Check \fIformulae\fR for Homebrew coding style violations\. This should be run before submitting a new formula\. . .IP @@ -635,6 +635,9 @@ If no \fIformulae\fR are provided, all of them are checked\. If \fB\-\-strict\fR is passed, additional checks are run, including RuboCop style checks\. . .IP +If \fB\-\-fix\fR is passed, style violations will be automatically fixed using RuboCop\'s \fB\-\-auto\-correct\fR feature\. +. +.IP If \fB\-\-online\fR is passed, additional slower checks that require a network connection are run\. . .IP @@ -650,25 +653,19 @@ If \fB\-\-display\-filename\fR is passed, every line of output is prefixed with \fBaudit\fR exits with a non\-zero status if any errors are found\. This is useful, for instance, for implementing pre\-commit hooks\. . .TP -\fBbottle\fR [\fB\-\-verbose\fR] [\fB\-\-no\-rebuild\fR] [\fB\-\-keep\-old\fR] [\fB\-\-skip\-relocation\fR] [\fB\-\-root\-url=<root_url>\fR] [\fB\-\-force\-core\-tap\fR]: +\fBbottle\fR [\fB\-\-verbose\fR] [\fB\-\-no\-rebuild\fR] [\fB\-\-keep\-old\fR] [\fB\-\-skip\-relocation\fR] [\fB\-\-root\-url=\fR\fIURL\fR] [\fB\-\-force\-core\-tap\fR]: . .TP -\fBbottle\fR \fB\-\-merge\fR [\fB\-\-no\-commit\fR] [\fB\-\-keep\-old\fR] [\fB\-\-write\fR]: -. -.IP +\fBbottle\fR \fB\-\-merge\fR [\fB\-\-no\-commit\fR] [\fB\-\-keep\-old\fR] [\fB\-\-write\fR] Generate a bottle (binary package) from a formula installed with \fB\-\-build\-bottle\fR\. . .TP -\fBbump\-formula\-pr\fR [\fB\-\-devel\fR] [\fB\-\-dry\-run\fR] [\fB\-\-audit\fR|\fB\-\-strict\fR] [\fB\-\-message=\fR\fImessage\fR] \fB\-\-url=\fR\fIurl\fR \fB\-\-sha256=\fR\fIsha\-256\fR \fIformula\fR: - -. -.TP -\fBbump\-formula\-pr\fR [\fB\-\-devel\fR] [\fB\-\-dry\-run\fR] [\fB\-\-audit\fR|\fB\-\-strict\fR] [\fB\-\-message=\fR\fImessage\fR] \fB\-\-tag=\fR\fItag\fR \fB\-\-revision=\fR\fIrevision\fR \fIformula\fR -Creates a pull request to update the formula with a new url or a new tag\. +\fBbump\-formula\-pr\fR [\fB\-\-devel\fR] [\fB\-\-dry\-run\fR [\fB\-\-write\fR]] [\fB\-\-audit\fR|\fB\-\-strict\fR] [\fB\-\-mirror=\fR\fIURL\fR] [\fB\-\-version=\fR\fIversion\fR] [\fB\-\-message=\fR\fImessage\fR] (\fB\-\-url=\fR\fIURL\fR \fB\-\-sha256=\fR\fIsha\-256\fR|\fB\-\-tag=\fR\fItag\fR \fB\-\-revision=\fR\fIrevision\fR) \fIformula\fR +Creates a pull request to update the formula with a new URL or a new tag\. . .IP -If a \fIurl\fR is specified, the \fIsha\-256\fR checksum of the new download must also be specified\. A best effort to determine the \fIsha\-256\fR and \fIformula\fR name will be made if either or both values are not supplied by the user\. +If a \fIURL\fR is specified, the \fIsha\-256\fR checksum of the new download must also be specified\. A best effort to determine the \fIsha\-256\fR and \fIformula\fR name will be made if either or both values are not supplied by the user\. . .IP If a \fItag\fR is specified, the git commit \fIrevision\fR corresponding to that tag must also be specified\. @@ -689,23 +686,20 @@ If \fB\-\-audit\fR is passed, run \fBbrew audit\fR before opening the PR\. If \fB\-\-strict\fR is passed, run \fBbrew audit \-\-strict\fR before opening the PR\. . .IP -If \fB\-\-mirror=\fR\fIurl\fR is passed, use the value as a mirror url\. +If \fB\-\-mirror=\fR\fIURL\fR is passed, use the value as a mirror URL\. . .IP -If \fB\-\-version=\fR\fIversion\fR is passed, use the value to override the value parsed from the url or tag\. Note that \fB\-\-version=0\fR can be used to delete an existing \fBversion\fR override from a formula if it has become redundant\. +If \fB\-\-version=\fR\fIversion\fR is passed, use the value to override the value parsed from the URL or tag\. Note that \fB\-\-version=0\fR can be used to delete an existing \fBversion\fR override from a formula if it has become redundant\. . .IP If \fB\-\-message=\fR\fImessage\fR is passed, append \fImessage\fR to the default PR message\. . .IP -Note that this command cannot be used to transition a formula from a url\-and\-sha256 style specification into a tag\-and\-revision style specification, nor vice versa\. It must use whichever style specification the preexisting formula already uses\. +Note that this command cannot be used to transition a formula from a URL\-and\-sha256 style specification into a tag\-and\-revision style specification, nor vice versa\. It must use whichever style specification the preexisting formula already uses\. . .TP \fBcreate\fR \fIURL\fR [\fB\-\-autotools\fR|\fB\-\-cmake\fR|\fB\-\-meson\fR] [\fB\-\-no\-fetch\fR] [\fB\-\-set\-name\fR \fIname\fR] [\fB\-\-set\-version\fR \fIversion\fR] [\fB\-\-tap\fR \fIuser\fR\fB/\fR\fIrepo\fR] -Generate a formula for the downloadable file at \fIURL\fR and open it in the editor\. Homebrew will attempt to automatically derive the formula name and version, but if it fails, you\'ll have to make your own template\. The \fBwget\fR formula serves as a simple example\. For the complete API have a look at -. -.IP -\fIhttp://www\.rubydoc\.info/github/Homebrew/brew/master/Formula\fR +Generate a formula for the downloadable file at \fIURL\fR and open it in the editor\. Homebrew will attempt to automatically derive the formula name and version, but if it fails, you\'ll have to make your own template\. The \fBwget\fR formula serves as a simple example\. For the complete API have a look at \fIhttp://www\.rubydoc\.info/github/Homebrew/brew/master/Formula\fR\. . .IP If \fB\-\-autotools\fR is passed, create a basic template for an Autotools\-style build\. If \fB\-\-cmake\fR is passed, create a basic template for a CMake\-style build\. If \fB\-\-meson\fR is passed, create a basic template for a Meson\-style build\. @@ -728,7 +722,11 @@ Open all of Homebrew for editing\. Open \fIformula\fR in the editor\. . .TP -\fBlinkage\fR [\fB\-\-test\fR] [\fB\-\-reverse\fR] \fIformula\-name\fR +\fBformula\fR \fIformula\fR +Display the path where \fIformula\fR is located\. +. +.TP +\fBlinkage\fR [\fB\-\-test\fR] [\fB\-\-reverse\fR] \fIformula\fR Checks the library links of an installed formula\. . .IP @@ -747,35 +745,52 @@ Generate Homebrew\'s manpages\. .IP If \fB\-\-fail\-if\-changed\fR is passed, the command will return a failing status code if changes are detected in the manpage outputs\. This can be used for CI to be notified when the manpages are out of date\. Additionally, the date used in new manpages will match those in the existing manpages (to allow comparison without factoring in the date)\. . -.P +.TP \fBpull\fR [\fB\-\-bottle\fR] [\fB\-\-bump\fR] [\fB\-\-clean\fR] [\fB\-\-ignore\-whitespace\fR] [\fB\-\-resolve\fR] [\fB\-\-branch\-okay\fR] [\fB\-\-no\-pbcopy\fR] [\fB\-\-no\-publish\fR] \fIpatch\-source\fR [\fIpatch\-source\fR] +Gets a patch from a GitHub commit or pull request and applies it to Homebrew\. Optionally, installs the formulae changed by the patch\. . -.IP "" 4 +.IP +Each \fIpatch\-source\fR may be one of: . -.nf - -Gets a patch from a GitHub commit or pull request and applies it to Homebrew\. -Optionally, installs the formulae changed by the patch\. - -Each <patch\-source> may be one of: - * The ID number of a PR (Pull Request) in the homebrew/core GitHub - repository - * The URL of a PR on GitHub, using either the web page or API URL - formats\. In this form, the PR may be on Homebrew/brew, - Homebrew/homebrew\-core or any tap\. - * The URL of a commit on GitHub - * A "http://bot\.brew\.sh/job/\.\.\." string specifying a testing job ID +.IP +~ The ID number of a PR (pull request) in the homebrew/core GitHub repository . -.fi +.IP +~ The URL of a PR on GitHub, using either the web page or API URL formats\. In this form, the PR may be on Homebrew/brew, Homebrew/homebrew\-core or any tap\. . -.IP "" 0 +.IP +~ The URL of a commit on GitHub . -.P -If \fB\-\-bottle\fR was passed, handle bottles, pulling the bottle\-update commit and publishing files on Bintray\. If \fB\-\-bump\fR was passed, for one\-formula PRs, automatically reword commit message to our preferred format\. If \fB\-\-clean\fR was passed, do not rewrite or otherwise modify the commits found in the pulled PR\. If \fB\-\-ignore\-whitespace\fR was passed, silently ignore whitespace discrepancies when applying diffs\. If \fB\-\-resolve\fR was passed, when a patch fails to apply, leave in progress and allow user to resolve, instead of aborting\. If \fB\-\-branch\-okay\fR was passed, do not warn if pulling to a branch besides master (useful for testing)\. If \fB\-\-no\-pbcopy\fR was passed, do not copy anything to the system If \fB\-\-no\-publish\fR was passed, do not publish bottles to Bintray\. +.IP +~ A "http://bot\.brew\.sh/job/\.\.\." string specifying a testing job ID +. +.IP +If \fB\-\-bottle\fR is passed, handle bottles, pulling the bottle\-update commit and publishing files on Bintray\. +. +.IP +If \fB\-\-bump\fR is passed, for one\-formula PRs, automatically reword commit message to our preferred format\. +. +.IP +If \fB\-\-clean\fR is passed, do not rewrite or otherwise modify the commits found in the pulled PR\. +. +.IP +If \fB\-\-ignore\-whitespace\fR is passed, silently ignore whitespace discrepancies when applying diffs\. +. +.IP +If \fB\-\-resolve\fR is passed, when a patch fails to apply, leave in progress and allow user to resolve, instead of aborting\. +. +.IP +If \fB\-\-branch\-okay\fR is passed, do not warn if pulling to a branch besides master (useful for testing)\. +. +.IP +If \fB\-\-no\-pbcopy\fR is passed, do not copy anything to the system clipboard\. +. +.IP +If \fB\-\-no\-publish\fR is passed, do not publish bottles to Bintray\. . .TP -\fBrelease\-notes\fR [\fIprevious_tag\fR] [\fIend_ref\fR] -Output the merged pull requests on Homebrew/brew between two Git refs\. If no \fBprevious_tag\fR is provided it defaults to the newest tag\. If no \fBend_ref\fR is provided it defaults to \fBorigin/master\fR\. +\fBrelease\-notes\fR [\fB\-\-markdown\fR] [\fIprevious_tag\fR] [\fIend_ref\fR] +Output the merged pull requests on Homebrew/brew between two Git refs\. If no \fIprevious_tag\fR is provided it defaults to the newest tag\. If no \fIend_ref\fR is provided it defaults to \fBorigin/master\fR\. . .IP If \fB\-\-markdown\fR is passed, output as a Markdown list\. @@ -801,24 +816,24 @@ 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\-v\fR] [\fB\-\-coverage\fR] [\fB\-\-generic\fR] [\fB\-\-no\-compat\fR] [\fB\-\-only=\fR<test_script/test_method>] [\fB\-\-seed\fR \fIseed\fR] [\fB\-\-trace\fR] [\fB\-\-online\fR] [\fB\-\-official\-cmd\-taps\fR] +\fBtests\fR [\fB\-v\fR] [\fB\-\-coverage\fR] [\fB\-\-generic\fR] [\fB\-\-no\-compat\fR] [\fB\-\-only=\fR\fItest_script\fR\fB:\fR\fItest_method\fR] [\fB\-\-seed\fR \fIseed\fR] [\fB\-\-trace\fR] [\fB\-\-online\fR] [\fB\-\-official\-cmd\-taps\fR] Run Homebrew\'s unit and integration tests\. . .TP -\fBupdate\-test\fR [\fB\-\-commit=<commit>\fR] [\fB\-\-before=<date>\fR] [\fB\-\-keep\-tmp\fR] +\fBupdate\-test\fR [\fB\-\-commit=\fR\fIcommit\fR] [\fB\-\-before=\fR\fIdate\fR] [\fB\-\-keep\-tmp\fR] Runs a test of \fBbrew update\fR with a new repository clone\. . .IP If no arguments are passed, use \fBorigin/master\fR as the start commit\. . .IP -If \fB\-\-commit=<commit>\fR is passed, use \fB<commit>\fR as the start commit\. +If \fB\-\-commit=\fR\fIcommit\fR is passed, use \fIcommit\fR as the start commit\. . .IP -If \fB\-\-before=<date>\fR is passed, use the commit at \fB<date>\fR as the start commit\. +If \fB\-\-before=\fR\fIdate\fR is passed, use the commit at \fIdate\fR as the start commit\. . .IP -If \fB\-\-to\-tag\fR is passed, set HOMEBREW_UPDATE_TO_TAG to test updating between tags\. +If \fB\-\-to\-tag\fR is passed, set \fBHOMEBREW_UPDATE_TO_TAG\fR to test updating between tags\. . .IP If \fB\-\-keep\-tmp\fR is passed, retain the temporary directory containing the new repository clone\. @@ -978,7 +993,7 @@ If set, Homebrew will not print the \fBHOMEBREW_INSTALL_BADGE\fR on a successful If set, Homebrew will not permit redirects from secure HTTPS to insecure HTTP\. . .IP -While ensuring your downloads are fully secure, this is likely to cause from\-source Sourceforge, some GNU & GNOME based formulae to fail to download\. +While ensuring your downloads are fully secure, this is likely to cause from\-source SourceForge, some GNU & GNOME based formulae to fail to download\. . .TP \fBHOMEBREW_NO_GITHUB_API\fR @@ -1049,10 +1064,10 @@ Homebrew Documentation: \fIhttps://github\.com/Homebrew/brew/blob/master/docs/\f Homebrew\'s lead maintainer is Mike McQuaid\. . .P -Homebrew\'s current maintainers are Misty De Meo, Andrew Janke, Xu Cheng, Tomasz Pajor, Josh Hagins, Baptiste Fontaine, Markus Reiter, ilovezfs, Tom Schoonjans, Uladzislau Shablinski, Tim Smith and Alex Dunn\. +Homebrew\'s current maintainers are Alyssa Ross, Andrew Janke, Baptiste Fontaine, Alex Dunn, FX Coudert, ilovezfs, Josh Hagins, JCount, Misty De Meo, Tomasz Pajor, Markus Reiter, Tim Smith, Tom Schoonjans, Uladzislau Shablinski and William Woodruff\. . .P -Former maintainers with significant contributions include Martin Afanasjew, Dominyk Tiller, Brett Koonce, Jack Nagel, Adam Vandenberg and Homebrew\'s creator: Max Howell\. +Former maintainers with significant contributions include Xu Cheng, Martin Afanasjew, Dominyk Tiller, Brett Koonce, Jack Nagel, Adam Vandenberg and Homebrew\'s creator: Max Howell\. . .SH "BUGS" See our issues on GitHub: |
