diff options
Diffstat (limited to 'Library')
291 files changed, 7271 insertions, 8311 deletions
diff --git a/Library/.rubocop.yml b/Library/.rubocop.yml index d6dc0c429..99de0d8a2 100644 --- a/Library/.rubocop.yml +++ b/Library/.rubocop.yml @@ -4,6 +4,8 @@ inherit_from: AllCops: TargetRubyVersion: 2.0 + Include: + - '**/.simplecov' Exclude: - 'Homebrew/cask/**/*' - 'Homebrew/vendor/**/*' diff --git a/Library/.rubocop_rules.yml b/Library/.rubocop_rules.yml index cde310930..543dc4018 100644 --- a/Library/.rubocop_rules.yml +++ b/Library/.rubocop_rules.yml @@ -1,4 +1,3 @@ - # ruby style guide favorite Style/StringLiterals: EnforcedStyle: double_quotes @@ -7,17 +6,30 @@ Style/StringLiterals: Style/StringLiteralsInInterpolation: EnforcedStyle: double_quotes +# only for numbers >= 1_000_000 +Style/NumericLiterals: + MinDigits: 7 + +# zero-prefixed octal literals are just too widely used (and mostly understood) +Style/NumericLiteralPrefix: + EnforcedOctalStyle: zero_only + # percent-x is allowed for multiline Style/CommandLiteral: EnforcedStyle: mixed +# depends_on foo: :bar looks rubbish +Style/HashSyntax: + EnforcedStyle: ruby19 + Exclude: + - 'Taps/**/*' + # paths abound, easy escape Style/RegexpLiteral: EnforcedStyle: slashes -# too prevalent to change this now, but might be discussed/changed later Style/Alias: - EnforcedStyle: prefer_alias_method + EnforcedStyle: prefer_alias # our current conditional style is established, clear and # requiring users to change that now would be confusing. @@ -58,14 +70,6 @@ Lint/ParenthesesAsGroupedExpression: Style/EmptyLineBetweenDefs: AllowAdjacentOneLineDefs: true -# port numbers and such tech stuff -Style/NumericLiterals: - Enabled: false - -# zero-prefixed octal literals are just too widely used (and mostly understood) -Style/NumericLiteralPrefix: - EnforcedOctalStyle: zero_only - # consistency and readability when faced with string interpolation Style/PercentLiteralDelimiters: PreferredDelimiters: @@ -93,15 +97,25 @@ Style/AlignParameters: # counterproductive in formulas, notably within the install method Style/GuardClause: - Enabled: false + Exclude: + - 'Taps/**/*' Style/IfUnlessModifier: + Exclude: + - 'Taps/**/*' + +# TODO: enforce when rubocop has fixed this +# https://github.com/bbatsov/rubocop/issues/3516 +Style/VariableNumber: + Enabled: false + +# TODO: enforce when rubocop has shipped this +# https://github.com/bbatsov/rubocop/pull/3513 +Style/TernaryParentheses: Enabled: false # dashes in filenames are typical -# TODO: enforce when rubocop has fixed this -# https://github.com/bbatsov/rubocop/issues/1545 Style/FileName: - Enabled: false + Regex: !ruby/regexp /^[\w\@\-\+\.]+(\.rb)?$/ # no percent word array, being friendly to non-ruby users # TODO: enforce when rubocop has fixed this @@ -134,6 +148,7 @@ Style/MethodName: Style/PredicateName: Exclude: - 'Homebrew/compat/**/*' + NameWhitelist: is_32_bit?, is_64_bit? # `formula do` uses nested method definitions Lint/NestedMethodDefinition: diff --git a/Library/.rubocop_todo.yml b/Library/.rubocop_todo.yml index a898d2f79..6a38e100f 100644 --- a/Library/.rubocop_todo.yml +++ b/Library/.rubocop_todo.yml @@ -1,21 +1,11 @@ # This configuration was generated by -# `rubocop --auto-gen-config --exclude-limit 30` -# on 2016-09-18 15:15:22 +0100 using RuboCop version 0.41.2. +# `rubocop --auto-gen-config --exclude-limit 100` +# on 2016-09-22 20:07:41 +0200 using RuboCop version 0.43.0. # 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: 4 -# Cop supports --auto-correct. -# Configuration parameters: AlignWith, SupportedStyles, AutoCorrect. -# SupportedStyles: keyword, variable, start_of_line -Lint/EndAlignment: - Exclude: - - 'Homebrew/download_strategy.rb' - - 'Homebrew/keg.rb' - - 'Homebrew/os/mac/cctools_mach.rb' - # Offense count: 18 Lint/HandleExceptions: Exclude: @@ -52,11 +42,6 @@ Lint/NestedMethodDefinition: - 'Homebrew/dev-cmd/bottle.rb' - 'Homebrew/dev-cmd/test-bot.rb' -# Offense count: 2 -Lint/NonLocalExitFromIterator: - Exclude: - - 'Homebrew/extend/pathname.rb' - # Offense count: 28 Lint/RescueException: Exclude: @@ -80,12 +65,7 @@ Lint/RescueException: # Offense count: 1 Lint/ShadowedException: Exclude: - - 'Homebrew/brew.rb' - -# Offense count: 2 -Lint/UselessAssignment: - Exclude: - - 'Homebrew/requirements.rb' + - 'Homebrew/utils/fork.rb' # Offense count: 18 Metrics/BlockNesting: @@ -94,64 +74,17 @@ Metrics/BlockNesting: # Offense count: 20 # Configuration parameters: CountComments. Metrics/ModuleLength: - Max: 400 + Max: 370 -# Offense count: 1 +# Offense count: 2 # Configuration parameters: CountKeywordArgs. Metrics/ParameterLists: Max: 6 -# Offense count: 2 -Performance/FixedSize: - Exclude: - - 'Homebrew/dev-cmd/audit.rb' - - 'Homebrew/dev-cmd/bottle.rb' - -# Offense count: 8 -Style/AccessorMethodName: - Exclude: - - 'Homebrew/download_strategy.rb' - - 'Homebrew/extend/ENV/std.rb' - - 'Homebrew/formula.rb' - - 'Homebrew/formula_lock.rb' - - 'Homebrew/formulary.rb' - - 'Homebrew/migrator.rb' - # Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. -# SupportedStyles: prefer_alias, prefer_alias_method -Style/Alias: - Exclude: - - 'Homebrew/blacklist.rb' - -# Offense count: 26 Style/CaseEquality: Exclude: - - 'Homebrew/cleanup.rb' - - 'Homebrew/cmd/search.rb' - 'Homebrew/compilers.rb' - - 'Homebrew/cxxstdlib.rb' - - 'Homebrew/debrew.rb' - - 'Homebrew/dependencies.rb' - - 'Homebrew/dependency_collector.rb' - - 'Homebrew/download_strategy.rb' - - 'Homebrew/formula.rb' - - 'Homebrew/options.rb' - - 'Homebrew/patch.rb' - - 'Homebrew/pkg_version.rb' - - 'Homebrew/requirement.rb' - - 'Homebrew/requirements.rb' - - 'Homebrew/software_spec.rb' - - 'Homebrew/version.rb' - -# Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: IndentWhenRelativeTo, SupportedStyles, IndentOneStep, IndentationWidth. -# SupportedStyles: case, end -Style/CaseIndentation: - Exclude: - - 'Homebrew/keg.rb' # Offense count: 11 Style/ClassVars: @@ -168,24 +101,6 @@ Style/ConstantName: Exclude: - 'Homebrew/os/mac.rb' -# Offense count: 10 -Style/DoubleNegation: - Exclude: - - 'Homebrew/extend/ARGV.rb' - - 'Homebrew/formula_installer.rb' - - 'Homebrew/os/mac/cctools_keg.rb' - - 'Homebrew/os/mac/ruby_keg.rb' - - 'Homebrew/os/mac/xcode.rb' - - 'Homebrew/requirement.rb' - - 'Homebrew/software_spec.rb' - -# Offense count: 1 -# Configuration parameters: EnforcedStyle, SupportedStyles. -# SupportedStyles: format, sprintf, percent -Style/FormatString: - Exclude: - - 'Homebrew/formula.rb' - # Offense count: 13 # Configuration parameters: AllowedVariables. Style/GlobalVars: @@ -193,22 +108,20 @@ Style/GlobalVars: - 'Homebrew/diagnostic.rb' - 'Homebrew/utils.rb' -# Offense count: 2 -Style/IdenticalConditionalBranches: +# Offense count: 51 +# Cop supports --auto-correct. +# Configuration parameters: MaxLineLength. +Style/IfUnlessModifier: Exclude: - - 'Homebrew/formula_lock.rb' + - 'Taps/**/*' + - 'Homebrew/dev-cmd/audit.rb' -# Offense count: 5 -# Configuration parameters: EnforcedStyle, SupportedStyles. -# SupportedStyles: snake_case, camelCase -Style/MethodName: - Exclude: - - 'Homebrew/compat/**/*' - - 'Homebrew/cleanup.rb' - - 'Homebrew/diagnostic.rb' - - 'Homebrew/formula_cellar_checks.rb' - - 'Homebrew/formula_installer.rb' - - 'Homebrew/os/mac/cctools_mach.rb' +# Offense count: 2 +# Cop supports --auto-correct. +# Configuration parameters: SupportedStyles, IndentationWidth. +# SupportedStyles: special_inside_parentheses, consistent, align_brackets +Style/IndentArray: + EnforcedStyle: special_inside_parentheses # Offense count: 7 # Configuration parameters: EnforcedStyle, SupportedStyles. @@ -219,8 +132,6 @@ Style/ModuleFunction: - 'Homebrew/os/mac.rb' - 'Homebrew/os/mac/xcode.rb' - 'Homebrew/os/mac/xquartz.rb' - - 'Homebrew/utils/github.rb' - - 'Homebrew/utils/json.rb' # Offense count: 8 Style/MultilineBlockChain: @@ -241,14 +152,6 @@ Style/MutableConstant: - 'Homebrew/tab.rb' - 'Homebrew/tap.rb' -# Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, MinBodyLength, SupportedStyles. -# SupportedStyles: skip_modifier_ifs, always -Style/Next: - Exclude: - - 'Homebrew/dev-cmd/test-bot.rb' - # Offense count: 9 Style/OpMethod: Exclude: @@ -257,37 +160,9 @@ Style/OpMethod: - 'Homebrew/install_renamed.rb' - 'Homebrew/options.rb' -# Offense count: 4 -# Configuration parameters: NamePrefix, NamePrefixBlacklist, NameWhitelist. -# NamePrefix: is_, has_, have_ -# NamePrefixBlacklist: is_, has_, have_ -# NameWhitelist: is_a? -Style/PredicateName: - Exclude: - - 'Homebrew/compat/**/*' - - 'Homebrew/download_strategy.rb' - - 'Homebrew/hardware.rb' - -# Offense count: 7 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles, AllowInnerSlashes. -# SupportedStyles: slashes, percent_r, mixed -Style/RegexpLiteral: - Exclude: - - 'Homebrew/diagnostic.rb' - - 'Homebrew/keg.rb' - - 'Homebrew/version.rb' - -# Offense count: 1 +# Offense count: 2 # Cop supports --auto-correct. -# Configuration parameters: AllowAsExpressionSeparator. -Style/Semicolon: - Exclude: - - 'Homebrew/descriptions.rb' - -# Offense count: 1 -# Configuration parameters: Methods. -# Methods: {"reduce"=>["a", "e"]}, {"inject"=>["a", "e"]} -Style/SingleLineBlockParams: - Exclude: - - 'Homebrew/diagnostic.rb' +# Configuration parameters: SupportedStyles. +# SupportedStyles: use_perl_names, use_english_names +Style/SpecialGlobalVars: + EnforcedStyle: use_perl_names diff --git a/Library/Homebrew/test/.simplecov b/Library/Homebrew/.simplecov index 7b057e878..bc4ed7bb1 100755 --- a/Library/Homebrew/test/.simplecov +++ b/Library/Homebrew/.simplecov @@ -1,8 +1,8 @@ #!/usr/bin/env ruby SimpleCov.start do - coverage_dir File.expand_path("../coverage", File.realpath(__FILE__)) - root File.expand_path("../..", File.realpath(__FILE__)) + coverage_dir File.expand_path("../test/coverage", File.realpath(__FILE__)) + root File.expand_path("..", File.realpath(__FILE__)) # We manage the result cache ourselves and the default of 10 minutes can be # too low (particularly on Travis CI), causing results from some integration @@ -16,14 +16,21 @@ SimpleCov.start do add_filter "/Homebrew/vendor/" if ENV["HOMEBREW_INTEGRATION_TEST"] - command_name ENV["HOMEBREW_INTEGRATION_TEST"] + command_name "#{ENV["HOMEBREW_INTEGRATION_TEST"]} (#{$$})" at_exit do exit_code = $!.nil? ? 0 : $!.status $stdout.reopen("/dev/null") - SimpleCov.result # Just save result, but don't write formatted output. + + # Just save result, but don't write formatted output. + coverage_result = Coverage.result + SimpleCov.add_not_loaded_files(coverage_result) + simplecov_result = SimpleCov::Result.new(coverage_result) + SimpleCov::ResultMerger.store_result(simplecov_result) + exit! exit_code end else + command_name "#{command_name} (#{$$})" # Not using this during integration tests makes the tests 4x times faster # without changing the coverage. track_files "#{SimpleCov.root}/**/*.rb" diff --git a/Library/Homebrew/brew.rb b/Library/Homebrew/brew.rb index eeadc70e1..1ba3fb8c2 100644 --- a/Library/Homebrew/brew.rb +++ b/Library/Homebrew/brew.rb @@ -14,7 +14,7 @@ $:.unshift(HOMEBREW_LIBRARY_PATH.to_s) require "global" if ARGV == %w[--version] || ARGV == %w[-v] - puts "Homebrew #{Homebrew.homebrew_version_string}" + puts "Homebrew #{HOMEBREW_VERSION}" puts "Homebrew/homebrew-core #{Homebrew.core_tap_version_string}" exit 0 end @@ -37,9 +37,9 @@ begin cmd = nil ARGV.dup.each_with_index do |arg, i| - if help_flag && cmd - break - elsif help_flag_list.include?(arg) + break if help_flag && cmd + + if help_flag_list.include?(arg) # Option-style help: Both `--help <cmd>` and `<cmd> --help` are fine. help_flag = true elsif arg == "help" && !cmd diff --git a/Library/Homebrew/brew.sh b/Library/Homebrew/brew.sh index fc2e6993c..22ebb87ed 100644 --- a/Library/Homebrew/brew.sh +++ b/Library/Homebrew/brew.sh @@ -1,4 +1,8 @@ -HOMEBREW_VERSION="0.9.9" +HOMEBREW_VERSION="$(git -C "$HOMEBREW_REPOSITORY" describe --tags --dirty 2>/dev/null)" +if [[ -z "$HOMEBREW_VERSION" ]] +then + HOMEBREW_VERSION=">1.0.0 (no git repository)" +fi onoe() { if [[ -t 2 ]] # check whether stderr is a tty. diff --git a/Library/Homebrew/build.rb b/Library/Homebrew/build.rb index f4dde895a..d3c2833d4 100644 --- a/Library/Homebrew/build.rb +++ b/Library/Homebrew/build.rb @@ -31,9 +31,8 @@ class Build def post_superenv_hacks # Only allow Homebrew-approved directories into the PATH, unless # a formula opts-in to allowing the user's path. - if formula.env.userpaths? || reqs.any? { |rq| rq.env.userpaths? } - ENV.userpaths! - end + return unless formula.env.userpaths? || reqs.any? { |rq| rq.env.userpaths? } + ENV.userpaths! end def effective_build_options_for(dependent) diff --git a/Library/Homebrew/build_options.rb b/Library/Homebrew/build_options.rb index 6af3220eb..e9a06f4e0 100644 --- a/Library/Homebrew/build_options.rb +++ b/Library/Homebrew/build_options.rb @@ -47,7 +47,7 @@ class BuildOptions def bottle? include? "build-bottle" end - alias_method :build_bottle?, :bottle? + alias build_bottle? bottle? # True if a {Formula} is being built with {Formula.head} instead of {Formula.stable}. # <pre>args << "--some-new-stuff" if build.head?</pre> diff --git a/Library/Homebrew/cask/.rubocop.yml b/Library/Homebrew/cask/.rubocop.yml index 31a2a193d..96a0b0e11 100644 --- a/Library/Homebrew/cask/.rubocop.yml +++ b/Library/Homebrew/cask/.rubocop.yml @@ -1,10 +1,8 @@ -require: 'rubocop-cask' - AllCops: TargetRubyVersion: 2.0 Exclude: + - '**/.simplecov' - '**/Casks/**/*' - - 'developer/**/*' - '**/vendor/**/*' Metrics/AbcSize: @@ -16,10 +14,10 @@ Metrics/ClassLength: Metrics/CyclomaticComplexity: Enabled: false -Metrics/MethodLength: +Metrics/LineLength: Enabled: false -Metrics/PerceivedComplexity: +Metrics/MethodLength: Enabled: false Metrics/ModuleLength: @@ -29,6 +27,16 @@ Metrics/ModuleLength: - 'lib/hbc/macos.rb' - 'lib/hbc/utils.rb' +Metrics/PerceivedComplexity: + Enabled: false + +Style/AlignHash: + EnforcedHashRocketStyle: table + EnforcedColonStyle: table + +Style/BarePercentLiterals: + EnforcedStyle: percent_q + Style/BlockDelimiters: EnforcedStyle: semantic FunctionalMethods: @@ -59,6 +67,8 @@ Style/BlockDelimiters: - chdir - context - create + - define_method + - define_singleton_method - each_with_object - fork - measure @@ -75,15 +85,47 @@ Style/BlockDelimiters: - lambda - proc - Style/ClassAndModuleChildren: - EnforcedStyle: compact + EnforcedStyle: nested -Style/PredicateName: - NameWhitelist: is_32_bit?, is_64_bit? +Style/Documentation: + Enabled: false + +Style/FileName: + Regex: !ruby/regexp /^((([\dA-Z]+|[\da-z]+)(_([\dA-Z]+|[\da-z]+))*|(\-\-)?([\dA-Z]+|[\da-z]+)(-([\dA-Z]+|[\da-z]+))*))(\.rb)?$/ + +Style/HashSyntax: + EnforcedStyle: ruby19_no_mixed_keys + +Style/IndentArray: + EnforcedStyle: align_brackets + +Style/IndentHash: + EnforcedStyle: align_braces + +Style/PercentLiteralDelimiters: + PreferredDelimiters: + '%': '{}' + '%i': '{}' + '%q': '{}' + '%Q': '{}' + '%r': '{}' + '%s': '()' + '%w': '[]' + '%W': '[]' + '%x': '()' Style/RaiseArgs: EnforcedStyle: exploded +Style/RegexpLiteral: + EnforcedStyle: percent_r + Style/StringLiterals: EnforcedStyle: double_quotes + +Style/StringLiteralsInInterpolation: + EnforcedStyle: double_quotes + +Style/TrailingCommaInLiteral: + EnforcedStyleForMultiline: comma diff --git a/Library/Homebrew/cask/.simplecov b/Library/Homebrew/cask/.simplecov index d1b045262..75a078be4 120000 --- a/Library/Homebrew/cask/.simplecov +++ b/Library/Homebrew/cask/.simplecov @@ -1 +1 @@ -../test/.simplecov
\ No newline at end of file +../.simplecov
\ No newline at end of file diff --git a/Library/Homebrew/cask/Gemfile b/Library/Homebrew/cask/Gemfile index af1c8d3bc..df06bd5d4 100644 --- a/Library/Homebrew/cask/Gemfile +++ b/Library/Homebrew/cask/Gemfile @@ -7,15 +7,21 @@ group :debug do gem "pry-byebug", platforms: :mri end -group :development do - gem "rubocop-cask", "~> 0.8.3" -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", # commit 83d8031ddde0927f87ef9327200a98583ca18d77 + require: false gem "codecov", require: false gem "minitest", "5.4.1" gem "minitest-reporters" gem "mocha", "1.1.0", require: false + gem "parallel_tests" gem "rspec", "~> 3.0.0" gem "rspec-its", require: false gem "rspec-wait", require: false diff --git a/Library/Homebrew/cask/Gemfile.lock b/Library/Homebrew/cask/Gemfile.lock index c9c2b5cca..93dd59712 100644 --- a/Library/Homebrew/cask/Gemfile.lock +++ b/Library/Homebrew/cask/Gemfile.lock @@ -1,8 +1,17 @@ +GIT + remote: https://github.com/colszowka/simplecov.git + revision: 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) - ast (2.3.0) builder (3.2.2) byebug (9.0.5) codecov (0.1.5) @@ -23,9 +32,9 @@ GEM ruby-progressbar mocha (1.1.0) metaclass (~> 0.0.1) - parser (2.3.1.2) - ast (~> 2.2) - powerpack (0.1.1) + parallel (1.9.0) + parallel_tests (2.9.0) + parallel pry (0.10.4) coderay (~> 1.1.0) method_source (~> 0.8.1) @@ -33,8 +42,6 @@ GEM pry-byebug (3.4.0) byebug (~> 9.0) pry (~> 0.10) - public_suffix (2.0.2) - rainbow (2.1.0) rake (10.4.2) rspec (3.0.0) rspec-core (~> 3.0.0) @@ -53,23 +60,9 @@ GEM rspec-support (3.0.4) rspec-wait (0.0.9) rspec (>= 3, < 4) - rubocop (0.41.2) - parser (>= 2.3.1.1, < 3.0) - powerpack (~> 0.1) - rainbow (>= 1.99.1, < 3.0) - ruby-progressbar (~> 1.7) - unicode-display_width (~> 1.0, >= 1.0.1) - rubocop-cask (0.8.3) - public_suffix (~> 2.0) - rubocop (~> 0.41.1) ruby-progressbar (1.8.1) - simplecov (0.12.0) - docile (~> 1.1.0) - json (>= 1.8, < 3) - simplecov-html (~> 0.10.0) simplecov-html (0.10.0) slop (3.6.0) - unicode-display_width (1.1.0) url (0.3.2) PLATFORMS @@ -80,13 +73,14 @@ DEPENDENCIES minitest (= 5.4.1) minitest-reporters mocha (= 1.1.0) + parallel_tests pry pry-byebug rake rspec (~> 3.0.0) rspec-its rspec-wait - rubocop-cask (~> 0.8.3) + simplecov (= 0.12.0)! BUNDLED WITH - 1.12.5 + 1.13.1 diff --git a/Library/Homebrew/cask/Rakefile b/Library/Homebrew/cask/Rakefile index 25deee407..ec6a4a7f6 100644 --- a/Library/Homebrew/cask/Rakefile +++ b/Library/Homebrew/cask/Rakefile @@ -1,29 +1,14 @@ require "rake/testtask" require "rspec/core/rake_task" -require "rubocop/rake_task" homebrew_repo = `brew --repository`.chomp $LOAD_PATH.unshift(File.expand_path("#{homebrew_repo}/Library/Homebrew")) $LOAD_PATH.unshift(File.expand_path("../lib", __FILE__)) namespace :test do - Rake::TestTask.new(:minitest) do |t| - # TODO: setting the --seed here is an ugly temporary hack, to remain only - # until test-suite glitches are fixed. - ENV["TESTOPTS"] = "--seed=14830" if ENV["TRAVIS"] - t.pattern = "test/**/*_test.rb" - t.libs << "test" - end - - RSpec::Core::RakeTask.new(:rspec) - - desc "Run tests for minitest and RSpec with coverage" - task :coverage do - ENV["HOMEBREW_TESTS_COVERAGE"] = "1" - - Rake::Task[:test].invoke - - if ENV["CODECOV_TOKEN"] + namespace :coverage do + desc "Upload coverage to Codecov" + task :upload do require "simplecov" require "codecov" formatter = SimpleCov::Formatter::Codecov.new @@ -32,15 +17,6 @@ namespace :test do end end -desc "Run tests for minitest and RSpec" -task test: ["test:minitest", "test:rspec"] - -RuboCop::RakeTask.new(:rubocop) do |t| - t.options = ["--force-exclusion"] -end - -task default: [:test, :rubocop] - desc "Open a REPL for debugging and experimentation" task :console do require "pry" diff --git a/Library/Homebrew/cask/cmd/brew-cask-tests.rb b/Library/Homebrew/cask/cmd/brew-cask-tests.rb index 92ef3ddd9..7ae71020e 100755 --- a/Library/Homebrew/cask/cmd/brew-cask-tests.rb +++ b/Library/Homebrew/cask/cmd/brew-cask-tests.rb @@ -1,5 +1,12 @@ require "English" +def run_tests(executable, files, args = []) + opts = [] + opts << "--serialize-stdout" if ENV["CI"] + + system "bundle", "exec", executable, *opts, "--", *args, "--", *files +end + repo_root = Pathname(__FILE__).realpath.parent.parent repo_root.cd do ENV["HOMEBREW_NO_ANALYTICS_THIS_RUN"] = "1" @@ -9,12 +16,26 @@ repo_root.cd do system "bundle", "install", "--path", "vendor/bundle" end - test_task = "test" - %w[rspec minitest coverage].each do |subtask| - next unless ARGV.flag?("--#{subtask}") - test_task = "test:#{subtask}" + rspec = ARGV.flag?("--rspec") || !ARGV.flag?("--minitest") + minitest = ARGV.flag?("--minitest") || !ARGV.flag?("--rspec") + + ENV["HOMEBREW_TESTS_COVERAGE"] = "1" if ARGV.flag?("--coverage") + + if rspec + run_tests "parallel_rspec", Dir["spec/**/*_spec.rb"], %w[ + --format progress + --format ParallelTests::RSpec::RuntimeLogger + --out tmp/parallel_runtime_rspec.log + ] + end + + if minitest + run_tests "parallel_test", Dir["test/**/*_test.rb"] + end + + if ENV["CODECOV_TOKEN"] + system "bundle", "exec", "rake", "test:coverage:upload" end - system "bundle", "exec", "rake", test_task Homebrew.failed = !$CHILD_STATUS.success? end diff --git a/Library/Homebrew/cask/lib/hbc.rb b/Library/Homebrew/cask/lib/hbc.rb index fd61558ab..62b391638 100644 --- a/Library/Homebrew/cask/lib/hbc.rb +++ b/Library/Homebrew/cask/lib/hbc.rb @@ -40,22 +40,22 @@ require "utils" require "vendor/plist/plist" module Hbc - include Hbc::Locations - include Hbc::Scopes - include Hbc::Options - include Hbc::Utils + include Locations + include Scopes + include Options + include Utils def self.init - Hbc::Cache.ensure_cache_exists - Hbc::Cache.migrate_legacy_cache + Cache.ensure_cache_exists + Cache.migrate_legacy_cache - Hbc::Caskroom.migrate_caskroom_from_repo_to_prefix - Hbc::Caskroom.ensure_caskroom_exists + Caskroom.migrate_caskroom_from_repo_to_prefix + Caskroom.ensure_caskroom_exists end def self.load(query) odebug "Loading Cask definitions" - cask = Hbc::Source.for_query(query).load + cask = Source.for_query(query).load cask.dumpcask cask end diff --git a/Library/Homebrew/cask/lib/hbc/artifact.rb b/Library/Homebrew/cask/lib/hbc/artifact.rb index 73bd582a5..ec808a614 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact.rb @@ -1,5 +1,3 @@ -module Hbc::Artifact; end - require "hbc/artifact/app" require "hbc/artifact/artifact" # generic 'artifact' stanza require "hbc/artifact/binary" @@ -24,42 +22,44 @@ require "hbc/artifact/suite" require "hbc/artifact/uninstall" require "hbc/artifact/zap" -module Hbc::Artifact - # NOTE: order is important here, since we want to extract nested containers - # before we handle any other artifacts - def self.artifacts - [ - Hbc::Artifact::PreflightBlock, - Hbc::Artifact::NestedContainer, - Hbc::Artifact::Installer, - Hbc::Artifact::App, - Hbc::Artifact::Suite, - Hbc::Artifact::Artifact, # generic 'artifact' stanza - Hbc::Artifact::Colorpicker, - Hbc::Artifact::Pkg, - Hbc::Artifact::Prefpane, - Hbc::Artifact::Qlplugin, - Hbc::Artifact::Font, - Hbc::Artifact::Service, - Hbc::Artifact::StageOnly, - Hbc::Artifact::Binary, - Hbc::Artifact::InputMethod, - Hbc::Artifact::InternetPlugin, - Hbc::Artifact::AudioUnitPlugin, - Hbc::Artifact::VstPlugin, - Hbc::Artifact::Vst3Plugin, - Hbc::Artifact::ScreenSaver, - Hbc::Artifact::Uninstall, - Hbc::Artifact::PostflightBlock, - Hbc::Artifact::Zap, - ] - end +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, + Font, + Service, + StageOnly, + Binary, + InputMethod, + InternetPlugin, + AudioUnitPlugin, + VstPlugin, + Vst3Plugin, + ScreenSaver, + Uninstall, + PostflightBlock, + Zap, + ] + end - def self.for_cask(cask) - odebug "Determining which artifacts are present in Cask #{cask}" - artifacts.select do |artifact| - odebug "Checking for artifact class #{artifact}" - artifact.me?(cask) + def self.for_cask(cask) + odebug "Determining which artifacts are present in Cask #{cask}" + artifacts.select do |artifact| + odebug "Checking for artifact class #{artifact}" + artifact.me?(cask) + end end end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/abstract_flight_block.rb b/Library/Homebrew/cask/lib/hbc/artifact/abstract_flight_block.rb index fcf98d7ad..30709a0b5 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/abstract_flight_block.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/abstract_flight_block.rb @@ -1,36 +1,40 @@ require "hbc/artifact/base" -class Hbc::Artifact::AbstractFlightBlock < Hbc::Artifact::Base - def self.artifact_dsl_key - super.to_s.sub(%r{_block$}, "").to_sym - end - - def self.uninstall_artifact_dsl_key - artifact_dsl_key.to_s.prepend("uninstall_").to_sym - end - - def self.class_for_dsl_key(dsl_key) - Object.const_get("Hbc::DSL::#{dsl_key.to_s.split('_').collect(&:capitalize).join}") - end - - def self.me?(cask) - cask.artifacts[artifact_dsl_key].any? || - cask.artifacts[uninstall_artifact_dsl_key].any? - end - - def install_phase - abstract_phase(self.class.artifact_dsl_key) - end - - def uninstall_phase - abstract_phase(self.class.uninstall_artifact_dsl_key) - end - - private - - def abstract_phase(dsl_key) - @cask.artifacts[dsl_key].each do |block| - self.class.class_for_dsl_key(dsl_key).new(@cask).instance_eval(&block) +module Hbc + module Artifact + class AbstractFlightBlock < Base + def self.artifact_dsl_key + super.to_s.sub(%r{_block$}, "").to_sym + end + + def self.uninstall_artifact_dsl_key + artifact_dsl_key.to_s.prepend("uninstall_").to_sym + end + + def self.class_for_dsl_key(dsl_key) + Object.const_get("Hbc::DSL::#{dsl_key.to_s.split("_").collect(&:capitalize).join}") + end + + def self.me?(cask) + cask.artifacts[artifact_dsl_key].any? || + cask.artifacts[uninstall_artifact_dsl_key].any? + end + + def install_phase + abstract_phase(self.class.artifact_dsl_key) + end + + def uninstall_phase + abstract_phase(self.class.uninstall_artifact_dsl_key) + end + + private + + def abstract_phase(dsl_key) + @cask.artifacts[dsl_key].each do |block| + self.class.class_for_dsl_key(dsl_key).new(@cask).instance_eval(&block) + end + end end end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/app.rb b/Library/Homebrew/cask/lib/hbc/artifact/app.rb index bbda16f74..cc6ef61a7 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/app.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/app.rb @@ -1,4 +1,8 @@ require "hbc/artifact/moved" -class Hbc::Artifact::App < Hbc::Artifact::Moved +module Hbc + module Artifact + class App < Moved + end + end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/artifact.rb b/Library/Homebrew/cask/lib/hbc/artifact/artifact.rb index e2c06eb70..cb35821cc 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/artifact.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/artifact.rb @@ -1,20 +1,24 @@ require "hbc/artifact/moved" -class Hbc::Artifact::Artifact < Hbc::Artifact::Moved - def self.artifact_english_name - "Generic Artifact" - end +module Hbc + module Artifact + class Artifact < Moved + def self.artifact_english_name + "Generic Artifact" + end - def self.artifact_dirmethod - :appdir - end + def self.artifact_dirmethod + :appdir + end - def load_specification(artifact_spec) - source_string, target_hash = artifact_spec - raise Hbc::CaskInvalidError.new(@cask.token, "no source given for artifact") if source_string.nil? - @source = @cask.staged_path.join(source_string) - raise Hbc::CaskInvalidError.new(@cask.token, "target required for generic artifact #{source_string}") unless target_hash.is_a?(Hash) - target_hash.assert_valid_keys(:target) - @target = Pathname.new(target_hash[:target]) + def load_specification(artifact_spec) + source_string, target_hash = artifact_spec + raise CaskInvalidError.new(@cask.token, "no source given for artifact") if source_string.nil? + @source = @cask.staged_path.join(source_string) + raise CaskInvalidError.new(@cask.token, "target required for generic artifact #{source_string}") unless target_hash.is_a?(Hash) + target_hash.assert_valid_keys(:target) + @target = Pathname.new(target_hash[:target]) + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/audio_unit_plugin.rb b/Library/Homebrew/cask/lib/hbc/artifact/audio_unit_plugin.rb index 7f3999306..3bad78073 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/audio_unit_plugin.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/audio_unit_plugin.rb @@ -1,4 +1,8 @@ require "hbc/artifact/moved" -class Hbc::Artifact::AudioUnitPlugin < Hbc::Artifact::Moved +module Hbc + module Artifact + class AudioUnitPlugin < Moved + end + end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/base.rb b/Library/Homebrew/cask/lib/hbc/artifact/base.rb index 9a07cc906..141ab6881 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/base.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/base.rb @@ -1,79 +1,83 @@ -class Hbc::Artifact::Base - def self.artifact_name - @artifact_name ||= name.sub(%r{^.*:}, "").gsub(%r{(.)([A-Z])}, '\1_\2').downcase - end - - def self.artifact_english_name - @artifact_english_name ||= name.sub(%r{^.*:}, "").gsub(%r{(.)([A-Z])}, '\1 \2') - end - - def self.artifact_english_article - @artifact_english_article ||= artifact_english_name =~ %r{^[aeiou]}i ? "an" : "a" - end - - def self.artifact_dsl_key - @artifact_dsl_key ||= artifact_name.to_sym - end - - def self.artifact_dirmethod - @artifact_dirmethod ||= "#{artifact_name}dir".to_sym - end - - def self.me?(cask) - cask.artifacts[artifact_dsl_key].any? - end - - 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) - # TODO: when stanza names are harmonized with class names, - # stanza may not be needed as an explicit argument - description = stanza.to_s - if key - arguments = arguments[key] - description.concat(" #{key.inspect}") - end - - # backward-compatible string value - arguments = { executable: arguments } if arguments.is_a?(String) - - # key sanity - permitted_keys = [:args, :input, :executable, :must_succeed, :sudo, :bsexec, :print_stdout, :print_stderr] - unknown_keys = arguments.keys - permitted_keys - unless unknown_keys.empty? - opoo %Q{Unknown arguments to #{description} -- #{unknown_keys.inspect} (ignored). Running "brew update; brew cleanup; brew cask cleanup" will likely fix it.} +module Hbc + module Artifact + class Base + def self.artifact_name + @artifact_name ||= name.sub(%r{^.*:}, "").gsub(%r{(.)([A-Z])}, '\1_\2').downcase + end + + def self.artifact_english_name + @artifact_english_name ||= name.sub(%r{^.*:}, "").gsub(%r{(.)([A-Z])}, '\1 \2') + end + + def self.artifact_english_article + @artifact_english_article ||= artifact_english_name =~ %r{^[aeiou]}i ? "an" : "a" + end + + def self.artifact_dsl_key + @artifact_dsl_key ||= artifact_name.to_sym + end + + def self.artifact_dirmethod + @artifact_dirmethod ||= "#{artifact_name}dir".to_sym + end + + def self.me?(cask) + cask.artifacts[artifact_dsl_key].any? + end + + 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) + # TODO: when stanza names are harmonized with class names, + # stanza may not be needed as an explicit argument + description = stanza.to_s + if key + arguments = arguments[key] + description.concat(" #{key.inspect}") + end + + # backward-compatible string value + arguments = { executable: arguments } if arguments.is_a?(String) + + # key sanity + permitted_keys = [:args, :input, :executable, :must_succeed, :sudo, :bsexec, :print_stdout, :print_stderr] + unknown_keys = arguments.keys - permitted_keys + unless unknown_keys.empty? + opoo %Q{Unknown arguments to #{description} -- #{unknown_keys.inspect} (ignored). Running "brew update; brew cleanup; brew cask cleanup" will likely fix it.} + end + arguments.reject! { |k| !permitted_keys.include?(k) } + + # key warnings + override_keys = override_arguments.keys + ignored_keys = arguments.keys & override_keys + unless ignored_keys.empty? + onoe "Some arguments to #{description} will be ignored -- :#{unknown_keys.inspect} (overridden)." + end + + # extract executable + executable = arguments.key?(:executable) ? arguments.delete(:executable) : nil + + arguments = default_arguments.merge arguments + arguments.merge! override_arguments + + [executable, arguments] + end + + def summary + {} + end + + def initialize(cask, command: SystemCommand, force: false) + @cask = cask + @command = command + @force = force + end end - arguments.reject! { |k| !permitted_keys.include?(k) } - - # key warnings - override_keys = override_arguments.keys - ignored_keys = arguments.keys & override_keys - unless ignored_keys.empty? - onoe "Some arguments to #{description} will be ignored -- :#{unknown_keys.inspect} (overridden)." - end - - # extract executable - executable = arguments.key?(:executable) ? arguments.delete(:executable) : nil - - arguments = default_arguments.merge arguments - arguments.merge! override_arguments - - [executable, arguments] - end - - def summary - {} - end - - def initialize(cask, command: Hbc::SystemCommand, force: false) - @cask = cask - @command = command - @force = force end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/binary.rb b/Library/Homebrew/cask/lib/hbc/artifact/binary.rb index ccaebe0c8..646e5c3ad 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/binary.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/binary.rb @@ -1,7 +1,11 @@ require "hbc/artifact/symlinked" -class Hbc::Artifact::Binary < Hbc::Artifact::Symlinked - def install_phase - super unless Hbc.no_binaries +module Hbc + module Artifact + class Binary < Symlinked + def install_phase + super unless Hbc.no_binaries + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/colorpicker.rb b/Library/Homebrew/cask/lib/hbc/artifact/colorpicker.rb index 7b56d0ffc..a866e64a5 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/colorpicker.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/colorpicker.rb @@ -1,4 +1,8 @@ require "hbc/artifact/moved" -class Hbc::Artifact::Colorpicker < Hbc::Artifact::Moved +module Hbc + module Artifact + class Colorpicker < Moved + end + end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/font.rb b/Library/Homebrew/cask/lib/hbc/artifact/font.rb index 9697d9e13..5c64869b6 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/font.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/font.rb @@ -1,4 +1,8 @@ require "hbc/artifact/moved" -class Hbc::Artifact::Font < Hbc::Artifact::Moved +module Hbc + module Artifact + class Font < Moved + end + end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/input_method.rb b/Library/Homebrew/cask/lib/hbc/artifact/input_method.rb index 3c7f3d990..0eb75a6c0 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/input_method.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/input_method.rb @@ -1,4 +1,8 @@ require "hbc/artifact/moved" -class Hbc::Artifact::InputMethod < Hbc::Artifact::Moved +module Hbc + module Artifact + class InputMethod < Moved + end + end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/installer.rb b/Library/Homebrew/cask/lib/hbc/artifact/installer.rb index 2f66397e9..b64b00fe3 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/installer.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/installer.rb @@ -1,41 +1,45 @@ require "hbc/artifact/base" -class Hbc::Artifact::Installer < Hbc::Artifact::Base - # TODO: for backward compatibility, removeme - def install - install_phase - end +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 + # 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 - puts <<-EOS.undent - To complete the installation of Cask #{@cask}, you must also - run the installer at + def install_phase + @cask.artifacts[self.class.artifact_dsl_key].each do |artifact| + if artifact.manual + puts <<-EOS.undent + To complete the installation of Cask #{@cask}, you must also + run the installer at - '#{@cask.staged_path.join(artifact.manual)}' + '#{@cask.staged_path.join(artifact.manual)}' - EOS - else - executable, script_arguments = self.class.read_script_arguments(artifact.script, - self.class.artifact_dsl_key.to_s, - { must_succeed: true, sudo: true }, - print_stdout: true) - ohai "Running #{self.class.artifact_dsl_key} script #{executable}" - raise Hbc::CaskInvalidError.new(@cask, "#{self.class.artifact_dsl_key} missing executable") if executable.nil? - executable_path = @cask.staged_path.join(executable) - @command.run("/bin/chmod", args: ["--", "+x", executable_path]) if File.exist?(executable_path) - @command.run(executable_path, script_arguments) + EOS + else + executable, script_arguments = self.class.read_script_arguments(artifact.script, + self.class.artifact_dsl_key.to_s, + { must_succeed: true, sudo: true }, + print_stdout: true) + ohai "Running #{self.class.artifact_dsl_key} script #{executable}" + raise CaskInvalidError.new(@cask, "#{self.class.artifact_dsl_key} missing executable") if executable.nil? + executable_path = @cask.staged_path.join(executable) + @command.run("/bin/chmod", args: ["--", "+x", executable_path]) if File.exist?(executable_path) + @command.run(executable_path, script_arguments) + end + end end - end - end - def uninstall_phase - odebug "Nothing to do. The #{self.class.artifact_dsl_key} artifact has no uninstall phase." + 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/internet_plugin.rb b/Library/Homebrew/cask/lib/hbc/artifact/internet_plugin.rb index a44418274..ab8586d69 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/internet_plugin.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/internet_plugin.rb @@ -1,4 +1,8 @@ require "hbc/artifact/moved" -class Hbc::Artifact::InternetPlugin < Hbc::Artifact::Moved +module Hbc + module Artifact + class InternetPlugin < Moved + end + end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/moved.rb b/Library/Homebrew/cask/lib/hbc/artifact/moved.rb index 8565ab836..6095887e3 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/moved.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/moved.rb @@ -1,88 +1,92 @@ require "hbc/artifact/relocated" -class Hbc::Artifact::Moved < Hbc::Artifact::Relocated - def self.english_description - "#{artifact_english_name}s" - end +module Hbc + module Artifact + class Moved < Relocated + def self.english_description + "#{artifact_english_name}s" + end - def install_phase - each_artifact do |artifact| - load_specification(artifact) - next unless preflight_checks - delete if Hbc::Utils.path_occupied?(target) && force - move - end - end + def install_phase + each_artifact do |artifact| + load_specification(artifact) + next unless preflight_checks + delete if Utils.path_occupied?(target) && force + move + end + end - def uninstall_phase - each_artifact do |artifact| - load_specification(artifact) - next unless File.exist?(target) - delete - end - end + def uninstall_phase + each_artifact do |artifact| + load_specification(artifact) + next unless File.exist?(target) + delete + end + end - private + private - def each_artifact - # the sort is for predictability between Ruby versions - @cask.artifacts[self.class.artifact_dsl_key].sort.each do |artifact| - yield artifact - end - end + def each_artifact + # the sort is for predictability between Ruby versions + @cask.artifacts[self.class.artifact_dsl_key].sort.each do |artifact| + yield artifact + end + end - def move - ohai "Moving #{self.class.artifact_english_name} '#{source.basename}' to '#{target}'" - target.dirname.mkpath - FileUtils.move(source, target) - add_altname_metadata target, source.basename.to_s - end + def move + ohai "Moving #{self.class.artifact_english_name} '#{source.basename}' to '#{target}'" + target.dirname.mkpath + FileUtils.move(source, target) + add_altname_metadata target, source.basename.to_s + end - def preflight_checks - if Hbc::Utils.path_occupied?(target) - if force - ohai(warning_target_exists { |s| s << "overwriting." }) - else - ohai(warning_target_exists { |s| s << "not moving." }) - return false + def preflight_checks + if Utils.path_occupied?(target) + if force + ohai(warning_target_exists { |s| s << "overwriting." }) + else + ohai(warning_target_exists { |s| s << "not moving." }) + return false + end + end + unless source.exist? + message = "It seems the #{self.class.artifact_english_name} source is not there: '#{source}'" + raise CaskError, message + end + true end - end - unless source.exist? - message = "It seems the #{self.class.artifact_english_name} source is not there: '#{source}'" - raise Hbc::CaskError, message - end - true - end - def warning_target_exists - message_parts = [ - "It seems there is already #{self.class.artifact_english_article} #{self.class.artifact_english_name} at '#{target}'", - ] - yield(message_parts) if block_given? - message_parts.join("; ") - end + def warning_target_exists + message_parts = [ + "It seems there is already #{self.class.artifact_english_article} #{self.class.artifact_english_name} at '#{target}'", + ] + yield(message_parts) if block_given? + message_parts.join("; ") + end - def delete - ohai "Removing #{self.class.artifact_english_name}: '#{target}'" - if MacOS.undeletable?(target) - raise Hbc::CaskError, "Cannot remove undeletable #{self.class.artifact_english_name}" - elsif force - Hbc::Utils.gain_permissions_remove(target, command: @command) - else - target.rmtree - end - end + def delete + ohai "Removing #{self.class.artifact_english_name}: '#{target}'" + raise CaskError, "Cannot remove undeletable #{self.class.artifact_english_name}" if MacOS.undeletable?(target) - def summarize_artifact(artifact_spec) - load_specification artifact_spec + if force + Utils.gain_permissions_remove(target, command: @command) + else + target.rmtree + end + end - if target.exist? - target_abv = " (#{target.abv})" - else - warning = "Missing #{self.class.artifact_english_name}" - warning = "#{Tty.red}#{warning}#{Tty.reset}: " - end + def summarize_artifact(artifact_spec) + load_specification artifact_spec - "#{warning}#{printable_target}#{target_abv}" + if target.exist? + target_abv = " (#{target.abv})" + else + warning = "Missing #{self.class.artifact_english_name}" + warning = "#{Tty.red}#{warning}#{Tty.reset}: " + end + + "#{warning}#{printable_target}#{target_abv}" + 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 68e4a552c..107640797 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/nested_container.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/nested_container.rb @@ -1,24 +1,28 @@ require "hbc/artifact/base" -class Hbc::Artifact::NestedContainer < Hbc::Artifact::Base - def install_phase - @cask.artifacts[:nested_container].each { |container| extract(container) } - end +module Hbc + module Artifact + class NestedContainer < Base + def install_phase + @cask.artifacts[:nested_container].each { |container| extract(container) } + end - def uninstall_phase - # no need to take action; is removed after extraction - 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 = Hbc::Container.for_path(source, @command) + def extract(container_relative_path) + source = @cask.staged_path.join(container_relative_path) + container = Container.for_path(source, @command) - unless container - raise Hbc::CaskError, "Aw dang, could not identify nested container at '#{source}'" - end + unless container + raise CaskError, "Aw dang, could not identify nested container at '#{source}'" + end - ohai "Extracting nested container #{source.basename}" - container.new(@cask, source, @command).extract - FileUtils.remove_entry_secure(source) + ohai "Extracting nested container #{source.basename}" + container.new(@cask, source, @command).extract + FileUtils.remove_entry_secure(source) + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/pkg.rb b/Library/Homebrew/cask/lib/hbc/artifact/pkg.rb index fb27308d7..e590a9082 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/pkg.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/pkg.rb @@ -1,53 +1,57 @@ require "hbc/artifact/base" -class Hbc::Artifact::Pkg < Hbc::Artifact::Base - attr_reader :pkg_relative_path +module Hbc + module Artifact + class Pkg < Base + attr_reader :pkg_relative_path - def self.artifact_dsl_key - :pkg - end + def self.artifact_dsl_key + :pkg + end - def load_pkg_description(pkg_description) - @pkg_relative_path = pkg_description.shift - @pkg_install_opts = pkg_description.shift - begin - if @pkg_install_opts.respond_to?(:keys) - @pkg_install_opts.assert_valid_keys(:allow_untrusted) - elsif @pkg_install_opts - raise + def load_pkg_description(pkg_description) + @pkg_relative_path = pkg_description.shift + @pkg_install_opts = pkg_description.shift + begin + if @pkg_install_opts.respond_to?(:keys) + @pkg_install_opts.assert_valid_keys(:allow_untrusted) + elsif @pkg_install_opts + raise + end + raise if pkg_description.nil? + rescue StandardError + raise CaskInvalidError.new(@cask, "Bad pkg stanza") + end end - raise if pkg_description.nil? - rescue StandardError - raise Hbc::CaskInvalidError.new(@cask, "Bad pkg stanza") - end - end - def pkg_install_opts(opt) - @pkg_install_opts[opt] if @pkg_install_opts.respond_to?(:keys) - end + def pkg_install_opts(opt) + @pkg_install_opts[opt] if @pkg_install_opts.respond_to?(:keys) + end - def install_phase - @cask.artifacts[:pkg].each { |pkg_description| run_installer(pkg_description) } - end + def install_phase + @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 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." - ohai "Package installers may write to any location; options such as --appdir are ignored." - source = @cask.staged_path.join(pkg_relative_path) - unless source.exist? - raise Hbc::CaskError, "pkg source file not found: '#{source}'" + def run_installer(pkg_description) + load_pkg_description pkg_description + ohai "Running installer for #{@cask}; your password may be necessary." + ohai "Package installers may write to any location; options such as --appdir are ignored." + source = @cask.staged_path.join(pkg_relative_path) + unless source.exist? + raise CaskError, "pkg source file not found: '#{source}'" + end + args = [ + "-pkg", source, + "-target", "/" + ] + args << "-verboseR" if Hbc.verbose + args << "-allowUntrusted" if pkg_install_opts :allow_untrusted + @command.run!("/usr/sbin/installer", sudo: true, args: args, print_stdout: true) + end end - args = [ - "-pkg", source, - "-target", "/" - ] - args << "-verboseR" if Hbc.verbose - args << "-allowUntrusted" if pkg_install_opts :allow_untrusted - @command.run!("/usr/sbin/installer", sudo: true, args: args, print_stdout: true) end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/postflight_block.rb b/Library/Homebrew/cask/lib/hbc/artifact/postflight_block.rb index 92b21a83f..bfe218f95 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/postflight_block.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/postflight_block.rb @@ -1,4 +1,8 @@ require "hbc/artifact/abstract_flight_block" -class Hbc::Artifact::PostflightBlock < Hbc::Artifact::AbstractFlightBlock +module Hbc + module Artifact + class PostflightBlock < AbstractFlightBlock + end + end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/preflight_block.rb b/Library/Homebrew/cask/lib/hbc/artifact/preflight_block.rb index 772a88016..35142df47 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/preflight_block.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/preflight_block.rb @@ -1,4 +1,8 @@ require "hbc/artifact/abstract_flight_block" -class Hbc::Artifact::PreflightBlock < Hbc::Artifact::AbstractFlightBlock +module Hbc + module Artifact + class PreflightBlock < AbstractFlightBlock + end + end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/prefpane.rb b/Library/Homebrew/cask/lib/hbc/artifact/prefpane.rb index e45cc0b19..a44f8ae3a 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/prefpane.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/prefpane.rb @@ -1,7 +1,11 @@ require "hbc/artifact/moved" -class Hbc::Artifact::Prefpane < Hbc::Artifact::Moved - def self.artifact_english_name - "Preference Pane" +module Hbc + module Artifact + class Prefpane < Moved + def self.artifact_english_name + "Preference Pane" + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/qlplugin.rb b/Library/Homebrew/cask/lib/hbc/artifact/qlplugin.rb index 6702aa5ef..ee41de2fe 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/qlplugin.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/qlplugin.rb @@ -1,21 +1,25 @@ require "hbc/artifact/moved" -class Hbc::Artifact::Qlplugin < Hbc::Artifact::Moved - def self.artifact_english_name - "QuickLook Plugin" - end +module Hbc + module Artifact + class Qlplugin < Moved + def self.artifact_english_name + "QuickLook Plugin" + end - def install_phase - super - reload_quicklook - end + def install_phase + super + reload_quicklook + end - def uninstall_phase - super - reload_quicklook - end + def uninstall_phase + super + reload_quicklook + end - def reload_quicklook - @command.run!("/usr/bin/qlmanage", args: ["-r"]) + def reload_quicklook + @command.run!("/usr/bin/qlmanage", args: ["-r"]) + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/relocated.rb b/Library/Homebrew/cask/lib/hbc/artifact/relocated.rb index cd0054188..953045b32 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/relocated.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/relocated.rb @@ -1,53 +1,57 @@ require "hbc/artifact/base" -class Hbc::Artifact::Relocated < Hbc::Artifact::Base - def summary - { - english_description: self.class.english_description, - contents: @cask.artifacts[self.class.artifact_dsl_key].map(&method(:summarize_artifact)).compact, - } - end - - attr_reader :source, :target - - def printable_target - target.to_s.sub(%r{^#{ENV['HOME']}(#{File::SEPARATOR}|$)}, "~/") - end - - ALT_NAME_ATTRIBUTE = "com.apple.metadata:kMDItemAlternateNames".freeze - - # Try to make the asset searchable under the target name. Spotlight - # respects this attribute for many filetypes, but ignores it for App - # bundles. Alfred 2.2 respects it even for App bundles. - def add_altname_metadata(file, altname) - return if altname.casecmp(file.basename).zero? - odebug "Adding #{ALT_NAME_ATTRIBUTE} metadata" - altnames = @command.run("/usr/bin/xattr", - args: ["-p", ALT_NAME_ATTRIBUTE, file.to_s], - print_stderr: false).stdout.sub(%r{\A\((.*)\)\Z}, '\1') - odebug "Existing metadata is: '#{altnames}'" - altnames.concat(", ") unless altnames.empty? - altnames.concat(%Q{"#{altname}"}) - altnames = "(#{altnames})" - - # Some packges are shipped as u=rx (e.g. Bitcoin Core) - @command.run!("/bin/chmod", args: ["--", "u=rwx", file.to_s, file.realpath.to_s]) - - @command.run!("/usr/bin/xattr", - args: ["-w", ALT_NAME_ATTRIBUTE, altnames, file.to_s], - print_stderr: false) - end - - def load_specification(artifact_spec) - source_string, target_hash = artifact_spec - raise Hbc::CaskInvalidError if source_string.nil? - @source = @cask.staged_path.join(source_string) - if target_hash - raise Hbc::CaskInvalidError unless target_hash.respond_to?(:keys) - target_hash.assert_valid_keys(:target) - @target = Hbc.send(self.class.artifact_dirmethod).join(target_hash[:target]) - else - @target = Hbc.send(self.class.artifact_dirmethod).join(source.basename) +module Hbc + module Artifact + class Relocated < Base + def summary + { + english_description: self.class.english_description, + contents: @cask.artifacts[self.class.artifact_dsl_key].map(&method(:summarize_artifact)).compact, + } + end + + attr_reader :source, :target + + def printable_target + target.to_s.sub(%r{^#{ENV['HOME']}(#{File::SEPARATOR}|$)}, "~/") + end + + ALT_NAME_ATTRIBUTE = "com.apple.metadata:kMDItemAlternateNames".freeze + + # Try to make the asset searchable under the target name. Spotlight + # respects this attribute for many filetypes, but ignores it for App + # bundles. Alfred 2.2 respects it even for App bundles. + def add_altname_metadata(file, altname) + return if altname.casecmp(file.basename).zero? + odebug "Adding #{ALT_NAME_ATTRIBUTE} metadata" + altnames = @command.run("/usr/bin/xattr", + args: ["-p", ALT_NAME_ATTRIBUTE, file.to_s], + print_stderr: false).stdout.sub(%r{\A\((.*)\)\Z}, '\1') + odebug "Existing metadata is: '#{altnames}'" + altnames.concat(", ") unless altnames.empty? + altnames.concat(%Q{"#{altname}"}) + altnames = "(#{altnames})" + + # Some packges are shipped as u=rx (e.g. Bitcoin Core) + @command.run!("/bin/chmod", args: ["--", "u=rwx", file.to_s, file.realpath.to_s]) + + @command.run!("/usr/bin/xattr", + args: ["-w", ALT_NAME_ATTRIBUTE, altnames, file.to_s], + print_stderr: false) + end + + def load_specification(artifact_spec) + source_string, target_hash = artifact_spec + raise CaskInvalidError if source_string.nil? + @source = @cask.staged_path.join(source_string) + if target_hash + raise CaskInvalidError unless target_hash.respond_to?(:keys) + target_hash.assert_valid_keys(:target) + @target = Hbc.send(self.class.artifact_dirmethod).join(target_hash[:target]) + else + @target = Hbc.send(self.class.artifact_dirmethod).join(source.basename) + end + end end end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/screen_saver.rb b/Library/Homebrew/cask/lib/hbc/artifact/screen_saver.rb index bbd929152..4cdc6037c 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/screen_saver.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/screen_saver.rb @@ -1,4 +1,8 @@ require "hbc/artifact/moved" -class Hbc::Artifact::ScreenSaver < Hbc::Artifact::Moved +module Hbc + module Artifact + class ScreenSaver < Moved + end + end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/service.rb b/Library/Homebrew/cask/lib/hbc/artifact/service.rb index d5a00e4fe..1af93c533 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/service.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/service.rb @@ -1,4 +1,8 @@ require "hbc/artifact/moved" -class Hbc::Artifact::Service < Hbc::Artifact::Moved +module Hbc + module Artifact + class Service < Moved + end + end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/stage_only.rb b/Library/Homebrew/cask/lib/hbc/artifact/stage_only.rb index 7a48b19aa..594c5bef9 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/stage_only.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/stage_only.rb @@ -1,15 +1,19 @@ require "hbc/artifact/base" -class Hbc::Artifact::StageOnly < Hbc::Artifact::Base - def self.artifact_dsl_key - :stage_only - end +module Hbc + module Artifact + class StageOnly < Base + def self.artifact_dsl_key + :stage_only + end - def install_phase - # do nothing - end + def install_phase + # do nothing + end - def uninstall_phase - # do nothing + def uninstall_phase + # do nothing + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/suite.rb b/Library/Homebrew/cask/lib/hbc/artifact/suite.rb index cdfb757dd..35251f70c 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/suite.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/suite.rb @@ -1,11 +1,15 @@ require "hbc/artifact/moved" -class Hbc::Artifact::Suite < Hbc::Artifact::Moved - def self.artifact_english_name - "App Suite" - end +module Hbc + module Artifact + class Suite < Moved + def self.artifact_english_name + "App Suite" + end - def self.artifact_dirmethod - :appdir + def self.artifact_dirmethod + :appdir + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/symlinked.rb b/Library/Homebrew/cask/lib/hbc/artifact/symlinked.rb index 7432df577..3ab45cccc 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/symlinked.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/symlinked.rb @@ -1,65 +1,69 @@ require "hbc/artifact/relocated" -class Hbc::Artifact::Symlinked < Hbc::Artifact::Relocated - def self.link_type_english_name - "Symlink" - end +module Hbc + module Artifact + class Symlinked < Relocated + def self.link_type_english_name + "Symlink" + end - def self.english_description - "#{artifact_english_name} #{link_type_english_name}s" - end + def self.english_description + "#{artifact_english_name} #{link_type_english_name}s" + end - def self.islink?(path) - path.symlink? - end + def self.islink?(path) + path.symlink? + end - def link(artifact_spec) - load_specification artifact_spec - return unless preflight_checks(source, target) - ohai "#{self.class.link_type_english_name}ing #{self.class.artifact_english_name} '#{source.basename}' to '#{target}'" - create_filesystem_link(source, target) - end + def link(artifact_spec) + load_specification artifact_spec + return unless preflight_checks(source, target) + ohai "#{self.class.link_type_english_name}ing #{self.class.artifact_english_name} '#{source.basename}' to '#{target}'" + create_filesystem_link(source, target) + end - def unlink(artifact_spec) - load_specification artifact_spec - return unless self.class.islink?(target) - ohai "Removing #{self.class.artifact_english_name} #{self.class.link_type_english_name.downcase}: '#{target}'" - target.delete - end + def unlink(artifact_spec) + load_specification artifact_spec + return unless self.class.islink?(target) + ohai "Removing #{self.class.artifact_english_name} #{self.class.link_type_english_name.downcase}: '#{target}'" + target.delete + end - def install_phase - @cask.artifacts[self.class.artifact_dsl_key].each(&method(:link)) - end + def install_phase + @cask.artifacts[self.class.artifact_dsl_key].each(&method(:link)) + end - def uninstall_phase - @cask.artifacts[self.class.artifact_dsl_key].each(&method(:unlink)) - end + def uninstall_phase + @cask.artifacts[self.class.artifact_dsl_key].each(&method(:unlink)) + end - def preflight_checks(source, target) - if target.exist? && !self.class.islink?(target) - ohai "It seems there is already #{self.class.artifact_english_article} #{self.class.artifact_english_name} at '#{target}'; not linking." - return false - end - unless source.exist? - raise Hbc::CaskError, "It seems the #{self.class.link_type_english_name.downcase} source is not there: '#{source}'" - end - true - end + def preflight_checks(source, target) + if target.exist? && !self.class.islink?(target) + ohai "It seems there is already #{self.class.artifact_english_article} #{self.class.artifact_english_name} at '#{target}'; not linking." + return false + end + unless source.exist? + raise CaskError, "It seems the #{self.class.link_type_english_name.downcase} source is not there: '#{source}'" + end + true + end - def create_filesystem_link(source, target) - Pathname.new(target).dirname.mkpath - @command.run!("/bin/ln", args: ["-hfs", "--", source, target]) - add_altname_metadata source, target.basename.to_s - end + def create_filesystem_link(source, target) + Pathname.new(target).dirname.mkpath + @command.run!("/bin/ln", args: ["-hfs", "--", source, target]) + add_altname_metadata source, target.basename.to_s + end - def summarize_artifact(artifact_spec) - load_specification artifact_spec + def summarize_artifact(artifact_spec) + load_specification artifact_spec - return unless self.class.islink?(target) + return unless self.class.islink?(target) - link_description = "#{Tty.red}Broken Link#{Tty.reset}: " unless target.exist? - target_readlink_abv = " (#{target.readlink.abv})" if target.readlink.exist? + link_description = "#{Tty.red}Broken Link#{Tty.reset}: " unless target.exist? + target_readlink_abv = " (#{target.readlink.abv})" if target.readlink.exist? - "#{link_description}#{printable_target} -> #{target.readlink}#{target_readlink_abv}" + "#{link_description}#{printable_target} -> #{target.readlink}#{target_readlink_abv}" + 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 12010aeb8..8b5603064 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/uninstall.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/uninstall.rb @@ -1,4 +1,8 @@ require "hbc/artifact/uninstall_base" -class Hbc::Artifact::Uninstall < Hbc::Artifact::UninstallBase +module Hbc + module Artifact + class Uninstall < UninstallBase + 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 f92e09a89..63ffd18c9 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/uninstall_base.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/uninstall_base.rb @@ -2,248 +2,252 @@ require "pathname" require "hbc/artifact/base" -class Hbc::Artifact::UninstallBase < Hbc::Artifact::Base - # TODO: 500 is also hardcoded in cask/pkg.rb, but much of - # that logic is probably in the wrong location - - PATH_ARG_SLICE_SIZE = 500 - - ORDERED_DIRECTIVES = [ - :early_script, - :launchctl, - :quit, - :signal, - :login_item, - :kext, - :script, - :pkgutil, - :delete, - :trash, - :rmdir, - ].freeze - - # TODO: these methods were consolidated here from separate - # sources and should be refactored for consistency - - def self.expand_path_strings(path_strings) - path_strings.map { |path_string| - path_string.start_with?("~") ? Pathname.new(path_string).expand_path : Pathname.new(path_string) - } - end +module Hbc + module Artifact + class UninstallBase < Base + # TODO: 500 is also hardcoded in cask/pkg.rb, but much of + # that logic is probably in the wrong location + + PATH_ARG_SLICE_SIZE = 500 + + ORDERED_DIRECTIVES = [ + :early_script, + :launchctl, + :quit, + :signal, + :login_item, + :kext, + :script, + :pkgutil, + :delete, + :trash, + :rmdir, + ].freeze + + # TODO: these methods were consolidated here from separate + # sources and should be refactored for consistency + + def self.expand_path_strings(path_strings) + path_strings.map { |path_string| + path_string.start_with?("~") ? Pathname.new(path_string).expand_path : Pathname.new(path_string) + } + end - def self.remove_relative_path_strings(action, path_strings) - relative = path_strings.map { |path_string| - path_string if %r{/\.\.(?:/|\Z)}.match(path_string) || !%r{\A/}.match(path_string) - }.compact - relative.each do |path_string| - opoo "Skipping #{action} for relative path #{path_string}" - end - path_strings - relative - end + def self.remove_relative_path_strings(action, path_strings) + relative = path_strings.map { |path_string| + path_string if %r{/\.\.(?:/|\Z)}.match(path_string) || !%r{\A/}.match(path_string) + }.compact + relative.each do |path_string| + opoo "Skipping #{action} for relative path #{path_string}" + end + path_strings - relative + end - def self.remove_undeletable_path_strings(action, path_strings) - undeletable = path_strings.map { |path_string| - path_string if MacOS.undeletable?(Pathname.new(path_string)) - }.compact - undeletable.each do |path_string| - opoo "Skipping #{action} for undeletable path #{path_string}" - end - path_strings - undeletable - end + def self.remove_undeletable_path_strings(action, path_strings) + undeletable = path_strings.map { |path_string| + path_string if MacOS.undeletable?(Pathname.new(path_string)) + }.compact + undeletable.each do |path_string| + opoo "Skipping #{action} for undeletable path #{path_string}" + end + path_strings - undeletable + end - def install_phase - odebug "Nothing to do. The uninstall artifact has no install phase." - end + def install_phase + odebug "Nothing to do. The uninstall artifact has no install phase." + end - def uninstall_phase - dispatch_uninstall_directives - end + def uninstall_phase + dispatch_uninstall_directives + end - def dispatch_uninstall_directives(expand_tilde = true) - directives_set = @cask.artifacts[stanza] - ohai "Running #{stanza} process for #{@cask}; your password may be necessary" + def dispatch_uninstall_directives(expand_tilde = true) + directives_set = @cask.artifacts[stanza] + ohai "Running #{stanza} process for #{@cask}; your password may be necessary" - directives_set.each do |directives| - warn_for_unknown_directives(directives) - end + directives_set.each do |directives| + warn_for_unknown_directives(directives) + end - ORDERED_DIRECTIVES.each do |directive_sym| - directives_set.select { |h| h.key?(directive_sym) }.each do |directives| - args = [directives] - args << expand_tilde if [:delete, :trash, :rmdir].include?(directive_sym) - send("uninstall_#{directive_sym}", *args) + ORDERED_DIRECTIVES.each do |directive_sym| + directives_set.select { |h| h.key?(directive_sym) }.each do |directives| + args = [directives] + args << expand_tilde if [:delete, :trash, :rmdir].include?(directive_sym) + send("uninstall_#{directive_sym}", *args) + end + end end - end - end - private + private - def stanza - self.class.artifact_dsl_key - end + def stanza + self.class.artifact_dsl_key + end - def warn_for_unknown_directives(directives) - unknown_keys = directives.keys - ORDERED_DIRECTIVES - return if unknown_keys.empty? - opoo %Q{Unknown arguments to #{stanza} -- #{unknown_keys.inspect}. Running "brew update; brew cleanup; brew cask cleanup" will likely fix it.} - end + def warn_for_unknown_directives(directives) + unknown_keys = directives.keys - ORDERED_DIRECTIVES + return if unknown_keys.empty? + opoo %Q{Unknown arguments to #{stanza} -- #{unknown_keys.inspect}. Running "brew update; brew cleanup; brew cask cleanup" will likely fix it.} + end - # Preserve prior functionality of script which runs first. Should rarely be needed. - # :early_script should not delete files, better defer that to :script. - # If Cask writers never need :early_script it may be removed in the future. - def uninstall_early_script(directives) - uninstall_script(directives, directive_name: :early_script) - end + # Preserve prior functionality of script which runs first. Should rarely be needed. + # :early_script should not delete files, better defer that to :script. + # If Cask writers never need :early_script it may be removed in the future. + def uninstall_early_script(directives) + uninstall_script(directives, directive_name: :early_script) + end - # :launchctl must come before :quit/:signal for cases where app would instantly re-launch - def uninstall_launchctl(directives) - Array(directives[:launchctl]).each do |service| - ohai "Removing launchctl service #{service}" - [false, true].each do |with_sudo| - plist_status = @command.run("/bin/launchctl", args: ["list", service], sudo: with_sudo, print_stderr: false).stdout - if plist_status =~ %r{^\{} - @command.run!("/bin/launchctl", args: ["remove", service], sudo: with_sudo) - sleep 1 + # :launchctl must come before :quit/:signal for cases where app would instantly re-launch + def uninstall_launchctl(directives) + Array(directives[:launchctl]).each do |service| + ohai "Removing launchctl service #{service}" + [false, true].each do |with_sudo| + plist_status = @command.run("/bin/launchctl", args: ["list", service], sudo: with_sudo, print_stderr: false).stdout + if plist_status =~ %r{^\{} + @command.run!("/bin/launchctl", args: ["remove", service], sudo: with_sudo) + sleep 1 + end + paths = ["/Library/LaunchAgents/#{service}.plist", + "/Library/LaunchDaemons/#{service}.plist"] + paths.each { |elt| elt.prepend(ENV["HOME"]) } unless with_sudo + paths = paths.map { |elt| Pathname(elt) }.select(&:exist?) + paths.each do |path| + @command.run!("/bin/rm", args: ["-f", "--", path], sudo: with_sudo) + end + # undocumented and untested: pass a path to uninstall :launchctl + next unless Pathname(service).exist? + @command.run!("/bin/launchctl", args: ["unload", "-w", "--", service], sudo: with_sudo) + @command.run!("/bin/rm", args: ["-f", "--", service], sudo: with_sudo) + sleep 1 + end end - paths = ["/Library/LaunchAgents/#{service}.plist", - "/Library/LaunchDaemons/#{service}.plist"] - paths.each { |elt| elt.prepend(ENV["HOME"]) } unless with_sudo - paths = paths.map { |elt| Pathname(elt) }.select(&:exist?) - paths.each do |path| - @command.run!("/bin/rm", args: ["-f", "--", path], sudo: with_sudo) + end + + # :quit/:signal must come before :kext so the kext will not be in use by a running process + def uninstall_quit(directives) + Array(directives[:quit]).each do |id| + ohai "Quitting application ID #{id}" + num_running = count_running_processes(id) + next unless num_running > 0 + @command.run!("/usr/bin/osascript", args: ["-e", %Q{tell application id "#{id}" to quit}], sudo: true) + sleep 3 end - # undocumented and untested: pass a path to uninstall :launchctl - next unless Pathname(service).exist? - @command.run!("/bin/launchctl", args: ["unload", "-w", "--", service], sudo: with_sudo) - @command.run!("/bin/rm", args: ["-f", "--", service], sudo: with_sudo) - sleep 1 end - end - end - # :quit/:signal must come before :kext so the kext will not be in use by a running process - def uninstall_quit(directives) - Array(directives[:quit]).each do |id| - ohai "Quitting application ID #{id}" - num_running = count_running_processes(id) - next unless num_running > 0 - @command.run!("/usr/bin/osascript", args: ["-e", %Q{tell application id "#{id}" to quit}], sudo: true) - sleep 3 - end - end + # :signal should come after :quit so it can be used as a backup when :quit fails + def uninstall_signal(directives) + Array(directives[:signal]).flatten.each_slice(2) do |pair| + raise CaskInvalidError.new(@cask, "Each #{stanza} :signal must have 2 elements.") unless pair.length == 2 + signal, id = pair + ohai "Signalling '#{signal}' to application ID '#{id}'" + pids = get_unix_pids(id) + next unless pids.any? + # Note that unlike :quit, signals are sent from the current user (not + # upgraded to the superuser). This is a todo item for the future, but + # there should be some additional thought/safety checks about that, as a + # misapplied "kill" by root could bring down the system. The fact that we + # learned the pid from AppleScript is already some degree of protection, + # though indirect. + odebug "Unix ids are #{pids.inspect} for processes with bundle identifier #{id}" + Process.kill(signal, *pids) + sleep 3 + end + end - # :signal should come after :quit so it can be used as a backup when :quit fails - def uninstall_signal(directives) - Array(directives[:signal]).flatten.each_slice(2) do |pair| - raise Hbc::CaskInvalidError.new(@cask, "Each #{stanza} :signal must have 2 elements.") unless pair.length == 2 - signal, id = pair - ohai "Signalling '#{signal}' to application ID '#{id}'" - pids = get_unix_pids(id) - next unless pids.any? - # Note that unlike :quit, signals are sent from the current user (not - # upgraded to the superuser). This is a todo item for the future, but - # there should be some additional thought/safety checks about that, as a - # misapplied "kill" by root could bring down the system. The fact that we - # learned the pid from AppleScript is already some degree of protection, - # though indirect. - odebug "Unix ids are #{pids.inspect} for processes with bundle identifier #{id}" - Process.kill(signal, *pids) - sleep 3 - end - end + def count_running_processes(bundle_id) + @command.run!("/usr/bin/osascript", + args: ["-e", %Q{tell application "System Events" to count processes whose bundle identifier is "#{bundle_id}"}], + sudo: true).stdout.to_i + end - def count_running_processes(bundle_id) - @command.run!("/usr/bin/osascript", - args: ["-e", %Q{tell application "System Events" to count processes whose bundle identifier is "#{bundle_id}"}], - sudo: true).stdout.to_i - end + def get_unix_pids(bundle_id) + pid_string = @command.run!("/usr/bin/osascript", + args: ["-e", %Q{tell application "System Events" to get the unix id of every process whose bundle identifier is "#{bundle_id}"}], + sudo: true).stdout.chomp + return [] unless pid_string =~ %r{\A\d+(?:\s*,\s*\d+)*\Z} # sanity check + pid_string.split(%r{\s*,\s*}).map(&:strip).map(&:to_i) + end - def get_unix_pids(bundle_id) - pid_string = @command.run!("/usr/bin/osascript", - args: ["-e", %Q{tell application "System Events" to get the unix id of every process whose bundle identifier is "#{bundle_id}"}], - sudo: true).stdout.chomp - return [] unless pid_string =~ %r{\A\d+(?:\s*,\s*\d+)*\Z} # sanity check - pid_string.split(%r{\s*,\s*}).map(&:strip).map(&:to_i) - end + def uninstall_login_item(directives) + Array(directives[:login_item]).each do |name| + ohai "Removing login item #{name}" + @command.run!("/usr/bin/osascript", + args: ["-e", %Q{tell application "System Events" to delete every login item whose name is "#{name}"}], + sudo: false) + sleep 1 + end + end - def uninstall_login_item(directives) - Array(directives[:login_item]).each do |name| - ohai "Removing login item #{name}" - @command.run!("/usr/bin/osascript", - args: ["-e", %Q{tell application "System Events" to delete every login item whose name is "#{name}"}], - sudo: false) - sleep 1 - end - end + # :kext should be unloaded before attempting to delete the relevant file + def uninstall_kext(directives) + Array(directives[:kext]).each do |kext| + ohai "Unloading kernel extension #{kext}" + is_loaded = @command.run!("/usr/sbin/kextstat", args: ["-l", "-b", kext], sudo: true).stdout + if is_loaded.length > 1 + @command.run!("/sbin/kextunload", args: ["-b", kext], sudo: true) + sleep 1 + end + end + end - # :kext should be unloaded before attempting to delete the relevant file - def uninstall_kext(directives) - Array(directives[:kext]).each do |kext| - ohai "Unloading kernel extension #{kext}" - is_loaded = @command.run!("/usr/sbin/kextstat", args: ["-l", "-b", kext], sudo: true).stdout - if is_loaded.length > 1 - @command.run!("/sbin/kextunload", args: ["-b", kext], sudo: true) + # :script must come before :pkgutil, :delete, or :trash so that the script file is not already deleted + def uninstall_script(directives, directive_name: :script) + executable, script_arguments = self.class.read_script_arguments(directives, + "uninstall", + { must_succeed: true, sudo: true }, + { print_stdout: true }, + directive_name) + 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) + @command.run(executable_path, script_arguments) sleep 1 end - end - end - - # :script must come before :pkgutil, :delete, or :trash so that the script file is not already deleted - def uninstall_script(directives, directive_name: :script) - executable, script_arguments = self.class.read_script_arguments(directives, - "uninstall", - { must_succeed: true, sudo: true }, - { print_stdout: true }, - directive_name) - ohai "Running uninstall script #{executable}" - raise Hbc::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) - @command.run(executable_path, script_arguments) - sleep 1 - end - def uninstall_pkgutil(directives) - ohai "Removing files from pkgutil Bill-of-Materials" - Array(directives[:pkgutil]).each do |regexp| - pkgs = Hbc::Pkg.all_matching(regexp, @command) - pkgs.each(&:uninstall) - end - end + def uninstall_pkgutil(directives) + ohai "Removing files from pkgutil Bill-of-Materials" + Array(directives[:pkgutil]).each do |regexp| + pkgs = Hbc::Pkg.all_matching(regexp, @command) + pkgs.each(&:uninstall) + end + end - 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) - @command.run!("/bin/rm", args: path_slice.unshift("-rf", "--"), sudo: true) - end - end + 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) + @command.run!("/bin/rm", args: path_slice.unshift("-rf", "--"), sudo: true) + end + end - # :trash functionality is stubbed as a synonym for :delete - # TODO: make :trash work differently, moving files to the Trash - def uninstall_trash(directives, expand_tilde = true) - uninstall_delete(directives, expand_tilde) - end + # :trash functionality is stubbed as a synonym for :delete + # TODO: make :trash work differently, moving files to the Trash + def uninstall_trash(directives, expand_tilde = true) + 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 - next if directory.to_s.empty? - ohai "Removing directory if empty: #{directory.to_s.utf8_inspect}" - directory = Pathname.new(directory) - next unless directory.exist? - @command.run!("/bin/rm", - args: ["-f", "--", directory.join(".DS_Store")], - sudo: true, - print_stderr: false) - @command.run("/bin/rmdir", - args: ["--", directory], - sudo: true, - print_stderr: false) + 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 + next if directory.to_s.empty? + ohai "Removing directory if empty: #{directory.to_s.utf8_inspect}" + directory = Pathname.new(directory) + next unless directory.exist? + @command.run!("/bin/rm", + args: ["-f", "--", directory.join(".DS_Store")], + sudo: true, + print_stderr: false) + @command.run("/bin/rmdir", + args: ["--", directory], + sudo: true, + print_stderr: false) + end + end end end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/vst3_plugin.rb b/Library/Homebrew/cask/lib/hbc/artifact/vst3_plugin.rb index 243884435..056fffc2a 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/vst3_plugin.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/vst3_plugin.rb @@ -1,4 +1,8 @@ require "hbc/artifact/moved" -class Hbc::Artifact::Vst3Plugin < Hbc::Artifact::Moved +module Hbc + module Artifact + class Vst3Plugin < Moved + end + end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/vst_plugin.rb b/Library/Homebrew/cask/lib/hbc/artifact/vst_plugin.rb index 8d0546480..f38804635 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/vst_plugin.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/vst_plugin.rb @@ -1,4 +1,8 @@ require "hbc/artifact/moved" -class Hbc::Artifact::VstPlugin < Hbc::Artifact::Moved +module Hbc + module Artifact + class VstPlugin < Moved + end + end end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/zap.rb b/Library/Homebrew/cask/lib/hbc/artifact/zap.rb index 8bd8da63b..503ea35c4 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/zap.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/zap.rb @@ -1,16 +1,20 @@ require "hbc/artifact/uninstall_base" -class Hbc::Artifact::Zap < Hbc::Artifact::UninstallBase - def install_phase - odebug "Nothing to do. The zap artifact has no install phase." - end +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 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) + def zap_phase + expand_tilde = true + dispatch_uninstall_directives(expand_tilde) + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/audit.rb b/Library/Homebrew/cask/lib/hbc/audit.rb index 98f09ffa4..476f2aec0 100644 --- a/Library/Homebrew/cask/lib/hbc/audit.rb +++ b/Library/Homebrew/cask/lib/hbc/audit.rb @@ -2,215 +2,217 @@ require "hbc/checkable" require "hbc/download" require "digest" -class Hbc::Audit - include Hbc::Checkable +module Hbc + class Audit + include Checkable - attr_reader :cask, :download + attr_reader :cask, :download - def initialize(cask, download: false, check_token_conflicts: false, command: Hbc::SystemCommand) - @cask = cask - @download = download - @check_token_conflicts = check_token_conflicts - @command = command - end + def initialize(cask, download: false, check_token_conflicts: false, command: SystemCommand) + @cask = cask + @download = download + @check_token_conflicts = check_token_conflicts + @command = command + end - def check_token_conflicts? - @check_token_conflicts - end + def check_token_conflicts? + @check_token_conflicts + end - def run! - check_required_stanzas - check_version - check_sha256 - check_appcast - check_url - check_generic_artifacts - check_token_conflicts - check_download - self - rescue StandardError => e - odebug "#{e.message}\n#{e.backtrace.join("\n")}" - add_error "exception while auditing #{cask}: #{e.message}" - self - end + def run! + check_required_stanzas + check_version + check_sha256 + check_appcast + check_url + check_generic_artifacts + check_token_conflicts + check_download + self + rescue StandardError => e + odebug "#{e.message}\n#{e.backtrace.join("\n")}" + add_error "exception while auditing #{cask}: #{e.message}" + self + end - def success? - !(errors? || warnings?) - end + def success? + !(errors? || warnings?) + end - def summary_header - "audit for #{cask}" - end + def summary_header + "audit for #{cask}" + end - private + private - def check_required_stanzas - odebug "Auditing required stanzas" - %i{version sha256 url homepage}.each do |sym| - add_error "a #{sym} stanza is required" unless cask.send(sym) + def check_required_stanzas + odebug "Auditing required stanzas" + %i{version sha256 url homepage}.each do |sym| + add_error "a #{sym} stanza is required" unless cask.send(sym) + end + add_error "a license stanza is required (:unknown is OK)" unless cask.license + add_error "at least one name stanza is required" if cask.name.empty? + # TODO: specific DSL knowledge should not be spread around in various files like this + # TODO: nested_container should not still be a pseudo-artifact at this point + installable_artifacts = cask.artifacts.reject { |k| [:uninstall, :zap, :nested_container].include?(k) } + add_error "at least one activatable artifact stanza is required" if installable_artifacts.empty? end - add_error "a license stanza is required (:unknown is OK)" unless cask.license - add_error "at least one name stanza is required" if cask.name.empty? - # TODO: specific DSL knowledge should not be spread around in various files like this - # TODO: nested_container should not still be a pseudo-artifact at this point - installable_artifacts = cask.artifacts.reject { |k| [:uninstall, :zap, :nested_container].include?(k) } - add_error "at least one activatable artifact stanza is required" if installable_artifacts.empty? - end - def check_version - return unless cask.version - check_no_string_version_latest - end + def check_version + return unless cask.version + check_no_string_version_latest + end - def check_no_string_version_latest - odebug "Verifying version :latest does not appear as a string ('latest')" - return unless cask.version.raw_version == "latest" - add_error "you should use version :latest instead of version 'latest'" - end + def check_no_string_version_latest + odebug "Verifying version :latest does not appear as a string ('latest')" + return unless cask.version.raw_version == "latest" + add_error "you should use version :latest instead of version 'latest'" + end - def check_sha256 - return unless cask.sha256 - check_sha256_no_check_if_latest - check_sha256_actually_256 - check_sha256_invalid - end + def check_sha256 + return unless cask.sha256 + check_sha256_no_check_if_latest + check_sha256_actually_256 + check_sha256_invalid + end - def check_sha256_no_check_if_latest - odebug "Verifying sha256 :no_check with version :latest" - return unless cask.version.latest? && cask.sha256 != :no_check - add_error "you should use sha256 :no_check when version is :latest" - end + def check_sha256_no_check_if_latest + odebug "Verifying sha256 :no_check with version :latest" + return unless cask.version.latest? && cask.sha256 != :no_check + add_error "you should use sha256 :no_check when version is :latest" + end - def check_sha256_actually_256(sha256: cask.sha256, stanza: "sha256") - odebug "Verifying #{stanza} string is a legal SHA-256 digest" - return unless sha256.is_a?(String) - return if sha256.length == 64 && sha256[%r{^[0-9a-f]+$}i] - add_error "#{stanza} string must be of 64 hexadecimal characters" - end + def check_sha256_actually_256(sha256: cask.sha256, stanza: "sha256") + odebug "Verifying #{stanza} string is a legal SHA-256 digest" + return unless sha256.is_a?(String) + return if sha256.length == 64 && sha256[%r{^[0-9a-f]+$}i] + add_error "#{stanza} string must be of 64 hexadecimal characters" + end - def check_sha256_invalid(sha256: cask.sha256, stanza: "sha256") - odebug "Verifying #{stanza} is not a known invalid value" - empty_sha256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" - return unless sha256 == empty_sha256 - add_error "cannot use the sha256 for an empty string in #{stanza}: #{empty_sha256}" - end + def check_sha256_invalid(sha256: cask.sha256, stanza: "sha256") + odebug "Verifying #{stanza} is not a known invalid value" + empty_sha256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + return unless sha256 == empty_sha256 + add_error "cannot use the sha256 for an empty string in #{stanza}: #{empty_sha256}" + end - def check_appcast - return unless cask.appcast - odebug "Auditing appcast" - check_appcast_has_checkpoint - return unless cask.appcast.checkpoint - check_sha256_actually_256(sha256: cask.appcast.checkpoint, stanza: "appcast :checkpoint") - check_sha256_invalid(sha256: cask.appcast.checkpoint, stanza: "appcast :checkpoint") - return unless download - check_appcast_http_code - check_appcast_checkpoint_accuracy - end + def check_appcast + return unless cask.appcast + odebug "Auditing appcast" + check_appcast_has_checkpoint + return unless cask.appcast.checkpoint + check_sha256_actually_256(sha256: cask.appcast.checkpoint, stanza: "appcast :checkpoint") + check_sha256_invalid(sha256: cask.appcast.checkpoint, stanza: "appcast :checkpoint") + return unless download + check_appcast_http_code + check_appcast_checkpoint_accuracy + end - def check_appcast_has_checkpoint - odebug "Verifying appcast has :checkpoint key" - add_error "a checkpoint sha256 is required for appcast" unless cask.appcast.checkpoint - end + def check_appcast_has_checkpoint + odebug "Verifying appcast has :checkpoint key" + add_error "a checkpoint sha256 is required for appcast" unless cask.appcast.checkpoint + end - def check_appcast_http_code - odebug "Verifying appcast returns 200 HTTP response code" - result = @command.run("/usr/bin/curl", args: ["--compressed", "--location", "--user-agent", Hbc::URL::FAKE_USER_AGENT, "--output", "/dev/null", "--write-out", "%{http_code}", cask.appcast], print_stderr: false) - if result.success? - http_code = result.stdout.chomp - add_warning "unexpected HTTP response code retrieving appcast: #{http_code}" unless http_code == "200" - else - add_warning "error retrieving appcast: #{result.stderr}" + def check_appcast_http_code + odebug "Verifying appcast returns 200 HTTP response code" + result = @command.run("/usr/bin/curl", args: ["--compressed", "--location", "--user-agent", URL::FAKE_USER_AGENT, "--output", "/dev/null", "--write-out", "%{http_code}", cask.appcast], print_stderr: false) + if result.success? + http_code = result.stdout.chomp + add_warning "unexpected HTTP response code retrieving appcast: #{http_code}" unless http_code == "200" + else + add_warning "error retrieving appcast: #{result.stderr}" + end end - end - def check_appcast_checkpoint_accuracy - odebug "Verifying appcast checkpoint is accurate" - result = @command.run("/usr/bin/curl", args: ["--compressed", "--location", "--user-agent", Hbc::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") - expected = cask.appcast.checkpoint - actual = Digest::SHA2.hexdigest(processed_appcast_text) - add_warning <<-EOS.undent unless expected == actual - appcast checkpoint mismatch - Expected: #{expected} - Actual: #{actual} - EOS - else - add_warning "error retrieving appcast: #{result.stderr}" + 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") + expected = cask.appcast.checkpoint + actual = Digest::SHA2.hexdigest(processed_appcast_text) + add_warning <<-EOS.undent unless expected == actual + appcast checkpoint mismatch + Expected: #{expected} + Actual: #{actual} + EOS + else + add_warning "error retrieving appcast: #{result.stderr}" + end end - end - def check_url - return unless cask.url - check_download_url_format - end + def check_url + return unless cask.url + check_download_url_format + end - def check_download_url_format - odebug "Auditing URL format" - if bad_sourceforge_url? - add_warning "SourceForge URL format incorrect. See https://github.com/caskroom/homebrew-cask/blob/master/doc/cask_language_reference/stanzas/url.md#sourceforgeosdn-urls" - elsif bad_osdn_url? - add_warning "OSDN URL format incorrect. See https://github.com/caskroom/homebrew-cask/blob/master/doc/cask_language_reference/stanzas/url.md#sourceforgeosdn-urls" + def check_download_url_format + odebug "Auditing URL format" + if bad_sourceforge_url? + add_warning "SourceForge URL format incorrect. See https://github.com/caskroom/homebrew-cask/blob/master/doc/cask_language_reference/stanzas/url.md#sourceforgeosdn-urls" + elsif bad_osdn_url? + add_warning "OSDN URL format incorrect. See https://github.com/caskroom/homebrew-cask/blob/master/doc/cask_language_reference/stanzas/url.md#sourceforgeosdn-urls" + end end - end - def bad_url_format?(regex, valid_formats_array) - return false unless cask.url.to_s =~ regex - valid_formats_array.none? { |format| cask.url.to_s =~ format } - end + def bad_url_format?(regex, valid_formats_array) + return false unless cask.url.to_s =~ regex + valid_formats_array.none? { |format| cask.url.to_s =~ format } + end - def bad_sourceforge_url? - bad_url_format?(%r{sourceforge}, - [ - %r{\Ahttps://sourceforge\.net/projects/[^/]+/files/latest/download\Z}, - %r{\Ahttps://downloads\.sourceforge\.net/(?!(project|sourceforge)\/)}, - # special cases: cannot find canonical format URL - %r{\Ahttps?://brushviewer\.sourceforge\.net/brushviewql\.zip\Z}, - %r{\Ahttps?://doublecommand\.sourceforge\.net/files/}, - %r{\Ahttps?://excalibur\.sourceforge\.net/get\.php\?id=}, - ]) - end + def bad_sourceforge_url? + bad_url_format?(%r{sourceforge}, + [ + %r{\Ahttps://sourceforge\.net/projects/[^/]+/files/latest/download\Z}, + %r{\Ahttps://downloads\.sourceforge\.net/(?!(project|sourceforge)\/)}, + # special cases: cannot find canonical format URL + %r{\Ahttps?://brushviewer\.sourceforge\.net/brushviewql\.zip\Z}, + %r{\Ahttps?://doublecommand\.sourceforge\.net/files/}, + %r{\Ahttps?://excalibur\.sourceforge\.net/get\.php\?id=}, + ]) + end - def bad_osdn_url? - bad_url_format?(%r{osd}, [%r{\Ahttps?://([^/]+.)?dl\.osdn\.jp/}]) - end + def bad_osdn_url? + bad_url_format?(%r{osd}, [%r{\Ahttps?://([^/]+.)?dl\.osdn\.jp/}]) + end - def check_generic_artifacts - cask.artifacts[:artifact].each do |source, target_hash| - unless target_hash.is_a?(Hash) && target_hash[:target] - add_error "target required for generic artifact #{source}" - next + def check_generic_artifacts + cask.artifacts[:artifact].each do |source, target_hash| + unless target_hash.is_a?(Hash) && target_hash[:target] + add_error "target required for generic artifact #{source}" + next + end + add_error "target must be absolute path for generic artifact #{source}" unless Pathname.new(target_hash[:target]).absolute? end - add_error "target must be absolute path for generic artifact #{source}" unless Pathname.new(target_hash[:target]).absolute? end - end - def check_token_conflicts - return unless check_token_conflicts? - return unless core_formula_names.include?(cask.token) - add_warning "possible duplicate, cask token conflicts with Homebrew core formula: #{core_formula_url}" - end + def check_token_conflicts + return unless check_token_conflicts? + return unless core_formula_names.include?(cask.token) + add_warning "possible duplicate, cask token conflicts with Homebrew core formula: #{core_formula_url}" + end - def core_tap - @core_tap ||= CoreTap.instance - end + def core_tap + @core_tap ||= CoreTap.instance + end - def core_formula_names - core_tap.formula_names - end + def core_formula_names + core_tap.formula_names + end - def core_formula_url - "#{core_tap.default_remote}/blob/master/Formula/#{cask.token}.rb" - end + def core_formula_url + "#{core_tap.default_remote}/blob/master/Formula/#{cask.token}.rb" + end - def check_download - return unless download && cask.url - odebug "Auditing download" - downloaded_path = download.perform - Hbc::Verify.all(cask, downloaded_path) - rescue => e - add_error "download not possible: #{e.message}" + def check_download + return unless download && cask.url + odebug "Auditing download" + downloaded_path = download.perform + Verify.all(cask, downloaded_path) + rescue => e + add_error "download not possible: #{e.message}" + end end end diff --git a/Library/Homebrew/cask/lib/hbc/auditor.rb b/Library/Homebrew/cask/lib/hbc/auditor.rb index 89947c1aa..6b0c1c476 100644 --- a/Library/Homebrew/cask/lib/hbc/auditor.rb +++ b/Library/Homebrew/cask/lib/hbc/auditor.rb @@ -1,10 +1,12 @@ -class Hbc::Auditor - def self.audit(cask, audit_download: false, check_token_conflicts: false) - download = audit_download && Hbc::Download.new(cask) - audit = Hbc::Audit.new(cask, download: download, - check_token_conflicts: check_token_conflicts) - audit.run! - puts audit.summary - audit.success? +module Hbc + class Auditor + def self.audit(cask, audit_download: false, check_token_conflicts: false) + download = audit_download && Download.new(cask) + audit = Audit.new(cask, download: download, + check_token_conflicts: check_token_conflicts) + audit.run! + puts audit.summary + audit.success? + end end end diff --git a/Library/Homebrew/cask/lib/hbc/cache.rb b/Library/Homebrew/cask/lib/hbc/cache.rb index 9fc5fe0f3..db3ec536b 100644 --- a/Library/Homebrew/cask/lib/hbc/cache.rb +++ b/Library/Homebrew/cask/lib/hbc/cache.rb @@ -1,21 +1,23 @@ -module Hbc::Cache - module_function +module Hbc + module Cache + module_function - def ensure_cache_exists - return if Hbc.cache.exist? - odebug "Creating Cache at #{Hbc.cache}" - Hbc.cache.mkpath - end + def ensure_cache_exists + return if Hbc.cache.exist? - def migrate_legacy_cache - if Hbc.legacy_cache.exist? - ohai "Migrating cached files to #{Hbc.cache}..." + odebug "Creating Cache at #{Hbc.cache}" + Hbc.cache.mkpath + end + def migrate_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(%r{\-((?:(\d|#{Hbc::DSL::Version::DIVIDER_REGEX})*\-\2*)*[^\-]+)$}x, + .sub(%r{\-((?:(\d|#{DSL::Version::DIVIDER_REGEX})*\-\2*)*[^\-]+)$}x, '--\1') renamed_file = Hbc.cache.join(new_name) diff --git a/Library/Homebrew/cask/lib/hbc/cask.rb b/Library/Homebrew/cask/lib/hbc/cask.rb index fd13a6fe7..756b05b83 100644 --- a/Library/Homebrew/cask/lib/hbc/cask.rb +++ b/Library/Homebrew/cask/lib/hbc/cask.rb @@ -2,92 +2,95 @@ require "forwardable" require "hbc/dsl" -class Hbc::Cask - extend Forwardable +module Hbc + class Cask + extend Forwardable - attr_reader :token, :sourcefile_path - def initialize(token, sourcefile_path: nil, dsl: nil, &block) - @token = token - @sourcefile_path = sourcefile_path - @dsl = dsl || Hbc::DSL.new(@token) - @dsl.instance_eval(&block) if block_given? - end - - Hbc::DSL::DSL_METHODS.each do |method_name| - define_method(method_name) { @dsl.send(method_name) } - end + attr_reader :token, :sourcefile_path + def initialize(token, sourcefile_path: nil, dsl: nil, &block) + @token = token + @sourcefile_path = sourcefile_path + @dsl = dsl || DSL.new(@token) + @dsl.instance_eval(&block) if block_given? + end - METADATA_SUBDIR = ".metadata".freeze + DSL::DSL_METHODS.each do |method_name| + define_method(method_name) { @dsl.send(method_name) } + end - def metadata_master_container_path - @metadata_master_container_path ||= caskroom_path.join(METADATA_SUBDIR) - end + METADATA_SUBDIR = ".metadata".freeze - def metadata_versioned_container_path - cask_version = version ? version : :unknown - metadata_master_container_path.join(cask_version.to_s) - end - - def metadata_path(timestamp = :latest, create = false) - return nil unless metadata_versioned_container_path.respond_to?(:join) - if create && timestamp == :latest - raise Hbc::CaskError, "Cannot create metadata path when timestamp is :latest" + def metadata_master_container_path + @metadata_master_container_path ||= caskroom_path.join(METADATA_SUBDIR) end - path = if timestamp == :latest - Pathname.glob(metadata_versioned_container_path.join("*")).sort.last - elsif timestamp == :now - Hbc::Utils.nowstamp_metadata_path(metadata_versioned_container_path) - else - metadata_versioned_container_path.join(timestamp) - end - if create - odebug "Creating metadata directory #{path}" - FileUtils.mkdir_p path + + def metadata_versioned_container_path + cask_version = version ? version : :unknown + metadata_master_container_path.join(cask_version.to_s) end - path - end - def metadata_subdir(leaf, timestamp = :latest, create = false) - if create && timestamp == :latest - raise Hbc::CaskError, "Cannot create metadata subdir when timestamp is :latest" + def metadata_path(timestamp = :latest, create = false) + return nil unless metadata_versioned_container_path.respond_to?(:join) + if create && timestamp == :latest + raise CaskError, "Cannot create metadata path when timestamp is :latest" + end + path = if timestamp == :latest + Pathname.glob(metadata_versioned_container_path.join("*")).sort.last + elsif timestamp == :now + Utils.nowstamp_metadata_path(metadata_versioned_container_path) + else + metadata_versioned_container_path.join(timestamp) + end + if create + odebug "Creating metadata directory #{path}" + FileUtils.mkdir_p path + end + path end - unless leaf.respond_to?(:length) && !leaf.empty? - raise Hbc::CaskError, "Cannot create metadata subdir for empty leaf" + + def metadata_subdir(leaf, timestamp = :latest, create = false) + if create && timestamp == :latest + raise CaskError, "Cannot create metadata subdir when timestamp is :latest" + end + unless leaf.respond_to?(:length) && !leaf.empty? + raise CaskError, "Cannot create metadata subdir for empty leaf" + end + parent = metadata_path(timestamp, create) + return nil unless parent.respond_to?(:join) + subdir = parent.join(leaf) + if create + odebug "Creating metadata subdirectory #{subdir}" + FileUtils.mkdir_p subdir + end + subdir end - parent = metadata_path(timestamp, create) - return nil unless parent.respond_to?(:join) - subdir = parent.join(leaf) - if create - odebug "Creating metadata subdirectory #{subdir}" - FileUtils.mkdir_p subdir + + def timestamped_versions + Pathname.glob(metadata_master_container_path.join("*", "*")) + .map { |p| p.relative_path_from(metadata_master_container_path) } + .sort_by(&:basename) # sort by timestamp + .map(&:split) end - subdir - end - def timestamped_versions - Pathname.glob(metadata_master_container_path.join("*", "*")) - .map { |p| p.relative_path_from(metadata_master_container_path) } - .sort_by(&:basename) # sort by timestamp - .map(&:split) - end + def versions + timestamped_versions.map(&:first) + .reverse + .uniq + .reverse + end - def versions - timestamped_versions.map(&:first) - .reverse - .uniq - .reverse - end + def installed? + !versions.empty? + end - def installed? - !versions.empty? - end + def to_s + @token + end - def to_s - @token - end + def dumpcask + return unless Hbc.respond_to?(:debug) + return unless Hbc.debug - def dumpcask - if Hbc.respond_to?(:debug) && Hbc.debug odebug "Cask instance dumps in YAML:" odebug "Cask instance toplevel:", to_yaml [ diff --git a/Library/Homebrew/cask/lib/hbc/cask_dependencies.rb b/Library/Homebrew/cask/lib/hbc/cask_dependencies.rb index 6cbfd05af..4b4f042d8 100644 --- a/Library/Homebrew/cask/lib/hbc/cask_dependencies.rb +++ b/Library/Homebrew/cask/lib/hbc/cask_dependencies.rb @@ -1,33 +1,35 @@ require "hbc/topological_hash" -class Hbc::CaskDependencies - attr_reader :cask, :graph, :sorted +module Hbc + class CaskDependencies + attr_reader :cask, :graph, :sorted - def initialize(cask) - @cask = cask - @graph = graph_dependencies - @sorted = sort - end + def initialize(cask) + @cask = cask + @graph = graph_dependencies + @sorted = sort + end - def graph_dependencies - deps_in = ->(csk) { csk.depends_on ? csk.depends_on.cask || [] : [] } - walk = lambda { |acc, deps| - deps.each do |dep| - next if acc.key?(dep) - succs = deps_in.call Hbc.load(dep) - acc[dep] = succs - walk.call(acc, succs) - end - acc - } + def graph_dependencies + deps_in = ->(csk) { csk.depends_on ? csk.depends_on.cask || [] : [] } + walk = lambda { |acc, deps| + deps.each do |dep| + next if acc.key?(dep) + succs = deps_in.call Hbc.load(dep) + acc[dep] = succs + walk.call(acc, succs) + end + acc + } - graphed = walk.call({}, @cask.depends_on.cask) - Hbc::TopologicalHash[graphed] - end + graphed = walk.call({}, @cask.depends_on.cask) + TopologicalHash[graphed] + end - def sort - @graph.tsort - rescue TSort::Cyclic - raise Hbc::CaskCyclicCaskDependencyError, @cask.token + def sort + @graph.tsort + rescue TSort::Cyclic + raise CaskCyclicCaskDependencyError, @cask.token + end end end diff --git a/Library/Homebrew/cask/lib/hbc/caskroom.rb b/Library/Homebrew/cask/lib/hbc/caskroom.rb index 7d02f3fa4..583cac34a 100644 --- a/Library/Homebrew/cask/lib/hbc/caskroom.rb +++ b/Library/Homebrew/cask/lib/hbc/caskroom.rb @@ -1,18 +1,26 @@ -module Hbc::Caskroom - module_function +module Hbc + module Caskroom + module_function + + def migrate_caskroom_from_repo_to_prefix + repo_caskroom = Hbc.homebrew_repository.join("Caskroom") + return if Hbc.caskroom.exist? + return unless repo_caskroom.directory? - def migrate_caskroom_from_repo_to_prefix - repo_caskroom = Hbc.homebrew_repository.join("Caskroom") - if !Hbc.caskroom.exist? && repo_caskroom.directory? ohai "Moving Caskroom from HOMEBREW_REPOSITORY to HOMEBREW_PREFIX" - FileUtils.mv repo_caskroom, Hbc.caskroom + + if Hbc.caskroom.parent.writable? + FileUtils.mv repo_caskroom, Hbc.caskroom + else + opoo "#{Hbc.caskroom.parent} is not writable, sudo is needed to move the Caskroom." + system "/usr/bin/sudo", "--", "/bin/mv", "--", repo_caskroom.to_s, Hbc.caskroom.parent.to_s + end end - end - def ensure_caskroom_exists - unless Hbc.caskroom.exist? - ohai "Creating Caskroom at #{Hbc.caskroom}" + def ensure_caskroom_exists + return if Hbc.caskroom.exist? + ohai "Creating Caskroom at #{Hbc.caskroom}" if Hbc.caskroom.parent.writable? Hbc.caskroom.mkpath else @@ -28,7 +36,7 @@ module Hbc::Caskroom # sudo in system is rude. system "/usr/bin/sudo", "--", "/bin/mkdir", "-p", "--", Hbc.caskroom unless Hbc.caskroom.parent == toplevel_dir - system "/usr/bin/sudo", "--", "/usr/sbin/chown", "-R", "--", "#{Hbc::Utils.current_user}:staff", Hbc.caskroom.parent.to_s + system "/usr/bin/sudo", "--", "/usr/sbin/chown", "-R", "--", "#{Utils.current_user}:staff", Hbc.caskroom.parent.to_s end end end diff --git a/Library/Homebrew/cask/lib/hbc/caveats.rb b/Library/Homebrew/cask/lib/hbc/caveats.rb index 04bbcf218..a85429151 100644 --- a/Library/Homebrew/cask/lib/hbc/caveats.rb +++ b/Library/Homebrew/cask/lib/hbc/caveats.rb @@ -1,12 +1,14 @@ -class Hbc::Caveats - def initialize(block) - @block = block - end +module Hbc + class Caveats + def initialize(block) + @block = block + end - def eval_and_print(cask) - dsl = Hbc::DSL::Caveats.new(cask) - retval = dsl.instance_eval(&@block) - return if retval.nil? - puts retval.to_s.sub(%r{[\r\n \t]*\Z}, "\n\n") + def eval_and_print(cask) + dsl = DSL::Caveats.new(cask) + retval = dsl.instance_eval(&@block) + return if retval.nil? + puts retval.to_s.sub(%r{[\r\n \t]*\Z}, "\n\n") + end end end diff --git a/Library/Homebrew/cask/lib/hbc/checkable.rb b/Library/Homebrew/cask/lib/hbc/checkable.rb index 9c12f80ca..42c47ea78 100644 --- a/Library/Homebrew/cask/lib/hbc/checkable.rb +++ b/Library/Homebrew/cask/lib/hbc/checkable.rb @@ -1,51 +1,53 @@ -module Hbc::Checkable - def errors - Array(@errors) - end +module Hbc + module Checkable + def errors + Array(@errors) + end - def warnings - Array(@warnings) - end + def warnings + Array(@warnings) + end - def add_error(message) - @errors ||= [] - @errors << message - end + def add_error(message) + @errors ||= [] + @errors << message + end - def add_warning(message) - @warnings ||= [] - @warnings << message - end + def add_warning(message) + @warnings ||= [] + @warnings << message + end - def errors? - Array(@errors).any? - end + def errors? + Array(@errors).any? + end - def warnings? - Array(@warnings).any? - end + def warnings? + Array(@warnings).any? + end - def result - if errors? - "#{Tty.red}failed#{Tty.reset}" - elsif warnings? - "#{Tty.yellow}warning#{Tty.reset}" - else - "#{Tty.green}passed#{Tty.reset}" + def result + if errors? + "#{Tty.red}failed#{Tty.reset}" + elsif warnings? + "#{Tty.yellow}warning#{Tty.reset}" + else + "#{Tty.green}passed#{Tty.reset}" + end end - end - def summary - summary = ["#{summary_header}: #{result}"] + def summary + summary = ["#{summary_header}: #{result}"] - errors.each do |error| - summary << " #{Tty.red}-#{Tty.reset} #{error}" - end + errors.each do |error| + summary << " #{Tty.red}-#{Tty.reset} #{error}" + end - warnings.each do |warning| - summary << " #{Tty.yellow}-#{Tty.reset} #{warning}" - end + warnings.each do |warning| + summary << " #{Tty.yellow}-#{Tty.reset} #{warning}" + end - summary.join("\n") + summary.join("\n") + end end end diff --git a/Library/Homebrew/cask/lib/hbc/cli.rb b/Library/Homebrew/cask/lib/hbc/cli.rb index 1378176da..3f67e131d 100644 --- a/Library/Homebrew/cask/lib/hbc/cli.rb +++ b/Library/Homebrew/cask/lib/hbc/cli.rb @@ -1,5 +1,3 @@ -class Hbc::CLI; end - require "optparse" require "shellwords" @@ -28,248 +26,250 @@ require "hbc/cli/internal_dump" require "hbc/cli/internal_help" require "hbc/cli/internal_stanza" -class Hbc::CLI - ALIASES = { - "ls" => "list", - "homepage" => "home", - "-S" => "search", # verb starting with "-" is questionable - "up" => "update", - "instal" => "install", # gem does the same - "rm" => "uninstall", - "remove" => "uninstall", - "abv" => "info", - "dr" => "doctor", - # aliases from Homebrew that we don't (yet) support - # 'ln' => 'link', - # 'configure' => 'diy', - # '--repo' => '--repository', - # 'environment' => '--env', - # '-c1' => '--config', - }.freeze +module Hbc + class CLI + ALIASES = { + "ls" => "list", + "homepage" => "home", + "-S" => "search", # verb starting with "-" is questionable + "up" => "update", + "instal" => "install", # gem does the same + "rm" => "uninstall", + "remove" => "uninstall", + "abv" => "info", + "dr" => "doctor", + # aliases from Homebrew that we don't (yet) support + # 'ln' => 'link', + # 'configure' => 'diy', + # '--repo' => '--repository', + # 'environment' => '--env', + # '-c1' => '--config', + }.freeze + + OPTIONS = { + "--caskroom=" => :caskroom=, + "--appdir=" => :appdir=, + "--colorpickerdir=" => :colorpickerdir=, + "--prefpanedir=" => :prefpanedir=, + "--qlplugindir=" => :qlplugindir=, + "--fontdir=" => :fontdir=, + "--servicedir=" => :servicedir=, + "--input_methoddir=" => :input_methoddir=, + "--internet_plugindir=" => :internet_plugindir=, + "--audio_unit_plugindir=" => :audio_unit_plugindir=, + "--vst_plugindir=" => :vst_plugindir=, + "--vst3_plugindir=" => :vst3_plugindir=, + "--screen_saverdir=" => :screen_saverdir=, + }.freeze - OPTIONS = { - "--caskroom=" => :caskroom=, - "--appdir=" => :appdir=, - "--colorpickerdir=" => :colorpickerdir=, - "--prefpanedir=" => :prefpanedir=, - "--qlplugindir=" => :qlplugindir=, - "--fontdir=" => :fontdir=, - "--servicedir=" => :servicedir=, - "--input_methoddir=" => :input_methoddir=, - "--internet_plugindir=" => :internet_plugindir=, - "--audio_unit_plugindir=" => :audio_unit_plugindir=, - "--vst_plugindir=" => :vst_plugindir=, - "--vst3_plugindir=" => :vst3_plugindir=, - "--screen_saverdir=" => :screen_saverdir=, + FLAGS = { + "--no-binaries" => :no_binaries=, + "--debug" => :debug=, + "--verbose" => :verbose=, + "--outdated" => :cleanup_outdated=, + "--help" => :help=, }.freeze - FLAGS = { - "--no-binaries" => :no_binaries=, - "--debug" => :debug=, - "--verbose" => :verbose=, - "--outdated" => :cleanup_outdated=, - "--help" => :help=, - }.freeze + def self.command_classes + @command_classes ||= self.constants + .map(&method(:const_get)) + .select { |sym| sym.respond_to?(:run) } + end - def self.command_classes - @command_classes ||= Hbc::CLI.constants - .map(&Hbc::CLI.method(:const_get)) - .select { |sym| sym.respond_to?(:run) } - end + def self.commands + @commands ||= command_classes.map(&:command_name) + end - def self.commands - @commands ||= command_classes.map(&:command_name) - end + def self.lookup_command(command_string) + @lookup ||= Hash[commands.zip(command_classes)] + command_string = ALIASES.fetch(command_string, command_string) + @lookup.fetch(command_string, command_string) + end - def self.lookup_command(command_string) - @lookup ||= Hash[commands.zip(command_classes)] - command_string = ALIASES.fetch(command_string, command_string) - @lookup.fetch(command_string, command_string) - end + # modified from Homebrew + def self.require?(path) + require path + true # OK if already loaded + rescue LoadError => e + # HACK: :( because we should raise on syntax errors + # but not if the file doesn't exist. + # TODO: make robust! + raise unless e.to_s.include? path + end - # modified from Homebrew - def self.require?(path) - require path - true # OK if already loaded - rescue LoadError => e - # HACK: :( because we should raise on syntax errors - # but not if the file doesn't exist. - # TODO: make robust! - raise unless e.to_s.include? path - end + def self.should_init?(command) + (command.is_a? Class) && (command < CLI::Base) && command.needs_init? + end - def self.should_init?(command) - (command.is_a? Class) && (command < Hbc::CLI::Base) && command.needs_init? - end + def self.run_command(command, *rest) + if command.respond_to?(:run) + # usual case: built-in command verb + command.run(*rest) + elsif require? Utils.which("brewcask-#{command}.rb").to_s + # external command as Ruby library on PATH, Homebrew-style + elsif command.to_s.include?("/") && require?(command.to_s) + # external command as Ruby library with literal path, useful + # for development and troubleshooting + sym = Pathname.new(command.to_s).basename(".rb").to_s.capitalize + klass = begin + self.const_get(sym) + rescue NameError + nil + end - def self.run_command(command, *rest) - if command.respond_to?(:run) - # usual case: built-in command verb - command.run(*rest) - elsif require? Hbc::Utils.which("brewcask-#{command}.rb").to_s - # external command as Ruby library on PATH, Homebrew-style - elsif command.to_s.include?("/") && require?(command.to_s) - # external command as Ruby library with literal path, useful - # for development and troubleshooting - sym = Pathname.new(command.to_s).basename(".rb").to_s.capitalize - klass = begin - Hbc::CLI.const_get(sym) - rescue NameError - nil - end - if klass.respond_to?(:run) - # invoke "run" on a Ruby library which follows our coding conventions - klass.run(*rest) + if klass.respond_to?(:run) + # invoke "run" on a Ruby library which follows our coding conventions + # other Ruby libraries must do everything via "require" + klass.run(*rest) + end + elsif Utils.which "brewcask-#{command}" + # arbitrary external executable on PATH, Homebrew-style + exec "brewcask-#{command}", *ARGV[1..-1] + elsif Pathname.new(command.to_s).executable? && + command.to_s.include?("/") && + !command.to_s.match(%r{\.rb$}) + # arbitrary external executable with literal path, useful + # for development and troubleshooting + exec command, *ARGV[1..-1] else - # other Ruby libraries must do everything via "require" + # failure + NullCommand.new(command).run end - elsif Hbc::Utils.which "brewcask-#{command}" - # arbitrary external executable on PATH, Homebrew-style - exec "brewcask-#{command}", *ARGV[1..-1] - elsif Pathname.new(command.to_s).executable? && - command.to_s.include?("/") && - !command.to_s.match(%r{\.rb$}) - # arbitrary external executable with literal path, useful - # for development and troubleshooting - exec command, *ARGV[1..-1] - else - # failure - Hbc::CLI::NullCommand.new(command).run end - end - def self.process(arguments) - 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 Hbc::CaskError, Hbc::CaskSha256MismatchError => e - msg = e.message - msg << e.backtrace.join("\n") if Hbc.debug - onoe msg - exit 1 - rescue StandardError, ScriptError, NoMemoryError => e - msg = e.message - msg << Hbc::Utils.error_message_with_suggestions - msg << e.backtrace.join("\n") - onoe msg - exit 1 - end - - def self.nice_listing(cask_list) - cask_taps = {} - cask_list.each do |c| - user, repo, token = c.split "/" - repo.sub!(%r{^homebrew-}i, "") - cask_taps[token] ||= [] - cask_taps[token].push "#{user}/#{repo}" + def self.process(arguments) + 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 + msg = e.message + msg << e.backtrace.join("\n") if Hbc.debug + onoe msg + exit 1 + rescue StandardError, ScriptError, NoMemoryError => e + msg = e.message + msg << Utils.error_message_with_suggestions + msg << e.backtrace.join("\n") + onoe msg + exit 1 end - list = [] - cask_taps.each do |token, taps| - if taps.length == 1 - list.push token - else - taps.each { |r| list.push [r, token].join "/" } + + def self.nice_listing(cask_list) + cask_taps = {} + cask_list.each do |c| + user, repo, token = c.split "/" + repo.sub!(%r{^homebrew-}i, "") + cask_taps[token] ||= [] + cask_taps[token].push "#{user}/#{repo}" + end + list = [] + cask_taps.each do |token, taps| + if taps.length == 1 + list.push token + else + taps.each { |r| list.push [r, token].join "/" } + end end + list.sort end - list.sort - end - def self.parser - # If you modify these arguments, please update USAGE.md - @parser ||= OptionParser.new do |opts| - OPTIONS.each do |option, method| - opts.on("#{option}" "PATH", Pathname) do |path| - Hbc.public_send(method, path) + def self.parser + # If you modify these arguments, please update USAGE.md + @parser ||= OptionParser.new do |opts| + OPTIONS.each do |option, method| + opts.on("#{option}" "PATH", Pathname) do |path| + Hbc.public_send(method, path) + end end - end - opts.on("--binarydir=PATH") do - opoo <<-EOS.undent - Option --binarydir is obsolete! - Homebrew-Cask now uses the same location as your Homebrew installation for executable links. - EOS - end + opts.on("--binarydir=PATH") do + opoo <<-EOS.undent + Option --binarydir is obsolete! + Homebrew-Cask now uses the same location as your Homebrew installation for executable links. + EOS + end - FLAGS.each do |flag, method| - opts.on(flag) do - Hbc.public_send(method, true) + FLAGS.each do |flag, method| + opts.on(flag) do + Hbc.public_send(method, true) + end end - end - opts.on("--version") do - raise OptionParser::InvalidOption # override default handling of --version + opts.on("--version") do + raise OptionParser::InvalidOption # override default handling of --version + end end end - end - def self.process_options(args) - all_args = Shellwords.shellsplit(ENV["HOMEBREW_CASK_OPTS"] || "") + args - remaining = [] - until all_args.empty? - begin - head = all_args.shift - remaining.concat(parser.parse([head])) - rescue OptionParser::InvalidOption - remaining << head - retry - rescue OptionParser::MissingArgument - raise Hbc::CaskError, "The option '#{head}' requires an argument" - rescue OptionParser::AmbiguousOption - raise Hbc::CaskError, "There is more than one possible option that starts with '#{head}'" + def self.process_options(args) + all_args = Shellwords.shellsplit(ENV["HOMEBREW_CASK_OPTS"] || "") + args + remaining = [] + until all_args.empty? + begin + head = all_args.shift + remaining.concat(parser.parse([head])) + rescue OptionParser::InvalidOption + remaining << head + retry + rescue OptionParser::MissingArgument + raise CaskError, "The option '#{head}' requires an argument" + rescue OptionParser::AmbiguousOption + raise CaskError, "There is more than one possible option that starts with '#{head}'" + end end - end - # for compat with Homebrew, not certain if this is desirable - Hbc.verbose = true if !ENV["VERBOSE"].nil? || !ENV["HOMEBREW_VERBOSE"].nil? + # for compat with Homebrew, not certain if this is desirable + Hbc.verbose = true if !ENV["VERBOSE"].nil? || !ENV["HOMEBREW_VERBOSE"].nil? - remaining - end - - class NullCommand - def initialize(attempted_verb) - @attempted_verb = attempted_verb + remaining end - def run(*args) - if args.include?("--version") || @attempted_verb == "--version" - puts Hbc.full_version - else - purpose - usage - unless @attempted_verb.to_s.strip.empty? || @attempted_verb == "help" - raise Hbc::CaskError, "Unknown command: #{@attempted_verb}" + class NullCommand + def initialize(attempted_verb) + @attempted_verb = attempted_verb + end + + def run(*args) + if args.include?("--version") || @attempted_verb == "--version" + puts Hbc.full_version + else + purpose + usage + unless @attempted_verb.to_s.strip.empty? || @attempted_verb == "help" + raise CaskError, "Unknown command: #{@attempted_verb}" + end end end - end - def purpose - puts <<-EOS.undent - brew-cask provides a friendly homebrew-style CLI workflow for the - administration of macOS applications distributed as binaries. + def purpose + puts <<-EOS.undent + brew-cask provides a friendly homebrew-style CLI workflow for the + administration of macOS applications distributed as binaries. - EOS - end + EOS + end - def usage - max_command_len = Hbc::CLI.commands.map(&:length).max + def usage + max_command_len = CLI.commands.map(&:length).max - puts "Commands:\n\n" - Hbc::CLI.command_classes.each do |klass| - next unless klass.visible - puts " #{klass.command_name.ljust(max_command_len)} #{_help_for(klass)}" + puts "Commands:\n\n" + CLI.command_classes.each do |klass| + next unless klass.visible + puts " #{klass.command_name.ljust(max_command_len)} #{_help_for(klass)}" + end + puts %Q{\nSee also "man brew-cask"} end - puts %Q{\nSee also "man brew-cask"} - end - def help - "" - end + def help + "" + end - def _help_for(klass) - klass.respond_to?(:help) ? klass.help : nil + def _help_for(klass) + klass.respond_to?(:help) ? klass.help : nil + end end end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/audit.rb b/Library/Homebrew/cask/lib/hbc/cli/audit.rb index 289547b44..a06f71c60 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/audit.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/audit.rb @@ -1,52 +1,56 @@ -class Hbc::CLI::Audit < Hbc::CLI::Base - def self.help - "verifies installability of Casks" - end - - def self.run(*args) - failed_casks = new(args, Hbc::Auditor).run - return if failed_casks.empty? - raise Hbc::CaskError, "audit failed for casks: #{failed_casks.join(' ')}" - end - - def initialize(args, auditor) - @args = args - @auditor = auditor - end - - def run - casks_to_audit.each_with_object([]) do |cask, failed| - failed << cask unless audit(cask) +module Hbc + class CLI + class Audit < Base + def self.help + "verifies installability of Casks" + end + + def self.run(*args) + failed_casks = new(args, Auditor).run + return if failed_casks.empty? + raise CaskError, "audit failed for casks: #{failed_casks.join(" ")}" + end + + def initialize(args, auditor) + @args = args + @auditor = auditor + end + + def run + casks_to_audit.each_with_object([]) do |cask, failed| + failed << cask unless audit(cask) + end + end + + def audit(cask) + odebug "Auditing Cask #{cask}" + @auditor.audit(cask, audit_download: audit_download?, + check_token_conflicts: check_token_conflicts?) + end + + def audit_download? + @args.include?("--download") + end + + def check_token_conflicts? + @args.include?("--token-conflicts") + end + + def casks_to_audit + if cask_tokens.empty? + Hbc.all + else + cask_tokens.map { |token| Hbc.load(token) } + end + end + + def cask_tokens + @cask_tokens ||= self.class.cask_tokens_from(@args) + end + + def self.needs_init? + true + end end end - - def audit(cask) - odebug "Auditing Cask #{cask}" - @auditor.audit(cask, audit_download: audit_download?, - check_token_conflicts: check_token_conflicts?) - end - - def audit_download? - @args.include?("--download") - end - - def check_token_conflicts? - @args.include?("--token-conflicts") - end - - def casks_to_audit - if cask_tokens.empty? - Hbc.all - else - cask_tokens.map { |token| Hbc.load(token) } - end - end - - def cask_tokens - @cask_tokens ||= self.class.cask_tokens_from(@args) - end - - def self.needs_init? - true - end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/base.rb b/Library/Homebrew/cask/lib/hbc/cli/base.rb index af03969af..6c706d537 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/base.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/base.rb @@ -1,21 +1,25 @@ -class Hbc::CLI::Base - def self.command_name - @command_name ||= name.sub(%r{^.*:}, "").gsub(%r{(.)([A-Z])}, '\1_\2').downcase - end +module Hbc + class CLI + class Base + def self.command_name + @command_name ||= name.sub(%r{^.*:}, "").gsub(%r{(.)([A-Z])}, '\1_\2').downcase + end - def self.visible - true - end + def self.visible + true + end - def self.cask_tokens_from(args) - args.reject { |a| a.empty? || a.chars.first == "-" } - end + def self.cask_tokens_from(args) + args.reject { |a| a.empty? || a.chars.first == "-" } + end - def self.help - "No help available for the #{command_name} command" - end + def self.help + "No help available for the #{command_name} command" + end - def self.needs_init? - false + def self.needs_init? + false + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/cat.rb b/Library/Homebrew/cask/lib/hbc/cli/cat.rb index d6d545c3b..75f6c1e91 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/cat.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/cat.rb @@ -1,15 +1,19 @@ -class Hbc::CLI::Cat < Hbc::CLI::Base - def self.run(*args) - cask_tokens = cask_tokens_from(args) - raise Hbc::CaskUnspecifiedError if cask_tokens.empty? - # only respects the first argument - cask_token = cask_tokens.first.sub(%r{\.rb$}i, "") - cask_path = Hbc.path(cask_token) - raise Hbc::CaskUnavailableError, cask_token.to_s unless cask_path.exist? - puts File.open(cask_path, &:read) - end +module Hbc + class CLI + class Cat < Base + def self.run(*args) + cask_tokens = cask_tokens_from(args) + raise CaskUnspecifiedError if cask_tokens.empty? + # only respects the first argument + cask_token = cask_tokens.first.sub(%r{\.rb$}i, "") + cask_path = Hbc.path(cask_token) + raise CaskUnavailableError, cask_token.to_s unless cask_path.exist? + puts File.open(cask_path, &:read) + end - def self.help - "dump raw source of the given Cask to the standard output" + def self.help + "dump raw source of the given Cask to the standard output" + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/cleanup.rb b/Library/Homebrew/cask/lib/hbc/cli/cleanup.rb index 4115d26fc..0296dc96d 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/cleanup.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/cleanup.rb @@ -1,108 +1,112 @@ -class Hbc::CLI::Cleanup < Hbc::CLI::Base - OUTDATED_DAYS = 10 - OUTDATED_TIMESTAMP = Time.now - (60 * 60 * 24 * OUTDATED_DAYS) - - def self.help - "cleans up cached downloads and tracker symlinks" - end - - def self.needs_init? - true - end +module Hbc + class CLI + class Cleanup < Base + OUTDATED_DAYS = 10 + OUTDATED_TIMESTAMP = Time.now - (60 * 60 * 24 * OUTDATED_DAYS) + + def self.help + "cleans up cached downloads and tracker symlinks" + end - def self.run(*args) - if args.empty? - default.cleanup! - else - default.cleanup(args) - end - end + def self.needs_init? + true + end - def self.default - @default ||= new(Hbc.cache, Hbc.cleanup_outdated) - end + def self.run(*args) + if args.empty? + default.cleanup! + else + default.cleanup(args) + end + end - attr_reader :cache_location, :outdated_only - def initialize(cache_location, outdated_only) - @cache_location = Pathname.new(cache_location) - @outdated_only = outdated_only - end + def self.default + @default ||= new(Hbc.cache, Hbc.cleanup_outdated) + end - def cleanup! - remove_cache_files - end + attr_reader :cache_location, :outdated_only + def initialize(cache_location, outdated_only) + @cache_location = Pathname.new(cache_location) + @outdated_only = outdated_only + end - def cleanup(tokens) - remove_cache_files(*tokens) - end + def cleanup! + remove_cache_files + end - def cache_files - return [] unless cache_location.exist? - cache_location.children - .map(&method(:Pathname)) - .reject(&method(:outdated?)) - end + def cleanup(tokens) + remove_cache_files(*tokens) + end - def outdated?(file) - outdated_only && file && file.stat.mtime > OUTDATED_TIMESTAMP - end + def cache_files + return [] unless cache_location.exist? + cache_location.children + .map(&method(:Pathname)) + .reject(&method(:outdated?)) + end - def incomplete?(file) - file.extname == ".incomplete" - end + def outdated?(file) + outdated_only && file && file.stat.mtime > OUTDATED_TIMESTAMP + end - def cache_incompletes - cache_files.select(&method(:incomplete?)) - end + def incomplete?(file) + file.extname == ".incomplete" + end - def cache_completes - cache_files.reject(&method(:incomplete?)) - end + def cache_incompletes + cache_files.select(&method(:incomplete?)) + end - def disk_cleanup_size - Hbc::Utils.size_in_bytes(cache_files) - end + def cache_completes + cache_files.reject(&method(:incomplete?)) + end - def remove_cache_files(*tokens) - message = "Removing cached downloads" - message.concat " for #{tokens.join(', ')}" unless tokens.empty? - message.concat " older than #{OUTDATED_DAYS} days old" if outdated_only - ohai message + def disk_cleanup_size + Utils.size_in_bytes(cache_files) + end - deletable_cache_files = if tokens.empty? - cache_files - else - start_withs = tokens.map { |token| "#{token}--" } + def remove_cache_files(*tokens) + message = "Removing cached downloads" + message.concat " for #{tokens.join(", ")}" unless tokens.empty? + message.concat " older than #{OUTDATED_DAYS} days old" if outdated_only + ohai message - cache_files.select { |path| - path.basename.to_s.start_with?(*start_withs) - } - end + deletable_cache_files = if tokens.empty? + cache_files + else + start_withs = tokens.map { |token| "#{token}--" } - delete_paths(deletable_cache_files) - end + cache_files.select { |path| + path.basename.to_s.start_with?(*start_withs) + } + end - def delete_paths(paths) - cleanup_size = 0 - processed_files = 0 - paths.each do |item| - next unless item.exist? - processed_files += 1 - if Hbc::Utils.file_locked?(item) - puts "skipping: #{item} is locked" - next + delete_paths(deletable_cache_files) end - puts item - item_size = File.size?(item) - cleanup_size += item_size unless item_size.nil? - item.unlink - end - if processed_files.zero? - puts "Nothing to do" - else - disk_space = disk_usage_readable(cleanup_size) - ohai "This operation has freed approximately #{disk_space} of disk space." + def delete_paths(paths) + cleanup_size = 0 + processed_files = 0 + paths.each do |item| + next unless item.exist? + processed_files += 1 + if Utils.file_locked?(item) + puts "skipping: #{item} is locked" + next + end + puts item + item_size = File.size?(item) + cleanup_size += item_size unless item_size.nil? + item.unlink + end + + if processed_files.zero? + puts "Nothing to do" + else + disk_space = disk_usage_readable(cleanup_size) + ohai "This operation has freed approximately #{disk_space} of disk space." + end + end end end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/create.rb b/Library/Homebrew/cask/lib/hbc/cli/create.rb index 3c1ac76ed..14860942f 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/create.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/create.rb @@ -1,37 +1,41 @@ -class Hbc::CLI::Create < Hbc::CLI::Base - def self.run(*args) - cask_tokens = cask_tokens_from(args) - raise Hbc::CaskUnspecifiedError if cask_tokens.empty? - cask_token = cask_tokens.first.sub(%r{\.rb$}i, "") - cask_path = Hbc.path(cask_token) - odebug "Creating Cask #{cask_token}" +module Hbc + class CLI + class Create < Base + def self.run(*args) + cask_tokens = cask_tokens_from(args) + raise CaskUnspecifiedError if cask_tokens.empty? + cask_token = cask_tokens.first.sub(%r{\.rb$}i, "") + cask_path = Hbc.path(cask_token) + odebug "Creating Cask #{cask_token}" - raise Hbc::CaskAlreadyCreatedError, cask_token if cask_path.exist? + raise CaskAlreadyCreatedError, cask_token if cask_path.exist? - File.open(cask_path, "w") do |f| - f.write template(cask_token) - end + File.open(cask_path, "w") do |f| + f.write template(cask_token) + end - exec_editor cask_path - end + exec_editor cask_path + end - def self.template(cask_token) - <<-EOS.undent - cask '#{cask_token}' do - version '' - sha256 '' + def self.template(cask_token) + <<-EOS.undent + cask '#{cask_token}' do + version '' + sha256 '' - url 'https://' - name '' - homepage '' - license :unknown # TODO: change license and remove this comment; ':unknown' is a machine-generated placeholder + url 'https://' + name '' + homepage '' + license :unknown # TODO: change license and remove this comment; ':unknown' is a machine-generated placeholder - app '' + app '' + end + EOS end - EOS - end - def self.help - "creates the given Cask and opens it in an editor" + def self.help + "creates the given Cask and opens it in an editor" + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/doctor.rb b/Library/Homebrew/cask/lib/hbc/cli/doctor.rb index 2632bcaef..34f000b29 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/doctor.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/doctor.rb @@ -1,205 +1,209 @@ -class Hbc::CLI::Doctor < Hbc::CLI::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(Hbc.homebrew_executable) - 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) - ohai "Running As Privileged User:", render_with_none_as_error(privileged_uid) - end +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(Hbc.homebrew_executable) + 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) + ohai "Running As Privileged User:", render_with_none_as_error(privileged_uid) + end - def self.alt_taps - Tap.select { |t| t.cask_dir && t != Hbc.default_tap } - .map(&:path) - 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.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 = Hbc::SystemCommand.run("/usr/bin/git", - args: %w[config --get remote.origin.url], - print_stderr: false).stdout.strip - end - if homebrew_origin !~ %r{\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_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 !~ %r{\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_repository - homebrew_constants("repository") - end + def self.homebrew_repository + homebrew_constants("repository") + end - def self.homebrew_cellar - homebrew_constants("cellar") - end + def self.homebrew_cellar + homebrew_constants("cellar") + end - def self.homebrew_version - homebrew_constants("version") - end + def self.homebrew_version + homebrew_constants("version") + end - def self.homebrew_taps - @homebrew_taps ||= if homebrew_repository.respond_to?(:join) - homebrew_repository.join("Library", "Taps") - end - end + def self.homebrew_taps + @homebrew_taps ||= if homebrew_repository.respond_to?(:join) + homebrew_repository.join("Library", "Taps") + end + 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] = Hbc::SystemCommand.run!(Hbc.homebrew_executable, - args: ["--#{name}"], - print_stderr: false) - .stdout - .strip - if @homebrew_constants[name] !~ %r{\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] - 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!(Hbc.homebrew_executable, + args: ["--#{name}"], + print_stderr: false) + .stdout + .strip + if @homebrew_constants[name] !~ %r{\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] + end - def self.locale_variables - ENV.keys.grep(%r{^(?:LC_\S+|LANG|LANGUAGE)\Z}).collect { |v| %Q{#{v}="#{ENV[v]}"} }.sort.join("\n") - end + def self.locale_variables + ENV.keys.grep(%r{^(?:LC_\S+|LANG|LANGUAGE)\Z}).collect { |v| %Q{#{v}="#{ENV[v]}"} }.sort.join("\n") + end - def self.privileged_uid - Process.euid == 0 ? "Yes #{error_string 'warning: not recommended'}" : "No" - rescue StandardError - notfound_string - end + def self.privileged_uid + Process.euid.zero? ? "Yes #{error_string "warning: not recommended"}" : "No" + rescue StandardError + notfound_string + end - def self.none_string - "<NONE>" - end + def self.none_string + "<NONE>" + end - def self.legacy_tap_pattern - %r{phinze} - end + def self.legacy_tap_pattern + %r{phinze} + end - def self.notfound_string - "#{Tty.red}Not Found - Unknown Error#{Tty.reset}" - end + def self.notfound_string + "#{Tty.red}Not Found - Unknown Error#{Tty.reset}" + end - def self.error_string(string = "Error") - "#{Tty.red}(#{string})#{Tty.reset}" - end + def self.error_string(string = "Error") + "#{Tty.red}(#{string})#{Tty.reset}" + end - def self.render_with_none(string) - return string if !string.nil? && string.respond_to?(:to_s) && !string.to_s.empty? - none_string - end + def self.render_with_none(string) + return string if !string.nil? && string.respond_to?(:to_s) && !string.to_s.empty? + 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}" - 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}" + 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? - none_string - elsif dir.to_s.match(legacy_tap_pattern) - dir.to_s.concat(" #{error_string 'Warning: legacy tap path'}") - else - dir.to_s + def self.render_tap_paths(paths) + paths = [paths] unless paths.respond_to?(:each) + paths.collect do |dir| + if dir.nil? || dir.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 + end + end end - end - end - def self.render_env_var(var) - if ENV.key?(var) - %Q{#{var}="#{ENV[var]}"} - else - none_string - end - end + def self.render_env_var(var) + if ENV.key?(var) + %Q{#{var}="#{ENV[var]}"} + else + none_string + end + 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 - if locations.empty? - none_string - else - locations.collect do |l| - "#{l} #{error_string 'error: legacy install. Run "brew uninstall --force brew-cask".'}" + # 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 + if locations.empty? + none_string + else + locations.collect do |l| + "#{l} #{error_string 'error: legacy install. Run "brew uninstall --force brew-cask".'}" + end + end end - end - end - def self.render_staging_location(path) - path = Pathname.new(path) - if !path.exist? - "#{path} #{error_string 'error: path does not exist'}}" - elsif !path.writable? - "#{path} #{error_string 'error: not writable by current user'}" - else - path - end - end + def self.render_staging_location(path) + path = Pathname.new(path) + if !path.exist? + "#{path} #{error_string "error: path does not exist"}}" + elsif !path.writable? + "#{path} #{error_string "error: not writable by current user"}" + else + path + end + end - def self.render_load_path(paths) - return "#{none_string} #{error_string}" if [*paths].empty? - paths - end + def self.render_load_path(paths) + return "#{none_string} #{error_string}" if [*paths].empty? + paths + end - def self.render_cached_downloads - cleanup = Hbc::CLI::Cleanup.default - files = cleanup.cache_files - count = 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] - end + def self.render_cached_downloads + cleanup = CLI::Cleanup.default + files = cleanup.cache_files + count = 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] + end - def self.help - "checks for configuration issues" + def self.help + "checks for configuration issues" + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/edit.rb b/Library/Homebrew/cask/lib/hbc/cli/edit.rb index b2d4a9156..3090cf196 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/edit.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/edit.rb @@ -1,18 +1,22 @@ -class Hbc::CLI::Edit < Hbc::CLI::Base - def self.run(*args) - cask_tokens = cask_tokens_from(args) - raise Hbc::CaskUnspecifiedError if cask_tokens.empty? - # only respects the first argument - cask_token = cask_tokens.first.sub(%r{\.rb$}i, "") - cask_path = Hbc.path(cask_token) - odebug "Opening editor for Cask #{cask_token}" - unless cask_path.exist? - raise Hbc::CaskUnavailableError, %Q{#{cask_token}, run "brew cask create #{cask_token}" to create a new Cask} - end - exec_editor cask_path - end +module Hbc + class CLI + class Edit < Base + def self.run(*args) + cask_tokens = cask_tokens_from(args) + raise CaskUnspecifiedError if cask_tokens.empty? + # only respects the first argument + cask_token = cask_tokens.first.sub(%r{\.rb$}i, "") + cask_path = Hbc.path(cask_token) + odebug "Opening editor for Cask #{cask_token}" + unless cask_path.exist? + raise CaskUnavailableError, %Q{#{cask_token}, run "brew cask create #{cask_token}" to create a new Cask} + end + exec_editor cask_path + end - def self.help - "edits the given Cask" + def self.help + "edits the given Cask" + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/fetch.rb b/Library/Homebrew/cask/lib/hbc/cli/fetch.rb index 647f2af2c..9b3d5099c 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/fetch.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/fetch.rb @@ -1,19 +1,23 @@ -class Hbc::CLI::Fetch < Hbc::CLI::Base - def self.run(*args) - cask_tokens = cask_tokens_from(args) - raise Hbc::CaskUnspecifiedError if cask_tokens.empty? - force = args.include? "--force" +module Hbc + class CLI + class Fetch < Base + def self.run(*args) + cask_tokens = cask_tokens_from(args) + raise CaskUnspecifiedError if cask_tokens.empty? + force = args.include? "--force" - cask_tokens.each do |cask_token| - ohai "Downloading external files for Cask #{cask_token}" - cask = Hbc.load(cask_token) - downloaded_path = Hbc::Download.new(cask, force: force).perform - Hbc::Verify.all(cask, downloaded_path) - ohai "Success! Downloaded to -> #{downloaded_path}" - end - end + cask_tokens.each do |cask_token| + ohai "Downloading external files for Cask #{cask_token}" + cask = Hbc.load(cask_token) + downloaded_path = Download.new(cask, force: force).perform + Verify.all(cask, downloaded_path) + ohai "Success! Downloaded to -> #{downloaded_path}" + end + end - def self.help - "downloads remote application files to local cache" + def self.help + "downloads remote application files to local cache" + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/home.rb b/Library/Homebrew/cask/lib/hbc/cli/home.rb index 9c8c0a0e4..b35b08279 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/home.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/home.rb @@ -1,18 +1,22 @@ -class Hbc::CLI::Home < Hbc::CLI::Base - def self.run(*cask_tokens) - if cask_tokens.empty? - odebug "Opening project homepage" - system "/usr/bin/open", "--", "http://caskroom.io/" - else - cask_tokens.each do |cask_token| - odebug "Opening homepage for Cask #{cask_token}" - cask = Hbc.load(cask_token) - system "/usr/bin/open", "--", cask.homepage +module Hbc + class CLI + class Home < Base + def self.run(*cask_tokens) + if cask_tokens.empty? + odebug "Opening project homepage" + system "/usr/bin/open", "--", "http://caskroom.io/" + else + cask_tokens.each do |cask_token| + odebug "Opening homepage for Cask #{cask_token}" + cask = Hbc.load(cask_token) + system "/usr/bin/open", "--", cask.homepage + end + end end - end - end - def self.help - "opens the homepage of the given Cask" + def self.help + "opens the homepage of the given Cask" + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/info.rb b/Library/Homebrew/cask/lib/hbc/cli/info.rb index 76f2d1366..7fbdff3eb 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/info.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/info.rb @@ -1,65 +1,69 @@ -class Hbc::CLI::Info < Hbc::CLI::Base - def self.run(*args) - cask_tokens = cask_tokens_from(args) - raise Hbc::CaskUnspecifiedError if cask_tokens.empty? - cask_tokens.each do |cask_token| - odebug "Getting info for Cask #{cask_token}" - cask = Hbc.load(cask_token) +module Hbc + class CLI + class Info < Base + def self.run(*args) + cask_tokens = cask_tokens_from(args) + raise CaskUnspecifiedError if cask_tokens.empty? + cask_tokens.each do |cask_token| + odebug "Getting info for Cask #{cask_token}" + cask = Hbc.load(cask_token) - info(cask) - end - end + info(cask) + end + end - def self.help - "displays information about the given Cask" - end + def self.help + "displays information about the given Cask" + end - def self.info(cask) - puts "#{cask.token}: #{cask.version}" - puts formatted_url(cask.homepage) if cask.homepage - installation_info(cask) - puts "From: #{formatted_url(github_info(cask))}" if github_info(cask) - name_info(cask) - artifact_info(cask) - Hbc::Installer.print_caveats(cask) - end + def self.info(cask) + puts "#{cask.token}: #{cask.version}" + puts formatted_url(cask.homepage) if cask.homepage + installation_info(cask) + puts "From: #{formatted_url(github_info(cask))}" if github_info(cask) + name_info(cask) + artifact_info(cask) + Installer.print_caveats(cask) + end - def self.formatted_url(url) - "#{Tty.em}#{url}#{Tty.reset}" - end + def self.formatted_url(url) + "#{Tty.em}#{url}#{Tty.reset}" + end - def self.installation_info(cask) - if cask.installed? - cask.versions.each do |version| - versioned_staged_path = cask.caskroom_path.join(version) + def self.installation_info(cask) + if cask.installed? + cask.versions.each do |version| + versioned_staged_path = cask.caskroom_path.join(version) - puts versioned_staged_path.to_s - .concat(" (") - .concat(versioned_staged_path.exist? ? versioned_staged_path.abv : "#{Tty.red}does not exist#{Tty.reset}") - .concat(")") + puts versioned_staged_path.to_s + .concat(" (") + .concat(versioned_staged_path.exist? ? versioned_staged_path.abv : "#{Tty.red}does not exist#{Tty.reset}") + .concat(")") + end + else + puts "Not installed" + end end - else - puts "Not installed" - end - end - def self.name_info(cask) - ohai cask.name.size > 1 ? "Names" : "Name" - puts cask.name.empty? ? "#{Tty.red}None#{Tty.reset}" : cask.name - end + def self.name_info(cask) + ohai cask.name.size > 1 ? "Names" : "Name" + puts cask.name.empty? ? "#{Tty.red}None#{Tty.reset}" : cask.name + end - def self.github_info(cask) - user, repo, token = Hbc::QualifiedToken.parse(Hbc.all_tokens.detect { |t| t.split("/").last == cask.token }) - "#{Tap.fetch(user, repo).default_remote}/blob/master/Casks/#{token}.rb" - end + def self.github_info(cask) + user, repo, token = QualifiedToken.parse(Hbc.all_tokens.detect { |t| t.split("/").last == cask.token }) + "#{Tap.fetch(user, repo).default_remote}/blob/master/Casks/#{token}.rb" + end - def self.artifact_info(cask) - ohai "Artifacts" - Hbc::DSL::ORDINARY_ARTIFACT_TYPES.each do |type| - next if cask.artifacts[type].empty? - cask.artifacts[type].each do |artifact| - activatable_item = type == :stage_only ? "<none>" : artifact.first - puts "#{activatable_item} (#{type})" + def self.artifact_info(cask) + ohai "Artifacts" + DSL::ORDINARY_ARTIFACT_TYPES.each do |type| + next if cask.artifacts[type].empty? + cask.artifacts[type].each do |artifact| + activatable_item = type == :stage_only ? "<none>" : artifact.first + puts "#{activatable_item} (#{type})" + end + end end end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/install.rb b/Library/Homebrew/cask/lib/hbc/cli/install.rb index 43eab9f3d..d7575344d 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/install.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/install.rb @@ -1,60 +1,63 @@ +module Hbc + class CLI + class Install < Base + def self.run(*args) + cask_tokens = cask_tokens_from(args) + raise CaskUnspecifiedError if cask_tokens.empty? + force = args.include? "--force" + skip_cask_deps = args.include? "--skip-cask-deps" + require_sha = args.include? "--require-sha" + retval = install_casks cask_tokens, force, skip_cask_deps, require_sha + # retval is ternary: true/false/nil -class Hbc::CLI::Install < Hbc::CLI::Base - def self.run(*args) - cask_tokens = cask_tokens_from(args) - raise Hbc::CaskUnspecifiedError if cask_tokens.empty? - force = args.include? "--force" - skip_cask_deps = args.include? "--skip-cask-deps" - require_sha = args.include? "--require-sha" - retval = install_casks cask_tokens, force, skip_cask_deps, require_sha - # retval is ternary: true/false/nil - - raise Hbc::CaskError, "nothing to install" if retval.nil? - raise Hbc::CaskError, "install incomplete" unless retval - end + raise CaskError, "nothing to install" if retval.nil? + raise CaskError, "install incomplete" unless retval + end - def self.install_casks(cask_tokens, force, skip_cask_deps, require_sha) - count = 0 - cask_tokens.each do |cask_token| - begin - cask = Hbc.load(cask_token) - Hbc::Installer.new(cask, - force: force, - skip_cask_deps: skip_cask_deps, - require_sha: require_sha).install - count += 1 - rescue Hbc::CaskAlreadyInstalledError => e - opoo e.message - count += 1 - rescue Hbc::CaskAutoUpdatesError => e - opoo e.message - count += 1 - rescue Hbc::CaskUnavailableError => e - warn_unavailable_with_suggestion cask_token, e - rescue Hbc::CaskNoShasumError => e - opoo e.message - count += 1 + def self.install_casks(cask_tokens, force, skip_cask_deps, require_sha) + count = 0 + cask_tokens.each do |cask_token| + begin + cask = Hbc.load(cask_token) + Installer.new(cask, + force: force, + skip_cask_deps: skip_cask_deps, + require_sha: require_sha).install + count += 1 + rescue CaskAlreadyInstalledError => e + opoo e.message + count += 1 + rescue CaskAutoUpdatesError => e + opoo e.message + count += 1 + rescue CaskUnavailableError => e + warn_unavailable_with_suggestion cask_token, e + rescue CaskNoShasumError => e + opoo e.message + count += 1 + end + end + count.zero? ? nil : count == cask_tokens.length end - end - count == 0 ? nil : count == cask_tokens.length - end - def self.warn_unavailable_with_suggestion(cask_token, e) - exact_match, partial_matches = Hbc::CLI::Search.search(cask_token) - errmsg = e.message - if exact_match - errmsg.concat(". Did you mean:\n#{exact_match}") - elsif !partial_matches.empty? - errmsg.concat(". Did you mean one of:\n#{puts_columns(partial_matches.take(20))}\n") - end - onoe errmsg - end + def self.warn_unavailable_with_suggestion(cask_token, e) + exact_match, partial_matches = Search.search(cask_token) + errmsg = e.message + if exact_match + errmsg.concat(". Did you mean:\n#{exact_match}") + elsif !partial_matches.empty? + errmsg.concat(". Did you mean one of:\n#{puts_columns(partial_matches.take(20))}\n") + end + onoe errmsg + end - def self.help - "installs the given Cask" - end + def self.help + "installs the given Cask" + end - def self.needs_init? - true + def self.needs_init? + true + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_audit_modified_casks.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_audit_modified_casks.rb index f05dbe803..47258a7b2 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/internal_audit_modified_casks.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_audit_modified_casks.rb @@ -1,135 +1,139 @@ -class Hbc::CLI::InternalAuditModifiedCasks < Hbc::CLI::InternalUseBase - RELEVANT_STANZAS = %i{version sha256 url appcast}.freeze +module Hbc + class CLI + class InternalAuditModifiedCasks < InternalUseBase + RELEVANT_STANZAS = %i{version sha256 url appcast}.freeze + + class << self + def needs_init? + true + end + + def run(*args) + commit_range = commit_range(args) + cleanup = args.any? { |a| a =~ %r{^-+c(leanup)?$}i } + new(commit_range, cleanup: cleanup).run + end + + def commit_range(args) + posargs = args.reject { |a| a.empty? || a.chars.first == "-" } + odie usage unless posargs.size == 1 + posargs.first + end + + def posargs(args) + args.reject { |a| a.empty? || a.chars.first == "-" } + end + + def usage + <<-EOS.undent + Usage: brew cask _audit_modified_casks [options...] <commit range> + + Given a range of Git commits, find any Casks that were modified and run `brew + cask audit' on them. If the `url', `version', or `sha256' stanzas were modified, + run with the `--download' flag to verify the hash. + + Options: + -c, --cleanup + Remove all cached downloads. Use with care. + EOS + end + end - class << self - def needs_init? - true - end + def initialize(commit_range, cleanup: false) + @commit_range = commit_range + @cleanup = cleanup + end - def run(*args) - commit_range = commit_range(args) - cleanup = args.any? { |a| a =~ %r{^-+c(leanup)?$}i } - new(commit_range, cleanup: cleanup).run - end + attr_reader :commit_range - def commit_range(args) - posargs = args.reject { |a| a.empty? || a.chars.first == "-" } - odie usage unless posargs.size == 1 - posargs.first - end + def cleanup? + @cleanup + end - def posargs(args) - args.reject { |a| a.empty? || a.chars.first == "-" } - end + def run + at_exit do + cleanup + end + + Dir.chdir git_root do + modified_cask_files.zip(modified_casks).each do |cask_file, cask| + audit(cask, cask_file) + end + end + report_failures + end - def usage - <<-EOS.undent - Usage: brew cask _audit_modified_casks [options...] <commit range> + def git_root + @git_root ||= git("rev-parse", "--show-toplevel") + end - Given a range of Git commits, find any Casks that were modified and run `brew - cask audit' on them. If the `url', `version', or `sha256' stanzas were modified, - run with the `--download' flag to verify the hash. + def modified_cask_files + @modified_cask_files ||= git_filter_cask_files("AM") + end - Options: - -c, --cleanup - Remove all cached downloads. Use with care. - EOS - end - end + def added_cask_files + @added_cask_files ||= git_filter_cask_files("A") + end - def initialize(commit_range, cleanup: false) - @commit_range = commit_range - @cleanup = cleanup - end + def git_filter_cask_files(filter) + git("diff", "--name-only", "--diff-filter=#{filter}", commit_range, + "--", Pathname.new(git_root).join("Casks", "*.rb").to_s).split("\n") + end - attr_reader :commit_range + def modified_casks + return @modified_casks if defined? @modified_casks + @modified_casks = modified_cask_files.map { |f| Hbc.load(f) } + if @modified_casks.any? + num_modified = @modified_casks.size + ohai "#{num_modified} modified #{pluralize("cask", num_modified)}: " \ + "#{@modified_casks.join(" ")}" + end + @modified_casks + end - def cleanup? - @cleanup - end + def audit(cask, cask_file) + audit_download = audit_download?(cask, cask_file) + check_token_conflicts = added_cask_files.include?(cask_file) + success = Auditor.audit(cask, audit_download: audit_download, + check_token_conflicts: check_token_conflicts) + failed_casks << cask unless success + end - def run - at_exit do - cleanup - end + def failed_casks + @failed_casks ||= [] + end - Dir.chdir git_root do - modified_cask_files.zip(modified_casks).each do |cask_file, cask| - audit(cask, cask_file) + def audit_download?(cask, cask_file) + cask.sha256 != :no_check && relevant_stanza_modified?(cask_file) end - end - report_failures - end - def git_root - @git_root ||= git(*%w[rev-parse --show-toplevel]) - end + def relevant_stanza_modified?(cask_file) + out = git("diff", commit_range, "--", cask_file) + out =~ %r{^\+\s*(#{RELEVANT_STANZAS.join('|')})} + end - def modified_cask_files - @modified_cask_files ||= git_filter_cask_files("AM") - end + def git(*args) + odebug ["git", *args].join(" ") + out, err, status = Open3.capture3("git", *args) + return out.chomp if status.success? + odie err.chomp + end - def added_cask_files - @added_cask_files ||= git_filter_cask_files("A") - end + def report_failures + return if failed_casks.empty? + num_failed = failed_casks.size + cask_pluralized = pluralize("cask", num_failed) + odie "audit failed for #{num_failed} #{cask_pluralized}: " \ + "#{failed_casks.join(" ")}" + end - def git_filter_cask_files(filter) - git("diff", "--name-only", "--diff-filter=#{filter}", commit_range, - "--", Pathname.new(git_root).join("Casks", "*.rb").to_s).split("\n") - end + def pluralize(str, num) + num == 1 ? str : "#{str}s" + end - def modified_casks - return @modified_casks if defined? @modified_casks - @modified_casks = modified_cask_files.map { |f| Hbc.load(f) } - if @modified_casks.any? - num_modified = @modified_casks.size - ohai "#{num_modified} modified #{pluralize('cask', num_modified)}: " \ - "#{@modified_casks.join(' ')}" + def cleanup + Cleanup.run if cleanup? + end end - @modified_casks - end - - def audit(cask, cask_file) - audit_download = audit_download?(cask, cask_file) - check_token_conflicts = added_cask_files.include?(cask_file) - success = Hbc::Auditor.audit(cask, audit_download: audit_download, - check_token_conflicts: check_token_conflicts) - failed_casks << cask unless success - end - - def failed_casks - @failed_casks ||= [] - end - - def audit_download?(cask, cask_file) - cask.sha256 != :no_check && relevant_stanza_modified?(cask_file) - end - - def relevant_stanza_modified?(cask_file) - out = git("diff", commit_range, "--", cask_file) - out =~ %r{^\+\s*(#{RELEVANT_STANZAS.join('|')})} - end - - def git(*args) - odebug ["git", *args].join(" ") - out, err, status = Open3.capture3("git", *args) - return out.chomp if status.success? - odie err.chomp - end - - def report_failures - return if failed_casks.empty? - num_failed = failed_casks.size - cask_pluralized = pluralize("cask", num_failed) - odie "audit failed for #{num_failed} #{cask_pluralized}: " \ - "#{failed_casks.join(' ')}" - end - - def pluralize(str, num) - num == 1 ? str : "#{str}s" - end - - def cleanup - Hbc::CLI::Cleanup.run if cleanup? end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_checkurl.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_checkurl.rb index d53f420e2..77cf250b1 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/internal_checkurl.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_checkurl.rb @@ -1,15 +1,19 @@ -class Hbc::CLI::InternalCheckurl < Hbc::CLI::InternalUseBase - def self.run(*args) - casks_to_check = args.empty? ? Hbc.all : args.map { |arg| Hbc.load(arg) } - casks_to_check.each do |cask| - odebug "Checking URL for Cask #{cask}" - checker = Hbc::UrlChecker.new(cask) - checker.run - puts checker.summary - end - end +module Hbc + class CLI + class InternalCheckurl < InternalUseBase + def self.run(*args) + casks_to_check = args.empty? ? Hbc.all : args.map { |arg| Hbc.load(arg) } + casks_to_check.each do |cask| + odebug "Checking URL for Cask #{cask}" + checker = UrlChecker.new(cask) + checker.run + puts checker.summary + end + end - def self.help - "checks for bad Cask URLs" + def self.help + "checks for bad Cask URLs" + 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 d1cfe8d63..af1494e5f 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/internal_dump.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_dump.rb @@ -1,30 +1,34 @@ -class Hbc::CLI::InternalDump < Hbc::CLI::InternalUseBase - def self.run(*arguments) - cask_tokens = cask_tokens_from(arguments) - raise Hbc::CaskUnspecifiedError if cask_tokens.empty? - retval = dump_casks(*cask_tokens) - # retval is ternary: true/false/nil +module Hbc + class CLI + class InternalDump < InternalUseBase + def self.run(*arguments) + cask_tokens = cask_tokens_from(arguments) + raise CaskUnspecifiedError if cask_tokens.empty? + retval = dump_casks(*cask_tokens) + # retval is ternary: true/false/nil - raise Hbc::CaskError, "nothing to dump" if retval.nil? - raise Hbc::CaskError, "dump incomplete" unless retval - end + raise CaskError, "nothing to dump" if retval.nil? + raise CaskError, "dump incomplete" unless retval + end - def self.dump_casks(*cask_tokens) - Hbc.debug = true # Yuck. At the moment this is the only way to make dumps visible - count = 0 - cask_tokens.each do |cask_token| - begin - cask = Hbc.load(cask_token) - count += 1 - cask.dumpcask - rescue StandardError => e - opoo "#{cask_token} was not found or would not load: #{e}" + def self.dump_casks(*cask_tokens) + Hbc.debug = true # Yuck. At the moment this is the only way to make dumps visible + count = 0 + cask_tokens.each do |cask_token| + begin + cask = Hbc.load(cask_token) + count += 1 + cask.dumpcask + rescue StandardError => e + opoo "#{cask_token} was not found or would not load: #{e}" + end + end + count.zero? ? nil : count == cask_tokens.length end - end - count == 0 ? nil : count == cask_tokens.length - end - def self.help - "Dump the given Cask in YAML format" + def self.help + "Dump the given Cask in YAML format" + end + 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 81d7ee673..6c646cfd7 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/internal_help.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_help.rb @@ -1,19 +1,23 @@ -class Hbc::CLI::InternalHelp < Hbc::CLI::InternalUseBase - def self.run(*_ignored) - max_command_len = Hbc::CLI.commands.map(&:length).max - puts "Unstable Internal-use Commands:\n\n" - Hbc::CLI.command_classes.each do |klass| - next if klass.visible - puts " #{klass.command_name.ljust(max_command_len)} #{help_for(klass)}" - end - puts "\n" - end +module Hbc + class CLI + class InternalHelp < InternalUseBase + def self.run(*_ignored) + max_command_len = CLI.commands.map(&:length).max + puts "Unstable Internal-use Commands:\n\n" + CLI.command_classes.each do |klass| + next if klass.visible + puts " #{klass.command_name.ljust(max_command_len)} #{help_for(klass)}" + end + puts "\n" + end - def self.help_for(klass) - klass.respond_to?(:help) ? klass.help : nil - end + def self.help_for(klass) + klass.respond_to?(:help) ? klass.help : nil + end - def self.help - "Print help strings for unstable internal-use commands" + def self.help + "Print help strings for unstable internal-use commands" + end + 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 651a9ae37..0265e34b7 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb @@ -1,127 +1,131 @@ -class Hbc::CLI::InternalStanza < Hbc::CLI::InternalUseBase - # Syntax - # - # brew cask _stanza <stanza_name> [ --table | --yaml | --inspect | --quiet ] [ <cask_token> ... ] - # - # If no tokens are given, then data for all Casks is returned. - # - # The pseudo-stanza "artifacts" is available. - # - # On failure, a blank line is returned on the standard output. - # - # Examples - # - # brew cask _stanza appcast --table - # brew cask _stanza app --table alfred google-chrome adium voicemac logisim vagrant - # brew cask _stanza url --table alfred google-chrome adium voicemac logisim vagrant - # brew cask _stanza version --table alfred google-chrome adium voicemac logisim vagrant - # brew cask _stanza artifacts --table --inspect alfred google-chrome adium voicemac logisim vagrant - # brew cask _stanza artifacts --table --yaml alfred google-chrome adium voicemac logisim vagrant - # +module Hbc + class CLI + class InternalStanza < InternalUseBase + # Syntax + # + # brew cask _stanza <stanza_name> [ --table | --yaml | --inspect | --quiet ] [ <cask_token> ... ] + # + # If no tokens are given, then data for all Casks is returned. + # + # The pseudo-stanza "artifacts" is available. + # + # On failure, a blank line is returned on the standard output. + # + # Examples + # + # brew cask _stanza appcast --table + # brew cask _stanza app --table alfred google-chrome adium voicemac logisim vagrant + # brew cask _stanza url --table alfred google-chrome adium voicemac logisim vagrant + # brew cask _stanza version --table alfred google-chrome adium voicemac logisim vagrant + # brew cask _stanza artifacts --table --inspect alfred google-chrome adium voicemac logisim vagrant + # brew cask _stanza artifacts --table --yaml alfred google-chrome adium voicemac logisim vagrant + # - # TODO: this should be retrievable from Hbc::DSL - ARTIFACTS = Set.new [ - :app, - :suite, - :artifact, - :prefpane, - :qlplugin, - :font, - :service, - :colorpicker, - :binary, - :input_method, - :internet_plugin, - :audio_unit_plugin, - :vst_plugin, - :vst3_plugin, - :screen_saver, - :pkg, - :installer, - :stage_only, - :nested_container, - :uninstall, - :postflight, - :uninstall_postflight, - :preflight, - :uninstall_postflight, - ] + # TODO: this should be retrievable from Hbc::DSL + ARTIFACTS = Set.new [ + :app, + :suite, + :artifact, + :prefpane, + :qlplugin, + :font, + :service, + :colorpicker, + :binary, + :input_method, + :internet_plugin, + :audio_unit_plugin, + :vst_plugin, + :vst3_plugin, + :screen_saver, + :pkg, + :installer, + :stage_only, + :nested_container, + :uninstall, + :postflight, + :uninstall_postflight, + :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 == "-" } - stanza = cask_tokens.shift.to_sym - cask_tokens = Hbc.all_tokens if cask_tokens.empty? + 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 == "-" } + stanza = cask_tokens.shift.to_sym + cask_tokens = Hbc.all_tokens if cask_tokens.empty? - retval = print_stanzas(stanza, format, table, quiet, *cask_tokens) + retval = print_stanzas(stanza, format, table, quiet, *cask_tokens) - # retval is ternary: true/false/nil - if retval.nil? - exit 1 if quiet - raise Hbc::CaskError, "nothing to print" - elsif !retval - exit 1 if quiet - raise Hbc::CaskError, "print incomplete" - end - end + # retval is ternary: true/false/nil + if retval.nil? + exit 1 if quiet + raise CaskError, "nothing to print" + elsif !retval + exit 1 if quiet + raise CaskError, "print incomplete" + end + end - def self.print_stanzas(stanza, format = nil, table = nil, quiet = nil, *cask_tokens) - count = 0 - if ARTIFACTS.include?(stanza) - artifact_name = stanza - stanza = :artifacts - end + def self.print_stanzas(stanza, format = nil, table = nil, quiet = nil, *cask_tokens) + count = 0 + if ARTIFACTS.include?(stanza) + artifact_name = stanza + stanza = :artifacts + end - cask_tokens.each do |cask_token| - print "#{cask_token}\t" if table + cask_tokens.each do |cask_token| + print "#{cask_token}\t" if table - begin - cask = Hbc.load(cask_token) - rescue StandardError - opoo "Cask '#{cask_token}' was not found" unless quiet - puts "" - next - end + begin + cask = Hbc.load(cask_token) + rescue StandardError + opoo "Cask '#{cask_token}' was not found" unless quiet + puts "" + next + end - unless cask.respond_to?(stanza) - opoo "no such stanza '#{stanza}' on Cask '#{cask_token}'" unless quiet - puts "" - next - end + unless cask.respond_to?(stanza) + opoo "no such stanza '#{stanza}' on Cask '#{cask_token}'" unless quiet + puts "" + next + end - begin - value = cask.send(stanza) - rescue StandardError - opoo "failure calling '#{stanza}' on Cask '#{cask_token}'" unless quiet - puts "" - next - end + begin + value = cask.send(stanza) + rescue StandardError + opoo "failure calling '#{stanza}' on Cask '#{cask_token}'" unless quiet + puts "" + next + end - if artifact_name && !value.key?(artifact_name) - opoo "no such stanza '#{artifact_name}' on Cask '#{cask_token}'" unless quiet - puts "" - next - end + if artifact_name && !value.key?(artifact_name) + opoo "no such stanza '#{artifact_name}' on Cask '#{cask_token}'" unless quiet + puts "" + next + end + + value = value.fetch(artifact_name).to_a.flatten if artifact_name - value = value.fetch(artifact_name).to_a.flatten if artifact_name + if format + puts value.send(format) + elsif artifact_name || value.is_a?(Symbol) + puts value.inspect + else + puts value.to_s + end - if format - puts value.send(format) - elsif artifact_name || value.is_a?(Symbol) - puts value.inspect - else - puts value.to_s + count += 1 + end + count.zero? ? nil : count == cask_tokens.length end - count += 1 + def self.help + "Extract and render a specific stanza for the given Casks" + end end - count == 0 ? nil : count == cask_tokens.length - end - - def self.help - "Extract and render a specific stanza for the given Casks" end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_use_base.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_use_base.rb index 6a4359ea1..96b6eeaa8 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/internal_use_base.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_use_base.rb @@ -1,9 +1,13 @@ -class Hbc::CLI::InternalUseBase < Hbc::CLI::Base - def self.command_name - super.sub(%r{^internal_}i, "_") - end +module Hbc + class CLI + class InternalUseBase < Base + def self.command_name + super.sub(%r{^internal_}i, "_") + end - def self.visible - false + def self.visible + false + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/list.rb b/Library/Homebrew/cask/lib/hbc/cli/list.rb index 88907a797..3a993f8e6 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/list.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/list.rb @@ -1,86 +1,90 @@ -class Hbc::CLI::List < Hbc::CLI::Base - def self.run(*arguments) - @options = {} - @options[:one] = true if arguments.delete("-1") - @options[:versions] = true if arguments.delete("--versions") +module Hbc + class CLI + class List < Base + def self.run(*arguments) + @options = {} + @options[:one] = true if arguments.delete("-1") + @options[:versions] = true if arguments.delete("--versions") - if arguments.delete("-l") - @options[:one] = true - opoo "Option -l is obsolete! Implying option -1." - end + if arguments.delete("-l") + @options[:one] = true + opoo "Option -l is obsolete! Implying option -1." + end - retval = arguments.any? ? list(*arguments) : list_installed - # retval is ternary: true/false/nil - if retval.nil? && !arguments.any? - opoo "nothing to list" # special case: avoid exit code - elsif retval.nil? - raise Hbc::CaskError, "nothing to list" - elsif !retval - raise Hbc::CaskError, "listing incomplete" - end - end + retval = arguments.any? ? list(*arguments) : list_installed + # retval is ternary: true/false/nil + if retval.nil? && !arguments.any? + opoo "nothing to list" # special case: avoid exit code + elsif retval.nil? + raise CaskError, "nothing to list" + elsif !retval + raise CaskError, "listing incomplete" + end + end - def self.list(*cask_tokens) - count = 0 + def self.list(*cask_tokens) + count = 0 - cask_tokens.each do |cask_token| - odebug "Listing files for Cask #{cask_token}" - begin - cask = Hbc.load(cask_token) + cask_tokens.each do |cask_token| + odebug "Listing files for Cask #{cask_token}" + begin + cask = Hbc.load(cask_token) - if cask.installed? - if @options[:one] - puts cask.token - elsif @options[:versions] - puts format_versioned(cask) - else - installed_caskfile = cask.metadata_master_container_path.join(*cask.timestamped_versions.last, "Casks", "#{cask_token}.rb") - cask = Hbc.load(installed_caskfile) - list_artifacts(cask) - end + if cask.installed? + if @options[:one] + puts cask.token + elsif @options[:versions] + puts format_versioned(cask) + else + installed_caskfile = cask.metadata_master_container_path.join(*cask.timestamped_versions.last, "Casks", "#{cask_token}.rb") + cask = Hbc.load(installed_caskfile) + list_artifacts(cask) + end - count += 1 - else - opoo "#{cask} is not installed" + count += 1 + else + opoo "#{cask} is not installed" + end + rescue CaskUnavailableError => e + onoe e + end end - rescue Hbc::CaskUnavailableError => e - onoe e - end - end - count == 0 ? nil : count == cask_tokens.length - end + count.zero? ? nil : count == cask_tokens.length + end - def self.list_artifacts(cask) - Hbc::Artifact.for_cask(cask).each do |artifact| - summary = artifact.new(cask).summary - ohai summary[:english_description], summary[:contents] unless summary.empty? - end - end + def self.list_artifacts(cask) + Artifact.for_cask(cask).each do |artifact| + summary = artifact.new(cask).summary + ohai summary[:english_description], summary[:contents] unless summary.empty? + end + end - def self.list_installed - installed_casks = Hbc.installed + def self.list_installed + installed_casks = Hbc.installed - if @options[:one] - puts installed_casks.map(&:to_s) - elsif @options[:versions] - puts installed_casks.map(&method(:format_versioned)) - else - puts_columns installed_casks.map(&:to_s) - end + if @options[:one] + puts installed_casks.map(&:to_s) + elsif @options[:versions] + puts installed_casks.map(&method(:format_versioned)) + else + puts_columns installed_casks.map(&:to_s) + end - installed_casks.empty? ? nil : true - end + installed_casks.empty? ? nil : true + end - def self.format_versioned(cask) - cask.to_s.concat(cask.versions.map(&:to_s).join(" ").prepend(" ")) - end + def self.format_versioned(cask) + cask.to_s.concat(cask.versions.map(&:to_s).join(" ").prepend(" ")) + end - def self.help - "with no args, lists installed Casks; given installed Casks, lists staged files" - end + def self.help + "with no args, lists installed Casks; given installed Casks, lists staged files" + end - def self.needs_init? - true + def self.needs_init? + true + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/search.rb b/Library/Homebrew/cask/lib/hbc/cli/search.rb index 5c57ba43d..b671ea862 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/search.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/search.rb @@ -1,55 +1,59 @@ -class Hbc::CLI::Search < Hbc::CLI::Base - def self.run(*arguments) - render_results(*search(*arguments)) - end +module Hbc + class CLI + class Search < Base + def self.run(*arguments) + render_results(*search(*arguments)) + end - def self.extract_regexp(string) - if string =~ %r{^/(.*)/$} - Regexp.last_match[1] - else - false - end - end + def self.extract_regexp(string) + if string =~ %r{^/(.*)/$} + Regexp.last_match[1] + else + false + end + end - def self.search(*arguments) - exact_match = nil - partial_matches = [] - search_term = arguments.join(" ") - search_regexp = extract_regexp arguments.first - all_tokens = Hbc::CLI.nice_listing(Hbc.all_tokens) - if search_regexp - search_term = arguments.first - partial_matches = all_tokens.grep(%r{#{search_regexp}}i) - else - simplified_tokens = all_tokens.map { |t| t.sub(%r{^.*\/}, "").gsub(%r{[^a-z0-9]+}i, "") } - simplified_search_term = search_term.sub(%r{\.rb$}i, "").gsub(%r{[^a-z0-9]+}i, "") - exact_match = simplified_tokens.grep(%r{^#{simplified_search_term}$}i) { |t| all_tokens[simplified_tokens.index(t)] }.first - partial_matches = simplified_tokens.grep(%r{#{simplified_search_term}}i) { |t| all_tokens[simplified_tokens.index(t)] } - partial_matches.delete(exact_match) - end - [exact_match, partial_matches, search_term] - end + def self.search(*arguments) + exact_match = nil + partial_matches = [] + search_term = arguments.join(" ") + search_regexp = extract_regexp arguments.first + all_tokens = CLI.nice_listing(Hbc.all_tokens) + if search_regexp + search_term = arguments.first + partial_matches = all_tokens.grep(%r{#{search_regexp}}i) + else + simplified_tokens = all_tokens.map { |t| t.sub(%r{^.*\/}, "").gsub(%r{[^a-z0-9]+}i, "") } + simplified_search_term = search_term.sub(%r{\.rb$}i, "").gsub(%r{[^a-z0-9]+}i, "") + exact_match = simplified_tokens.grep(%r{^#{simplified_search_term}$}i) { |t| all_tokens[simplified_tokens.index(t)] }.first + partial_matches = simplified_tokens.grep(%r{#{simplified_search_term}}i) { |t| all_tokens[simplified_tokens.index(t)] } + partial_matches.delete(exact_match) + end + [exact_match, partial_matches, search_term] + end - def self.render_results(exact_match, partial_matches, search_term) - if !exact_match && partial_matches.empty? - puts "No Cask found for \"#{search_term}\"." - return - end - if exact_match - ohai "Exact match" - puts exact_match - end - unless partial_matches.empty? - if extract_regexp search_term - ohai "Regexp matches" - else - ohai "Partial matches" + def self.render_results(exact_match, partial_matches, search_term) + if !exact_match && partial_matches.empty? + puts "No Cask found for \"#{search_term}\"." + return + end + if exact_match + ohai "Exact match" + puts exact_match + end + unless partial_matches.empty? + if extract_regexp search_term + ohai "Regexp matches" + else + ohai "Partial matches" + end + puts_columns partial_matches + end end - puts_columns partial_matches - end - end - def self.help - "searches all known Casks" + def self.help + "searches all known Casks" + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/style.rb b/Library/Homebrew/cask/lib/hbc/cli/style.rb index 8793d2afd..638e25685 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/style.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/style.rb @@ -1,69 +1,73 @@ require "English" -class Hbc::CLI::Style < Hbc::CLI::Base - def self.help - "checks Cask style using RuboCop" - end +module Hbc + class CLI + class Style < Base + def self.help + "checks Cask style using RuboCop" + end - def self.run(*args) - retval = new(args).run - raise Hbc::CaskError, "style check failed" unless retval - end + def self.run(*args) + retval = new(args).run + raise CaskError, "style check failed" unless retval + end - attr_reader :args - def initialize(args) - @args = args - end + attr_reader :args + def initialize(args) + @args = args + end - def run - install_rubocop - system "rubocop", *rubocop_args, "--", *cask_paths - $CHILD_STATUS.success? - end + def run + install_rubocop + system "rubocop", *rubocop_args, "--", *cask_paths + $CHILD_STATUS.success? + end - RUBOCOP_CASK_VERSION = "~> 0.8.3".freeze + RUBOCOP_CASK_VERSION = "~> 0.8.3".freeze - def install_rubocop - Hbc::Utils.capture_stderr do - begin - Homebrew.install_gem_setup_path! "rubocop-cask", RUBOCOP_CASK_VERSION, "rubocop" - rescue SystemExit - raise Hbc::CaskError, $stderr.string.chomp.sub("#{Tty.red}Error#{Tty.reset}: ", "") + def install_rubocop + Utils.capture_stderr do + begin + Homebrew.install_gem_setup_path! "rubocop-cask", RUBOCOP_CASK_VERSION, "rubocop" + rescue SystemExit + raise CaskError, $stderr.string.chomp.sub("#{Tty.red}Error#{Tty.reset}: ", "") + end + end end - end - end - def cask_paths - @cask_paths ||= if cask_tokens.empty? - Hbc.all_tapped_cask_dirs - elsif cask_tokens.any? { |file| File.exist?(file) } - cask_tokens - else - cask_tokens.map { |token| Hbc.path(token) } - end - end + def cask_paths + @cask_paths ||= if cask_tokens.empty? + Hbc.all_tapped_cask_dirs + elsif cask_tokens.any? { |file| File.exist?(file) } + cask_tokens + else + cask_tokens.map { |token| Hbc.path(token) } + end + end - def cask_tokens - @cask_tokens ||= self.class.cask_tokens_from(args) - end + def cask_tokens + @cask_tokens ||= self.class.cask_tokens_from(args) + end - def rubocop_args - fix? ? autocorrect_args : default_args - end + def rubocop_args + fix? ? autocorrect_args : default_args + end - def default_args - ["--format", "simple", "--force-exclusion", "--config", rubocop_config] - end + def default_args + ["--format", "simple", "--force-exclusion", "--config", rubocop_config] + end - def autocorrect_args - default_args + ["--auto-correct"] - end + def autocorrect_args + default_args + ["--auto-correct"] + end - def rubocop_config - Hbc.default_tap.cask_dir.join(".rubocop.yml") - end + def rubocop_config + Hbc.default_tap.cask_dir.join(".rubocop.yml") + end - def fix? - args.any? { |arg| arg =~ %r{--(fix|(auto-?)?correct)} } + def fix? + args.any? { |arg| arg =~ %r{--(fix|(auto-?)?correct)} } + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/uninstall.rb b/Library/Homebrew/cask/lib/hbc/cli/uninstall.rb index ae15414b7..2bebb97b0 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/uninstall.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/uninstall.rb @@ -1,40 +1,44 @@ -class Hbc::CLI::Uninstall < Hbc::CLI::Base - def self.run(*args) - cask_tokens = cask_tokens_from(args) - raise Hbc::CaskUnspecifiedError if cask_tokens.empty? - force = args.include? "--force" +module Hbc + class CLI + class Uninstall < Base + def self.run(*args) + cask_tokens = cask_tokens_from(args) + raise CaskUnspecifiedError if cask_tokens.empty? + force = args.include? "--force" - cask_tokens.each do |cask_token| - odebug "Uninstalling Cask #{cask_token}" - cask = Hbc.load(cask_token) + cask_tokens.each do |cask_token| + odebug "Uninstalling Cask #{cask_token}" + cask = Hbc.load(cask_token) - raise Hbc::CaskNotInstalledError, cask unless cask.installed? || force + raise CaskNotInstalledError, cask unless cask.installed? || force - latest_installed_version = cask.timestamped_versions.last + latest_installed_version = cask.timestamped_versions.last - unless latest_installed_version.nil? - latest_installed_cask_file = cask.metadata_master_container_path - .join(latest_installed_version.join(File::Separator), - "Casks", "#{cask_token}.rb") + unless latest_installed_version.nil? + latest_installed_cask_file = cask.metadata_master_container_path + .join(latest_installed_version.join(File::Separator), + "Casks", "#{cask_token}.rb") - # use the same cask file that was used for installation, if possible - cask = Hbc.load(latest_installed_cask_file) if latest_installed_cask_file.exist? - end + # use the same cask file that was used for installation, if possible + cask = Hbc.load(latest_installed_cask_file) if latest_installed_cask_file.exist? + end - Hbc::Installer.new(cask, force: force).uninstall + Installer.new(cask, force: force).uninstall - next if (versions = cask.versions).empty? + next if (versions = cask.versions).empty? - single = versions.count == 1 + single = versions.count == 1 - puts <<-EOS.undent - #{cask_token} #{versions.join(', ')} #{single ? 'is' : 'are'} still installed. - Remove #{single ? 'it' : 'them all'} with `brew cask uninstall --force #{cask_token}`. - EOS - end - end + puts <<-EOS.undent + #{cask_token} #{versions.join(", ")} #{single ? "is" : "are"} still installed. + Remove #{single ? "it" : "them all"} with `brew cask uninstall --force #{cask_token}`. + EOS + end + end - def self.help - "uninstalls the given Cask" + def self.help + "uninstalls the given Cask" + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/update.rb b/Library/Homebrew/cask/lib/hbc/cli/update.rb index ceb947544..1d6ed2af5 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/update.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/update.rb @@ -1,16 +1,20 @@ -class Hbc::CLI::Update < Hbc::CLI::Base - def self.run(*_ignored) - result = Hbc::SystemCommand.run(Hbc.homebrew_executable, - args: %w[update]) - # TODO: separating stderr/stdout is undesirable here. - # Hbc::SystemCommand should have an option for plain - # unbuffered output. - print result.stdout - $stderr.print result.stderr - exit result.exit_status - end +module Hbc + class CLI + class Update < Base + def self.run(*_ignored) + result = SystemCommand.run(Hbc.homebrew_executable, + args: %w[update]) + # TODO: separating stderr/stdout is undesirable here. + # Hbc::SystemCommand should have an option for plain + # unbuffered output. + print result.stdout + $stderr.print result.stderr + exit result.exit_status + end - def self.help - "a synonym for 'brew update'" + def self.help + "a synonym for 'brew update'" + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/cli/zap.rb b/Library/Homebrew/cask/lib/hbc/cli/zap.rb index 081378330..2f9723858 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/zap.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/zap.rb @@ -1,15 +1,19 @@ -class Hbc::CLI::Zap < Hbc::CLI::Base - def self.run(*args) - cask_tokens = cask_tokens_from(args) - raise Hbc::CaskUnspecifiedError if cask_tokens.empty? - cask_tokens.each do |cask_token| - odebug "Zapping Cask #{cask_token}" - cask = Hbc.load(cask_token) - Hbc::Installer.new(cask).zap - end - end +module Hbc + class CLI + class Zap < Base + def self.run(*args) + cask_tokens = cask_tokens_from(args) + raise CaskUnspecifiedError if cask_tokens.empty? + cask_tokens.each do |cask_token| + odebug "Zapping Cask #{cask_token}" + cask = Hbc.load(cask_token) + Installer.new(cask).zap + end + end - def self.help - "zaps all files associated with the given Cask" + def self.help + "zaps all files associated with the given Cask" + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/container.rb b/Library/Homebrew/cask/lib/hbc/container.rb index e2b21a3ef..01dd10337 100644 --- a/Library/Homebrew/cask/lib/hbc/container.rb +++ b/Library/Homebrew/cask/lib/hbc/container.rb @@ -1,5 +1,3 @@ -class Hbc::Container; end - require "hbc/container/base" require "hbc/container/air" require "hbc/container/bzip2" @@ -22,47 +20,49 @@ require "hbc/container/xip" require "hbc/container/xz" require "hbc/container/zip" -class Hbc::Container - def self.autodetect_containers - [ - Hbc::Container::Pkg, - Hbc::Container::Ttf, - Hbc::Container::Otf, - Hbc::Container::Air, - Hbc::Container::Cab, - Hbc::Container::Dmg, - Hbc::Container::SevenZip, - Hbc::Container::Sit, - Hbc::Container::Rar, - Hbc::Container::Zip, - Hbc::Container::Xip, # needs to be before xar as this is a cpio inside a gzip inside a xar - Hbc::Container::Xar, # need to be before tar as tar can also list xar - Hbc::Container::Tar, # or compressed tar (bzip2/gzip/lzma/xz) - Hbc::Container::Bzip2, # pure bzip2 - Hbc::Container::Gzip, # pure gzip - Hbc::Container::Lzma, # pure lzma - Hbc::Container::Xz, # pure xz - ] - # for explicit use only (never autodetected): - # Hbc::Container::Naked - # Hbc::Container::GenericUnar - end +module Hbc + class Container + def self.autodetect_containers + [ + Pkg, + Ttf, + Otf, + Air, + Cab, + Dmg, + SevenZip, + 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 + Gzip, # pure gzip + Lzma, # pure lzma + Xz, # pure xz + ] + # for explicit use only (never autodetected): + # Hbc::Container::Naked + # Hbc::Container::GenericUnar + end - def self.for_path(path, command) - odebug "Determining which containers to use based on filetype" - criteria = Hbc::Container::Criteria.new(path, command) - autodetect_containers.find do |c| - odebug "Checking container class #{c}" - c.me?(criteria) + def self.for_path(path, command) + odebug "Determining which containers to use based on filetype" + criteria = Criteria.new(path, command) + autodetect_containers.find do |c| + odebug "Checking container class #{c}" + c.me?(criteria) + end end - end - def self.from_type(type) - odebug "Determining which containers to use based on 'container :type'" - begin - Hbc::Container.const_get(type.to_s.split("_").map(&:capitalize).join) - rescue NameError - false + def self.from_type(type) + odebug "Determining which containers to use based on 'container :type'" + begin + self.const_get(type.to_s.split("_").map(&:capitalize).join) + rescue NameError + false + end end end end diff --git a/Library/Homebrew/cask/lib/hbc/container/air.rb b/Library/Homebrew/cask/lib/hbc/container/air.rb index fc618db83..4b083e538 100644 --- a/Library/Homebrew/cask/lib/hbc/container/air.rb +++ b/Library/Homebrew/cask/lib/hbc/container/air.rb @@ -1,33 +1,37 @@ require "hbc/container/base" -class Hbc::Container::Air < Hbc::Container::Base - INSTALLER_PATHNAME = - Pathname("/Applications/Utilities/Adobe AIR Application Installer.app" \ - "/Contents/MacOS/Adobe AIR Application Installer") - - def self.me?(criteria) - %w[.air].include?(criteria.path.extname) - end - - def self.installer_cmd - return @installer_cmd ||= INSTALLER_PATHNAME if installer_exist? - raise Hbc::CaskError, <<-EOS.undent - Adobe AIR runtime not present, try installing it via - - brew cask install adobe-air - - EOS - end - - def self.installer_exist? - INSTALLER_PATHNAME.exist? - end - - def extract - install = @command.run(self.class.installer_cmd, - args: ["-silent", "-location", @cask.staged_path, Pathname.new(@path).realpath]) - - return unless install.exit_status == 9 - raise Hbc::CaskError, "Adobe AIR application #{@cask} already exists on the system, and cannot be reinstalled." +module Hbc + class Container + class Air < Base + INSTALLER_PATHNAME = + Pathname("/Applications/Utilities/Adobe AIR Application Installer.app" \ + "/Contents/MacOS/Adobe AIR Application Installer") + + def self.me?(criteria) + %w[.air].include?(criteria.path.extname) + end + + def self.installer_cmd + return @installer_cmd ||= INSTALLER_PATHNAME if installer_exist? + raise CaskError, <<-EOS.undent + Adobe AIR runtime not present, try installing it via + + brew cask install adobe-air + + EOS + end + + def self.installer_exist? + INSTALLER_PATHNAME.exist? + end + + def extract + install = @command.run(self.class.installer_cmd, + args: ["-silent", "-location", @cask.staged_path, Pathname.new(@path).realpath]) + + return unless install.exit_status == 9 + raise CaskError, "Adobe AIR application #{@cask} already exists on the system, and cannot be reinstalled." + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/container/base.rb b/Library/Homebrew/cask/lib/hbc/container/base.rb index 42331df31..1f1c9ad9b 100644 --- a/Library/Homebrew/cask/lib/hbc/container/base.rb +++ b/Library/Homebrew/cask/lib/hbc/container/base.rb @@ -1,37 +1,41 @@ -class Hbc::Container::Base - def initialize(cask, path, command, nested: false) - @cask = cask - @path = path - @command = command - @nested = nested - end +module Hbc + class Container + class Base + def initialize(cask, path, command, nested: false) + @cask = cask + @path = path + @command = command + @nested = nested + end - def extract_nested_inside(dir) - children = Pathname.new(dir).children + def extract_nested_inside(dir) + children = Pathname.new(dir).children - nested_container = children[0] + nested_container = children[0] - unless children.count == 1 && - !nested_container.directory? && - @cask.artifacts[:nested_container].empty? && - extract_nested_container(nested_container) + unless children.count == 1 && + !nested_container.directory? && + @cask.artifacts[:nested_container].empty? && + extract_nested_container(nested_container) - children.each do |src| - dest = @cask.staged_path.join(src.basename) - FileUtils.rm_r(dest) if dest.exist? - FileUtils.mv(src, dest) + children.each do |src| + dest = @cask.staged_path.join(src.basename) + FileUtils.rm_r(dest) if dest.exist? + FileUtils.mv(src, dest) + end + end end - end - end - def extract_nested_container(source) - container = Hbc::Container.for_path(source, @command) + def extract_nested_container(source) + container = Container.for_path(source, @command) - return false unless container + return false unless container - ohai "Extracting nested container #{source.basename}" - container.new(@cask, source, @command, nested: true).extract + ohai "Extracting nested container #{source.basename}" + container.new(@cask, source, @command, nested: true).extract - true + true + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/container/bzip2.rb b/Library/Homebrew/cask/lib/hbc/container/bzip2.rb index 617c68b32..81808071f 100644 --- a/Library/Homebrew/cask/lib/hbc/container/bzip2.rb +++ b/Library/Homebrew/cask/lib/hbc/container/bzip2.rb @@ -2,17 +2,21 @@ require "tmpdir" require "hbc/container/base" -class Hbc::Container::Bzip2 < Hbc::Container::Base - def self.me?(criteria) - criteria.magic_number(%r{^BZh}n) - end +module Hbc + class Container + class Bzip2 < Base + def self.me?(criteria) + criteria.magic_number(%r{^BZh}n) + end - def extract - Dir.mktmpdir do |unpack_dir| - @command.run!("/usr/bin/ditto", args: ["--", @path, unpack_dir]) - @command.run!("/usr/bin/bunzip2", args: ["--quiet", "--", Pathname.new(unpack_dir).join(@path.basename)]) + def extract + Dir.mktmpdir do |unpack_dir| + @command.run!("/usr/bin/ditto", args: ["--", @path, unpack_dir]) + @command.run!("/usr/bin/bunzip2", args: ["--quiet", "--", Pathname.new(unpack_dir).join(@path.basename)]) - extract_nested_inside(unpack_dir) + extract_nested_inside(unpack_dir) + end + end end end end diff --git a/Library/Homebrew/cask/lib/hbc/container/cab.rb b/Library/Homebrew/cask/lib/hbc/container/cab.rb index 28000a5a3..d32b1b205 100644 --- a/Library/Homebrew/cask/lib/hbc/container/cab.rb +++ b/Library/Homebrew/cask/lib/hbc/container/cab.rb @@ -2,25 +2,29 @@ require "tmpdir" require "hbc/container/base" -class Hbc::Container::Cab < Hbc::Container::Base - def self.me?(criteria) - cabextract = Hbc.homebrew_prefix.join("bin", "cabextract") +module Hbc + class Container + class Cab < Base + def self.me?(criteria) + cabextract = Hbc.homebrew_prefix.join("bin", "cabextract") - criteria.magic_number(%r{^MSCF}n) && - cabextract.exist? && - criteria.command.run(cabextract, args: ["-t", "--", criteria.path.to_s]).stderr.empty? - end + criteria.magic_number(%r{^MSCF}n) && + cabextract.exist? && + criteria.command.run(cabextract, args: ["-t", "--", criteria.path.to_s]).stderr.empty? + end - def extract - cabextract = Hbc.homebrew_prefix.join("bin", "cabextract") + def extract + cabextract = Hbc.homebrew_prefix.join("bin", "cabextract") - unless cabextract.exist? - raise Hbc::CaskError, "Expected to find cabextract executable. Cask '#{@cask}' must add: depends_on formula: 'cabextract'" - end + unless cabextract.exist? + raise CaskError, "Expected to find cabextract executable. Cask '#{@cask}' must add: depends_on formula: 'cabextract'" + end - Dir.mktmpdir do |unpack_dir| - @command.run!(cabextract, args: ["-d", unpack_dir, "--", @path]) - @command.run!("/usr/bin/ditto", args: ["--", unpack_dir, @cask.staged_path]) + Dir.mktmpdir do |unpack_dir| + @command.run!(cabextract, args: ["-d", unpack_dir, "--", @path]) + @command.run!("/usr/bin/ditto", args: ["--", unpack_dir, @cask.staged_path]) + end + end end end end diff --git a/Library/Homebrew/cask/lib/hbc/container/criteria.rb b/Library/Homebrew/cask/lib/hbc/container/criteria.rb index 2ebb9d6fa..207c5f3cd 100644 --- a/Library/Homebrew/cask/lib/hbc/container/criteria.rb +++ b/Library/Homebrew/cask/lib/hbc/container/criteria.rb @@ -1,18 +1,22 @@ -class Hbc::Container::Criteria - attr_reader :path, :command +module Hbc + class Container + class Criteria + attr_reader :path, :command - def initialize(path, command) - @path = path - @command = command - end + def initialize(path, command) + @path = path + @command = command + end - def extension(regex) - path.extname.sub(%r{^\.}, "") =~ Regexp.new(regex.source, regex.options | Regexp::IGNORECASE) - end + def extension(regex) + path.extname.sub(%r{^\.}, "") =~ Regexp.new(regex.source, regex.options | Regexp::IGNORECASE) + end - def magic_number(regex) - # 262: length of the longest regex (currently: Hbc::Container::Tar) - @magic_number ||= File.open(@path, "rb") { |f| f.read(262) } - @magic_number =~ regex + def magic_number(regex) + # 262: length of the longest regex (currently: Hbc::Container::Tar) + @magic_number ||= File.open(@path, "rb") { |f| f.read(262) } + @magic_number =~ regex + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/container/dmg.rb b/Library/Homebrew/cask/lib/hbc/container/dmg.rb index 7e4b9340d..d53c077cb 100644 --- a/Library/Homebrew/cask/lib/hbc/container/dmg.rb +++ b/Library/Homebrew/cask/lib/hbc/container/dmg.rb @@ -3,123 +3,127 @@ require "tempfile" require "hbc/container/base" -class Hbc::Container::Dmg < Hbc::Container::Base - def self.me?(criteria) - !criteria.command.run("/usr/bin/hdiutil", - # realpath is a failsafe against unusual filenames - args: ["imageinfo", Pathname.new(criteria.path).realpath], - print_stderr: false).stdout.empty? - end +module Hbc + class Container + class Dmg < Base + def self.me?(criteria) + !criteria.command.run("/usr/bin/hdiutil", + # realpath is a failsafe against unusual filenames + args: ["imageinfo", Pathname.new(criteria.path).realpath], + print_stderr: false).stdout.empty? + end - attr_reader :mounts - def initialize(*args) - super(*args) - @mounts = [] - end + attr_reader :mounts + def initialize(*args) + super(*args) + @mounts = [] + end - def extract - mount! - assert_mounts_found - extract_mounts - ensure - eject! - end + def extract + mount! + assert_mounts_found + extract_mounts + ensure + eject! + end - def mount! - plist = @command.run!("/usr/bin/hdiutil", - # realpath is a failsafe against unusual filenames - args: %w[mount -plist -nobrowse -readonly -noidme -mountrandom /tmp] + [Pathname.new(@path).realpath], - input: %w[y]) - .plist - @mounts = mounts_from_plist(plist) - end + def mount! + plist = @command.run!("/usr/bin/hdiutil", + # realpath is a failsafe against unusual filenames + args: %w[mount -plist -nobrowse -readonly -noidme -mountrandom /tmp] + [Pathname.new(@path).realpath], + input: %w[y]) + .plist + @mounts = mounts_from_plist(plist) + end - def eject! - @mounts.each do |mount| - # realpath is a failsafe against unusual filenames - mountpath = Pathname.new(mount).realpath - next unless mountpath.exist? - - begin - tries ||= 2 - @command.run("/usr/sbin/diskutil", - args: ["eject", mountpath], - print_stderr: false) - - raise Hbc::CaskError, "Failed to eject #{mountpath}" if mountpath.exist? - rescue Hbc::CaskError => e - raise e if (tries -= 1).zero? - sleep 1 - retry + def eject! + @mounts.each do |mount| + # realpath is a failsafe against unusual filenames + mountpath = Pathname.new(mount).realpath + next unless mountpath.exist? + + begin + tries ||= 2 + @command.run("/usr/sbin/diskutil", + args: ["eject", mountpath], + print_stderr: false) + + raise CaskError, "Failed to eject #{mountpath}" if mountpath.exist? + rescue CaskError => e + raise e if (tries -= 1).zero? + sleep 1 + retry + end + end end - end - end - private + private - def extract_mounts - @mounts.each(&method(:extract_mount)) - end + def extract_mounts + @mounts.each(&method(:extract_mount)) + end - def extract_mount(mount) - Tempfile.open(["", ".bom"]) do |bomfile| - bomfile.close + def extract_mount(mount) + Tempfile.open(["", ".bom"]) do |bomfile| + bomfile.close - Tempfile.open(["", ".list"]) do |filelist| - filelist.write(bom_filelist_from_path(mount)) - filelist.close + Tempfile.open(["", ".list"]) do |filelist| + filelist.write(bom_filelist_from_path(mount)) + filelist.close - @command.run!("/usr/bin/mkbom", args: ["-s", "-i", filelist.path, "--", bomfile.path]) - @command.run!("/usr/bin/ditto", args: ["--bom", bomfile.path, "--", mount, @cask.staged_path]) + @command.run!("/usr/bin/mkbom", args: ["-s", "-i", filelist.path, "--", bomfile.path]) + @command.run!("/usr/bin/ditto", args: ["--bom", bomfile.path, "--", mount, @cask.staged_path]) + end + end end - end - end - def bom_filelist_from_path(mount) - Dir.chdir(mount) { - Dir.glob("**/*", File::FNM_DOTMATCH).map { |path| - next if skip_path?(Pathname(path)) - path == "." ? path : path.prepend("./") - }.compact.join("\n").concat("\n") - } - end + def bom_filelist_from_path(mount) + Dir.chdir(mount) { + Dir.glob("**/*", File::FNM_DOTMATCH).map { |path| + next if skip_path?(Pathname(path)) + path == "." ? path : path.prepend("./") + }.compact.join("\n").concat("\n") + } + end - def skip_path?(path) - dmg_metadata?(path) || system_dir_symlink?(path) - end + def skip_path?(path) + dmg_metadata?(path) || system_dir_symlink?(path) + end - # unnecessary DMG metadata - DMG_METADATA_FILES = %w[ - .background - .com.apple.timemachine.donotpresent - .DocumentRevisions-V100 - .DS_Store - .fseventsd - .MobileBackups - .Spotlight-V100 - .TemporaryItems - .Trashes - .VolumeIcon.icns - ].to_set.freeze - - def dmg_metadata?(path) - relative_root = path.sub(%r{/.*}, "") - DMG_METADATA_FILES.include?(relative_root.basename.to_s) - end + # unnecessary DMG metadata + DMG_METADATA_FILES = %w[ + .background + .com.apple.timemachine.donotpresent + .DocumentRevisions-V100 + .DS_Store + .fseventsd + .MobileBackups + .Spotlight-V100 + .TemporaryItems + .Trashes + .VolumeIcon.icns + ].to_set.freeze + + def dmg_metadata?(path) + relative_root = path.sub(%r{/.*}, "") + DMG_METADATA_FILES.include?(relative_root.basename.to_s) + end - def system_dir_symlink?(path) - # symlinks to system directories (commonly to /Applications) - path.symlink? && MacOS.system_dir?(path.readlink) - end + def system_dir_symlink?(path) + # symlinks to system directories (commonly to /Applications) + path.symlink? && MacOS.system_dir?(path.readlink) + end - def mounts_from_plist(plist) - return [] unless plist.respond_to?(:fetch) - plist.fetch("system-entities", []).map { |entity| - entity["mount-point"] - }.compact - end + def mounts_from_plist(plist) + return [] unless plist.respond_to?(:fetch) + plist.fetch("system-entities", []).map { |entity| + entity["mount-point"] + }.compact + end - def assert_mounts_found - raise Hbc::CaskError, "No mounts found in '#{@path}'; perhaps it is a bad DMG?" if @mounts.empty? + def assert_mounts_found + raise CaskError, "No mounts found in '#{@path}'; perhaps it is a bad DMG?" if @mounts.empty? + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/container/generic_unar.rb b/Library/Homebrew/cask/lib/hbc/container/generic_unar.rb index 1dcc0997a..32bbc8d15 100644 --- a/Library/Homebrew/cask/lib/hbc/container/generic_unar.rb +++ b/Library/Homebrew/cask/lib/hbc/container/generic_unar.rb @@ -2,25 +2,29 @@ require "tmpdir" require "hbc/container/base" -class Hbc::Container::GenericUnar < Hbc::Container::Base - def self.me?(criteria) - lsar = Hbc.homebrew_prefix.join("bin", "lsar") - lsar.exist? && - criteria.command.run(lsar, - args: ["-l", "-t", "--", criteria.path], - print_stderr: false).stdout.chomp.end_with?("passed, 0 failed.") - end +module Hbc + class Container + class GenericUnar < Base + def self.me?(criteria) + lsar = Hbc.homebrew_prefix.join("bin", "lsar") + lsar.exist? && + criteria.command.run(lsar, + args: ["-l", "-t", "--", criteria.path], + print_stderr: false).stdout.chomp.end_with?("passed, 0 failed.") + end - def extract - unar = Hbc.homebrew_prefix.join("bin", "unar") + def extract + unar = Hbc.homebrew_prefix.join("bin", "unar") - unless unar.exist? - raise Hbc::CaskError, "Expected to find unar executable. Cask #{@cask} must add: depends_on formula: 'unar'" - end + unless unar.exist? + raise CaskError, "Expected to find unar executable. Cask #{@cask} must add: depends_on formula: 'unar'" + end - Dir.mktmpdir do |unpack_dir| - @command.run!(unar, args: ["-force-overwrite", "-quiet", "-no-directory", "-output-directory", unpack_dir, "--", @path]) - @command.run!("/usr/bin/ditto", args: ["--", unpack_dir, @cask.staged_path]) + Dir.mktmpdir do |unpack_dir| + @command.run!(unar, args: ["-force-overwrite", "-quiet", "-no-directory", "-output-directory", unpack_dir, "--", @path]) + @command.run!("/usr/bin/ditto", args: ["--", unpack_dir, @cask.staged_path]) + end + end end end end diff --git a/Library/Homebrew/cask/lib/hbc/container/gzip.rb b/Library/Homebrew/cask/lib/hbc/container/gzip.rb index 161578162..7e4722a7f 100644 --- a/Library/Homebrew/cask/lib/hbc/container/gzip.rb +++ b/Library/Homebrew/cask/lib/hbc/container/gzip.rb @@ -2,17 +2,21 @@ require "tmpdir" require "hbc/container/base" -class Hbc::Container::Gzip < Hbc::Container::Base - def self.me?(criteria) - criteria.magic_number(%r{^\037\213}n) - end +module Hbc + class Container + class Gzip < Base + def self.me?(criteria) + criteria.magic_number(%r{^\037\213}n) + end - def extract - Dir.mktmpdir do |unpack_dir| - @command.run!("/usr/bin/ditto", args: ["--", @path, unpack_dir]) - @command.run!("/usr/bin/gunzip", args: ["--quiet", "--name", "--", Pathname.new(unpack_dir).join(@path.basename)]) + def extract + Dir.mktmpdir do |unpack_dir| + @command.run!("/usr/bin/ditto", args: ["--", @path, unpack_dir]) + @command.run!("/usr/bin/gunzip", args: ["--quiet", "--name", "--", Pathname.new(unpack_dir).join(@path.basename)]) - extract_nested_inside(unpack_dir) + extract_nested_inside(unpack_dir) + end + end end end end diff --git a/Library/Homebrew/cask/lib/hbc/container/lzma.rb b/Library/Homebrew/cask/lib/hbc/container/lzma.rb index e538b3779..a91132b55 100644 --- a/Library/Homebrew/cask/lib/hbc/container/lzma.rb +++ b/Library/Homebrew/cask/lib/hbc/container/lzma.rb @@ -2,22 +2,26 @@ require "tmpdir" require "hbc/container/base" -class Hbc::Container::Lzma < Hbc::Container::Base - def self.me?(criteria) - criteria.magic_number(%r{^\]\000\000\200\000}n) - end +module Hbc + class Container + class Lzma < Base + def self.me?(criteria) + criteria.magic_number(%r{^\]\000\000\200\000}n) + end - def extract - unlzma = Hbc.homebrew_prefix.join("bin", "unlzma") + def extract + unlzma = Hbc.homebrew_prefix.join("bin", "unlzma") - unless unlzma.exist? - raise Hbc::CaskError, "Expected to find unlzma executable. Cask '#{@cask}' must add: depends_on formula: 'lzma'" - end + unless unlzma.exist? + raise CaskError, "Expected to find unlzma executable. Cask '#{@cask}' must add: depends_on formula: 'lzma'" + end - Dir.mktmpdir do |unpack_dir| - @command.run!("/usr/bin/ditto", args: ["--", @path, unpack_dir]) - @command.run!(unlzma, args: ["-q", "--", Pathname(unpack_dir).join(@path.basename)]) - @command.run!("/usr/bin/ditto", args: ["--", unpack_dir, @cask.staged_path]) + Dir.mktmpdir do |unpack_dir| + @command.run!("/usr/bin/ditto", args: ["--", @path, unpack_dir]) + @command.run!(unlzma, args: ["-q", "--", Pathname(unpack_dir).join(@path.basename)]) + @command.run!("/usr/bin/ditto", args: ["--", unpack_dir, @cask.staged_path]) + end + end end end end diff --git a/Library/Homebrew/cask/lib/hbc/container/naked.rb b/Library/Homebrew/cask/lib/hbc/container/naked.rb index 596f50789..375d62f7a 100644 --- a/Library/Homebrew/cask/lib/hbc/container/naked.rb +++ b/Library/Homebrew/cask/lib/hbc/container/naked.rb @@ -1,19 +1,23 @@ require "hbc/container/base" -class Hbc::Container::Naked < Hbc::Container::Base - # Either inherit from this class and override with self.me?(criteria), - # or use this class directly as "container type: :naked", - # in which case self.me? is not called. - def self.me?(*) - false - end +module Hbc + class Container + class Naked < Base + # Either inherit from this class and override with self.me?(criteria), + # or use this class directly as "container type: :naked", + # in which case self.me? is not called. + def self.me?(*) + false + end - def extract - @command.run!("/usr/bin/ditto", args: ["--", @path, @cask.staged_path.join(target_file)]) - end + def extract + @command.run!("/usr/bin/ditto", args: ["--", @path, @cask.staged_path.join(target_file)]) + end - def target_file - return @path.basename if @nested - URI.decode(File.basename(@cask.url.path)) + def target_file + return @path.basename if @nested + URI.decode(File.basename(@cask.url.path)) + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/container/otf.rb b/Library/Homebrew/cask/lib/hbc/container/otf.rb index f9a25e1ed..66222ad8d 100644 --- a/Library/Homebrew/cask/lib/hbc/container/otf.rb +++ b/Library/Homebrew/cask/lib/hbc/container/otf.rb @@ -1,7 +1,11 @@ require "hbc/container/naked" -class Hbc::Container::Otf < Hbc::Container::Naked - def self.me?(criteria) - criteria.magic_number(%r{^OTTO}n) +module Hbc + class Container + class Otf < Naked + def self.me?(criteria) + criteria.magic_number(%r{^OTTO}n) + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/container/pkg.rb b/Library/Homebrew/cask/lib/hbc/container/pkg.rb index 5d2282d0f..dfd62a863 100644 --- a/Library/Homebrew/cask/lib/hbc/container/pkg.rb +++ b/Library/Homebrew/cask/lib/hbc/container/pkg.rb @@ -1,9 +1,13 @@ require "hbc/container/naked" -class Hbc::Container::Pkg < Hbc::Container::Naked - def self.me?(criteria) - criteria.extension(%r{m?pkg$}) && - (criteria.path.directory? || - criteria.magic_number(%r{^xar!}n)) +module Hbc + class Container + class Pkg < Naked + def self.me?(criteria) + criteria.extension(%r{m?pkg$}) && + (criteria.path.directory? || + criteria.magic_number(%r{^xar!}n)) + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/container/rar.rb b/Library/Homebrew/cask/lib/hbc/container/rar.rb index 9c144006f..bcf225623 100644 --- a/Library/Homebrew/cask/lib/hbc/container/rar.rb +++ b/Library/Homebrew/cask/lib/hbc/container/rar.rb @@ -1,8 +1,12 @@ require "hbc/container/generic_unar" -class Hbc::Container::Rar < Hbc::Container::GenericUnar - def self.me?(criteria) - criteria.magic_number(%r{^Rar!}n) && - super +module Hbc + class Container + class Rar < GenericUnar + def self.me?(criteria) + criteria.magic_number(%r{^Rar!}n) && + super + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/container/seven_zip.rb b/Library/Homebrew/cask/lib/hbc/container/seven_zip.rb index f0d183064..7a144d532 100644 --- a/Library/Homebrew/cask/lib/hbc/container/seven_zip.rb +++ b/Library/Homebrew/cask/lib/hbc/container/seven_zip.rb @@ -1,9 +1,13 @@ require "hbc/container/generic_unar" -class Hbc::Container::SevenZip < Hbc::Container::GenericUnar - def self.me?(criteria) - # TODO: cover self-extracting archives - criteria.magic_number(%r{^7z}n) && - super +module Hbc + class Container + class SevenZip < GenericUnar + def self.me?(criteria) + # TODO: cover self-extracting archives + criteria.magic_number(%r{^7z}n) && + super + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/container/sit.rb b/Library/Homebrew/cask/lib/hbc/container/sit.rb index 155b93f3f..2d8849399 100644 --- a/Library/Homebrew/cask/lib/hbc/container/sit.rb +++ b/Library/Homebrew/cask/lib/hbc/container/sit.rb @@ -1,8 +1,12 @@ require "hbc/container/generic_unar" -class Hbc::Container::Sit < Hbc::Container::GenericUnar - def self.me?(criteria) - criteria.magic_number(%r{^StuffIt}n) && - super +module Hbc + class Container + class Sit < GenericUnar + def self.me?(criteria) + criteria.magic_number(%r{^StuffIt}n) && + super + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/container/tar.rb b/Library/Homebrew/cask/lib/hbc/container/tar.rb index 8bc7c5f64..df77e454d 100644 --- a/Library/Homebrew/cask/lib/hbc/container/tar.rb +++ b/Library/Homebrew/cask/lib/hbc/container/tar.rb @@ -2,17 +2,21 @@ require "tmpdir" require "hbc/container/base" -class Hbc::Container::Tar < Hbc::Container::Base - def self.me?(criteria) - criteria.magic_number(%r{^.{257}ustar}n) || - # or compressed tar (bzip2/gzip/lzma/xz) - IO.popen(["/usr/bin/tar", "-t", "-f", criteria.path.to_s], err: "/dev/null") { |io| !io.read(1).nil? } - end +module Hbc + class Container + class Tar < Base + def self.me?(criteria) + criteria.magic_number(%r{^.{257}ustar}n) || + # or compressed tar (bzip2/gzip/lzma/xz) + IO.popen(["/usr/bin/tar", "-t", "-f", criteria.path.to_s], err: "/dev/null") { |io| !io.read(1).nil? } + end - def extract - Dir.mktmpdir do |unpack_dir| - @command.run!("/usr/bin/tar", args: ["-x", "-f", @path, "-C", unpack_dir]) - @command.run!("/usr/bin/ditto", args: ["--", unpack_dir, @cask.staged_path]) + def extract + Dir.mktmpdir do |unpack_dir| + @command.run!("/usr/bin/tar", args: ["-x", "-f", @path, "-C", unpack_dir]) + @command.run!("/usr/bin/ditto", args: ["--", unpack_dir, @cask.staged_path]) + end + end end end end diff --git a/Library/Homebrew/cask/lib/hbc/container/ttf.rb b/Library/Homebrew/cask/lib/hbc/container/ttf.rb index 8d787f360..62ca29b22 100644 --- a/Library/Homebrew/cask/lib/hbc/container/ttf.rb +++ b/Library/Homebrew/cask/lib/hbc/container/ttf.rb @@ -1,10 +1,14 @@ require "hbc/container/naked" -class Hbc::Container::Ttf < Hbc::Container::Naked - def self.me?(criteria) - # TrueType Font - criteria.magic_number(%r{^\000\001\000\000\000}n) || - # Truetype Font Collection - criteria.magic_number(%r{^ttcf}n) +module Hbc + class Container + class Ttf < Naked + def self.me?(criteria) + # TrueType Font + criteria.magic_number(%r{^\000\001\000\000\000}n) || + # Truetype Font Collection + criteria.magic_number(%r{^ttcf}n) + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/container/xar.rb b/Library/Homebrew/cask/lib/hbc/container/xar.rb index 5afc78bc5..228ab2343 100644 --- a/Library/Homebrew/cask/lib/hbc/container/xar.rb +++ b/Library/Homebrew/cask/lib/hbc/container/xar.rb @@ -2,15 +2,19 @@ require "tmpdir" require "hbc/container/base" -class Hbc::Container::Xar < Hbc::Container::Base - def self.me?(criteria) - criteria.magic_number(%r{^xar!}n) - end +module Hbc + class Container + class Xar < Base + def self.me?(criteria) + criteria.magic_number(%r{^xar!}n) + end - def extract - Dir.mktmpdir do |unpack_dir| - @command.run!("/usr/bin/xar", args: ["-x", "-f", @path, "-C", unpack_dir]) - @command.run!("/usr/bin/ditto", args: ["--", unpack_dir, @cask.staged_path]) + def extract + Dir.mktmpdir do |unpack_dir| + @command.run!("/usr/bin/xar", args: ["-x", "-f", @path, "-C", unpack_dir]) + @command.run!("/usr/bin/ditto", args: ["--", unpack_dir, @cask.staged_path]) + end + end end end end diff --git a/Library/Homebrew/cask/lib/hbc/container/xip.rb b/Library/Homebrew/cask/lib/hbc/container/xip.rb index 579f28fe0..2d0f17e2e 100644 --- a/Library/Homebrew/cask/lib/hbc/container/xip.rb +++ b/Library/Homebrew/cask/lib/hbc/container/xip.rb @@ -1,24 +1,28 @@ require "tmpdir" -class Hbc::Container::Xip < Hbc::Container::Base - def self.me?(criteria) - criteria.magic_number(%r{^xar!}n) && - IO.popen(["/usr/bin/xar", "-t", "-f", criteria.path.to_s], err: "/dev/null") { |io| io.read =~ %r{\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." +module Hbc + class Container + class Xip < Base + def self.me?(criteria) + criteria.magic_number(%r{^xar!}n) && + IO.popen(["/usr/bin/xar", "-t", "-f", criteria.path.to_s], err: "/dev/null") { |io| io.read =~ %r{\AContent\nMetadata\n\Z} } end - @command.run!("/usr/bin/xar", args: ["-x", "-f", @path, "Content", "-C", unpack_dir]) + 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")]) + 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 diff --git a/Library/Homebrew/cask/lib/hbc/container/xz.rb b/Library/Homebrew/cask/lib/hbc/container/xz.rb index 228532943..831bef5aa 100644 --- a/Library/Homebrew/cask/lib/hbc/container/xz.rb +++ b/Library/Homebrew/cask/lib/hbc/container/xz.rb @@ -2,22 +2,26 @@ require "tmpdir" require "hbc/container/base" -class Hbc::Container::Xz < Hbc::Container::Base - def self.me?(criteria) - criteria.magic_number(%r{^\xFD7zXZ\x00}n) - end +module Hbc + class Container + class Xz < Base + def self.me?(criteria) + criteria.magic_number(%r{^\xFD7zXZ\x00}n) + end - def extract - unxz = Hbc.homebrew_prefix.join("bin", "unxz") + def extract + unxz = Hbc.homebrew_prefix.join("bin", "unxz") - unless unxz.exist? - raise Hbc::CaskError, "Expected to find unxz executable. Cask '#{@cask}' must add: depends_on formula: 'xz'" - end + unless unxz.exist? + raise CaskError, "Expected to find unxz executable. Cask '#{@cask}' must add: depends_on formula: 'xz'" + end - Dir.mktmpdir do |unpack_dir| - @command.run!("/usr/bin/ditto", args: ["--", @path, unpack_dir]) - @command.run!(unxz, args: ["-q", "--", Pathname(unpack_dir).join(@path.basename)]) - @command.run!("/usr/bin/ditto", args: ["--", unpack_dir, @cask.staged_path]) + Dir.mktmpdir do |unpack_dir| + @command.run!("/usr/bin/ditto", args: ["--", @path, unpack_dir]) + @command.run!(unxz, args: ["-q", "--", Pathname(unpack_dir).join(@path.basename)]) + @command.run!("/usr/bin/ditto", args: ["--", unpack_dir, @cask.staged_path]) + end + end end end end diff --git a/Library/Homebrew/cask/lib/hbc/container/zip.rb b/Library/Homebrew/cask/lib/hbc/container/zip.rb index c6702fbb5..86e2d1bd6 100644 --- a/Library/Homebrew/cask/lib/hbc/container/zip.rb +++ b/Library/Homebrew/cask/lib/hbc/container/zip.rb @@ -1,15 +1,19 @@ require "hbc/container/base" -class Hbc::Container::Zip < Hbc::Container::Base - def self.me?(criteria) - criteria.magic_number(%r{^PK(\003\004|\005\006)}n) - end +module Hbc + class Container + class Zip < Base + def self.me?(criteria) + criteria.magic_number(%r{^PK(\003\004|\005\006)}n) + end - def extract - Dir.mktmpdir do |unpack_dir| - @command.run!("/usr/bin/ditto", args: ["-x", "-k", "--", @path, unpack_dir]) + def extract + Dir.mktmpdir do |unpack_dir| + @command.run!("/usr/bin/ditto", args: ["-x", "-k", "--", @path, unpack_dir]) - extract_nested_inside(unpack_dir) + extract_nested_inside(unpack_dir) + end + end end end end diff --git a/Library/Homebrew/cask/lib/hbc/download.rb b/Library/Homebrew/cask/lib/hbc/download.rb index 18dd7fe44..4166fc74d 100644 --- a/Library/Homebrew/cask/lib/hbc/download.rb +++ b/Library/Homebrew/cask/lib/hbc/download.rb @@ -1,43 +1,45 @@ require "fileutils" require "hbc/verify" -class Hbc::Download - attr_reader :cask - - def initialize(cask, force: false) - @cask = cask - @force = force - end - - def perform - clear_cache - fetch - downloaded_path - end - - private - - attr_reader :force - attr_accessor :downloaded_path - - def downloader - @downloader ||= case cask.url.using - when :svn - Hbc::SubversionDownloadStrategy.new(cask) - when :post - Hbc::CurlPostDownloadStrategy.new(cask) - else - Hbc::CurlDownloadStrategy.new(cask) - end - end - - def clear_cache - downloader.clear_cache if force || cask.version.latest? - end - - def fetch - self.downloaded_path = downloader.fetch - rescue StandardError => e - raise Hbc::CaskError, "Download failed on Cask '#{cask}' with message: #{e}" +module Hbc + class Download + attr_reader :cask + + def initialize(cask, force: false) + @cask = cask + @force = force + end + + def perform + clear_cache + fetch + downloaded_path + end + + private + + attr_reader :force + attr_accessor :downloaded_path + + def downloader + @downloader ||= case cask.url.using + when :svn + SubversionDownloadStrategy.new(cask) + when :post + CurlPostDownloadStrategy.new(cask) + else + CurlDownloadStrategy.new(cask) + end + end + + def clear_cache + downloader.clear_cache if force || cask.version.latest? + end + + def fetch + self.downloaded_path = downloader.fetch + rescue StandardError => e + raise CaskError, "Download failed on Cask '#{cask}' with message: #{e}" + end end end diff --git a/Library/Homebrew/cask/lib/hbc/download_strategy.rb b/Library/Homebrew/cask/lib/hbc/download_strategy.rb index 88ffb5050..400b9ffc8 100644 --- a/Library/Homebrew/cask/lib/hbc/download_strategy.rb +++ b/Library/Homebrew/cask/lib/hbc/download_strategy.rb @@ -6,327 +6,329 @@ require "cgi" # * Our overridden fetch methods are expected to return # a value: the successfully downloaded file. -class Hbc::AbstractDownloadStrategy - attr_reader :cask, :name, :url, :uri_object, :version - - def initialize(cask, command = Hbc::SystemCommand) - @cask = cask - @command = command - # TODO: this excess of attributes is a function of integrating - # with Homebrew's classes. Later we should be able to remove - # these in favor of @cask - @name = cask.token - @url = cask.url.to_s - @uri_object = cask.url - @version = cask.version - end +module Hbc + class AbstractDownloadStrategy + attr_reader :cask, :name, :url, :uri_object, :version + + def initialize(cask, command = SystemCommand) + @cask = cask + @command = command + # TODO: this excess of attributes is a function of integrating + # with Homebrew's classes. Later we should be able to remove + # these in favor of @cask + @name = cask.token + @url = cask.url.to_s + @uri_object = cask.url + @version = cask.version + end - # All download strategies are expected to implement these methods - def fetch; end + # All download strategies are expected to implement these methods + def fetch; end - def cached_location; end + def cached_location; end - def clear_cache; end -end + def clear_cache; end + end -class Hbc::HbVCSDownloadStrategy < Hbc::AbstractDownloadStrategy - REF_TYPES = [:branch, :revision, :revisions, :tag].freeze + class HbVCSDownloadStrategy < AbstractDownloadStrategy + REF_TYPES = [:branch, :revision, :revisions, :tag].freeze - def initialize(cask, command = Hbc::SystemCommand) - super - @ref_type, @ref = extract_ref - @clone = Hbc.cache.join(cache_filename) - end + def initialize(cask, command = SystemCommand) + super + @ref_type, @ref = extract_ref + @clone = Hbc.cache.join(cache_filename) + end - def extract_ref - key = REF_TYPES.find { |type| - uri_object.respond_to?(type) && uri_object.send(type) - } - [key, key ? uri_object.send(key) : nil] - end + def extract_ref + key = REF_TYPES.find { |type| + uri_object.respond_to?(type) && uri_object.send(type) + } + [key, key ? uri_object.send(key) : nil] + end - def cache_filename - "#{name}--#{cache_tag}" - end + def cache_filename + "#{name}--#{cache_tag}" + end - def cache_tag - "__UNKNOWN__" - end + def cache_tag + "__UNKNOWN__" + end - def cached_location - @clone - end + def cached_location + @clone + end - def clear_cache - cached_location.rmtree if cached_location.exist? + def clear_cache + cached_location.rmtree if cached_location.exist? + end end -end -class Hbc::CurlDownloadStrategy < Hbc::AbstractDownloadStrategy - # TODO: should be part of url object - def mirrors - @mirrors ||= [] - end + class CurlDownloadStrategy < AbstractDownloadStrategy + # TODO: should be part of url object + def mirrors + @mirrors ||= [] + end - def tarball_path - @tarball_path ||= Hbc.cache.join("#{name}--#{version}#{ext}") - end + def tarball_path + @tarball_path ||= Hbc.cache.join("#{name}--#{version}#{ext}") + end - def temporary_path - @temporary_path ||= tarball_path.sub(%r{$}, ".incomplete") - end + def temporary_path + @temporary_path ||= tarball_path.sub(%r{$}, ".incomplete") + end - def cached_location - tarball_path - end + def cached_location + tarball_path + end - def clear_cache - [cached_location, temporary_path].each do |f| - next unless f.exist? - raise CurlDownloadStrategyError, "#{f} is in use by another process" if Hbc::Utils.file_locked?(f) - f.unlink + def clear_cache + [cached_location, temporary_path].each do |f| + next unless f.exist? + raise CurlDownloadStrategyError, "#{f} is in use by another process" if Utils.file_locked?(f) + f.unlink + end end - end - def downloaded_size - temporary_path.size? || 0 - end + def downloaded_size + temporary_path.size? || 0 + end - def _fetch - odebug "Calling curl with args #{cask_curl_args.utf8_inspect}" - curl(*cask_curl_args) - end + def _fetch + odebug "Calling curl with args #{cask_curl_args.utf8_inspect}" + curl(*cask_curl_args) + end - def fetch - ohai "Downloading #{@url}" - if tarball_path.exist? - puts "Already downloaded: #{tarball_path}" - else - had_incomplete_download = temporary_path.exist? - begin - File.open(temporary_path, "w+") do |f| - f.flock(File::LOCK_EX) - _fetch - f.flock(File::LOCK_UN) - end - rescue ErrorDuringExecution - # 33 == range not supported - # try wiping the incomplete download and retrying once - if $CHILD_STATUS.exitstatus == 33 && had_incomplete_download - ohai "Trying a full download" - temporary_path.unlink - had_incomplete_download = false - retry + def fetch + ohai "Downloading #{@url}" + if tarball_path.exist? + puts "Already downloaded: #{tarball_path}" + else + had_incomplete_download = temporary_path.exist? + begin + File.open(temporary_path, "w+") do |f| + f.flock(File::LOCK_EX) + _fetch + f.flock(File::LOCK_UN) + end + rescue ErrorDuringExecution + # 33 == range not supported + # try wiping the incomplete download and retrying once + if $CHILD_STATUS.exitstatus == 33 && had_incomplete_download + ohai "Trying a full download" + temporary_path.unlink + had_incomplete_download = false + retry + end + + msg = @url + msg.concat("\nThe incomplete download is cached at #{temporary_path}") if temporary_path.exist? + raise CurlDownloadStrategyError, msg end - - msg = @url - msg.concat("\nThe incomplete download is cached at #{temporary_path}") if temporary_path.exist? - raise CurlDownloadStrategyError, msg + ignore_interrupts { temporary_path.rename(tarball_path) } end - ignore_interrupts { temporary_path.rename(tarball_path) } - end - tarball_path - rescue CurlDownloadStrategyError - raise if mirrors.empty? - puts "Trying a mirror..." - @url = mirrors.shift - retry - end + tarball_path + rescue CurlDownloadStrategyError + raise if mirrors.empty? + puts "Trying a mirror..." + @url = mirrors.shift + retry + end - private + private - def cask_curl_args - default_curl_args.tap do |args| - args.concat(user_agent_args) - args.concat(cookies_args) - args.concat(referer_args) + def cask_curl_args + default_curl_args.tap do |args| + args.concat(user_agent_args) + args.concat(cookies_args) + args.concat(referer_args) + end end - end - - def default_curl_args - [url, "-C", downloaded_size, "-o", temporary_path] - end - def user_agent_args - if uri_object.user_agent - ["-A", uri_object.user_agent] - else - [] + def default_curl_args + [url, "-C", downloaded_size, "-o", temporary_path] end - end - def cookies_args - if uri_object.cookies - [ - "-b", - # sort_by is for predictability between Ruby versions - uri_object - .cookies - .sort_by(&:to_s) - .map { |key, value| "#{CGI.escape(key.to_s)}=#{CGI.escape(value.to_s)}" } - .join(";"), - ] - else - [] + def user_agent_args + if uri_object.user_agent + ["-A", uri_object.user_agent] + else + [] + end end - end - def referer_args - if uri_object.referer - ["-e", uri_object.referer] - else - [] + def cookies_args + if uri_object.cookies + [ + "-b", + # sort_by is for predictability between Ruby versions + uri_object + .cookies + .sort_by(&:to_s) + .map { |key, value| "#{CGI.escape(key.to_s)}=#{CGI.escape(value.to_s)}" } + .join(";"), + ] + else + [] + end end - end - def ext - Pathname.new(@url).extname - end -end + def referer_args + if uri_object.referer + ["-e", uri_object.referer] + else + [] + end + end -class Hbc::CurlPostDownloadStrategy < Hbc::CurlDownloadStrategy - def cask_curl_args - super - default_curl_args.concat(post_args) + def ext + Pathname.new(@url).extname + end end - def post_args - if uri_object.data - # sort_by is for predictability between Ruby versions - uri_object - .data - .sort_by(&:to_s) - .map { |key, value| ["-d", "#{CGI.escape(key.to_s)}=#{CGI.escape(value.to_s)}"] } - .flatten - else - ["-X", "POST"] + class CurlPostDownloadStrategy < CurlDownloadStrategy + def cask_curl_args + super + default_curl_args.concat(post_args) end - end -end -class Hbc::SubversionDownloadStrategy < Hbc::HbVCSDownloadStrategy - def cache_tag - # TODO: pass versions as symbols, support :head here - version == "head" ? "svn-HEAD" : "svn" + def post_args + if uri_object.data + # sort_by is for predictability between Ruby versions + uri_object + .data + .sort_by(&:to_s) + .map { |key, value| ["-d", "#{CGI.escape(key.to_s)}=#{CGI.escape(value.to_s)}"] } + .flatten + else + ["-X", "POST"] + end + end end - def repo_valid? - @clone.join(".svn").directory? - end + class SubversionDownloadStrategy < HbVCSDownloadStrategy + def cache_tag + # TODO: pass versions as symbols, support :head here + version == "head" ? "svn-HEAD" : "svn" + end - def repo_url - `svn info '#{@clone}' 2>/dev/null`.strip[%r{^URL: (.+)$}, 1] - end + def repo_valid? + @clone.join(".svn").directory? + end - # super does not provide checks for already-existing downloads - def fetch - if tarball_path.exist? - puts "Already downloaded: #{tarball_path}" - else - @url = @url.sub(%r{^svn\+}, "") if @url =~ %r{^svn\+http://} - ohai "Checking out #{@url}" + def repo_url + `svn info '#{@clone}' 2>/dev/null`.strip[%r{^URL: (.+)$}, 1] + end - clear_cache unless @url.chomp("/") == repo_url || quiet_system("svn", "switch", @url, @clone) + # super does not provide checks for already-existing downloads + def fetch + if tarball_path.exist? + puts "Already downloaded: #{tarball_path}" + else + @url = @url.sub(%r{^svn\+}, "") if @url =~ %r{^svn\+http://} + ohai "Checking out #{@url}" - if @clone.exist? && !repo_valid? - puts "Removing invalid SVN repo from cache" - clear_cache - end + clear_cache unless @url.chomp("/") == repo_url || quiet_system("svn", "switch", @url, @clone) - case @ref_type - when :revision - fetch_repo @clone, @url, @ref - when :revisions - # nil is OK for main_revision, as fetch_repo will then get latest - main_revision = @ref[:trunk] - fetch_repo @clone, @url, main_revision, true + if @clone.exist? && !repo_valid? + puts "Removing invalid SVN repo from cache" + clear_cache + end - fetch_externals do |external_name, external_url| - fetch_repo @clone + external_name, external_url, @ref[external_name], true + case @ref_type + when :revision + fetch_repo @clone, @url, @ref + when :revisions + # nil is OK for main_revision, as fetch_repo will then get latest + main_revision = @ref[:trunk] + fetch_repo @clone, @url, main_revision, true + + fetch_externals do |external_name, external_url| + fetch_repo @clone + external_name, external_url, @ref[external_name], true + end + else + fetch_repo @clone, @url end - else - fetch_repo @clone, @url + compress end - compress + tarball_path end - tarball_path - end - # This primary reason for redefining this method is the trust_cert - # option, controllable from the Cask definition. We also force - # consistent timestamps. The rest of this method is similar to - # Homebrew's, but translated to local idiom. - def fetch_repo(target, url, revision = uri_object.revision, ignore_externals = false) - # Use "svn up" when the repository already exists locally. - # This saves on bandwidth and will have a similar effect to verifying the - # cache as it will make any changes to get the right revision. - svncommand = target.directory? ? "up" : "checkout" - args = [svncommand] - - # SVN shipped with XCode 3.1.4 can't force a checkout. - args << "--force" unless MacOS.version == :leopard - - # make timestamps consistent for checksumming - args.concat(%w[--config-option config:miscellany:use-commit-times=yes]) - - if uri_object.trust_cert - args << "--trust-server-cert" - args << "--non-interactive" - end - - args << url unless target.directory? - args << target - args << "-r" << revision if revision - args << "--ignore-externals" if ignore_externals - @command.run!("/usr/bin/svn", - args: args, - print_stderr: false) - end + # This primary reason for redefining this method is the trust_cert + # option, controllable from the Cask definition. We also force + # consistent timestamps. The rest of this method is similar to + # Homebrew's, but translated to local idiom. + def fetch_repo(target, url, revision = uri_object.revision, ignore_externals = false) + # Use "svn up" when the repository already exists locally. + # This saves on bandwidth and will have a similar effect to verifying the + # cache as it will make any changes to get the right revision. + svncommand = target.directory? ? "up" : "checkout" + args = [svncommand] + + # SVN shipped with XCode 3.1.4 can't force a checkout. + args << "--force" unless MacOS.version == :leopard + + # make timestamps consistent for checksumming + args.concat(%w[--config-option config:miscellany:use-commit-times=yes]) + + if uri_object.trust_cert + args << "--trust-server-cert" + args << "--non-interactive" + end - def tarball_path - @tarball_path ||= cached_location.dirname.join(cached_location.basename.to_s + "-#{@cask.version}.tar") - end + args << url unless target.directory? + args << target + args << "-r" << revision if revision + args << "--ignore-externals" if ignore_externals + @command.run!("/usr/bin/svn", + args: args, + print_stderr: false) + end - def shell_quote(str) - # Oh god escaping shell args. - # See http://notetoself.vrensk.com/2008/08/escaping-single-quotes-in-ruby-harder-than-expected/ - str.gsub(%r{\\|'}) { |c| "\\#{c}" } - end + def tarball_path + @tarball_path ||= cached_location.dirname.join(cached_location.basename.to_s + "-#{@cask.version}.tar") + end - def fetch_externals - `svn propget svn:externals '#{shell_quote(@url)}'`.chomp.each_line do |line| - name, url = line.split(%r{\s+}) - yield name, url + def shell_quote(str) + # Oh god escaping shell args. + # See http://notetoself.vrensk.com/2008/08/escaping-single-quotes-in-ruby-harder-than-expected/ + str.gsub(%r{\\|'}) { |c| "\\#{c}" } end - end - private - - # TODO/UPDATE: the tar approach explained below is fragile - # against challenges such as case-sensitive filesystems, - # and must be re-implemented. - # - # Seems nutty: we "download" the contents into a tape archive. - # Why? - # * A single file is tractable to the rest of the Cask toolchain, - # * An alternative would be to create a Directory container type. - # However, some type of file-serialization trick would still be - # needed in order to enable calculating a single checksum over - # a directory. So, in that alternative implementation, the - # special cases would propagate outside this class, including - # the use of tar or equivalent. - # * SubversionDownloadStrategy.cached_location is not versioned - # * tarball_path provides a needed return value for our overridden - # fetch method. - # * We can also take this private opportunity to strip files from - # the download which are protocol-specific. - - def compress - Dir.chdir(cached_location) do - @command.run!("/usr/bin/tar", - args: ['-s/^\.//', "--exclude", ".svn", "-cf", Pathname.new(tarball_path), "--", "."], - print_stderr: false) + def fetch_externals + `svn propget svn:externals '#{shell_quote(@url)}'`.chomp.each_line do |line| + name, url = line.split(%r{\s+}) + yield name, url + end + end + + private + + # TODO/UPDATE: the tar approach explained below is fragile + # against challenges such as case-sensitive filesystems, + # and must be re-implemented. + # + # Seems nutty: we "download" the contents into a tape archive. + # Why? + # * A single file is tractable to the rest of the Cask toolchain, + # * An alternative would be to create a Directory container type. + # However, some type of file-serialization trick would still be + # needed in order to enable calculating a single checksum over + # a directory. So, in that alternative implementation, the + # special cases would propagate outside this class, including + # the use of tar or equivalent. + # * SubversionDownloadStrategy.cached_location is not versioned + # * tarball_path provides a needed return value for our overridden + # fetch method. + # * We can also take this private opportunity to strip files from + # the download which are protocol-specific. + + def compress + Dir.chdir(cached_location) do + @command.run!("/usr/bin/tar", + args: ['-s/^\.//', "--exclude", ".svn", "-cf", Pathname.new(tarball_path), "--", "."], + print_stderr: false) + end + clear_cache end - clear_cache end end diff --git a/Library/Homebrew/cask/lib/hbc/dsl.rb b/Library/Homebrew/cask/lib/hbc/dsl.rb index f39012542..83c0bf1fb 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl.rb @@ -1,7 +1,5 @@ require "set" -class Hbc::DSL; end - require "hbc/dsl/appcast" require "hbc/dsl/base" require "hbc/dsl/caveats" @@ -18,266 +16,276 @@ require "hbc/dsl/uninstall_postflight" require "hbc/dsl/uninstall_preflight" require "hbc/dsl/version" -class Hbc::DSL - ORDINARY_ARTIFACT_TYPES = [ - :app, - :artifact, - :audio_unit_plugin, - :binary, - :colorpicker, - :font, - :input_method, - :internet_plugin, - :pkg, - :prefpane, - :qlplugin, - :screen_saver, - :service, - :stage_only, - :suite, - :vst_plugin, - :vst3_plugin, - ].freeze - - ACTIVATABLE_ARTIFACT_TYPES = ([:installer, *ORDINARY_ARTIFACT_TYPES] - [:stage_only]).freeze - - SPECIAL_ARTIFACT_TYPES = [ - :uninstall, - :zap, +module Hbc + class DSL + ORDINARY_ARTIFACT_TYPES = [ + :app, + :artifact, + :audio_unit_plugin, + :binary, + :colorpicker, + :font, + :input_method, + :internet_plugin, + :pkg, + :prefpane, + :qlplugin, + :screen_saver, + :service, + :stage_only, + :suite, + :vst_plugin, + :vst3_plugin, + ].freeze + + ACTIVATABLE_ARTIFACT_TYPES = ([:installer, *ORDINARY_ARTIFACT_TYPES] - [:stage_only]).freeze + + SPECIAL_ARTIFACT_TYPES = [ + :uninstall, + :zap, + ].freeze + + ARTIFACT_BLOCK_TYPES = [ + :preflight, + :postflight, + :uninstall_preflight, + :uninstall_postflight, ].freeze - ARTIFACT_BLOCK_TYPES = [ - :preflight, - :postflight, - :uninstall_preflight, - :uninstall_postflight, - ].freeze - - DSL_METHODS = Set.new [ - :accessibility_access, - :appcast, - :artifacts, - :auto_updates, - :caskroom_path, - :caveats, - :conflicts_with, - :container, - :depends_on, - :gpg, - :homepage, - :license, - :name, - :sha256, - :staged_path, - :url, - :version, - :appdir, - *ORDINARY_ARTIFACT_TYPES, - *ACTIVATABLE_ARTIFACT_TYPES, - *SPECIAL_ARTIFACT_TYPES, - *ARTIFACT_BLOCK_TYPES, - ].freeze - - attr_reader :token - def initialize(token) - @token = token - end - - def name(*args) - @name ||= [] - return @name if args.empty? - @name.concat(args.flatten) - end + DSL_METHODS = Set.new [ + :accessibility_access, + :appcast, + :artifacts, + :auto_updates, + :caskroom_path, + :caveats, + :conflicts_with, + :container, + :depends_on, + :gpg, + :homepage, + :license, + :name, + :sha256, + :staged_path, + :url, + :version, + :appdir, + *ORDINARY_ARTIFACT_TYPES, + *ACTIVATABLE_ARTIFACT_TYPES, + *SPECIAL_ARTIFACT_TYPES, + *ARTIFACT_BLOCK_TYPES, + ].freeze + + attr_reader :token + def initialize(token) + @token = token + end - def assert_only_one_stanza_allowed(stanza, arg_given) - return unless instance_variable_defined?("@#{stanza}") && arg_given - raise Hbc::CaskInvalidError.new(token, "'#{stanza}' stanza may only appear once") - end + def name(*args) + @name ||= [] + return @name if args.empty? + @name.concat(args.flatten) + end - def homepage(homepage = nil) - assert_only_one_stanza_allowed :homepage, !homepage.nil? - @homepage ||= homepage - end + def assert_only_one_stanza_allowed(stanza, arg_given) + return unless instance_variable_defined?("@#{stanza}") && arg_given + raise CaskInvalidError.new(token, "'#{stanza}' stanza may only appear once") + end - def url(*args, &block) - url_given = !args.empty? || block_given? - return @url unless url_given - assert_only_one_stanza_allowed :url, url_given - @url ||= begin - Hbc::URL.from(*args, &block) - rescue StandardError => e - raise Hbc::CaskInvalidError.new(token, "'url' stanza failed with: #{e}") + def homepage(homepage = nil) + assert_only_one_stanza_allowed :homepage, !homepage.nil? + @homepage ||= homepage end - end - def appcast(*args) - return @appcast if args.empty? - assert_only_one_stanza_allowed :appcast, !args.empty? - @appcast ||= begin - Hbc::DSL::Appcast.new(*args) unless args.empty? - rescue StandardError => e - raise Hbc::CaskInvalidError.new(token, e) + def url(*args, &block) + url_given = !args.empty? || block_given? + return @url unless url_given + assert_only_one_stanza_allowed :url, url_given + @url ||= begin + URL.from(*args, &block) + rescue StandardError => e + raise CaskInvalidError.new(token, "'url' stanza failed with: #{e}") + end end - end - def gpg(*args) - return @gpg if args.empty? - assert_only_one_stanza_allowed :gpg, !args.empty? - @gpg ||= begin - Hbc::DSL::Gpg.new(*args) unless args.empty? - rescue StandardError => e - raise Hbc::CaskInvalidError.new(token, e) + def appcast(*args) + return @appcast if args.empty? + assert_only_one_stanza_allowed :appcast, !args.empty? + @appcast ||= begin + DSL::Appcast.new(*args) unless args.empty? + rescue StandardError => e + raise CaskInvalidError.new(token, e) + end end - end - def container(*args) - return @container if args.empty? - # TODO: remove this constraint, and instead merge multiple container stanzas - assert_only_one_stanza_allowed :container, !args.empty? - @container ||= begin - Hbc::DSL::Container.new(*args) unless args.empty? - rescue StandardError => e - raise Hbc::CaskInvalidError.new(token, e) + def gpg(*args) + return @gpg if args.empty? + assert_only_one_stanza_allowed :gpg, !args.empty? + @gpg ||= begin + DSL::Gpg.new(*args) unless args.empty? + rescue StandardError => e + raise CaskInvalidError.new(token, e) + end end - # TODO: remove this backward-compatibility section after removing nested_container - if @container && @container.nested - artifacts[:nested_container] << @container.nested + + def container(*args) + return @container if args.empty? + # TODO: remove this constraint, and instead merge multiple container stanzas + assert_only_one_stanza_allowed :container, !args.empty? + @container ||= begin + DSL::Container.new(*args) unless args.empty? + rescue StandardError => e + raise CaskInvalidError.new(token, e) + end + # TODO: remove this backward-compatibility section after removing nested_container + if @container && @container.nested + artifacts[:nested_container] << @container.nested + end + @container end - @container - end - SYMBOLIC_VERSIONS = Set.new [ - :latest, - ] + SYMBOLIC_VERSIONS = Set.new [ + :latest, + ] - def version(arg = nil) - return @version if arg.nil? - assert_only_one_stanza_allowed :version, !arg.nil? - raise Hbc::CaskInvalidError.new(token, "invalid 'version' value: '#{arg.inspect}'") if !arg.is_a?(String) && !SYMBOLIC_VERSIONS.include?(arg) - @version ||= Hbc::DSL::Version.new(arg) - end + def version(arg = nil) + return @version if arg.nil? + assert_only_one_stanza_allowed :version, !arg.nil? + raise CaskInvalidError.new(token, "invalid 'version' value: '#{arg.inspect}'") if !arg.is_a?(String) && !SYMBOLIC_VERSIONS.include?(arg) + @version ||= DSL::Version.new(arg) + end - SYMBOLIC_SHA256S = Set.new [ - :no_check, - ] + SYMBOLIC_SHA256S = Set.new [ + :no_check, + ] - def sha256(arg = nil) - return @sha256 if arg.nil? - assert_only_one_stanza_allowed :sha256, !arg.nil? - raise Hbc::CaskInvalidError.new(token, "invalid 'sha256' value: '#{arg.inspect}'") if !arg.is_a?(String) && !SYMBOLIC_SHA256S.include?(arg) - @sha256 ||= arg - end + def sha256(arg = nil) + return @sha256 if arg.nil? + assert_only_one_stanza_allowed :sha256, !arg.nil? + raise CaskInvalidError.new(token, "invalid 'sha256' value: '#{arg.inspect}'") if !arg.is_a?(String) && !SYMBOLIC_SHA256S.include?(arg) + @sha256 ||= arg + end - def license(arg = nil) - return @license if arg.nil? - assert_only_one_stanza_allowed :license, !arg.nil? - @license ||= begin - Hbc::DSL::License.new(arg) unless arg.nil? - rescue StandardError => e - raise Hbc::CaskInvalidError.new(token, e) + def license(arg = nil) + return @license if arg.nil? + assert_only_one_stanza_allowed :license, !arg.nil? + @license ||= begin + DSL::License.new(arg) unless arg.nil? + rescue StandardError => e + raise CaskInvalidError.new(token, e) + end end - end - # depends_on uses a load method so that multiple stanzas can be merged - def depends_on(*args) - return @depends_on if args.empty? - @depends_on ||= Hbc::DSL::DependsOn.new - begin - @depends_on.load(*args) unless args.empty? - rescue RuntimeError => e - raise Hbc::CaskInvalidError.new(token, e) + # depends_on uses a load method so that multiple stanzas can be merged + def depends_on(*args) + return @depends_on if args.empty? + @depends_on ||= DSL::DependsOn.new + begin + @depends_on.load(*args) unless args.empty? + rescue RuntimeError => e + raise CaskInvalidError.new(token, e) + end + @depends_on end - @depends_on - end - def conflicts_with(*args) - return @conflicts_with if args.empty? - # TODO: remove this constraint, and instead merge multiple conflicts_with stanzas - assert_only_one_stanza_allowed :conflicts_with, !args.empty? - @conflicts_with ||= begin - Hbc::DSL::ConflictsWith.new(*args) unless args.empty? - rescue StandardError => e - raise Hbc::CaskInvalidError.new(token, e) + def conflicts_with(*args) + return @conflicts_with if args.empty? + # TODO: remove this constraint, and instead merge multiple conflicts_with stanzas + assert_only_one_stanza_allowed :conflicts_with, !args.empty? + @conflicts_with ||= begin + DSL::ConflictsWith.new(*args) unless args.empty? + rescue StandardError => e + raise CaskInvalidError.new(token, e) + end end - end - def artifacts - @artifacts ||= Hash.new { |hash, key| hash[key] = Set.new } - end + def artifacts + @artifacts ||= Hash.new { |hash, key| hash[key] = Set.new } + end - def caskroom_path - @caskroom_path ||= Hbc.caskroom.join(token) - end + def caskroom_path + @caskroom_path ||= Hbc.caskroom.join(token) + end - def staged_path - return @staged_path if @staged_path - cask_version = version || :unknown - @staged_path = caskroom_path.join(cask_version.to_s) - end + def staged_path + return @staged_path if @staged_path + cask_version = version || :unknown + @staged_path = caskroom_path.join(cask_version.to_s) + end - def caveats(*string, &block) - @caveats ||= [] - if block_given? - @caveats << Hbc::Caveats.new(block) - elsif string.any? - @caveats << string.map { |s| s.to_s.sub(%r{[\r\n \t]*\Z}, "\n\n") } + def caveats(*string, &block) + @caveats ||= [] + if block_given? + @caveats << Hbc::Caveats.new(block) + elsif string.any? + @caveats << string.map { |s| s.to_s.sub(%r{[\r\n \t]*\Z}, "\n\n") } + end + @caveats end - @caveats - end - def accessibility_access(accessibility_access = nil) - assert_only_one_stanza_allowed :accessibility_access, !accessibility_access.nil? - @accessibility_access ||= accessibility_access - end + def accessibility_access(accessibility_access = nil) + assert_only_one_stanza_allowed :accessibility_access, !accessibility_access.nil? + @accessibility_access ||= accessibility_access + end - def auto_updates(auto_updates = nil) - assert_only_one_stanza_allowed :auto_updates, !auto_updates.nil? - @auto_updates ||= auto_updates - end + def auto_updates(auto_updates = nil) + assert_only_one_stanza_allowed :auto_updates, !auto_updates.nil? + @auto_updates ||= auto_updates + end - ORDINARY_ARTIFACT_TYPES.each do |type| - define_method(type) do |*args| - if type == :stage_only && args != [true] - raise Hbc::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 Hbc::CaskInvalidError.new(token, "'stage_only' must be the only activatable artifact") + 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") + end end end - end - def installer(*args) - return artifacts[:installer] if args.empty? - artifacts[:installer] << Hbc::DSL::Installer.new(*args) - raise "'stage_only' must be the only activatable artifact" if artifacts.key?(:stage_only) - rescue StandardError => e - raise Hbc::CaskInvalidError.new(token, e) - end + def installer(*args) + return artifacts[:installer] if args.empty? + artifacts[:installer] << DSL::Installer.new(*args) + raise "'stage_only' must be the only activatable artifact" if artifacts.key?(:stage_only) + rescue StandardError => e + raise CaskInvalidError.new(token, e) + end - SPECIAL_ARTIFACT_TYPES.each do |type| - define_method(type) do |*args| - artifacts[type].merge(args) + SPECIAL_ARTIFACT_TYPES.each do |type| + define_method(type) do |*args| + artifacts[type].merge(args) + end end - end - ARTIFACT_BLOCK_TYPES.each do |type| - define_method(type) do |&block| - artifacts[type] << block + ARTIFACT_BLOCK_TYPES.each do |type| + define_method(type) do |&block| + artifacts[type] << block + end end - end - def method_missing(method, *) - Hbc::Utils.method_missing_message(method, token) - nil - end + def method_missing(method, *) + if method + Utils.method_missing_message(method, token) + nil + else + super + end + end - def appdir - self.class.appdir - end + def respond_to_missing?(*) + true + end + + def appdir + self.class.appdir + end - def self.appdir - Hbc.appdir.sub(%r{\/$}, "") + def self.appdir + Hbc.appdir.sub(%r{\/$}, "") + end end end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb b/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb index b02616cfe..2f1245d3d 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb @@ -1,17 +1,21 @@ -class Hbc::DSL::Appcast - attr_reader :parameters, :checkpoint +module Hbc + class DSL + class Appcast + attr_reader :parameters, :checkpoint - def initialize(uri, parameters = {}) - @parameters = parameters - @uri = Hbc::UnderscoreSupportingURI.parse(uri) - @checkpoint = @parameters[:checkpoint] - end + def initialize(uri, parameters = {}) + @parameters = parameters + @uri = UnderscoreSupportingURI.parse(uri) + @checkpoint = @parameters[:checkpoint] + end - def to_yaml - [@uri, @parameters].to_yaml - end + def to_yaml + [@uri, @parameters].to_yaml + end - def to_s - @uri.to_s + def to_s + @uri.to_s + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/base.rb b/Library/Homebrew/cask/lib/hbc/dsl/base.rb index 4bf62014e..ccf93dae9 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/base.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/base.rb @@ -1,21 +1,33 @@ -class Hbc::DSL::Base - extend Forwardable +module Hbc + class DSL + class Base + extend Forwardable - def initialize(cask, command = Hbc::SystemCommand) - @cask = cask - @command = command - end + def initialize(cask, command = SystemCommand) + @cask = cask + @command = command + end - def_delegators :@cask, :token, :version, :caskroom_path, :staged_path, :appdir + def_delegators :@cask, :token, :version, :caskroom_path, :staged_path, :appdir - def system_command(executable, options = {}) - @command.run!(executable, options) - end + def system_command(executable, options = {}) + @command.run!(executable, options) + end + + def method_missing(method, *) + if method + underscored_class = self.class.name.gsub(%r{([[:lower:]])([[:upper:]][[:lower:]])}, '\1_\2').downcase + section = underscored_class.downcase.split("::").last + Utils.method_missing_message(method, @cask.to_s, section) + nil + else + super + end + end - def method_missing(method, *) - underscored_class = self.class.name.gsub(%r{([[:lower:]])([[:upper:]][[:lower:]])}, '\1_\2').downcase - section = underscored_class.downcase.split("::").last - Hbc::Utils.method_missing_message(method, @cask.to_s, section) - nil + def respond_to_missing?(*) + true + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/caveats.rb b/Library/Homebrew/cask/lib/hbc/dsl/caveats.rb index d872f49cb..5efd7d562 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/caveats.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/caveats.rb @@ -5,108 +5,112 @@ # ( The return value of the last method in the block is also sent # to the output by the caller, but that feature is only for the # convenience of Cask authors. ) -class Hbc::DSL::Caveats < Hbc::DSL::Base - def path_environment_variable(path) - puts <<-EOS.undent - To use #{@cask}, you may need to add the #{path} directory - to your PATH environment variable, eg (for bash shell): +module Hbc + class DSL + class Caveats < Base + def path_environment_variable(path) + puts <<-EOS.undent + To use #{@cask}, you may need to add the #{path} directory + to your PATH environment variable, eg (for bash shell): - export PATH=#{path}:"$PATH" + export PATH=#{path}:"$PATH" - EOS - end + EOS + end - def zsh_path_helper(path) - puts <<-EOS.undent - To use #{@cask}, zsh users may need to add the following line to their - ~/.zprofile. (Among other effects, #{path} will be added to the - PATH environment variable): + def zsh_path_helper(path) + puts <<-EOS.undent + To use #{@cask}, zsh users may need to add the following line to their + ~/.zprofile. (Among other effects, #{path} will be added to the + PATH environment variable): - eval `/usr/libexec/path_helper -s` + eval `/usr/libexec/path_helper -s` - EOS - end + EOS + end - def files_in_usr_local - localpath = "/usr/local" - return unless Hbc.homebrew_prefix.to_s.downcase.start_with?(localpath) - puts <<-EOS.undent - Cask #{@cask} installs files under "#{localpath}". The presence of such - files can cause warnings when running "brew doctor", which is considered - to be a bug in Homebrew-Cask. + def files_in_usr_local + localpath = "/usr/local" + return unless Hbc.homebrew_prefix.to_s.downcase.start_with?(localpath) + puts <<-EOS.undent + Cask #{@cask} installs files under "#{localpath}". The presence of such + files can cause warnings when running "brew doctor", which is considered + to be a bug in Homebrew-Cask. - EOS - end + EOS + end - def depends_on_java(java_version = "any") - if java_version == "any" - puts <<-EOS.undent - #{@cask} requires Java. You can install the latest version with + def depends_on_java(java_version = "any") + if java_version == "any" + puts <<-EOS.undent + #{@cask} requires Java. You can install the latest version with - brew cask install java + brew cask install java - EOS - elsif java_version.include?("8") || java_version.include?("+") - puts <<-EOS.undent - #{@cask} requires Java #{java_version}. You can install the latest version with + EOS + elsif java_version.include?("8") || java_version.include?("+") + puts <<-EOS.undent + #{@cask} requires Java #{java_version}. You can install the latest version with - brew cask install java + brew cask install java - EOS - else - puts <<-EOS.undent - #{@cask} requires Java #{java_version}. You can install it with + EOS + else + puts <<-EOS.undent + #{@cask} requires Java #{java_version}. You can install it with - brew cask install caskroom/versions/java#{java_version} + brew cask install caskroom/versions/java#{java_version} - EOS - end - end + EOS + end + end - def logout - puts <<-EOS.undent - You must log out and log back in for the installation of #{@cask} - to take effect. + def logout + puts <<-EOS.undent + You must log out and log back in for the installation of #{@cask} + to take effect. - EOS - end + EOS + end - def reboot - puts <<-EOS.undent - You must reboot for the installation of #{@cask} to take effect. + def reboot + puts <<-EOS.undent + You must reboot for the installation of #{@cask} to take effect. - EOS - end + EOS + end - def discontinued - puts <<-EOS.undent - #{@cask} has been officially discontinued upstream. - It may stop working correctly (or at all) in recent versions of macOS. + def discontinued + puts <<-EOS.undent + #{@cask} has been officially discontinued upstream. + It may stop working correctly (or at all) in recent versions of macOS. - EOS - end + EOS + end - def free_license(web_page) - puts <<-EOS.undent - The vendor offers a free license for #{@cask} at - #{web_page} + def free_license(web_page) + puts <<-EOS.undent + The vendor offers a free license for #{@cask} at + #{web_page} - EOS - end + EOS + end - def malware(radar_number) - puts <<-EOS.undent - #{@cask} has been reported to bundle malware. Like with any app, use at your own risk. + def malware(radar_number) + puts <<-EOS.undent + #{@cask} has been reported to bundle malware. Like with any app, use at your own risk. - A report has been made to Apple about this app. Their certificate will hopefully be revoked. - See the public report at - https://openradar.appspot.com/#{radar_number} + A report has been made to Apple about this app. Their certificate will hopefully be revoked. + See the public report at + https://openradar.appspot.com/#{radar_number} - If this report is accurate, please duplicate it at - https://bugreport.apple.com/ - If this report is a mistake, please let us know by opening an issue at - https://github.com/caskroom/homebrew-cask/issues/new + If this report is accurate, please duplicate it at + https://bugreport.apple.com/ + If this report is a mistake, please let us know by opening an issue at + https://github.com/caskroom/homebrew-cask/issues/new - EOS + EOS + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/conflicts_with.rb b/Library/Homebrew/cask/lib/hbc/dsl/conflicts_with.rb index b2de2cd45..e121e5373 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/conflicts_with.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/conflicts_with.rb @@ -1,30 +1,34 @@ -class Hbc::DSL::ConflictsWith - VALID_KEYS = Set.new [ - :formula, - :cask, - :macos, - :arch, - :x11, - :java, - ] +module Hbc + class DSL + class ConflictsWith + VALID_KEYS = Set.new [ + :formula, + :cask, + :macos, + :arch, + :x11, + :java, + ] - attr_accessor(*VALID_KEYS) - attr_accessor :pairs + attr_accessor(*VALID_KEYS) + attr_accessor :pairs - def initialize(pairs = {}) - @pairs = pairs - pairs.each do |key, value| - raise "invalid conflicts_with key: '#{key.inspect}'" unless VALID_KEYS.include?(key) - writer_method = "#{key}=".to_sym - send(writer_method, value) - end - end + def initialize(pairs = {}) + @pairs = pairs + pairs.each do |key, value| + raise "invalid conflicts_with key: '#{key.inspect}'" unless VALID_KEYS.include?(key) + writer_method = "#{key}=".to_sym + send(writer_method, value) + end + end - def to_yaml - @pairs.to_yaml - end + def to_yaml + @pairs.to_yaml + end - def to_s - @pairs.inspect + def to_s + @pairs.inspect + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/container.rb b/Library/Homebrew/cask/lib/hbc/dsl/container.rb index 39f156668..56db31d97 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/container.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/container.rb @@ -1,26 +1,30 @@ -class Hbc::DSL::Container - VALID_KEYS = Set.new [ - :type, - :nested, - ] +module Hbc + class DSL + class Container + VALID_KEYS = Set.new [ + :type, + :nested, + ] - attr_accessor(*VALID_KEYS) - attr_accessor :pairs + attr_accessor(*VALID_KEYS) + attr_accessor :pairs - def initialize(pairs = {}) - @pairs = pairs - pairs.each do |key, value| - raise "invalid container key: '#{key.inspect}'" unless VALID_KEYS.include?(key) - writer_method = "#{key}=".to_sym - send(writer_method, value) - end - end + def initialize(pairs = {}) + @pairs = pairs + pairs.each do |key, value| + raise "invalid container key: '#{key.inspect}'" unless VALID_KEYS.include?(key) + writer_method = "#{key}=".to_sym + send(writer_method, value) + end + end - def to_yaml - @pairs.to_yaml - end + def to_yaml + @pairs.to_yaml + end - def to_s - @pairs.inspect + def to_s + @pairs.inspect + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/depends_on.rb b/Library/Homebrew/cask/lib/hbc/dsl/depends_on.rb index a7dba3643..0e80938b7 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/depends_on.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/depends_on.rb @@ -1,124 +1,128 @@ require "rubygems" -class Hbc::DSL::DependsOn - VALID_KEYS = Set.new [ - :formula, - :cask, - :macos, - :arch, - :x11, - :java, - ].freeze +module Hbc + class DSL + class DependsOn + VALID_KEYS = Set.new [ + :formula, + :cask, + :macos, + :arch, + :x11, + :java, + ].freeze - VALID_ARCHES = { - intel: { type: :intel, bits: [32, 64] }, - ppc: { type: :ppc, bits: [32, 64] }, - # specific - i386: { type: :intel, bits: 32 }, - x86_64: { type: :intel, bits: 64 }, - ppc_7400: { type: :ppc, bits: 32 }, - ppc_64: { type: :ppc, bits: 64 }, - }.freeze + VALID_ARCHES = { + intel: { type: :intel, bits: [32, 64] }, + ppc: { type: :ppc, bits: [32, 64] }, + # specific + i386: { type: :intel, bits: 32 }, + x86_64: { type: :intel, bits: 64 }, + ppc_7400: { type: :ppc, bits: 32 }, + ppc_64: { type: :ppc, bits: 64 }, + }.freeze - # Intentionally undocumented: catch variant spellings. - ARCH_SYNONYMS = { - x86_32: :i386, - x8632: :i386, - x8664: :x86_64, - intel_32: :i386, - intel32: :i386, - intel_64: :x86_64, - intel64: :x86_64, - amd_64: :x86_64, - amd64: :x86_64, - ppc7400: :ppc_7400, - ppc_32: :ppc_7400, - ppc32: :ppc_7400, - ppc64: :ppc_64, - }.freeze + # Intentionally undocumented: catch variant spellings. + ARCH_SYNONYMS = { + x86_32: :i386, + x8632: :i386, + x8664: :x86_64, + intel_32: :i386, + intel32: :i386, + intel_64: :x86_64, + intel64: :x86_64, + amd_64: :x86_64, + amd64: :x86_64, + ppc7400: :ppc_7400, + ppc_32: :ppc_7400, + ppc32: :ppc_7400, + ppc64: :ppc_64, + }.freeze - attr_accessor :java - attr_accessor :pairs - attr_reader :arch, :cask, :formula, :macos, :x11 + attr_accessor :java + attr_accessor :pairs + attr_reader :arch, :cask, :formula, :macos, :x11 - def initialize - @pairs ||= {} - end + def initialize + @pairs ||= {} + end - def load(pairs = {}) - pairs.each do |key, value| - raise "invalid depends_on key: '#{key.inspect}'" unless VALID_KEYS.include?(key) - writer_method = "#{key}=".to_sym - @pairs[key] = send(writer_method, value) - end - end + def load(pairs = {}) + pairs.each do |key, value| + raise "invalid depends_on key: '#{key.inspect}'" unless VALID_KEYS.include?(key) + writer_method = "#{key}=".to_sym + @pairs[key] = send(writer_method, value) + end + end - def self.coerce_os_release(arg) - @macos_symbols ||= MacOS::Version::SYMBOLS - @inverted_macos_symbols ||= @macos_symbols.invert + def self.coerce_os_release(arg) + @macos_symbols ||= MacOS::Version::SYMBOLS + @inverted_macos_symbols ||= @macos_symbols.invert - begin - if arg.is_a?(Symbol) - Gem::Version.new(@macos_symbols.fetch(arg)) - elsif arg =~ %r{^\s*:?([a-z]\S+)\s*$}i - Gem::Version.new(@macos_symbols.fetch(Regexp.last_match[1].downcase.to_sym)) - elsif @inverted_macos_symbols.key?(arg) - Gem::Version.new(arg) - else - raise + begin + if arg.is_a?(Symbol) + Gem::Version.new(@macos_symbols.fetch(arg)) + elsif arg =~ %r{^\s*:?([a-z]\S+)\s*$}i + Gem::Version.new(@macos_symbols.fetch(Regexp.last_match[1].downcase.to_sym)) + elsif @inverted_macos_symbols.key?(arg) + Gem::Version.new(arg) + else + raise + end + rescue StandardError + raise "invalid 'depends_on macos' value: #{arg.inspect}" + end end - rescue StandardError - raise "invalid 'depends_on macos' value: #{arg.inspect}" - end - end - def formula=(*arg) - @formula ||= [] - @formula.concat(Array(*arg)) - end + def formula=(*arg) + @formula ||= [] + @formula.concat(Array(*arg)) + end - def cask=(*arg) - @cask ||= [] - @cask.concat(Array(*arg)) - end + def cask=(*arg) + @cask ||= [] + @cask.concat(Array(*arg)) + end - def macos=(*arg) - @macos ||= [] - macos = if arg.count == 1 && arg.first =~ %r{^\s*(<|>|[=<>]=)\s*(\S+)\s*$} - raise "'depends_on macos' comparison expressions cannot be combined" unless @macos.empty? - operator = Regexp.last_match[1].to_sym - release = self.class.coerce_os_release(Regexp.last_match[2]) - [[operator, release]] - else - raise "'depends_on macos' comparison expressions cannot be combined" if @macos.first.is_a?(Symbol) - Array(*arg).map { |elt| - self.class.coerce_os_release(elt) - }.sort - end - @macos.concat(macos) - end + def macos=(*arg) + @macos ||= [] + macos = if arg.count == 1 && arg.first =~ %r{^\s*(<|>|[=<>]=)\s*(\S+)\s*$} + raise "'depends_on macos' comparison expressions cannot be combined" unless @macos.empty? + operator = Regexp.last_match[1].to_sym + release = self.class.coerce_os_release(Regexp.last_match[2]) + [[operator, release]] + else + raise "'depends_on macos' comparison expressions cannot be combined" if @macos.first.is_a?(Symbol) + Array(*arg).map { |elt| + self.class.coerce_os_release(elt) + }.sort + end + @macos.concat(macos) + end - def arch=(*arg) - @arch ||= [] - arches = Array(*arg).map { |elt| - elt = elt.to_s.downcase.sub(%r{^:}, "").tr("-", "_").to_sym - ARCH_SYNONYMS.key?(elt) ? ARCH_SYNONYMS[elt] : elt - } - invalid_arches = arches - VALID_ARCHES.keys - raise "invalid 'depends_on arch' values: #{invalid_arches.inspect}" unless invalid_arches.empty? - @arch.concat(arches.map { |arch| VALID_ARCHES[arch] }) - end + def arch=(*arg) + @arch ||= [] + arches = Array(*arg).map { |elt| + elt = elt.to_s.downcase.sub(%r{^:}, "").tr("-", "_").to_sym + ARCH_SYNONYMS.key?(elt) ? ARCH_SYNONYMS[elt] : elt + } + invalid_arches = arches - VALID_ARCHES.keys + raise "invalid 'depends_on arch' values: #{invalid_arches.inspect}" unless invalid_arches.empty? + @arch.concat(arches.map { |arch| VALID_ARCHES[arch] }) + end - def x11=(arg) - raise "invalid 'depends_on x11' value: #{arg.inspect}" unless [true, false].include?(arg) - @x11 = arg - end + def x11=(arg) + raise "invalid 'depends_on x11' value: #{arg.inspect}" unless [true, false].include?(arg) + @x11 = arg + end - def to_yaml - @pairs.to_yaml - end + def to_yaml + @pairs.to_yaml + end - def to_s - @pairs.inspect + def to_s + @pairs.inspect + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/gpg.rb b/Library/Homebrew/cask/lib/hbc/dsl/gpg.rb index 9496a8c05..572ede227 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/gpg.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/gpg.rb @@ -1,43 +1,47 @@ -class Hbc::DSL::Gpg - KEY_PARAMETERS = Set.new [ - :key_id, - :key_url, - ] +module Hbc + class DSL + class Gpg + KEY_PARAMETERS = Set.new [ + :key_id, + :key_url, + ] - VALID_PARAMETERS = Set.new [] - VALID_PARAMETERS.merge KEY_PARAMETERS + VALID_PARAMETERS = Set.new [] + VALID_PARAMETERS.merge KEY_PARAMETERS - attr_accessor(*VALID_PARAMETERS) - attr_accessor :signature + attr_accessor(*VALID_PARAMETERS) + attr_accessor :signature - def initialize(signature, parameters = {}) - @parameters = parameters - @signature = Hbc::UnderscoreSupportingURI.parse(signature) - parameters.each do |hkey, hvalue| - raise "invalid 'gpg' parameter: '#{hkey.inspect}'" unless VALID_PARAMETERS.include?(hkey) - writer_method = "#{hkey}=".to_sym - hvalue = Hbc::UnderscoreSupportingURI.parse(hvalue) if hkey == :key_url - valid_id?(hvalue) if hkey == :key_id - send(writer_method, hvalue) - end - return if KEY_PARAMETERS.intersection(parameters.keys).length == 1 - raise "'gpg' stanza must include exactly one of: '#{KEY_PARAMETERS.to_a}'" - end + def initialize(signature, parameters = {}) + @parameters = parameters + @signature = UnderscoreSupportingURI.parse(signature) + parameters.each do |hkey, hvalue| + raise "invalid 'gpg' parameter: '#{hkey.inspect}'" unless VALID_PARAMETERS.include?(hkey) + writer_method = "#{hkey}=".to_sym + hvalue = UnderscoreSupportingURI.parse(hvalue) if hkey == :key_url + valid_id?(hvalue) if hkey == :key_id + send(writer_method, hvalue) + end + return if KEY_PARAMETERS.intersection(parameters.keys).length == 1 + raise "'gpg' stanza must include exactly one of: '#{KEY_PARAMETERS.to_a}'" + end - def valid_id?(id) - legal_lengths = Set.new [8, 16, 40] - is_valid = id.is_a?(String) && legal_lengths.include?(id.length) && id[%r{^[0-9a-f]+$}i] - raise "invalid ':key_id' value: '#{id.inspect}'" unless is_valid + def valid_id?(id) + legal_lengths = Set.new [8, 16, 40] + is_valid = id.is_a?(String) && legal_lengths.include?(id.length) && id[%r{^[0-9a-f]+$}i] + raise "invalid ':key_id' value: '#{id.inspect}'" unless is_valid - is_valid - end + is_valid + end - def to_yaml - # bug, :key_url value is not represented as an instance of Hbc::UnderscoreSupportingURI - [@signature, @parameters].to_yaml - end + def to_yaml + # bug, :key_url value is not represented as an instance of Hbc::UnderscoreSupportingURI + [@signature, @parameters].to_yaml + end - def to_s - @signature.to_s + def to_s + @signature.to_s + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/installer.rb b/Library/Homebrew/cask/lib/hbc/dsl/installer.rb index 74b4b3a91..92561c703 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/installer.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/installer.rb @@ -1,28 +1,32 @@ -class Hbc::DSL::Installer - VALID_KEYS = Set.new [ - :manual, - :script, - ] +module Hbc + class DSL + class Installer + VALID_KEYS = Set.new [ + :manual, + :script, + ] - attr_accessor(*VALID_KEYS) + attr_accessor(*VALID_KEYS) - def initialize(*parameters) - raise Hbc::CaskInvalidError.new(token, "'installer' stanza requires an argument") if parameters.empty? - parameters = {}.merge(*parameters) - if parameters.key?(:script) && !parameters[:script].respond_to?(:key?) - if parameters.key?(:executable) - raise Hbc::CaskInvalidError.new(token, "'installer' stanza gave arguments for both :script and :executable") + def initialize(*parameters) + raise CaskInvalidError.new(token, "'installer' stanza requires an argument") if parameters.empty? + parameters = {}.merge(*parameters) + if parameters.key?(:script) && !parameters[:script].respond_to?(:key?) + if parameters.key?(:executable) + raise CaskInvalidError.new(token, "'installer' stanza gave arguments for both :script and :executable") + end + parameters[:executable] = parameters[:script] + parameters.delete(:script) + parameters = { script: parameters } + end + unless parameters.keys.length == 1 + raise "invalid 'installer' stanza: only one of #{VALID_KEYS.inspect} is permitted" + end + key = parameters.keys.first + raise "invalid 'installer' stanza key: '#{key.inspect}'" unless VALID_KEYS.include?(key) + writer_method = "#{key}=".to_sym + send(writer_method, parameters[key]) end - parameters[:executable] = parameters[:script] - parameters.delete(:script) - parameters = { script: parameters } end - unless parameters.keys.length == 1 - raise "invalid 'installer' stanza: only one of #{VALID_KEYS.inspect} is permitted" - end - key = parameters.keys.first - raise "invalid 'installer' stanza key: '#{key.inspect}'" unless VALID_KEYS.include?(key) - writer_method = "#{key}=".to_sym - send(writer_method, parameters[key]) end end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/license.rb b/Library/Homebrew/cask/lib/hbc/dsl/license.rb index 5f607c268..affbc08f5 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/license.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/license.rb @@ -1,66 +1,70 @@ -class Hbc::DSL::License - # a generic category can always be given as a license, so - # category names should be given as both key and value - VALID_LICENSES = { - # license category - unknown: :unknown, +module Hbc + class DSL + class License + # a generic category can always be given as a license, so + # category names should be given as both key and value + VALID_LICENSES = { + # license category + unknown: :unknown, - other: :other, + other: :other, - closed: :closed, - commercial: :closed, - gratis: :closed, - freemium: :closed, + closed: :closed, + commercial: :closed, + gratis: :closed, + freemium: :closed, - oss: :oss, - affero: :oss, - apache: :oss, - arphic: :oss, - artistic: :oss, - bsd: :oss, - cc: :oss, - eclipse: :oss, - gpl: :oss, - isc: :oss, - lppl: :oss, - ncsa: :oss, - mit: :oss, - mpl: :oss, - ofl: :oss, - public_domain: :oss, - ubuntu_font: :oss, - x11: :oss, - }.freeze + oss: :oss, + affero: :oss, + apache: :oss, + arphic: :oss, + artistic: :oss, + bsd: :oss, + cc: :oss, + eclipse: :oss, + gpl: :oss, + isc: :oss, + lppl: :oss, + ncsa: :oss, + mit: :oss, + mpl: :oss, + ofl: :oss, + public_domain: :oss, + ubuntu_font: :oss, + x11: :oss, + }.freeze - DEFAULT_LICENSE = :unknown - DEFAULT_CATEGORY = VALID_LICENSES[DEFAULT_LICENSE] + DEFAULT_LICENSE = :unknown + DEFAULT_CATEGORY = VALID_LICENSES[DEFAULT_LICENSE] - attr_reader :value + attr_reader :value - def self.check_constants - categories = Set.new(VALID_LICENSES.values) - categories.each do |cat| - next if VALID_LICENSES.key?(cat) - raise "license category is not a value: '#{@cat.inspect}'" - end - end + def self.check_constants + categories = Set.new(VALID_LICENSES.values) + categories.each do |cat| + next if VALID_LICENSES.key?(cat) + raise "license category is not a value: '#{@cat.inspect}'" + end + end - def self.category(license) - VALID_LICENSES.fetch(license, DEFAULT_CATEGORY) - end + def self.category(license) + VALID_LICENSES.fetch(license, DEFAULT_CATEGORY) + end - def initialize(arg) - @value = arg - @value = DEFAULT_LICENSE if @value.nil? - return if VALID_LICENSES.key?(@value) - raise "invalid license value: '#{@value.inspect}'" - end + def initialize(arg) + @value = arg + @value = DEFAULT_LICENSE if @value.nil? + return if VALID_LICENSES.key?(@value) + raise "invalid license value: '#{@value.inspect}'" + end - def category - self.class.category(@value) - end + def category + self.class.category(@value) + end - def to_s - @value.inspect + def to_s + @value.inspect + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/postflight.rb b/Library/Homebrew/cask/lib/hbc/dsl/postflight.rb index 321c7e81a..1026f6de6 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/postflight.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/postflight.rb @@ -1,9 +1,13 @@ require "hbc/staged" -class Hbc::DSL::Postflight < Hbc::DSL::Base - include Hbc::Staged +module Hbc + class DSL + class Postflight < Base + include Staged - def suppress_move_to_applications(options = {}) - # TODO: Remove from all casks because it is no longer needed + def suppress_move_to_applications(options = {}) + # TODO: Remove from all casks because it is no longer needed + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/preflight.rb b/Library/Homebrew/cask/lib/hbc/dsl/preflight.rb index a0d53c69c..55a778706 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/preflight.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/preflight.rb @@ -1,3 +1,7 @@ -class Hbc::DSL::Preflight < Hbc::DSL::Base - include Hbc::Staged +module Hbc + class DSL + class Preflight < Base + include Staged + end + end end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/stanza_proxy.rb b/Library/Homebrew/cask/lib/hbc/dsl/stanza_proxy.rb index 02c76fb27..b1a850c5a 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/stanza_proxy.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/stanza_proxy.rb @@ -1,37 +1,49 @@ -class Hbc::DSL::StanzaProxy - attr_reader :type +module Hbc + class DSL + class StanzaProxy + attr_reader :type - def self.once(type) - resolved = nil - new(type) { resolved ||= yield } - end + def self.once(type) + resolved = nil + new(type) { resolved ||= yield } + end - def initialize(type, &resolver) - @type = type - @resolver = resolver - end + def initialize(type, &resolver) + @type = type + @resolver = resolver + end - def proxy? - true - end + def proxy? + true + end - def to_s - @resolver.call.to_s - end + def to_s + @resolver.call.to_s + end - # Serialization for dumpcask - def encode_with(coder) - coder["type"] = type - coder["resolved"] = @resolver.call - end + # Serialization for dumpcask + def encode_with(coder) + coder["type"] = type + coder["resolved"] = @resolver.call + end - def respond_to?(symbol, include_private = false) - return true if %i{encode_with proxy? to_s type}.include?(symbol) - return false if symbol == :to_ary - @resolver.call.respond_to?(symbol, include_private) - end + def method_missing(method, *args) + if method != :to_ary + @resolver.call.send(method, *args) + else + super + end + end + + def respond_to?(method, include_private = false) + return true if %i{encode_with proxy? to_s type}.include?(method) + return false if method == :to_ary + @resolver.call.respond_to?(method, include_private) + end - def method_missing(symbol, *args) - @resolver.call.send(symbol, *args) + def respond_to_missing?(*) + true + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/uninstall_postflight.rb b/Library/Homebrew/cask/lib/hbc/dsl/uninstall_postflight.rb index bd8777ca7..f481cc357 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/uninstall_postflight.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/uninstall_postflight.rb @@ -1,2 +1,6 @@ -class Hbc::DSL::UninstallPostflight < Hbc::DSL::Base +module Hbc + class DSL + class UninstallPostflight < Base + end + end end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/uninstall_preflight.rb b/Library/Homebrew/cask/lib/hbc/dsl/uninstall_preflight.rb index 994151c25..36cdec12f 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/uninstall_preflight.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/uninstall_preflight.rb @@ -1,5 +1,9 @@ require "hbc/staged" -class Hbc::DSL::UninstallPreflight < Hbc::DSL::Base - include Hbc::Staged +module Hbc + class DSL + class UninstallPreflight < Base + include Staged + end + end end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/version.rb b/Library/Homebrew/cask/lib/hbc/dsl/version.rb index e01e67ea2..d4697460a 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/version.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/version.rb @@ -1,111 +1,115 @@ -class Hbc::DSL::Version < ::String - DIVIDERS = { - "." => :dots, - "-" => :hyphens, - "_" => :underscores, - "/" => :slashes, - }.freeze - - DIVIDER_REGEX = %r{(#{DIVIDERS.keys.map { |v| Regexp.quote(v) }.join('|')})} - - MAJOR_MINOR_PATCH_REGEX = %r{^(\d+)(?:\.(\d+)(?:\.(\d+))?)?} - - class << self - private - - def define_divider_methods(divider) - define_divider_deletion_method(divider) - define_divider_conversion_methods(divider) - end +module Hbc + class DSL + class Version < ::String + DIVIDERS = { + "." => :dots, + "-" => :hyphens, + "_" => :underscores, + "/" => :slashes, + }.freeze + + DIVIDER_REGEX = %r{(#{DIVIDERS.keys.map { |v| Regexp.quote(v) }.join('|')})} + + MAJOR_MINOR_PATCH_REGEX = %r{^(\d+)(?:\.(\d+)(?:\.(\d+))?)?} + + class << self + private + + def define_divider_methods(divider) + define_divider_deletion_method(divider) + define_divider_conversion_methods(divider) + end + + def define_divider_deletion_method(divider) + method_name = deletion_method_name(divider) + define_method(method_name) do + version { delete(divider) } + end + end + + def deletion_method_name(divider) + "no_#{DIVIDERS[divider]}" + end + + def define_divider_conversion_methods(left_divider) + (DIVIDERS.keys - [left_divider]).each do |right_divider| + define_divider_conversion_method(left_divider, right_divider) + end + end + + def define_divider_conversion_method(left_divider, right_divider) + method_name = conversion_method_name(left_divider, right_divider) + define_method(method_name) do + version { gsub(left_divider, right_divider) } + end + end + + def conversion_method_name(left_divider, right_divider) + "#{DIVIDERS[left_divider]}_to_#{DIVIDERS[right_divider]}" + end + end - def define_divider_deletion_method(divider) - method_name = deletion_method_name(divider) - define_method(method_name) do - version { delete(divider) } + DIVIDERS.keys.each do |divider| + define_divider_methods(divider) end - end - def deletion_method_name(divider) - "no_#{DIVIDERS[divider]}" - end + attr_reader :raw_version - def define_divider_conversion_methods(left_divider) - (DIVIDERS.keys - [left_divider]).each do |right_divider| - define_divider_conversion_method(left_divider, right_divider) + def initialize(raw_version) + @raw_version = raw_version + super(raw_version.to_s) end - end - def define_divider_conversion_method(left_divider, right_divider) - method_name = conversion_method_name(left_divider, right_divider) - define_method(method_name) do - version { gsub(left_divider, right_divider) } + def latest? + to_s == "latest" end - end - def conversion_method_name(left_divider, right_divider) - "#{DIVIDERS[left_divider]}_to_#{DIVIDERS[right_divider]}" - end - end - - DIVIDERS.keys.each do |divider| - define_divider_methods(divider) - end - - attr_reader :raw_version - - def initialize(raw_version) - @raw_version = raw_version - super(raw_version.to_s) - end - - def latest? - to_s == "latest" - end - - def major - version { slice(MAJOR_MINOR_PATCH_REGEX, 1) } - end + def major + version { slice(MAJOR_MINOR_PATCH_REGEX, 1) } + end - def minor - version { slice(MAJOR_MINOR_PATCH_REGEX, 2) } - end + def minor + version { slice(MAJOR_MINOR_PATCH_REGEX, 2) } + end - def patch - version { slice(MAJOR_MINOR_PATCH_REGEX, 3) } - end + def patch + version { slice(MAJOR_MINOR_PATCH_REGEX, 3) } + end - def major_minor - version { [major, minor].reject(&:empty?).join(".") } - end + def major_minor + version { [major, minor].reject(&:empty?).join(".") } + end - def major_minor_patch - version { [major, minor, patch].reject(&:empty?).join(".") } - end + def major_minor_patch + version { [major, minor, patch].reject(&:empty?).join(".") } + end - def before_comma - version { split(",", 2)[0] } - end + def before_comma + version { split(",", 2)[0] } + end - def after_comma - version { split(",", 2)[1] } - end + def after_comma + version { split(",", 2)[1] } + end - def before_colon - version { split(":", 2)[0] } - end + def before_colon + version { split(":", 2)[0] } + end - def after_colon - version { split(":", 2)[1] } - end + def after_colon + version { split(":", 2)[1] } + end - def no_dividers - version { gsub(DIVIDER_REGEX, "") } - end + def no_dividers + version { gsub(DIVIDER_REGEX, "") } + end - private + private - def version - return self if empty? || latest? - self.class.new(yield) + def version + return self if empty? || latest? + self.class.new(yield) + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/exceptions.rb b/Library/Homebrew/cask/lib/hbc/exceptions.rb index 8813aaedf..f77106d92 100644 --- a/Library/Homebrew/cask/lib/hbc/exceptions.rb +++ b/Library/Homebrew/cask/lib/hbc/exceptions.rb @@ -1,146 +1,148 @@ -class Hbc::CaskError < RuntimeError; end +module Hbc + class CaskError < RuntimeError; end -class Hbc::AbstractCaskErrorWithToken < Hbc::CaskError - attr_reader :token + class AbstractCaskErrorWithToken < CaskError + attr_reader :token - def initialize(token) - @token = token + def initialize(token) + @token = token + end end -end -class Hbc::CaskNotInstalledError < Hbc::AbstractCaskErrorWithToken - def to_s - "#{token} is not installed" + class CaskNotInstalledError < AbstractCaskErrorWithToken + def to_s + "#{token} is not installed" + end end -end -class Hbc::CaskUnavailableError < Hbc::AbstractCaskErrorWithToken - def to_s - "No available Cask for #{token}" + class CaskUnavailableError < AbstractCaskErrorWithToken + def to_s + "No available Cask for #{token}" + end end -end -class Hbc::CaskAlreadyCreatedError < Hbc::AbstractCaskErrorWithToken - def to_s - %Q{A Cask for #{token} already exists. Run "brew cask cat #{token}" to see it.} + class CaskAlreadyCreatedError < AbstractCaskErrorWithToken + def to_s + %Q{A Cask for #{token} already exists. Run "brew cask cat #{token}" to see it.} + end end -end -class Hbc::CaskAlreadyInstalledError < Hbc::AbstractCaskErrorWithToken - def to_s - %Q{A Cask for #{token} is already installed. Add the "--force" option to force re-install.} + class CaskAlreadyInstalledError < AbstractCaskErrorWithToken + def to_s + %Q{A Cask for #{token} is already installed. Add the "--force" option to force re-install.} + end end -end -class Hbc::CaskAutoUpdatesError < Hbc::AbstractCaskErrorWithToken - def to_s - %Q{A Cask for #{token} is already installed and using auto-updates. Add the "--force" option to force re-install.} + class CaskAutoUpdatesError < AbstractCaskErrorWithToken + def to_s + %Q{A Cask for #{token} is already installed and using auto-updates. Add the "--force" option to force re-install.} + end end -end -class Hbc::CaskCommandFailedError < Hbc::CaskError - def initialize(cmd, stdout, stderr, status) - @cmd = cmd - @stdout = stdout - @stderr = stderr - @status = status - end + class CaskCommandFailedError < CaskError + def initialize(cmd, stdout, stderr, status) + @cmd = cmd + @stdout = stdout + @stderr = stderr + @status = status + end - def to_s - <<-EOS -Command failed to execute! + def to_s + <<-EOS + Command failed to execute! -==> Failed command: -#{@cmd} + ==> Failed command: + #{@cmd} -==> Standard Output of failed command: -#{@stdout} + ==> Standard Output of failed command: + #{@stdout} -==> Standard Error of failed command: -#{@stderr} + ==> Standard Error of failed command: + #{@stderr} -==> Exit status of failed command: -#{@status.inspect} - EOS + ==> Exit status of failed command: + #{@status.inspect} + EOS + end end -end -class Hbc::CaskX11DependencyError < Hbc::AbstractCaskErrorWithToken - def to_s - <<-EOS.undent - #{token} requires XQuartz/X11, which can be installed via homebrew-cask by + class CaskX11DependencyError < AbstractCaskErrorWithToken + def to_s + <<-EOS.undent + #{token} requires XQuartz/X11, which can be installed via homebrew-cask by - brew cask install xquartz + brew cask install xquartz - or manually, by downloading the package from + or manually, by downloading the package from - https://www.xquartz.org/ - EOS + https://www.xquartz.org/ + EOS + end end -end -class Hbc::CaskCyclicCaskDependencyError < Hbc::AbstractCaskErrorWithToken - def to_s - "Cask '#{token}' includes cyclic dependencies on other Casks and could not be installed." + class CaskCyclicCaskDependencyError < AbstractCaskErrorWithToken + def to_s + "Cask '#{token}' includes cyclic dependencies on other Casks and could not be installed." + end end -end -class Hbc::CaskUnspecifiedError < Hbc::CaskError - def to_s - "This command requires a Cask token" + class CaskUnspecifiedError < CaskError + def to_s + "This command requires a Cask token" + end end -end -class Hbc::CaskInvalidError < Hbc::AbstractCaskErrorWithToken - attr_reader :submsg - def initialize(token, *submsg) - super(token) - @submsg = submsg.join(" ") - end + class CaskInvalidError < AbstractCaskErrorWithToken + attr_reader :submsg + def initialize(token, *submsg) + super(token) + @submsg = submsg.join(" ") + end - def to_s - "Cask '#{token}' definition is invalid" + (!submsg.empty? ? ": #{submsg}" : "") + def to_s + "Cask '#{token}' definition is invalid" + (!submsg.empty? ? ": #{submsg}" : "") + end end -end -class Hbc::CaskTokenDoesNotMatchError < Hbc::CaskInvalidError - def initialize(token, header_token) - super(token, "Bad header line: '#{header_token}' does not match file name") + class CaskTokenDoesNotMatchError < CaskInvalidError + def initialize(token, header_token) + super(token, "Bad header line: '#{header_token}' does not match file name") + end end -end -class Hbc::CaskSha256MissingError < ArgumentError -end - -class Hbc::CaskSha256MismatchError < RuntimeError - attr_reader :path, :expected, :actual - def initialize(path, expected, actual) - @path = path - @expected = expected - @actual = actual + class CaskSha256MissingError < ArgumentError end - def to_s - <<-EOS.undent - sha256 mismatch - Expected: #{expected} - Actual: #{actual} - File: #{path} - To retry an incomplete download, remove the file above. - EOS - end -end + class CaskSha256MismatchError < RuntimeError + attr_reader :path, :expected, :actual + def initialize(path, expected, actual) + @path = path + @expected = expected + @actual = actual + end -class Hbc::CaskNoShasumError < Hbc::CaskError - attr_reader :token - def initialize(token) - @token = token + def to_s + <<-EOS.undent + sha256 mismatch + Expected: #{expected} + Actual: #{actual} + File: #{path} + To retry an incomplete download, remove the file above. + EOS + end end - def to_s - <<-EOS.undent - Cask '#{token}' does not have a sha256 checksum defined and was not installed. - This means you have the "--require-sha" option set, perhaps in your HOMEBREW_CASK_OPTS. - EOS + class CaskNoShasumError < CaskError + attr_reader :token + def initialize(token) + @token = token + end + + def to_s + <<-EOS.undent + Cask '#{token}' does not have a sha256 checksum defined and was not installed. + This means you have the "--require-sha" option set, perhaps in your HOMEBREW_CASK_OPTS. + EOS + end end end diff --git a/Library/Homebrew/cask/lib/hbc/extend/hash.rb b/Library/Homebrew/cask/lib/hbc/extend/hash.rb index dc28cfb29..3a06ba3af 100644 --- a/Library/Homebrew/cask/lib/hbc/extend/hash.rb +++ b/Library/Homebrew/cask/lib/hbc/extend/hash.rb @@ -2,6 +2,6 @@ class Hash def assert_valid_keys(*valid_keys) unknown_keys = keys - valid_keys return if unknown_keys.empty? - raise Hbc::CaskError, %Q{Unknown keys: #{unknown_keys.inspect}. Running "#{UPDATE_CMD}" will likely fix it.} + raise CaskError, %Q{Unknown keys: #{unknown_keys.inspect}. Running "#{UPDATE_CMD}" will likely fix it.} end end diff --git a/Library/Homebrew/cask/lib/hbc/fetcher.rb b/Library/Homebrew/cask/lib/hbc/fetcher.rb index 44a898ce0..6f58ca023 100644 --- a/Library/Homebrew/cask/lib/hbc/fetcher.rb +++ b/Library/Homebrew/cask/lib/hbc/fetcher.rb @@ -1,22 +1,24 @@ require "open3" -class Hbc::Fetcher - TIMEOUT = 10 +module Hbc + class Fetcher + TIMEOUT = 10 - def self.head(url) - if url.to_s =~ %r{googlecode} - googlecode_fake_head(url) - else - Hbc::SystemCommand.run("/usr/bin/curl", - args: ["--max-time", TIMEOUT, "--silent", "--location", "--head", url]).stdout + def self.head(url) + if url.to_s =~ %r{googlecode} + googlecode_fake_head(url) + else + SystemCommand.run("/usr/bin/curl", + args: ["--max-time", TIMEOUT, "--silent", "--location", "--head", url]).stdout + end end - end - # google code does not properly respond to HTTP HEAD requests, like a jerk - # this fakes a HEAD by doing a GET, taking the first 20 lines, then running away - def self.googlecode_fake_head(url) - command = "curl --max-time #{TIMEOUT} --verbose --location '#{url}' | head -n 20 > /dev/null" - stderr = Open3.capture3(command)[1] - stderr.split("\n").grep(%r{^< }).map { |line| line.sub(%r{^< }, "") }.join("\n") + # google code does not properly respond to HTTP HEAD requests, like a jerk + # this fakes a HEAD by doing a GET, taking the first 20 lines, then running away + def self.googlecode_fake_head(url) + command = "curl --max-time #{TIMEOUT} --verbose --location '#{url}' | head -n 20 > /dev/null" + stderr = Open3.capture3(command)[1] + stderr.split("\n").grep(%r{^< }).map { |line| line.sub(%r{^< }, "") }.join("\n") + end end end diff --git a/Library/Homebrew/cask/lib/hbc/installer.rb b/Library/Homebrew/cask/lib/hbc/installer.rb index 72a9b3077..f0cc0d1a9 100644 --- a/Library/Homebrew/cask/lib/hbc/installer.rb +++ b/Library/Homebrew/cask/lib/hbc/installer.rb @@ -4,142 +4,144 @@ require "hbc/cask_dependencies" require "hbc/staged" require "hbc/verify" -class Hbc::Installer - # TODO: it is unwise for Hbc::Staged to be a module, when we are - # dealing with both staged and unstaged Casks here. This should - # either be a class which is only sometimes instantiated, or there - # should be explicit checks on whether staged state is valid in - # every method. - include Hbc::Staged - include Hbc::Verify - - attr_reader :force, :skip_cask_deps - - PERSISTENT_METADATA_SUBDIRS = ["gpg"].freeze - - def initialize(cask, command: Hbc::SystemCommand, force: false, skip_cask_deps: false, require_sha: false) - @cask = cask - @command = command - @force = force - @skip_cask_deps = skip_cask_deps - @require_sha = require_sha - end +module Hbc + class Installer + # TODO: it is unwise for Hbc::Staged to be a module, when we are + # dealing with both staged and unstaged Casks here. This should + # either be a class which is only sometimes instantiated, or there + # should be explicit checks on whether staged state is valid in + # every method. + include Staged + include Verify + + attr_reader :force, :skip_cask_deps + + PERSISTENT_METADATA_SUBDIRS = ["gpg"].freeze + + def initialize(cask, command: SystemCommand, force: false, skip_cask_deps: false, require_sha: false) + @cask = cask + @command = command + @force = force + @skip_cask_deps = skip_cask_deps + @require_sha = require_sha + end - def self.print_caveats(cask) - odebug "Printing caveats" - unless cask.caveats.empty? - output = capture_output do - cask.caveats.each do |caveat| - if caveat.respond_to?(:eval_and_print) - caveat.eval_and_print(cask) - else - puts caveat + def self.print_caveats(cask) + odebug "Printing caveats" + unless cask.caveats.empty? + output = capture_output do + cask.caveats.each do |caveat| + if caveat.respond_to?(:eval_and_print) + caveat.eval_and_print(cask) + else + puts caveat + end end end - end - unless output.empty? - ohai "Caveats" - puts output + unless output.empty? + ohai "Caveats" + puts output + end end end - end - - def self.capture_output(&block) - old_stdout = $stdout - $stdout = Buffer.new($stdout.tty?) - block.call - output = $stdout.string - $stdout = old_stdout - output - end - def install - odebug "Hbc::Installer.install" - - if @cask.installed? && @cask.auto_updates && !force - raise Hbc::CaskAutoUpdatesError, @cask + def self.capture_output(&block) + old_stdout = $stdout + $stdout = Buffer.new($stdout.tty?) + block.call + output = $stdout.string + $stdout = old_stdout + output end - raise Hbc::CaskAlreadyInstalledError, @cask if @cask.installed? && !force + def install + odebug "Hbc::Installer.install" + + if @cask.installed? && @cask.auto_updates && !force + raise CaskAutoUpdatesError, @cask + end - print_caveats + raise CaskAlreadyInstalledError, @cask if @cask.installed? && !force + + print_caveats + + begin + satisfy_dependencies + verify_has_sha if @require_sha && !@force + download + verify + extract_primary_container + install_artifacts + save_caskfile + enable_accessibility_access + rescue StandardError => e + purge_versioned_files + raise e + end - begin - satisfy_dependencies - verify_has_sha if @require_sha && !@force - download - verify - extract_primary_container - install_artifacts - save_caskfile - enable_accessibility_access - rescue StandardError => e - purge_versioned_files - raise e + puts summary end - puts summary - end - - def summary - s = if MacOS.version >= :lion && !ENV["HOMEBREW_NO_EMOJI"] - (ENV["HOMEBREW_INSTALL_BADGE"] || "\xf0\x9f\x8d\xba") + " " - else - "#{Tty.blue}==>#{Tty.reset} #{Tty.white}Success!#{Tty.reset} " - end - s << "#{@cask} was successfully installed!" - end + def summary + s = if MacOS.version >= :lion && !ENV["HOMEBREW_NO_EMOJI"] + (ENV["HOMEBREW_INSTALL_BADGE"] || "\xf0\x9f\x8d\xba") + " " + else + "#{Tty.blue}==>#{Tty.reset} #{Tty.white}Success!#{Tty.reset} " + end + s << "#{@cask} was successfully installed!" + end - def download - odebug "Downloading" - download = Hbc::Download.new(@cask, force: false) - @downloaded_path = download.perform - odebug "Downloaded to -> #{@downloaded_path}" - @downloaded_path - end + def download + odebug "Downloading" + download = Download.new(@cask, force: false) + @downloaded_path = download.perform + odebug "Downloaded to -> #{@downloaded_path}" + @downloaded_path + end - def verify_has_sha - odebug "Checking cask has checksum" - return unless @cask.sha256 == :no_check - raise Hbc::CaskNoShasumError, @cask - end + def verify_has_sha + odebug "Checking cask has checksum" + return unless @cask.sha256 == :no_check + raise CaskNoShasumError, @cask + end - def verify - Hbc::Verify.all(@cask, @downloaded_path) - end + def verify + Verify.all(@cask, @downloaded_path) + end - def extract_primary_container - odebug "Extracting primary container" - FileUtils.mkdir_p @cask.staged_path - container = if @cask.container && @cask.container.type - Hbc::Container.from_type(@cask.container.type) - else - Hbc::Container.for_path(@downloaded_path, @command) - end - unless container - raise Hbc::CaskError, "Uh oh, could not figure out how to unpack '#{@downloaded_path}'" + def extract_primary_container + odebug "Extracting primary container" + FileUtils.mkdir_p @cask.staged_path + container = if @cask.container && @cask.container.type + Container.from_type(@cask.container.type) + else + Container.for_path(@downloaded_path, @command) + end + unless container + raise CaskError, "Uh oh, could not figure out how to unpack '#{@downloaded_path}'" + end + odebug "Using container class #{container} for #{@downloaded_path}" + container.new(@cask, @downloaded_path, @command).extract end - odebug "Using container class #{container} for #{@downloaded_path}" - container.new(@cask, @downloaded_path, @command).extract - end - def install_artifacts - odebug "Installing artifacts" - artifacts = Hbc::Artifact.for_cask(@cask) - odebug "#{artifacts.length} artifact/s defined", artifacts - artifacts.each do |artifact| - odebug "Installing artifact of class #{artifact}" - options = { command: @command, force: force } - artifact.new(@cask, options).install_phase + def install_artifacts + odebug "Installing artifacts" + artifacts = Artifact.for_cask(@cask) + odebug "#{artifacts.length} artifact/s defined", artifacts + artifacts.each do |artifact| + odebug "Installing artifact of class #{artifact}" + options = { command: @command, force: force } + artifact.new(@cask, options).install_phase + end end - end - # TODO: move dependencies to a separate class - # dependencies should also apply for "brew cask stage" - # override dependencies with --force or perhaps --force-deps - def satisfy_dependencies - if @cask.depends_on + # TODO: move dependencies to a separate class + # dependencies should also apply for "brew cask stage" + # override dependencies with --force or perhaps --force-deps + def satisfy_dependencies + return unless @cask.depends_on + ohai "Satisfying dependencies" macos_dependencies arch_dependencies @@ -148,195 +150,200 @@ class Hbc::Installer cask_dependencies unless skip_cask_deps puts "complete" end - end - def macos_dependencies - return unless @cask.depends_on.macos - if @cask.depends_on.macos.first.is_a?(Array) - operator, release = @cask.depends_on.macos.first - unless MacOS.version.send(operator, release) - raise Hbc::CaskError, "Cask #{@cask} depends on macOS release #{operator} #{release}, but you are running release #{MacOS.version}." - end - elsif @cask.depends_on.macos.length > 1 - unless @cask.depends_on.macos.include?(Gem::Version.new(MacOS.version.to_s)) - raise Hbc::CaskError, "Cask #{@cask} depends on macOS release being one of [#{@cask.depends_on.macos.map(&:to_s).join(', ')}], but you are running release #{MacOS.version}." - end - else - unless MacOS.version == @cask.depends_on.macos.first - raise Hbc::CaskError, "Cask #{@cask} depends on macOS release #{@cask.depends_on.macos.first}, but you are running release #{MacOS.version}." + def macos_dependencies + return unless @cask.depends_on.macos + if @cask.depends_on.macos.first.is_a?(Array) + operator, release = @cask.depends_on.macos.first + unless MacOS.version.send(operator, release) + raise CaskError, "Cask #{@cask} depends on macOS release #{operator} #{release}, but you are running release #{MacOS.version}." + end + elsif @cask.depends_on.macos.length > 1 + unless @cask.depends_on.macos.include?(Gem::Version.new(MacOS.version.to_s)) + raise CaskError, "Cask #{@cask} depends on macOS release being one of [#{@cask.depends_on.macos.map(&:to_s).join(", ")}], but you are running release #{MacOS.version}." + end + else + unless MacOS.version == @cask.depends_on.macos.first + raise CaskError, "Cask #{@cask} depends on macOS release #{@cask.depends_on.macos.first}, but you are running release #{MacOS.version}." + end end end - end - def arch_dependencies - return if @cask.depends_on.arch.nil? - @current_arch ||= { type: Hardware::CPU.type, bits: Hardware::CPU.bits } - return if @cask.depends_on.arch.any? { |arch| - arch[:type] == @current_arch[:type] && - Array(arch[:bits]).include?(@current_arch[:bits]) - } - raise Hbc::CaskError, "Cask #{@cask} depends on hardware architecture being one of [#{@cask.depends_on.arch.map(&:to_s).join(', ')}], but you are running #{@current_arch}" - end + def arch_dependencies + return if @cask.depends_on.arch.nil? + @current_arch ||= { type: Hardware::CPU.type, bits: Hardware::CPU.bits } + return if @cask.depends_on.arch.any? { |arch| + arch[:type] == @current_arch[:type] && + Array(arch[:bits]).include?(@current_arch[:bits]) + } + raise CaskError, "Cask #{@cask} depends on hardware architecture being one of [#{@cask.depends_on.arch.map(&:to_s).join(", ")}], but you are running #{@current_arch}" + end - def x11_dependencies - return unless @cask.depends_on.x11 - raise Hbc::CaskX11DependencyError, @cask.token if Hbc.x11_libpng.select(&:exist?).empty? - end + def x11_dependencies + return unless @cask.depends_on.x11 + raise CaskX11DependencyError, @cask.token if Hbc.x11_libpng.select(&:exist?).empty? + end - def formula_dependencies - return unless @cask.depends_on.formula && !@cask.depends_on.formula.empty? - ohai "Installing Formula dependencies from Homebrew" - @cask.depends_on.formula.each do |dep_name| - print "#{dep_name} ... " - installed = @command.run(Hbc.homebrew_executable, - args: ["list", "--versions", dep_name], - print_stderr: false).stdout.include?(dep_name) - if installed - puts "already installed" - else - @command.run!(Hbc.homebrew_executable, - args: ["install", dep_name]) - puts "done" + def formula_dependencies + return unless @cask.depends_on.formula && !@cask.depends_on.formula.empty? + ohai "Installing Formula dependencies from Homebrew" + @cask.depends_on.formula.each do |dep_name| + print "#{dep_name} ... " + installed = @command.run(Hbc.homebrew_executable, + args: ["list", "--versions", dep_name], + print_stderr: false).stdout.include?(dep_name) + if installed + puts "already installed" + else + @command.run!(Hbc.homebrew_executable, + args: ["install", dep_name]) + puts "done" + end end end - end - def cask_dependencies - return unless @cask.depends_on.cask && !@cask.depends_on.cask.empty? - ohai "Installing Cask dependencies: #{@cask.depends_on.cask.join(', ')}" - deps = Hbc::CaskDependencies.new(@cask) - deps.sorted.each do |dep_token| - puts "#{dep_token} ..." - dep = Hbc.load(dep_token) - if dep.installed? - puts "already installed" - else - Hbc::Installer.new(dep, force: false, skip_cask_deps: true).install - puts "done" + def cask_dependencies + return unless @cask.depends_on.cask && !@cask.depends_on.cask.empty? + ohai "Installing Cask dependencies: #{@cask.depends_on.cask.join(", ")}" + deps = CaskDependencies.new(@cask) + deps.sorted.each do |dep_token| + puts "#{dep_token} ..." + dep = Hbc.load(dep_token) + if dep.installed? + puts "already installed" + else + Installer.new(dep, force: false, skip_cask_deps: true).install + puts "done" + end end end - end - def print_caveats - self.class.print_caveats(@cask) - end + def print_caveats + self.class.print_caveats(@cask) + end - # TODO: logically could be in a separate class - def enable_accessibility_access - return unless @cask.accessibility_access - ohai "Enabling accessibility access" - if MacOS.version <= :mountain_lion - @command.run!("/usr/bin/touch", - args: [Hbc.pre_mavericks_accessibility_dotfile], - sudo: true) - elsif MacOS.version <= :yosemite - @command.run!("/usr/bin/sqlite3", - args: [ - Hbc.tcc_db, - "INSERT OR REPLACE INTO access VALUES('kTCCServiceAccessibility','#{bundle_identifier}',0,1,1,NULL);", - ], - sudo: true) - else - @command.run!("/usr/bin/sqlite3", - args: [ - Hbc.tcc_db, - "INSERT OR REPLACE INTO access VALUES('kTCCServiceAccessibility','#{bundle_identifier}',0,1,1,NULL,NULL);", - ], - sudo: true) + # TODO: logically could be in a separate class + def enable_accessibility_access + return unless @cask.accessibility_access + ohai "Enabling accessibility access" + if MacOS.version <= :mountain_lion + @command.run!("/usr/bin/touch", + args: [Hbc.pre_mavericks_accessibility_dotfile], + sudo: true) + elsif MacOS.version <= :yosemite + @command.run!("/usr/bin/sqlite3", + args: [ + Hbc.tcc_db, + "INSERT OR REPLACE INTO access VALUES('kTCCServiceAccessibility','#{bundle_identifier}',0,1,1,NULL);", + ], + sudo: true) + elsif MacOS.version <= :el_capitan + @command.run!("/usr/bin/sqlite3", + args: [ + Hbc.tcc_db, + "INSERT OR REPLACE INTO access VALUES('kTCCServiceAccessibility','#{bundle_identifier}',0,1,1,NULL,NULL);", + ], + sudo: true) + else + opoo <<-EOS.undent + Accessibility access cannot be enabled automatically on this version of macOS. + See System Preferences to enable it manually. + EOS + end end - end - def disable_accessibility_access - return unless @cask.accessibility_access - if MacOS.version >= :mavericks - ohai "Disabling accessibility access" - @command.run!("/usr/bin/sqlite3", - args: [ - Hbc.tcc_db, - "DELETE FROM access WHERE client='#{bundle_identifier}';", - ], - sudo: true) - else - opoo <<-EOS.undent - Accessibility access was enabled for #{@cask}, but it is not safe to disable - automatically on this version of macOS. See System Preferences. - EOS + def disable_accessibility_access + return unless @cask.accessibility_access + if MacOS.version >= :mavericks && MacOS.version <= :el_capitan + ohai "Disabling accessibility access" + @command.run!("/usr/bin/sqlite3", + args: [ + Hbc.tcc_db, + "DELETE FROM access WHERE client='#{bundle_identifier}';", + ], + sudo: true) + else + opoo <<-EOS.undent + Accessibility access cannot be disabled automatically on this version of macOS. + See System Preferences to disable it manually. + EOS + end end - end - def save_caskfile - timestamp = :now - create = true - savedir = @cask.metadata_subdir("Casks", timestamp, create) - if Dir.entries(savedir).size > 2 - # should not happen - raise Hbc::CaskAlreadyInstalledError, @cask unless force - savedir.rmtree - FileUtils.mkdir_p savedir + def save_caskfile + timestamp = :now + create = true + savedir = @cask.metadata_subdir("Casks", timestamp, create) + if Dir.entries(savedir).size > 2 + # should not happen + raise CaskAlreadyInstalledError, @cask unless force + savedir.rmtree + FileUtils.mkdir_p savedir + end + FileUtils.copy(@cask.sourcefile_path, savedir) if @cask.sourcefile_path end - FileUtils.copy(@cask.sourcefile_path, savedir) if @cask.sourcefile_path - end - def uninstall - odebug "Hbc::Installer.uninstall" - disable_accessibility_access - uninstall_artifacts - purge_versioned_files - purge_caskroom_path if force - end + def uninstall + odebug "Hbc::Installer.uninstall" + disable_accessibility_access + uninstall_artifacts + purge_versioned_files + purge_caskroom_path if force + end - def uninstall_artifacts - odebug "Un-installing artifacts" - artifacts = Hbc::Artifact.for_cask(@cask) - 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 + def uninstall_artifacts + odebug "Un-installing artifacts" + artifacts = Artifact.for_cask(@cask) + 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 + end end - end - def zap - ohai %Q{Implied "brew cask uninstall #{@cask}"} - uninstall_artifacts - if Hbc::Artifact::Zap.me?(@cask) - ohai "Dispatching zap stanza" - Hbc::Artifact::Zap.new(@cask, command: @command).zap_phase - else - opoo "No zap stanza present for Cask '#{@cask}'" + def zap + ohai %Q{Implied "brew cask uninstall #{@cask}"} + uninstall_artifacts + if Artifact::Zap.me?(@cask) + ohai "Dispatching zap stanza" + Artifact::Zap.new(@cask, command: @command).zap_phase + else + opoo "No zap stanza present for Cask '#{@cask}'" + end + ohai "Removing all staged versions of Cask '#{@cask}'" + purge_caskroom_path end - ohai "Removing all staged versions of Cask '#{@cask}'" - purge_caskroom_path - end - def gain_permissions_remove(path) - Hbc::Utils.gain_permissions_remove(path, command: @command) - end + def gain_permissions_remove(path) + Utils.gain_permissions_remove(path, command: @command) + end - def purge_versioned_files - odebug "Purging files for version #{@cask.version} of Cask #{@cask}" + def purge_versioned_files + odebug "Purging files for version #{@cask.version} of Cask #{@cask}" - # versioned staged distribution - gain_permissions_remove(@cask.staged_path) if !@cask.staged_path.nil? && @cask.staged_path.exist? + # versioned staged distribution + gain_permissions_remove(@cask.staged_path) if !@cask.staged_path.nil? && @cask.staged_path.exist? - # Homebrew-Cask metadata - if @cask.metadata_versioned_container_path.respond_to?(:children) && - @cask.metadata_versioned_container_path.exist? - @cask.metadata_versioned_container_path.children.each do |subdir| - unless PERSISTENT_METADATA_SUBDIRS.include?(subdir.basename) - gain_permissions_remove(subdir) + # Homebrew-Cask metadata + if @cask.metadata_versioned_container_path.respond_to?(:children) && + @cask.metadata_versioned_container_path.exist? + @cask.metadata_versioned_container_path.children.each do |subdir| + unless PERSISTENT_METADATA_SUBDIRS.include?(subdir.basename) + gain_permissions_remove(subdir) + end end end - end - @cask.metadata_versioned_container_path.rmdir_if_possible - @cask.metadata_master_container_path.rmdir_if_possible + @cask.metadata_versioned_container_path.rmdir_if_possible + @cask.metadata_master_container_path.rmdir_if_possible - # toplevel staged distribution - @cask.caskroom_path.rmdir_if_possible - end + # toplevel staged distribution + @cask.caskroom_path.rmdir_if_possible + end - def purge_caskroom_path - odebug "Purging all staged versions of Cask #{@cask}" - gain_permissions_remove(@cask.caskroom_path) + def purge_caskroom_path + odebug "Purging all staged versions of Cask #{@cask}" + gain_permissions_remove(@cask.caskroom_path) + end end end diff --git a/Library/Homebrew/cask/lib/hbc/locations.rb b/Library/Homebrew/cask/lib/hbc/locations.rb index 5e18ba8fe..32c95413c 100644 --- a/Library/Homebrew/cask/lib/hbc/locations.rb +++ b/Library/Homebrew/cask/lib/hbc/locations.rb @@ -1,196 +1,198 @@ -module Hbc::Locations - def self.included(base) - base.extend(ClassMethods) - end - - module ClassMethods - def legacy_caskroom - @legacy_caskroom ||= Pathname.new("/opt/homebrew-cask/Caskroom") +module Hbc + module Locations + def self.included(base) + base.extend(ClassMethods) end - def default_caskroom - @default_caskroom ||= homebrew_prefix.join("Caskroom") - end + module ClassMethods + def legacy_caskroom + @legacy_caskroom ||= Pathname.new("/opt/homebrew-cask/Caskroom") + end - def caskroom - @caskroom ||= begin - if Hbc::Utils.path_occupied?(legacy_caskroom) - opoo <<-EOS.undent - The default Caskroom location has moved to #{default_caskroom}. + def default_caskroom + @default_caskroom ||= homebrew_prefix.join("Caskroom") + end - Please migrate your Casks to the new location and delete #{legacy_caskroom}, - or if you would like to keep your Caskroom at #{legacy_caskroom}, add the - following to your HOMEBREW_CASK_OPTS: + def caskroom + @caskroom ||= begin + if Utils.path_occupied?(legacy_caskroom) + opoo <<-EOS.undent + The default Caskroom location has moved to #{default_caskroom}. - --caskroom=#{legacy_caskroom} + Please migrate your Casks to the new location and delete #{legacy_caskroom}, + or if you would like to keep your Caskroom at #{legacy_caskroom}, add the + following to your HOMEBREW_CASK_OPTS: - For more details on each of those options, see https://github.com/caskroom/homebrew-cask/issues/21913. - EOS - legacy_caskroom - else - default_caskroom + --caskroom=#{legacy_caskroom} + + For more details on each of those options, see https://github.com/caskroom/homebrew-cask/issues/21913. + EOS + legacy_caskroom + else + default_caskroom + end end end - end - def caskroom=(caskroom) - @caskroom = caskroom - end + def caskroom=(caskroom) + @caskroom = caskroom + end - def legacy_cache - @legacy_cache ||= homebrew_cache.join("Casks") - end + def legacy_cache + @legacy_cache ||= homebrew_cache.join("Casks") + end - def cache - @cache ||= homebrew_cache.join("Cask") - end + def cache + @cache ||= homebrew_cache.join("Cask") + end - attr_writer :appdir + attr_writer :appdir - def appdir - @appdir ||= Pathname.new("/Applications").expand_path - end + def appdir + @appdir ||= Pathname.new("/Applications").expand_path + end - attr_writer :prefpanedir + attr_writer :prefpanedir - def prefpanedir - @prefpanedir ||= Pathname.new("~/Library/PreferencePanes").expand_path - end + def prefpanedir + @prefpanedir ||= Pathname.new("~/Library/PreferencePanes").expand_path + end - attr_writer :qlplugindir + attr_writer :qlplugindir - def qlplugindir - @qlplugindir ||= Pathname.new("~/Library/QuickLook").expand_path - end + def qlplugindir + @qlplugindir ||= Pathname.new("~/Library/QuickLook").expand_path + end - attr_writer :fontdir + attr_writer :fontdir - def fontdir - @fontdir ||= Pathname.new("~/Library/Fonts").expand_path - end + def fontdir + @fontdir ||= Pathname.new("~/Library/Fonts").expand_path + end - attr_writer :colorpickerdir + attr_writer :colorpickerdir - def colorpickerdir - @colorpickerdir ||= Pathname.new("~/Library/ColorPickers").expand_path - end + def colorpickerdir + @colorpickerdir ||= Pathname.new("~/Library/ColorPickers").expand_path + end - attr_writer :servicedir + attr_writer :servicedir - def servicedir - @servicedir ||= Pathname.new("~/Library/Services").expand_path - end + def servicedir + @servicedir ||= Pathname.new("~/Library/Services").expand_path + end - attr_writer :binarydir + attr_writer :binarydir - def binarydir - @binarydir ||= homebrew_prefix.join("bin") - end + def binarydir + @binarydir ||= homebrew_prefix.join("bin") + end - attr_writer :input_methoddir + attr_writer :input_methoddir - def input_methoddir - @input_methoddir ||= Pathname.new("~/Library/Input Methods").expand_path - end + def input_methoddir + @input_methoddir ||= Pathname.new("~/Library/Input Methods").expand_path + end - attr_writer :internet_plugindir + attr_writer :internet_plugindir - def internet_plugindir - @internet_plugindir ||= Pathname.new("~/Library/Internet Plug-Ins").expand_path - end + def internet_plugindir + @internet_plugindir ||= Pathname.new("~/Library/Internet Plug-Ins").expand_path + end - attr_writer :audio_unit_plugindir + attr_writer :audio_unit_plugindir - def audio_unit_plugindir - @audio_unit_plugindir ||= Pathname.new("~/Library/Audio/Plug-Ins/Components").expand_path - end + def audio_unit_plugindir + @audio_unit_plugindir ||= Pathname.new("~/Library/Audio/Plug-Ins/Components").expand_path + end - attr_writer :vst_plugindir + attr_writer :vst_plugindir - def vst_plugindir - @vst_plugindir ||= Pathname.new("~/Library/Audio/Plug-Ins/VST").expand_path - end + def vst_plugindir + @vst_plugindir ||= Pathname.new("~/Library/Audio/Plug-Ins/VST").expand_path + end - attr_writer :vst3_plugindir + attr_writer :vst3_plugindir - def vst3_plugindir - @vst3_plugindir ||= Pathname.new("~/Library/Audio/Plug-Ins/VST3").expand_path - end + def vst3_plugindir + @vst3_plugindir ||= Pathname.new("~/Library/Audio/Plug-Ins/VST3").expand_path + end - attr_writer :screen_saverdir + attr_writer :screen_saverdir - def screen_saverdir - @screen_saverdir ||= Pathname.new("~/Library/Screen Savers").expand_path - end + def screen_saverdir + @screen_saverdir ||= Pathname.new("~/Library/Screen Savers").expand_path + end - attr_writer :default_tap + attr_writer :default_tap - def default_tap - @default_tap ||= Tap.fetch("caskroom", "homebrew-cask") - end + def default_tap + @default_tap ||= Tap.fetch("caskroom", "homebrew-cask") + end - def path(query) - query = query.sub(%r{\.rb$}i, "") - token_with_tap = if query.include?("/") - query - else - all_tokens.detect do |tap_and_token| - tap_and_token.split("/")[2] == query + def path(query) + query = query.sub(%r{\.rb$}i, "") + token_with_tap = if query.include?("/") + query + else + all_tokens.detect do |tap_and_token| + tap_and_token.split("/")[2] == query + end end - end - if token_with_tap - user, repo, token = token_with_tap.split("/") - Tap.fetch(user, repo).cask_dir.join("#{token}.rb") - else - default_tap.cask_dir.join("#{query}.rb") + if token_with_tap + user, repo, token = token_with_tap.split("/") + Tap.fetch(user, repo).cask_dir.join("#{token}.rb") + else + default_tap.cask_dir.join("#{query}.rb") + end end - end - def tcc_db - @tcc_db ||= Pathname.new("/Library/Application Support/com.apple.TCC/TCC.db") - end + def tcc_db + @tcc_db ||= Pathname.new("/Library/Application Support/com.apple.TCC/TCC.db") + end - def pre_mavericks_accessibility_dotfile - @pre_mavericks_accessibility_dotfile ||= Pathname.new("/private/var/db/.AccessibilityAPIEnabled") - end + def pre_mavericks_accessibility_dotfile + @pre_mavericks_accessibility_dotfile ||= Pathname.new("/private/var/db/.AccessibilityAPIEnabled") + end - def x11_executable - @x11_executable ||= Pathname.new("/usr/X11/bin/X") - end + def x11_executable + @x11_executable ||= Pathname.new("/usr/X11/bin/X") + end - def x11_libpng - @x11_libpng ||= [Pathname.new("/opt/X11/lib/libpng.dylib"), Pathname.new("/usr/X11/lib/libpng.dylib")] - end + def x11_libpng + @x11_libpng ||= [Pathname.new("/opt/X11/lib/libpng.dylib"), Pathname.new("/usr/X11/lib/libpng.dylib")] + end - def homebrew_cache - @homebrew_cache ||= HOMEBREW_CACHE - end + def homebrew_cache + @homebrew_cache ||= HOMEBREW_CACHE + end - def homebrew_cache=(path) - @homebrew_cache = path ? Pathname.new(path) : path - end + def homebrew_cache=(path) + @homebrew_cache = path ? Pathname.new(path) : path + end - def homebrew_executable - @homebrew_executable ||= HOMEBREW_BREW_FILE - end + def homebrew_executable + @homebrew_executable ||= HOMEBREW_BREW_FILE + end - def homebrew_prefix - # where Homebrew links - @homebrew_prefix ||= HOMEBREW_PREFIX - end + def homebrew_prefix + # where Homebrew links + @homebrew_prefix ||= HOMEBREW_PREFIX + end - def homebrew_prefix=(path) - @homebrew_prefix = path ? Pathname.new(path) : path - end + def homebrew_prefix=(path) + @homebrew_prefix = path ? Pathname.new(path) : path + end - def homebrew_repository - # where Homebrew's .git dir is found - @homebrew_repository ||= HOMEBREW_REPOSITORY - end + def homebrew_repository + # where Homebrew's .git dir is found + @homebrew_repository ||= HOMEBREW_REPOSITORY + end - def homebrew_repository=(path) - @homebrew_repository = path ? Pathname.new(path) : path + def homebrew_repository=(path) + @homebrew_repository = path ? Pathname.new(path) : path + end end end end diff --git a/Library/Homebrew/cask/lib/hbc/macos.rb b/Library/Homebrew/cask/lib/hbc/macos.rb index 5e25c657e..fb15be108 100644 --- a/Library/Homebrew/cask/lib/hbc/macos.rb +++ b/Library/Homebrew/cask/lib/hbc/macos.rb @@ -2,377 +2,377 @@ require "set" require "os/mac/version" -module OS::Mac - SYSTEM_DIRS = [ - "/", - "/Applications", - "/Applications/Utilities", - "/Incompatible Software", - "/Library", - "/Library/Application Support", - "/Library/Audio", - "/Library/Caches", - "/Library/ColorPickers", - "/Library/ColorSync", - "/Library/Components", - "/Library/Compositions", - "/Library/Contextual Menu Items", - "/Library/CoreMediaIO", - "/Library/Desktop Pictures", - "/Library/Developer", - "/Library/Dictionaries", - "/Library/DirectoryServices", - "/Library/Documentation", - "/Library/Extensions", - "/Library/Filesystems", - "/Library/Fonts", - "/Library/Frameworks", - "/Library/Graphics", - "/Library/Image Capture", - "/Library/Input Methods", - "/Library/Internet Plug-Ins", - "/Library/Java", - "/Library/Keyboard Layouts", - "/Library/Keychains", - "/Library/LaunchAgents", - "/Library/LaunchDaemons", - "/Library/Logs", - "/Library/Messages", - "/Library/Modem Scripts", - "/Library/OpenDirectory", - "/Library/PDF Services", - "/Library/Perl", - "/Library/PreferencePanes", - "/Library/Preferences", - "/Library/Printers", - "/Library/PrivilegedHelperTools", - "/Library/Python", - "/Library/QuickLook", - "/Library/QuickTime", - "/Library/Receipts", - "/Library/Ruby", - "/Library/Sandbox", - "/Library/Screen Savers", - "/Library/ScriptingAdditions", - "/Library/Scripts", - "/Library/Security", - "/Library/Speech", - "/Library/Spelling", - "/Library/Spotlight", - "/Library/StartupItems", - "/Library/SystemProfiler", - "/Library/Updates", - "/Library/User Pictures", - "/Library/Video", - "/Library/WebServer", - "/Library/Widgets", - "/Library/iTunes", - "/Network", - "/System", - "/System/Library", - "/System/Library/Accessibility", - "/System/Library/Accounts", - "/System/Library/Address Book Plug-Ins", - "/System/Library/Assistant", - "/System/Library/Automator", - "/System/Library/BridgeSupport", - "/System/Library/Caches", - "/System/Library/ColorPickers", - "/System/Library/ColorSync", - "/System/Library/Colors", - "/System/Library/Components", - "/System/Library/Compositions", - "/System/Library/CoreServices", - "/System/Library/DTDs", - "/System/Library/DirectoryServices", - "/System/Library/Displays", - "/System/Library/Extensions", - "/System/Library/Filesystems", - "/System/Library/Filters", - "/System/Library/Fonts", - "/System/Library/Frameworks", - "/System/Library/Graphics", - "/System/Library/IdentityServices", - "/System/Library/Image Capture", - "/System/Library/Input Methods", - "/System/Library/InternetAccounts", - "/System/Library/Java", - "/System/Library/KerberosPlugins", - "/System/Library/Keyboard Layouts", - "/System/Library/Keychains", - "/System/Library/LaunchAgents", - "/System/Library/LaunchDaemons", - "/System/Library/LinguisticData", - "/System/Library/LocationBundles", - "/System/Library/LoginPlugins", - "/System/Library/Messages", - "/System/Library/Metadata", - "/System/Library/MonitorPanels", - "/System/Library/OpenDirectory", - "/System/Library/OpenSSL", - "/System/Library/Password Server Filters", - "/System/Library/PerformanceMetrics", - "/System/Library/Perl", - "/System/Library/PreferencePanes", - "/System/Library/Printers", - "/System/Library/PrivateFrameworks", - "/System/Library/QuickLook", - "/System/Library/QuickTime", - "/System/Library/QuickTimeJava", - "/System/Library/Recents", - "/System/Library/SDKSettingsPlist", - "/System/Library/Sandbox", - "/System/Library/Screen Savers", - "/System/Library/ScreenReader", - "/System/Library/ScriptingAdditions", - "/System/Library/ScriptingDefinitions", - "/System/Library/Security", - "/System/Library/Services", - "/System/Library/Sounds", - "/System/Library/Speech", - "/System/Library/Spelling", - "/System/Library/Spotlight", - "/System/Library/StartupItems", - "/System/Library/SyncServices", - "/System/Library/SystemConfiguration", - "/System/Library/SystemProfiler", - "/System/Library/Tcl", - "/System/Library/TextEncodings", - "/System/Library/User Template", - "/System/Library/UserEventPlugins", - "/System/Library/Video", - "/System/Library/WidgetResources", - "/User Information", - "/Users", - "/Volumes", - "/bin", - "/boot", - "/cores", - "/dev", - "/etc", - "/etc/X11", - "/etc/opt", - "/etc/sgml", - "/etc/xml", - "/home", - "/libexec", - "/lost+found", - "/media", - "/mnt", - "/net", - "/opt", - "/private", - "/private/etc", - "/private/tftpboot", - "/private/tmp", - "/private/var", - "/proc", - "/root", - "/sbin", - "/srv", - "/tmp", - "/usr", - "/usr/X11R6", - "/usr/bin", - "/usr/etc", - "/usr/include", - "/usr/lib", - "/usr/libexec", - "/usr/local", - "/usr/local/Cellar", - "/usr/local/Frameworks", - "/usr/local/Library", - "/usr/local/bin", - "/usr/local/etc", - "/usr/local/include", - "/usr/local/lib", - "/usr/local/libexec", - "/usr/local/opt", - "/usr/local/share", - "/usr/local/share/man", - "/usr/local/share/man/man1", - "/usr/local/share/man/man2", - "/usr/local/share/man/man3", - "/usr/local/share/man/man4", - "/usr/local/share/man/man5", - "/usr/local/share/man/man6", - "/usr/local/share/man/man7", - "/usr/local/share/man/man8", - "/usr/local/share/man/man9", - "/usr/local/share/man/mann", - "/usr/local/var", - "/usr/local/var/lib", - "/usr/local/var/lock", - "/usr/local/var/run", - "/usr/sbin", - "/usr/share", - "/usr/share/man", - "/usr/share/man/man1", - "/usr/share/man/man2", - "/usr/share/man/man3", - "/usr/share/man/man4", - "/usr/share/man/man5", - "/usr/share/man/man6", - "/usr/share/man/man7", - "/usr/share/man/man8", - "/usr/share/man/man9", - "/usr/share/man/mann", - "/usr/src", - "/var", - "/var/cache", - "/var/lib", - "/var/lock", - "/var/log", - "/var/mail", - "/var/run", - "/var/spool", - "/var/spool/mail", - "/var/tmp", - ] - .map(&method(:Pathname)) - .to_set - .freeze +module OS + module Mac + SYSTEM_DIRS = [ + "/", + "/Applications", + "/Applications/Utilities", + "/Incompatible Software", + "/Library", + "/Library/Application Support", + "/Library/Audio", + "/Library/Caches", + "/Library/ColorPickers", + "/Library/ColorSync", + "/Library/Components", + "/Library/Compositions", + "/Library/Contextual Menu Items", + "/Library/CoreMediaIO", + "/Library/Desktop Pictures", + "/Library/Developer", + "/Library/Dictionaries", + "/Library/DirectoryServices", + "/Library/Documentation", + "/Library/Extensions", + "/Library/Filesystems", + "/Library/Fonts", + "/Library/Frameworks", + "/Library/Graphics", + "/Library/Image Capture", + "/Library/Input Methods", + "/Library/Internet Plug-Ins", + "/Library/Java", + "/Library/Keyboard Layouts", + "/Library/Keychains", + "/Library/LaunchAgents", + "/Library/LaunchDaemons", + "/Library/Logs", + "/Library/Messages", + "/Library/Modem Scripts", + "/Library/OpenDirectory", + "/Library/PDF Services", + "/Library/Perl", + "/Library/PreferencePanes", + "/Library/Preferences", + "/Library/Printers", + "/Library/PrivilegedHelperTools", + "/Library/Python", + "/Library/QuickLook", + "/Library/QuickTime", + "/Library/Receipts", + "/Library/Ruby", + "/Library/Sandbox", + "/Library/Screen Savers", + "/Library/ScriptingAdditions", + "/Library/Scripts", + "/Library/Security", + "/Library/Speech", + "/Library/Spelling", + "/Library/Spotlight", + "/Library/StartupItems", + "/Library/SystemProfiler", + "/Library/Updates", + "/Library/User Pictures", + "/Library/Video", + "/Library/WebServer", + "/Library/Widgets", + "/Library/iTunes", + "/Network", + "/System", + "/System/Library", + "/System/Library/Accessibility", + "/System/Library/Accounts", + "/System/Library/Address Book Plug-Ins", + "/System/Library/Assistant", + "/System/Library/Automator", + "/System/Library/BridgeSupport", + "/System/Library/Caches", + "/System/Library/ColorPickers", + "/System/Library/ColorSync", + "/System/Library/Colors", + "/System/Library/Components", + "/System/Library/Compositions", + "/System/Library/CoreServices", + "/System/Library/DTDs", + "/System/Library/DirectoryServices", + "/System/Library/Displays", + "/System/Library/Extensions", + "/System/Library/Filesystems", + "/System/Library/Filters", + "/System/Library/Fonts", + "/System/Library/Frameworks", + "/System/Library/Graphics", + "/System/Library/IdentityServices", + "/System/Library/Image Capture", + "/System/Library/Input Methods", + "/System/Library/InternetAccounts", + "/System/Library/Java", + "/System/Library/KerberosPlugins", + "/System/Library/Keyboard Layouts", + "/System/Library/Keychains", + "/System/Library/LaunchAgents", + "/System/Library/LaunchDaemons", + "/System/Library/LinguisticData", + "/System/Library/LocationBundles", + "/System/Library/LoginPlugins", + "/System/Library/Messages", + "/System/Library/Metadata", + "/System/Library/MonitorPanels", + "/System/Library/OpenDirectory", + "/System/Library/OpenSSL", + "/System/Library/Password Server Filters", + "/System/Library/PerformanceMetrics", + "/System/Library/Perl", + "/System/Library/PreferencePanes", + "/System/Library/Printers", + "/System/Library/PrivateFrameworks", + "/System/Library/QuickLook", + "/System/Library/QuickTime", + "/System/Library/QuickTimeJava", + "/System/Library/Recents", + "/System/Library/SDKSettingsPlist", + "/System/Library/Sandbox", + "/System/Library/Screen Savers", + "/System/Library/ScreenReader", + "/System/Library/ScriptingAdditions", + "/System/Library/ScriptingDefinitions", + "/System/Library/Security", + "/System/Library/Services", + "/System/Library/Sounds", + "/System/Library/Speech", + "/System/Library/Spelling", + "/System/Library/Spotlight", + "/System/Library/StartupItems", + "/System/Library/SyncServices", + "/System/Library/SystemConfiguration", + "/System/Library/SystemProfiler", + "/System/Library/Tcl", + "/System/Library/TextEncodings", + "/System/Library/User Template", + "/System/Library/UserEventPlugins", + "/System/Library/Video", + "/System/Library/WidgetResources", + "/User Information", + "/Users", + "/Volumes", + "/bin", + "/boot", + "/cores", + "/dev", + "/etc", + "/etc/X11", + "/etc/opt", + "/etc/sgml", + "/etc/xml", + "/home", + "/libexec", + "/lost+found", + "/media", + "/mnt", + "/net", + "/opt", + "/private", + "/private/etc", + "/private/tftpboot", + "/private/tmp", + "/private/var", + "/proc", + "/root", + "/sbin", + "/srv", + "/tmp", + "/usr", + "/usr/X11R6", + "/usr/bin", + "/usr/etc", + "/usr/include", + "/usr/lib", + "/usr/libexec", + "/usr/local", + "/usr/local/Cellar", + "/usr/local/Frameworks", + "/usr/local/Library", + "/usr/local/bin", + "/usr/local/etc", + "/usr/local/include", + "/usr/local/lib", + "/usr/local/libexec", + "/usr/local/opt", + "/usr/local/share", + "/usr/local/share/man", + "/usr/local/share/man/man1", + "/usr/local/share/man/man2", + "/usr/local/share/man/man3", + "/usr/local/share/man/man4", + "/usr/local/share/man/man5", + "/usr/local/share/man/man6", + "/usr/local/share/man/man7", + "/usr/local/share/man/man8", + "/usr/local/share/man/man9", + "/usr/local/share/man/mann", + "/usr/local/var", + "/usr/local/var/lib", + "/usr/local/var/lock", + "/usr/local/var/run", + "/usr/sbin", + "/usr/share", + "/usr/share/man", + "/usr/share/man/man1", + "/usr/share/man/man2", + "/usr/share/man/man3", + "/usr/share/man/man4", + "/usr/share/man/man5", + "/usr/share/man/man6", + "/usr/share/man/man7", + "/usr/share/man/man8", + "/usr/share/man/man9", + "/usr/share/man/mann", + "/usr/src", + "/var", + "/var/cache", + "/var/lib", + "/var/lock", + "/var/log", + "/var/mail", + "/var/run", + "/var/spool", + "/var/spool/mail", + "/var/tmp", + ] + .map(&method(:Pathname)) + .to_set + .freeze - # TODO: There should be a way to specify a containing - # directory under which nothing can be deleted. - UNDELETABLE_DIRS = [ - "~/", - "~/Applications", - "~/Desktop", - "~/Documents", - "~/Downloads", - "~/Mail", - "~/Movies", - "~/Music", - "~/Music/iTunes", - "~/Music/iTunes/iTunes Music", - "~/Music/iTunes/Album Artwork", - "~/News", - "~/Pictures", - "~/Pictures/Desktops", - "~/Pictures/Photo Booth", - "~/Pictures/iChat Icons", - "~/Pictures/iPhoto Library", - "~/Public", - "~/Sites", - "~/Library", - "~/Library/.localized", - "~/Library/Accessibility", - "~/Library/Accounts", - "~/Library/Address Book Plug-Ins", - "~/Library/Application Scripts", - "~/Library/Application Support", - "~/Library/Application Support/Apple", - "~/Library/Application Support/com.apple.AssistiveControl", - "~/Library/Application Support/com.apple.QuickLook", - "~/Library/Application Support/com.apple.TCC", - "~/Library/Assistants", - "~/Library/Audio", - "~/Library/Automator", - "~/Library/Autosave Information", - "~/Library/Caches", - "~/Library/Calendars", - "~/Library/ColorPickers", - "~/Library/ColorSync", - "~/Library/Colors", - "~/Library/Components", - "~/Library/Compositions", - "~/Library/Containers", - "~/Library/Contextual Menu Items", - "~/Library/Cookies", - "~/Library/DTDs", - "~/Library/Desktop Pictures", - "~/Library/Developer", - "~/Library/Dictionaries", - "~/Library/DirectoryServices", - "~/Library/Displays", - "~/Library/Documentation", - "~/Library/Extensions", - "~/Library/Favorites", - "~/Library/FileSync", - "~/Library/Filesystems", - "~/Library/Filters", - "~/Library/FontCollections", - "~/Library/Fonts", - "~/Library/Frameworks", - "~/Library/GameKit", - "~/Library/Graphics", - "~/Library/Group Containers", - "~/Library/Icons", - "~/Library/IdentityServices", - "~/Library/Image Capture", - "~/Library/Images", - "~/Library/Input Methods", - "~/Library/Internet Plug-Ins", - "~/Library/InternetAccounts", - "~/Library/iTunes", - "~/Library/KeyBindings", - "~/Library/Keyboard Layouts", - "~/Library/Keychains", - "~/Library/LaunchAgents", - "~/Library/LaunchDaemons", - "~/Library/LocationBundles", - "~/Library/LoginPlugins", - "~/Library/Logs", - "~/Library/Mail", - "~/Library/Mail Downloads", - "~/Library/Messages", - "~/Library/Metadata", - "~/Library/Mobile Documents", - "~/Library/MonitorPanels", - "~/Library/OpenDirectory", - "~/Library/PDF Services", - "~/Library/PhonePlugins", - "~/Library/Phones", - "~/Library/PreferencePanes", - "~/Library/Preferences", - "~/Library/Printers", - "~/Library/PrivateFrameworks", - "~/Library/PubSub", - "~/Library/QuickLook", - "~/Library/QuickTime", - "~/Library/Receipts", - "~/Library/Recent Servers", - "~/Library/Recents", - "~/Library/Safari", - "~/Library/Saved Application State", - "~/Library/Screen Savers", - "~/Library/ScreenReader", - "~/Library/ScriptingAdditions", - "~/Library/ScriptingDefinitions", - "~/Library/Scripts", - "~/Library/Security", - "~/Library/Services", - "~/Library/Sounds", - "~/Library/Speech", - "~/Library/Spelling", - "~/Library/Spotlight", - "~/Library/StartupItems", - "~/Library/StickiesDatabase", - "~/Library/Sync Services", - "~/Library/SyncServices", - "~/Library/SyncedPreferences", - "~/Library/TextEncodings", - "~/Library/User Pictures", - "~/Library/Video", - "~/Library/Voices", - "~/Library/WebKit", - "~/Library/WidgetResources", - "~/Library/Widgets", - "~/Library/Workflows", - ] - .map { |x| Pathname(x.sub(%r{^~(?=(/|$))}, Dir.home)).expand_path } - .to_set - .union(SYSTEM_DIRS) - .freeze + # TODO: There should be a way to specify a containing + # directory under which nothing can be deleted. + UNDELETABLE_DIRS = [ + "~/", + "~/Applications", + "~/Desktop", + "~/Documents", + "~/Downloads", + "~/Mail", + "~/Movies", + "~/Music", + "~/Music/iTunes", + "~/Music/iTunes/iTunes Music", + "~/Music/iTunes/Album Artwork", + "~/News", + "~/Pictures", + "~/Pictures/Desktops", + "~/Pictures/Photo Booth", + "~/Pictures/iChat Icons", + "~/Pictures/iPhoto Library", + "~/Public", + "~/Sites", + "~/Library", + "~/Library/.localized", + "~/Library/Accessibility", + "~/Library/Accounts", + "~/Library/Address Book Plug-Ins", + "~/Library/Application Scripts", + "~/Library/Application Support", + "~/Library/Application Support/Apple", + "~/Library/Application Support/com.apple.AssistiveControl", + "~/Library/Application Support/com.apple.QuickLook", + "~/Library/Application Support/com.apple.TCC", + "~/Library/Assistants", + "~/Library/Audio", + "~/Library/Automator", + "~/Library/Autosave Information", + "~/Library/Caches", + "~/Library/Calendars", + "~/Library/ColorPickers", + "~/Library/ColorSync", + "~/Library/Colors", + "~/Library/Components", + "~/Library/Compositions", + "~/Library/Containers", + "~/Library/Contextual Menu Items", + "~/Library/Cookies", + "~/Library/DTDs", + "~/Library/Desktop Pictures", + "~/Library/Developer", + "~/Library/Dictionaries", + "~/Library/DirectoryServices", + "~/Library/Displays", + "~/Library/Documentation", + "~/Library/Extensions", + "~/Library/Favorites", + "~/Library/FileSync", + "~/Library/Filesystems", + "~/Library/Filters", + "~/Library/FontCollections", + "~/Library/Fonts", + "~/Library/Frameworks", + "~/Library/GameKit", + "~/Library/Graphics", + "~/Library/Group Containers", + "~/Library/Icons", + "~/Library/IdentityServices", + "~/Library/Image Capture", + "~/Library/Images", + "~/Library/Input Methods", + "~/Library/Internet Plug-Ins", + "~/Library/InternetAccounts", + "~/Library/iTunes", + "~/Library/KeyBindings", + "~/Library/Keyboard Layouts", + "~/Library/Keychains", + "~/Library/LaunchAgents", + "~/Library/LaunchDaemons", + "~/Library/LocationBundles", + "~/Library/LoginPlugins", + "~/Library/Logs", + "~/Library/Mail", + "~/Library/Mail Downloads", + "~/Library/Messages", + "~/Library/Metadata", + "~/Library/Mobile Documents", + "~/Library/MonitorPanels", + "~/Library/OpenDirectory", + "~/Library/PDF Services", + "~/Library/PhonePlugins", + "~/Library/Phones", + "~/Library/PreferencePanes", + "~/Library/Preferences", + "~/Library/Printers", + "~/Library/PrivateFrameworks", + "~/Library/PubSub", + "~/Library/QuickLook", + "~/Library/QuickTime", + "~/Library/Receipts", + "~/Library/Recent Servers", + "~/Library/Recents", + "~/Library/Safari", + "~/Library/Saved Application State", + "~/Library/Screen Savers", + "~/Library/ScreenReader", + "~/Library/ScriptingAdditions", + "~/Library/ScriptingDefinitions", + "~/Library/Scripts", + "~/Library/Security", + "~/Library/Services", + "~/Library/Sounds", + "~/Library/Speech", + "~/Library/Spelling", + "~/Library/Spotlight", + "~/Library/StartupItems", + "~/Library/StickiesDatabase", + "~/Library/Sync Services", + "~/Library/SyncServices", + "~/Library/SyncedPreferences", + "~/Library/TextEncodings", + "~/Library/User Pictures", + "~/Library/Video", + "~/Library/Voices", + "~/Library/WebKit", + "~/Library/WidgetResources", + "~/Library/Widgets", + "~/Library/Workflows", + ] + .map { |x| Pathname(x.sub(%r{^~(?=(/|$))}, Dir.home)).expand_path } + .to_set + .union(SYSTEM_DIRS) + .freeze - def system_dir?(dir) - SYSTEM_DIRS.include?(Pathname.new(dir).expand_path) - end + def system_dir?(dir) + SYSTEM_DIRS.include?(Pathname.new(dir).expand_path) + end - def undeletable?(dir) - UNDELETABLE_DIRS.include?(Pathname.new(dir).expand_path) + def undeletable?(dir) + UNDELETABLE_DIRS.include?(Pathname.new(dir).expand_path) + end end - - alias release version end diff --git a/Library/Homebrew/cask/lib/hbc/options.rb b/Library/Homebrew/cask/lib/hbc/options.rb index c0e3e2ed0..e9ba54ff6 100644 --- a/Library/Homebrew/cask/lib/hbc/options.rb +++ b/Library/Homebrew/cask/lib/hbc/options.rb @@ -1,37 +1,39 @@ -module Hbc::Options - def self.included(base) - base.extend(ClassMethods) - end +module Hbc + module Options + def self.included(base) + base.extend(ClassMethods) + end - module ClassMethods - attr_writer :no_binaries + module ClassMethods + attr_writer :no_binaries - def no_binaries - @no_binaries ||= false - end + def no_binaries + @no_binaries ||= false + end - attr_writer :debug + attr_writer :debug - def debug - @debug ||= false - end + def debug + @debug ||= false + end - attr_writer :verbose + attr_writer :verbose - def verbose - @verbose ||= false - end + def verbose + @verbose ||= false + end - attr_writer :cleanup_outdated + attr_writer :cleanup_outdated - def cleanup_outdated - @cleanup_outdated ||= false - end + def cleanup_outdated + @cleanup_outdated ||= false + end - attr_writer :help + attr_writer :help - def help - @help ||= false + def help + @help ||= false + end end end end diff --git a/Library/Homebrew/cask/lib/hbc/pkg.rb b/Library/Homebrew/cask/lib/hbc/pkg.rb index 6f8d28c24..7f187c9de 100644 --- a/Library/Homebrew/cask/lib/hbc/pkg.rb +++ b/Library/Homebrew/cask/lib/hbc/pkg.rb @@ -1,113 +1,115 @@ -class Hbc::Pkg - def self.all_matching(regexp, command) - command.run("/usr/sbin/pkgutil", args: ["--pkgs=#{regexp}"]).stdout.split("\n").map { |package_id| - new(package_id.chomp, command) - } - end +module Hbc + class Pkg + def self.all_matching(regexp, command) + command.run("/usr/sbin/pkgutil", args: ["--pkgs=#{regexp}"]).stdout.split("\n").map { |package_id| + new(package_id.chomp, command) + } + end - attr_reader :package_id + attr_reader :package_id - def initialize(package_id, command = Hbc::SystemCommand) - @package_id = package_id - @command = command - end + def initialize(package_id, command = SystemCommand) + @package_id = package_id + @command = command + end - def uninstall - odebug "Deleting pkg files" - pkgutil_bom_files.each_slice(500) do |file_slice| - @command.run("/bin/rm", args: file_slice.unshift("-f", "--"), sudo: true) - end - odebug "Deleting pkg symlinks and special files" - pkgutil_bom_specials.each_slice(500) do |file_slice| - @command.run("/bin/rm", args: file_slice.unshift("-f", "--"), sudo: true) - end - odebug "Deleting pkg directories" - _deepest_path_first(pkgutil_bom_dirs).each do |dir| - next unless dir.exist? && !MacOS.undeletable?(dir) - _with_full_permissions(dir) do - _clean_broken_symlinks(dir) - _clean_ds_store(dir) - _rmdir(dir) + def uninstall + odebug "Deleting pkg files" + pkgutil_bom_files.each_slice(500) do |file_slice| + @command.run("/bin/rm", args: file_slice.unshift("-f", "--"), sudo: true) + end + odebug "Deleting pkg symlinks and special files" + pkgutil_bom_specials.each_slice(500) do |file_slice| + @command.run("/bin/rm", args: file_slice.unshift("-f", "--"), sudo: true) end + odebug "Deleting pkg directories" + _deepest_path_first(pkgutil_bom_dirs).each do |dir| + next unless dir.exist? && !MacOS.undeletable?(dir) + _with_full_permissions(dir) do + _clean_broken_symlinks(dir) + _clean_ds_store(dir) + _rmdir(dir) + end + end + forget end - forget - end - def forget - odebug "Unregistering pkg receipt (aka forgetting)" - @command.run!("/usr/sbin/pkgutil", args: ["--forget", package_id], sudo: true) - end + def forget + odebug "Unregistering pkg receipt (aka forgetting)" + @command.run!("/usr/sbin/pkgutil", args: ["--forget", package_id], sudo: true) + end - def pkgutil_bom(*type) - @command.run!("/usr/sbin/pkgutil", args: [*type, "--files", package_id].compact) - .stdout - .split("\n") - .map { |path| root.join(path) } - end + def pkgutil_bom(*type) + @command.run!("/usr/sbin/pkgutil", args: [*type, "--files", package_id].compact) + .stdout + .split("\n") + .map { |path| root.join(path) } + end - def pkgutil_bom_files - @pkgutil_bom_files ||= pkgutil_bom("--only-files") - end + def pkgutil_bom_files + @pkgutil_bom_files ||= pkgutil_bom("--only-files") + end - def pkgutil_bom_dirs - @pkgutil_bom_dirs ||= pkgutil_bom("--only-dirs") - end + def pkgutil_bom_dirs + @pkgutil_bom_dirs ||= pkgutil_bom("--only-dirs") + end - def pkgutil_bom_all - @pkgutil_bom_all ||= pkgutil_bom - end + def pkgutil_bom_all + @pkgutil_bom_all ||= pkgutil_bom + end - def pkgutil_bom_specials - pkgutil_bom_all - pkgutil_bom_files - pkgutil_bom_dirs - end + def pkgutil_bom_specials + pkgutil_bom_all - pkgutil_bom_files - pkgutil_bom_dirs + end - def root - @root ||= Pathname(info.fetch("volume")).join(info.fetch("install-location")) - end + def root + @root ||= Pathname(info.fetch("volume")).join(info.fetch("install-location")) + end - def info - @command.run!("/usr/sbin/pkgutil", args: ["--pkg-info-plist", package_id]) - .plist - end + def info + @command.run!("/usr/sbin/pkgutil", args: ["--pkg-info-plist", package_id]) + .plist + end - def _rmdir(path) - @command.run!("/bin/rmdir", args: ["--", path], sudo: true) if path.children.empty? - end + def _rmdir(path) + @command.run!("/bin/rmdir", args: ["--", path], sudo: true) if path.children.empty? + end - def _with_full_permissions(path) - original_mode = (path.stat.mode % 0o1000).to_s(8) - # TODO: similarly read and restore macOS flags (cf man chflags) - @command.run!("/bin/chmod", args: ["--", "777", path], sudo: true) - yield - ensure - if path.exist? # block may have removed dir - @command.run!("/bin/chmod", args: ["--", original_mode, path], sudo: true) + def _with_full_permissions(path) + original_mode = (path.stat.mode % 0o1000).to_s(8) + # TODO: similarly read and restore macOS flags (cf man chflags) + @command.run!("/bin/chmod", args: ["--", "777", path], sudo: true) + yield + ensure + if path.exist? # block may have removed dir + @command.run!("/bin/chmod", args: ["--", original_mode, path], sudo: true) + end end - end - def _deepest_path_first(paths) - paths.sort do |path_a, path_b| - path_b.to_s.split("/").count <=> path_a.to_s.split("/").count + def _deepest_path_first(paths) + paths.sort do |path_a, path_b| + path_b.to_s.split("/").count <=> path_a.to_s.split("/").count + end end - 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 - def _clean_broken_symlinks(dir) - dir.children.each do |child| - if _broken_symlink?(child) - @command.run!("/bin/rm", args: ["--", child], sudo: true) + # Some pkgs leave broken symlinks hanging around; we clean them out before + # attempting to rmdir to prevent extra cruft from lying around after + # uninstall + def _clean_broken_symlinks(dir) + dir.children.each do |child| + if _broken_symlink?(child) + @command.run!("/bin/rm", args: ["--", child], sudo: true) + end end end - end - def _clean_ds_store(dir) - ds_store = dir.join(".DS_Store") - @command.run!("/bin/rm", args: ["--", ds_store], sudo: true) if ds_store.exist? - end + def _clean_ds_store(dir) + ds_store = dir.join(".DS_Store") + @command.run!("/bin/rm", args: ["--", ds_store], sudo: true) if ds_store.exist? + end - def _broken_symlink?(path) - path.symlink? && !path.exist? + def _broken_symlink?(path) + path.symlink? && !path.exist? + end end end diff --git a/Library/Homebrew/cask/lib/hbc/qualified_token.rb b/Library/Homebrew/cask/lib/hbc/qualified_token.rb index 635e1cb3d..ccfe08b45 100644 --- a/Library/Homebrew/cask/lib/hbc/qualified_token.rb +++ b/Library/Homebrew/cask/lib/hbc/qualified_token.rb @@ -1,37 +1,39 @@ -module Hbc::QualifiedToken - REPO_PREFIX = "homebrew-".freeze +module Hbc + module QualifiedToken + REPO_PREFIX = "homebrew-".freeze - # per https://github.com/Homebrew/homebrew/blob/4c7bc9ec3bca729c898ee347b6135ba692ee0274/Library/Homebrew/cmd/tap.rb#L121 - USER_REGEX = %r{[a-z_\-]+} + # per https://github.com/Homebrew/homebrew/blob/4c7bc9ec3bca729c898ee347b6135ba692ee0274/Library/Homebrew/cmd/tap.rb#L121 + USER_REGEX = %r{[a-z_\-]+} - # per https://github.com/Homebrew/homebrew/blob/4c7bc9ec3bca729c898ee347b6135ba692ee0274/Library/Homebrew/cmd/tap.rb#L121 - REPO_REGEX = %r{(?:#{REPO_PREFIX})?\w+} + # per https://github.com/Homebrew/homebrew/blob/4c7bc9ec3bca729c898ee347b6135ba692ee0274/Library/Homebrew/cmd/tap.rb#L121 + REPO_REGEX = %r{(?:#{REPO_PREFIX})?\w+} - # per https://github.com/caskroom/homebrew-cask/blob/master/CONTRIBUTING.md#generating-a-token-for-the-cask - TOKEN_REGEX = %r{[a-z0-9\-]+} + # per https://github.com/caskroom/homebrew-cask/blob/master/CONTRIBUTING.md#generating-a-token-for-the-cask + TOKEN_REGEX = %r{[a-z0-9\-]+} - TAP_REGEX = %r{#{USER_REGEX}[/\-]#{REPO_REGEX}} + TAP_REGEX = %r{#{USER_REGEX}[/\-]#{REPO_REGEX}} - QUALIFIED_TOKEN_REGEX ||= %r{#{TAP_REGEX}/#{TOKEN_REGEX}} + QUALIFIED_TOKEN_REGEX ||= %r{#{TAP_REGEX}/#{TOKEN_REGEX}} - def self.parse(arg) - return nil unless arg.is_a?(String) && arg.downcase =~ %r{^#{QUALIFIED_TOKEN_REGEX}$} - path_elements = arg.downcase.split("/") - if path_elements.count == 2 - # eg phinze-cask/google-chrome. - # Not certain this form is needed, but it was supported in the past. - token = path_elements[1] - dash_elements = path_elements[0].split("-") - repo = dash_elements.pop - dash_elements.pop if dash_elements.count > 1 && dash_elements[-1] + "-" == REPO_PREFIX - user = dash_elements.join("-") - else - # eg caskroom/cask/google-chrome - # per https://github.com/Homebrew/homebrew/wiki/brew-tap - user, repo, token = path_elements + def self.parse(arg) + return nil unless arg.is_a?(String) && arg.downcase =~ %r{^#{QUALIFIED_TOKEN_REGEX}$} + path_elements = arg.downcase.split("/") + if path_elements.count == 2 + # eg phinze-cask/google-chrome. + # Not certain this form is needed, but it was supported in the past. + token = path_elements[1] + dash_elements = path_elements[0].split("-") + repo = dash_elements.pop + dash_elements.pop if dash_elements.count > 1 && dash_elements[-1] + "-" == REPO_PREFIX + user = dash_elements.join("-") + else + # eg caskroom/cask/google-chrome + # per https://github.com/Homebrew/homebrew/wiki/brew-tap + user, repo, token = path_elements + end + repo.sub!(%r{^#{REPO_PREFIX}}, "") + odebug "[user, repo, token] might be [#{user}, #{repo}, #{token}]" + [user, repo, token] end - repo.sub!(%r{^#{REPO_PREFIX}}, "") - odebug "[user, repo, token] might be [#{user}, #{repo}, #{token}]" - [user, repo, token] end end diff --git a/Library/Homebrew/cask/lib/hbc/scopes.rb b/Library/Homebrew/cask/lib/hbc/scopes.rb index 431c3ff47..8520028c9 100644 --- a/Library/Homebrew/cask/lib/hbc/scopes.rb +++ b/Library/Homebrew/cask/lib/hbc/scopes.rb @@ -1,45 +1,47 @@ -module Hbc::Scopes - def self.included(base) - base.extend(ClassMethods) - end - - module ClassMethods - def all - @all_casks ||= {} - all_tokens.map { |t| @all_casks[t] ||= load(t) } +module Hbc + module Scopes + def self.included(base) + base.extend(ClassMethods) end - def all_tapped_cask_dirs - Tap.map(&:cask_dir).compact - end + module ClassMethods + def all + @all_casks ||= {} + all_tokens.map { |t| @all_casks[t] ||= load(t) } + end - def all_tokens - Tap.map { |t| - t.cask_files.map { |p| - "#{t.name}/#{File.basename(p, ".rb")}" - } - }.flatten - end + def all_tapped_cask_dirs + Tap.map(&:cask_dir).compact + end - def installed - # Hbc.load has some DWIM which is slow. Optimize here - # by spoon-feeding Hbc.load fully-qualified paths. - # TODO: speed up Hbc::Source::Tapped (main perf drag is calling Hbc.all_tokens repeatedly) - # TODO: ability to specify expected source when calling Hbc.load (minor perf benefit) - Pathname.glob(caskroom.join("*")) - .map { |caskroom_path| - token = caskroom_path.basename.to_s + def all_tokens + Tap.map { |t| + t.cask_files.map { |p| + "#{t.name}/#{File.basename(p, ".rb")}" + } + }.flatten + end - path_to_cask = all_tapped_cask_dirs.find { |tap_dir| - tap_dir.join("#{token}.rb").exist? - } + def installed + # Hbc.load has some DWIM which is slow. Optimize here + # by spoon-feeding Hbc.load fully-qualified paths. + # TODO: speed up Hbc::Source::Tapped (main perf drag is calling Hbc.all_tokens repeatedly) + # TODO: ability to specify expected source when calling Hbc.load (minor perf benefit) + Pathname.glob(caskroom.join("*")) + .map { |caskroom_path| + token = caskroom_path.basename.to_s + + path_to_cask = all_tapped_cask_dirs.find { |tap_dir| + tap_dir.join("#{token}.rb").exist? + } - if path_to_cask - Hbc.load(path_to_cask.join("#{token}.rb")) - else - Hbc.load(token) - end - } + if path_to_cask + Hbc.load(path_to_cask.join("#{token}.rb")) + else + Hbc.load(token) + end + } + end end end end diff --git a/Library/Homebrew/cask/lib/hbc/source.rb b/Library/Homebrew/cask/lib/hbc/source.rb index af298108a..b4d105894 100644 --- a/Library/Homebrew/cask/lib/hbc/source.rb +++ b/Library/Homebrew/cask/lib/hbc/source.rb @@ -1,5 +1,3 @@ -module Hbc::Source; end - require "hbc/source/gone" require "hbc/source/path_slash_required" require "hbc/source/path_slash_optional" @@ -8,30 +6,32 @@ require "hbc/source/untapped_qualified" require "hbc/source/tapped" require "hbc/source/uri" -module Hbc::Source - def self.sources - [ - Hbc::Source::URI, - Hbc::Source::PathSlashRequired, - Hbc::Source::TappedQualified, - Hbc::Source::UntappedQualified, - Hbc::Source::Tapped, - Hbc::Source::PathSlashOptional, - Hbc::Source::Gone, - ] - end +module Hbc + module Source + def self.sources + [ + URI, + PathSlashRequired, + TappedQualified, + UntappedQualified, + Tapped, + PathSlashOptional, + Gone, + ] + end - def self.for_query(query) - odebug "Translating '#{query}' into a valid Cask source" - raise Hbc::CaskUnavailableError, query if query.to_s =~ %r{^\s*$} - source = sources.find { |s| - odebug "Testing source class #{s}" - s.me?(query) - } - raise Hbc::CaskUnavailableError, query unless source - odebug "Success! Using source class #{source}" - resolved_cask_source = source.new(query) - odebug "Resolved Cask URI or file source to '#{resolved_cask_source}'" - resolved_cask_source + def self.for_query(query) + odebug "Translating '#{query}' into a valid Cask source" + raise CaskUnavailableError, query if query.to_s =~ %r{^\s*$} + source = sources.find { |s| + odebug "Testing source class #{s}" + s.me?(query) + } + raise CaskUnavailableError, query unless source + odebug "Success! Using source class #{source}" + resolved_cask_source = source.new(query) + odebug "Resolved Cask URI or file source to '#{resolved_cask_source}'" + resolved_cask_source + end end end diff --git a/Library/Homebrew/cask/lib/hbc/source/gone.rb b/Library/Homebrew/cask/lib/hbc/source/gone.rb index 2b9f2b5f2..1c744d0db 100644 --- a/Library/Homebrew/cask/lib/hbc/source/gone.rb +++ b/Library/Homebrew/cask/lib/hbc/source/gone.rb @@ -1,19 +1,23 @@ -class Hbc::Source::Gone - def self.me?(query) - Hbc::WithoutSource.new(query).installed? - end +module Hbc + module Source + class Gone + def self.me?(query) + WithoutSource.new(query).installed? + end - attr_reader :query + attr_reader :query - def initialize(query) - @query = query - end + def initialize(query) + @query = query + end - def load - Hbc::WithoutSource.new(query) - end + def load + WithoutSource.new(query) + end - def to_s - "" + def to_s + "" + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/source/path_base.rb b/Library/Homebrew/cask/lib/hbc/source/path_base.rb index bd85ab425..5725380ec 100644 --- a/Library/Homebrew/cask/lib/hbc/source/path_base.rb +++ b/Library/Homebrew/cask/lib/hbc/source/path_base.rb @@ -1,69 +1,73 @@ require "rubygems" -class Hbc::Source::PathBase - # derived classes must define method self.me? +module Hbc + module Source + class PathBase + # derived classes must define method self.me? - def self.path_for_query(query) - query_string = query.to_s - Pathname.new(query_string.end_with?(".rb") ? query_string : query_string + ".rb") - end + def self.path_for_query(query) + query_string = query.to_s + Pathname.new(query_string.end_with?(".rb") ? query_string : query_string + ".rb") + end - attr_reader :path + attr_reader :path - def initialize(path) - @path = Pathname(path).expand_path - end + def initialize(path) + @path = Pathname(path).expand_path + end - def load - raise Hbc::CaskError, "File '#{path}' does not exist" unless path.exist? - raise Hbc::CaskError, "File '#{path}' is not readable" unless path.readable? - raise Hbc::CaskError, "File '#{path}' is not a plain file" unless path.file? - load_cask - end + def load + raise CaskError, "File '#{path}' does not exist" unless path.exist? + raise CaskError, "File '#{path}' is not readable" unless path.readable? + raise CaskError, "File '#{path}' is not a plain file" unless path.file? + load_cask + end - def to_s - # stringify to fully-resolved location - path.to_s - end + def to_s + # stringify to fully-resolved location + path.to_s + end - private + private - def load_cask - instance_eval(cask_contents, __FILE__, __LINE__) - rescue Hbc::CaskError, StandardError, ScriptError => e - # bug: e.message.concat doesn't work with Hbc::CaskError exceptions - raise e, e.message.concat(" while loading '#{path}'") - end + def load_cask + instance_eval(cask_contents, __FILE__, __LINE__) + rescue CaskError, StandardError, ScriptError => e + # bug: e.message.concat doesn't work with CaskError exceptions + raise e, e.message.concat(" while loading '#{path}'") + end - def cask_contents - File.open(path, "rb") do |handle| - contents = handle.read - if defined?(Encoding) - contents.force_encoding("UTF-8") - else - contents + def cask_contents + File.open(path, "rb") do |handle| + contents = handle.read + if defined?(Encoding) + contents.force_encoding("UTF-8") + else + contents + end + end end - end - end - def cask(header_token, &block) - build_cask(Hbc::Cask, header_token, &block) - end + def cask(header_token, &block) + build_cask(Cask, header_token, &block) + end - def test_cask(header_token, &block) - build_cask(Hbc::TestCask, header_token, &block) - end + def test_cask(header_token, &block) + build_cask(TestCask, header_token, &block) + end - def build_cask(cask_class, header_token, &block) - if header_token.is_a?(Hash) - # Cask file is using old `cask :v1 => 'token'` syntax - header_token = header_token.values.first - end - raise Hbc::CaskTokenDoesNotMatchError.new(cask_token, header_token) unless cask_token == header_token - cask_class.new(cask_token, sourcefile_path: path, &block) - end + def build_cask(cask_class, header_token, &block) + if header_token.is_a?(Hash) + # Cask file is using old `cask :v1 => 'token'` syntax + header_token = header_token.values.first + end + raise CaskTokenDoesNotMatchError.new(cask_token, header_token) unless cask_token == header_token + cask_class.new(cask_token, sourcefile_path: path, &block) + end - def cask_token - path.basename.to_s.sub(%r{\.rb}, "") + def cask_token + path.basename.to_s.sub(%r{\.rb}, "") + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/source/path_slash_optional.rb b/Library/Homebrew/cask/lib/hbc/source/path_slash_optional.rb index fb34c481a..d96a41130 100644 --- a/Library/Homebrew/cask/lib/hbc/source/path_slash_optional.rb +++ b/Library/Homebrew/cask/lib/hbc/source/path_slash_optional.rb @@ -1,8 +1,12 @@ require "hbc/source/path_base" -class Hbc::Source::PathSlashOptional < Hbc::Source::PathBase - def self.me?(query) - path = path_for_query(query) - path.exist? +module Hbc + module Source + class PathSlashOptional < PathBase + def self.me?(query) + path = path_for_query(query) + path.exist? + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/source/path_slash_required.rb b/Library/Homebrew/cask/lib/hbc/source/path_slash_required.rb index 0c533a8a5..2753b1710 100644 --- a/Library/Homebrew/cask/lib/hbc/source/path_slash_required.rb +++ b/Library/Homebrew/cask/lib/hbc/source/path_slash_required.rb @@ -1,8 +1,12 @@ require "hbc/source/path_base" -class Hbc::Source::PathSlashRequired < Hbc::Source::PathBase - def self.me?(query) - path = path_for_query(query) - path.to_s.include?("/") && path.exist? +module Hbc + module Source + class PathSlashRequired < PathBase + def self.me?(query) + path = path_for_query(query) + path.to_s.include?("/") && path.exist? + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/source/tapped.rb b/Library/Homebrew/cask/lib/hbc/source/tapped.rb index da9366840..6716e3a35 100644 --- a/Library/Homebrew/cask/lib/hbc/source/tapped.rb +++ b/Library/Homebrew/cask/lib/hbc/source/tapped.rb @@ -1,35 +1,39 @@ -class Hbc::Source::Tapped - def self.me?(query) - path_for_query(query).exist? - end +module Hbc + module Source + class Tapped + def self.me?(query) + path_for_query(query).exist? + end - def self.path_for_query(query) - # Repeating Hbc.all_tokens is very slow for operations such as - # brew cask list, but memoizing the value might cause breakage - # elsewhere, given that installation and tap status is permitted - # to change during the course of an invocation. - token_with_tap = Hbc.all_tokens.find { |t| t.split("/").last == query.sub(%r{\.rb$}i, "") } - if token_with_tap - user, repo, token = token_with_tap.split("/") - Tap.fetch(user, repo).cask_dir.join("#{token}.rb") - else - Hbc.default_tap.cask_dir.join(query.sub(%r{(\.rb)?$}i, ".rb")) - end - end + def self.path_for_query(query) + # Repeating Hbc.all_tokens is very slow for operations such as + # brew cask list, but memoizing the value might cause breakage + # elsewhere, given that installation and tap status is permitted + # to change during the course of an invocation. + token_with_tap = Hbc.all_tokens.find { |t| t.split("/").last == query.sub(%r{\.rb$}i, "") } + if token_with_tap + user, repo, token = token_with_tap.split("/") + Tap.fetch(user, repo).cask_dir.join("#{token}.rb") + else + Hbc.default_tap.cask_dir.join(query.sub(%r{(\.rb)?$}i, ".rb")) + end + end - attr_reader :token + attr_reader :token - def initialize(token) - @token = token - end + def initialize(token) + @token = token + end - def load - path = self.class.path_for_query(token) - Hbc::Source::PathSlashOptional.new(path).load - end + def load + path = self.class.path_for_query(token) + PathSlashOptional.new(path).load + end - def to_s - # stringify to fully-resolved location - self.class.path_for_query(token).expand_path.to_s + def to_s + # stringify to fully-resolved location + self.class.path_for_query(token).expand_path.to_s + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/source/tapped_qualified.rb b/Library/Homebrew/cask/lib/hbc/source/tapped_qualified.rb index 1da013db2..52191f279 100644 --- a/Library/Homebrew/cask/lib/hbc/source/tapped_qualified.rb +++ b/Library/Homebrew/cask/lib/hbc/source/tapped_qualified.rb @@ -1,22 +1,26 @@ require "hbc/source/tapped" -class Hbc::Source::TappedQualified < Hbc::Source::Tapped - def self.me?(query) - return if (tap = tap_for_query(query)).nil? +module Hbc + module Source + class TappedQualified < Tapped + def self.me?(query) + return if (tap = tap_for_query(query)).nil? - tap.installed? && path_for_query(query).exist? - end + tap.installed? && path_for_query(query).exist? + end - def self.tap_for_query(query) - qualified_token = Hbc::QualifiedToken.parse(query) - return if qualified_token.nil? + def self.tap_for_query(query) + qualified_token = QualifiedToken.parse(query) + return if qualified_token.nil? - user, repo, token = qualified_token - Tap.fetch(user, repo) - end + user, repo = qualified_token[0..1] + Tap.fetch(user, repo) + end - def self.path_for_query(query) - user, repo, token = Hbc::QualifiedToken.parse(query) - Tap.fetch(user, repo).cask_dir.join(token.sub(%r{(\.rb)?$}i, ".rb")) + def self.path_for_query(query) + user, repo, token = QualifiedToken.parse(query) + Tap.fetch(user, repo).cask_dir.join(token.sub(%r{(\.rb)?$}i, ".rb")) + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/source/untapped_qualified.rb b/Library/Homebrew/cask/lib/hbc/source/untapped_qualified.rb index 7188d34ce..6041605d8 100644 --- a/Library/Homebrew/cask/lib/hbc/source/untapped_qualified.rb +++ b/Library/Homebrew/cask/lib/hbc/source/untapped_qualified.rb @@ -1,10 +1,14 @@ require "hbc/source/tapped_qualified" -class Hbc::Source::UntappedQualified < Hbc::Source::TappedQualified - def self.me?(query) - return if (tap = tap_for_query(query)).nil? +module Hbc + module Source + class UntappedQualified < TappedQualified + def self.me?(query) + return if (tap = tap_for_query(query)).nil? - tap.install - tap.installed? && path_for_query(query).exist? + tap.install + tap.installed? && path_for_query(query).exist? + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/source/uri.rb b/Library/Homebrew/cask/lib/hbc/source/uri.rb index 99bc50688..09fab4bd0 100644 --- a/Library/Homebrew/cask/lib/hbc/source/uri.rb +++ b/Library/Homebrew/cask/lib/hbc/source/uri.rb @@ -1,28 +1,32 @@ -class Hbc::Source::URI - def self.me?(query) - !(query.to_s =~ URI.regexp).nil? - end +module Hbc + module Source + class URI + def self.me?(query) + !(query.to_s =~ ::URI.regexp).nil? + end - attr_reader :uri + attr_reader :uri - def initialize(uri) - @uri = uri - end + def initialize(uri) + @uri = uri + end - def load - Hbc.cache.mkpath - path = Hbc.cache.join(File.basename(uri)) - ohai "Downloading #{uri}" - odebug "Download target -> #{path}" - begin - curl(uri, "-o", path.to_s) - rescue ErrorDuringExecution - raise Hbc::CaskUnavailableError, uri - end - Hbc::Source::PathSlashOptional.new(path).load - end + def load + Hbc.cache.mkpath + path = Hbc.cache.join(File.basename(uri)) + ohai "Downloading #{uri}" + odebug "Download target -> #{path}" + begin + curl(uri, "-o", path.to_s) + rescue ErrorDuringExecution + raise CaskUnavailableError, uri + end + PathSlashOptional.new(path).load + end - def to_s - uri.to_s + def to_s + uri.to_s + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/staged.rb b/Library/Homebrew/cask/lib/hbc/staged.rb index 7e2c93541..dcc05ef5d 100644 --- a/Library/Homebrew/cask/lib/hbc/staged.rb +++ b/Library/Homebrew/cask/lib/hbc/staged.rb @@ -1,48 +1,50 @@ -module Hbc::Staged - def info_plist_file(index = 0) - index = 0 if index == :first - index = 1 if index == :second - index = -1 if index == :last - Hbc.appdir.join(@cask.artifacts[:app].to_a.at(index).first, "Contents", "Info.plist") - end - - def plist_exec(cmd) - @command.run!("/usr/libexec/PlistBuddy", args: ["-c", cmd, info_plist_file]) - end - - def plist_set(key, value) - plist_exec("Set #{key} #{value}") - rescue StandardError => e - raise Hbc::CaskError, "#{@cask.token}: 'plist_set' failed with: #{e}" - end - - def bundle_identifier - plist_exec("Print CFBundleIdentifier").stdout.chomp - rescue StandardError => e - raise Hbc::CaskError, "#{@cask.token}: 'bundle_identifier' failed with: #{e}" - end - - def set_permissions(paths, permissions_str) - full_paths = remove_nonexistent(paths) - return if full_paths.empty? - @command.run!("/bin/chmod", args: ["-R", "--", permissions_str] + full_paths, - sudo: true) - end - - def set_ownership(paths, user: current_user, group: "staff") - full_paths = remove_nonexistent(paths) - return if full_paths.empty? - @command.run!("/usr/sbin/chown", args: ["-R", "--", "#{user}:#{group}"] + full_paths, - sudo: true) - end - - def current_user - Hbc::Utils.current_user - end - - private - - def remove_nonexistent(paths) - Array(paths).map { |p| Pathname(p).expand_path }.select(&:exist?) +module Hbc + module Staged + def info_plist_file(index = 0) + index = 0 if index == :first + index = 1 if index == :second + index = -1 if index == :last + Hbc.appdir.join(@cask.artifacts[:app].to_a.at(index).first, "Contents", "Info.plist") + end + + def plist_exec(cmd) + @command.run!("/usr/libexec/PlistBuddy", args: ["-c", cmd, info_plist_file]) + end + + def plist_set(key, value) + plist_exec("Set #{key} #{value}") + rescue StandardError => e + raise CaskError, "#{@cask.token}: 'plist_set' failed with: #{e}" + end + + def bundle_identifier + plist_exec("Print CFBundleIdentifier").stdout.chomp + rescue StandardError => e + raise CaskError, "#{@cask.token}: 'bundle_identifier' failed with: #{e}" + end + + def set_permissions(paths, permissions_str) + full_paths = remove_nonexistent(paths) + return if full_paths.empty? + @command.run!("/bin/chmod", args: ["-R", "--", permissions_str] + full_paths, + sudo: true) + end + + def set_ownership(paths, user: current_user, group: "staff") + full_paths = remove_nonexistent(paths) + return if full_paths.empty? + @command.run!("/usr/sbin/chown", args: ["-R", "--", "#{user}:#{group}"] + full_paths, + sudo: true) + end + + def current_user + Utils.current_user + end + + private + + def remove_nonexistent(paths) + Array(paths).map { |p| Pathname(p).expand_path }.select(&:exist?) + end end end diff --git a/Library/Homebrew/cask/lib/hbc/system_command.rb b/Library/Homebrew/cask/lib/hbc/system_command.rb index bb8d91504..160aadff9 100644 --- a/Library/Homebrew/cask/lib/hbc/system_command.rb +++ b/Library/Homebrew/cask/lib/hbc/system_command.rb @@ -1,173 +1,179 @@ require "open3" require "shellwords" -class Hbc::SystemCommand - attr_reader :command +module Hbc + class SystemCommand + attr_reader :command - def self.run(executable, options = {}) - new(executable, options).run! - end + def self.run(executable, options = {}) + new(executable, options).run! + end - def self.run!(command, options = {}) - run(command, options.merge(must_succeed: true)) - end + def self.run!(command, options = {}) + run(command, options.merge(must_succeed: true)) + end - def run! - @processed_output = { stdout: "", stderr: "" } - odebug "Executing: #{expanded_command.utf8_inspect}" - - each_output_line do |type, line| - case type - when :stdout - processed_output[:stdout] << line - ohai line.chomp if options[:print_stdout] - when :stderr - processed_output[:stderr] << line - ohai line.chomp if options[:print_stderr] + def run! + @processed_output = { stdout: "", stderr: "" } + odebug "Executing: #{expanded_command.utf8_inspect}" + + each_output_line do |type, line| + case type + when :stdout + processed_output[:stdout] << line + ohai line.chomp if options[:print_stdout] + when :stderr + processed_output[:stderr] << line + ohai line.chomp if options[:print_stderr] + end end - end - assert_success if options[:must_succeed] - result - end + assert_success if options[:must_succeed] + result + end - def initialize(executable, options) - @executable = executable - @options = options - process_options! - end + def initialize(executable, options) + @executable = executable + @options = options + process_options! + end - private - - attr_reader :executable, :options, :processed_output, :processed_status - - def process_options! - options.assert_valid_keys :input, :print_stdout, :print_stderr, :args, :must_succeed, :sudo, :bsexec - sudo_prefix = %w[/usr/bin/sudo -E --] - bsexec_prefix = ["/bin/launchctl", "bsexec", options[:bsexec] == :startup ? "/" : options[:bsexec]] - @command = [executable] - options[:print_stderr] = true unless options.key?(:print_stderr) - @command.unshift(*bsexec_prefix) if options[:bsexec] - @command.unshift(*sudo_prefix) if options[:sudo] - @command.concat(options[:args]) if options.key?(:args) && !options[:args].empty? - @command[0] = Shellwords.shellescape(@command[0]) if @command.size == 1 - nil - end + private + + attr_reader :executable, :options, :processed_output, :processed_status + + def process_options! + options.assert_valid_keys :input, :print_stdout, :print_stderr, :args, :must_succeed, :sudo, :bsexec + sudo_prefix = %w[/usr/bin/sudo -E --] + bsexec_prefix = ["/bin/launchctl", "bsexec", options[:bsexec] == :startup ? "/" : options[:bsexec]] + @command = [executable] + options[:print_stderr] = true unless options.key?(:print_stderr) + @command.unshift(*bsexec_prefix) if options[:bsexec] + @command.unshift(*sudo_prefix) if options[:sudo] + @command.concat(options[:args]) if options.key?(:args) && !options[:args].empty? + @command[0] = Shellwords.shellescape(@command[0]) if @command.size == 1 + nil + end - def assert_success - return if processed_status && processed_status.success? - raise Hbc::CaskCommandFailedError.new(command.utf8_inspect, processed_output[:stdout], processed_output[:stderr], processed_status) - end + def assert_success + return if processed_status && processed_status.success? + raise CaskCommandFailedError.new(command.utf8_inspect, processed_output[:stdout], processed_output[:stderr], processed_status) + end - def expanded_command - @expanded_command ||= command.map { |arg| - if arg.respond_to?(:to_path) - File.absolute_path(arg) - else - String(arg) - end - } - end + def expanded_command + @expanded_command ||= command.map { |arg| + if arg.respond_to?(:to_path) + File.absolute_path(arg) + else + String(arg) + end + } + end - def each_output_line(&b) - raw_stdin, raw_stdout, raw_stderr, raw_wait_thr = - Open3.popen3(*expanded_command) + def each_output_line(&b) + raw_stdin, raw_stdout, raw_stderr, raw_wait_thr = + Open3.popen3(*expanded_command) - write_input_to(raw_stdin) if options[:input] - raw_stdin.close_write - each_line_from [raw_stdout, raw_stderr], &b + write_input_to(raw_stdin) if options[:input] + raw_stdin.close_write + each_line_from [raw_stdout, raw_stderr], &b - @processed_status = raw_wait_thr.value - end + @processed_status = raw_wait_thr.value + end - def write_input_to(raw_stdin) - Array(options[:input]).each { |line| raw_stdin.puts line } - end + def write_input_to(raw_stdin) + Array(options[:input]).each { |line| raw_stdin.puts line } + end - def each_line_from(sources) - loop do - readable_sources = IO.select(sources)[0] - readable_sources.delete_if(&:eof?).first(1).each do |source| - type = (source == sources[0] ? :stdout : :stderr) - begin - yield(type, source.readline_nonblock || "") - rescue IO::WaitReadable, EOFError - next + def each_line_from(sources) + loop do + readable_sources = IO.select(sources)[0] + readable_sources.delete_if(&:eof?).first(1).each do |source| + type = (source == sources[0] ? :stdout : :stderr) + begin + yield(type, source.readline_nonblock || "") + rescue IO::WaitReadable, EOFError + next + end end + break if readable_sources.empty? end - break if readable_sources.empty? + sources.each(&:close_read) end - sources.each(&:close_read) - end - def result - Hbc::SystemCommand::Result.new(command, - processed_output[:stdout], - processed_output[:stderr], - processed_status.exitstatus) + def result + Result.new(command, + processed_output[:stdout], + processed_output[:stderr], + processed_status.exitstatus) + end end end -class Hbc::SystemCommand::Result - attr_accessor :command, :stdout, :stderr, :exit_status +module Hbc + class SystemCommand + class Result + attr_accessor :command, :stdout, :stderr, :exit_status - def initialize(command, stdout, stderr, exit_status) - @command = command - @stdout = stdout - @stderr = stderr - @exit_status = exit_status - end + def initialize(command, stdout, stderr, exit_status) + @command = command + @stdout = stdout + @stderr = stderr + @exit_status = exit_status + end - def plist - @plist ||= self.class._parse_plist(@command, @stdout.dup) - end + def plist + @plist ||= self.class._parse_plist(@command, @stdout.dup) + end - def success? - @exit_status == 0 - end + def success? + @exit_status.zero? + end - def merged_output - @merged_output ||= @stdout + @stderr - end + def merged_output + @merged_output ||= @stdout + @stderr + end - def to_s - @stdout - end + def to_s + @stdout + end - def self._warn_plist_garbage(command, garbage) - return true unless garbage =~ %r{\S} - external = File.basename(command.first) - lines = garbage.strip.split("\n") - opoo "Non-XML stdout from #{external}:" - $stderr.puts lines.map { |l| " #{l}" } - end + def self._warn_plist_garbage(command, garbage) + return true unless garbage =~ %r{\S} + external = File.basename(command.first) + lines = garbage.strip.split("\n") + opoo "Non-XML stdout from #{external}:" + $stderr.puts lines.map { |l| " #{l}" } + end - def self._parse_plist(command, output) - raise Hbc::CaskError, "Empty plist input" unless output =~ %r{\S} - output.sub!(%r{\A(.*?)(<\?\s*xml)}m, '\2') - _warn_plist_garbage(command, Regexp.last_match[1]) if Hbc.debug - output.sub!(%r{(<\s*/\s*plist\s*>)(.*?)\Z}m, '\1') - _warn_plist_garbage(command, Regexp.last_match[2]) - xml = Plist.parse_xml(output) - unless xml.respond_to?(:keys) && !xml.keys.empty? - raise Hbc::CaskError, <<-EOS -Empty result parsing plist output from command. - command was: - #{command.utf8_inspect} - output we attempted to parse: - #{output} - EOS + def self._parse_plist(command, output) + raise CaskError, "Empty plist input" unless output =~ %r{\S} + output.sub!(%r{\A(.*?)(<\?\s*xml)}m, '\2') + _warn_plist_garbage(command, Regexp.last_match[1]) if Hbc.debug + output.sub!(%r{(<\s*/\s*plist\s*>)(.*?)\Z}m, '\1') + _warn_plist_garbage(command, Regexp.last_match[2]) + xml = Plist.parse_xml(output) + unless xml.respond_to?(:keys) && !xml.keys.empty? + raise CaskError, <<-EOS + Empty result parsing plist output from command. + command was: + #{command.utf8_inspect} + output we attempted to parse: + #{output} + EOS + end + xml + rescue Plist::ParseError => e + raise CaskError, <<-EOS + Error parsing plist output from command. + command was: + #{command.utf8_inspect} + error was: + #{e} + output we attempted to parse: + #{output} + EOS + end end - xml - rescue Plist::ParseError => e - raise Hbc::CaskError, <<-EOS -Error parsing plist output from command. - command was: - #{command.utf8_inspect} - error was: - #{e} - output we attempted to parse: - #{output} - EOS end end diff --git a/Library/Homebrew/cask/lib/hbc/topological_hash.rb b/Library/Homebrew/cask/lib/hbc/topological_hash.rb index bbad1bb4d..2e484a28d 100644 --- a/Library/Homebrew/cask/lib/hbc/topological_hash.rb +++ b/Library/Homebrew/cask/lib/hbc/topological_hash.rb @@ -1,12 +1,14 @@ require "tsort" # a basic topologically sortable hashmap -class Hbc::TopologicalHash < Hash - include TSort +module Hbc + class TopologicalHash < Hash + include TSort - alias tsort_each_node each_key + alias tsort_each_node each_key - def tsort_each_child(node, &block) - fetch(node).each(&block) + def tsort_each_child(node, &block) + fetch(node).each(&block) + end end end diff --git a/Library/Homebrew/cask/lib/hbc/underscore_supporting_uri.rb b/Library/Homebrew/cask/lib/hbc/underscore_supporting_uri.rb index 34bfea387..8f8f66f43 100644 --- a/Library/Homebrew/cask/lib/hbc/underscore_supporting_uri.rb +++ b/Library/Homebrew/cask/lib/hbc/underscore_supporting_uri.rb @@ -1,26 +1,28 @@ require "uri" -module Hbc::UnderscoreSupportingURI - def self.parse(maybe_uri) - return nil if maybe_uri.nil? - URI.parse(maybe_uri) - rescue URI::InvalidURIError => e - scheme, host, path = simple_parse(maybe_uri) - raise e unless path && host.include?("_") - URI.parse(without_host_underscores(scheme, host, path)).tap do |uri| - uri.instance_variable_set("@host", host) +module Hbc + module UnderscoreSupportingURI + def self.parse(maybe_uri) + return nil if maybe_uri.nil? + URI.parse(maybe_uri) + rescue URI::InvalidURIError => e + scheme, host, path = simple_parse(maybe_uri) + raise e unless path && host.include?("_") + URI.parse(without_host_underscores(scheme, host, path)).tap do |uri| + uri.instance_variable_set("@host", host) + end end - end - def self.simple_parse(maybe_uri) - scheme, host_and_path = maybe_uri.split("://") - host, path = host_and_path.split("/", 2) - [scheme, host, path] - rescue StandardError - nil - end + def self.simple_parse(maybe_uri) + scheme, host_and_path = maybe_uri.split("://") + host, path = host_and_path.split("/", 2) + [scheme, host, path] + rescue StandardError + nil + end - def self.without_host_underscores(scheme, host, path) - ["#{scheme}:/", host.tr("_", "-"), path].join("/") + def self.without_host_underscores(scheme, host, path) + ["#{scheme}:/", host.tr("_", "-"), path].join("/") + end end end diff --git a/Library/Homebrew/cask/lib/hbc/url.rb b/Library/Homebrew/cask/lib/hbc/url.rb index 5f763ca8a..c09aaa061 100644 --- a/Library/Homebrew/cask/lib/hbc/url.rb +++ b/Library/Homebrew/cask/lib/hbc/url.rb @@ -1,37 +1,39 @@ require "forwardable" -class Hbc::URL - FAKE_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10) http://caskroom.io".freeze +module Hbc + class URL + FAKE_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10) http://caskroom.io".freeze - attr_reader :using, :revision, :trust_cert, :uri, :cookies, :referer, :data + attr_reader :using, :revision, :trust_cert, :uri, :cookies, :referer, :data - extend Forwardable - def_delegators :uri, :path, :scheme, :to_s + extend Forwardable + def_delegators :uri, :path, :scheme, :to_s - def self.from(*args, &block) - if block_given? - Hbc::DSL::StanzaProxy.once(self) { new(*block.call) } - else - new(*args) + def self.from(*args, &block) + if block_given? + Hbc::DSL::StanzaProxy.once(self) { new(*block.call) } + else + new(*args) + end end - end - def initialize(uri, options = {}) - @uri = Hbc::UnderscoreSupportingURI.parse(uri) - @user_agent = options[:user_agent] - @cookies = options[:cookies] - @referer = options[:referer] - @using = options[:using] - @revision = options[:revision] - @trust_cert = options[:trust_cert] - @data = options[:data] - end + def initialize(uri, options = {}) + @uri = Hbc::UnderscoreSupportingURI.parse(uri) + @user_agent = options[:user_agent] + @cookies = options[:cookies] + @referer = options[:referer] + @using = options[:using] + @revision = options[:revision] + @trust_cert = options[:trust_cert] + @data = options[:data] + end - def user_agent - if @user_agent == :fake - FAKE_USER_AGENT - else - @user_agent + def user_agent + if @user_agent == :fake + FAKE_USER_AGENT + else + @user_agent + end end end end diff --git a/Library/Homebrew/cask/lib/hbc/url_checker.rb b/Library/Homebrew/cask/lib/hbc/url_checker.rb index 8737903df..4dc1f136a 100644 --- a/Library/Homebrew/cask/lib/hbc/url_checker.rb +++ b/Library/Homebrew/cask/lib/hbc/url_checker.rb @@ -1,75 +1,77 @@ require "hbc/checkable" -class Hbc::UrlChecker - attr_accessor :cask, :response_status, :headers +module Hbc + class UrlChecker + attr_accessor :cask, :response_status, :headers - include Hbc::Checkable + include Checkable - def initialize(cask, fetcher = Hbc::Fetcher) - @cask = cask - @fetcher = fetcher - @headers = {} - end + def initialize(cask, fetcher = Fetcher) + @cask = cask + @fetcher = fetcher + @headers = {} + end - def summary_header - "url check result for #{cask}" - end + def summary_header + "url check result for #{cask}" + end - def run - _get_data_from_request - return if errors? - _check_response_status - end + def run + _get_data_from_request + return if errors? + _check_response_status + end - HTTP_RESPONSES = [ - "HTTP/1.0 200 OK", - "HTTP/1.1 200 OK", - "HTTP/1.1 302 Found", - ].freeze + HTTP_RESPONSES = [ + "HTTP/1.0 200 OK", + "HTTP/1.1 200 OK", + "HTTP/1.1 302 Found", + ].freeze - OK_RESPONSES = { - "http" => HTTP_RESPONSES, - "https" => HTTP_RESPONSES, - "ftp" => ["OK"], - }.freeze + OK_RESPONSES = { + "http" => HTTP_RESPONSES, + "https" => HTTP_RESPONSES, + "ftp" => ["OK"], + }.freeze - def _check_response_status - ok = OK_RESPONSES[cask.url.scheme] - return if ok.include?(@response_status) - add_error "unexpected http response, expecting #{ok.map(&:utf8_inspect).join(' or ')}, got #{@response_status.utf8_inspect}" - end + def _check_response_status + ok = OK_RESPONSES[cask.url.scheme] + return if ok.include?(@response_status) + add_error "unexpected http response, expecting #{ok.map(&:utf8_inspect).join(" or ")}, got #{@response_status.utf8_inspect}" + end - def _get_data_from_request - response = @fetcher.head(cask.url) + def _get_data_from_request + response = @fetcher.head(cask.url) - if response.empty? - add_error "timeout while requesting #{cask.url}" - return - end + if response.empty? + add_error "timeout while requesting #{cask.url}" + return + end - response_lines = response.split("\n").map(&:chomp) + response_lines = response.split("\n").map(&:chomp) - case cask.url.scheme - when "http", "https" then - @response_status = response_lines.grep(%r{^HTTP}).last - if @response_status.respond_to?(:strip) - @response_status.strip! - unless response_lines.index(@response_status).nil? - http_headers = response_lines[(response_lines.index(@response_status) + 1)..-1] - http_headers.each do |line| - header_name, header_value = line.split(": ") - @headers[header_name] = header_value + case cask.url.scheme + when "http", "https" then + @response_status = response_lines.grep(%r{^HTTP}).last + if @response_status.respond_to?(:strip) + @response_status.strip! + unless response_lines.index(@response_status).nil? + http_headers = response_lines[(response_lines.index(@response_status) + 1)..-1] + http_headers.each do |line| + header_name, header_value = line.split(": ") + @headers[header_name] = header_value + end end end + when "ftp" then + @response_status = "OK" + response_lines.each do |line| + header_name, header_value = line.split(": ") + @headers[header_name] = header_value + end + else + add_error "unknown scheme for #{cask.url}" end - when "ftp" then - @response_status = "OK" - response_lines.each do |line| - header_name, header_value = line.split(": ") - @headers[header_name] = header_value - end - else - add_error "unknown scheme for #{cask.url}" end end end diff --git a/Library/Homebrew/cask/lib/hbc/utils.rb b/Library/Homebrew/cask/lib/hbc/utils.rb index 599127523..9159544a6 100644 --- a/Library/Homebrew/cask/lib/hbc/utils.rb +++ b/Library/Homebrew/cask/lib/hbc/utils.rb @@ -1,5 +1,3 @@ -module Hbc::Utils; end - require "yaml" require "open3" require "stringio" @@ -32,165 +30,168 @@ end # global methods def odebug(title, *sput) - if Hbc.respond_to?(:debug) && Hbc.debug - width = Tty.width * 4 - 6 - if $stdout.tty? && title.to_s.length > width - title = title.to_s[0, width - 3] + "..." - end - puts "#{Tty.magenta}==>#{Tty.reset} #{Tty.white}#{title}#{Tty.reset}" - puts sput unless sput.empty? + return unless Hbc.respond_to?(:debug) + return unless Hbc.debug + + width = Tty.width * 4 - 6 + if $stdout.tty? && title.to_s.length > width + title = title.to_s[0, width - 3] + "..." end + puts "#{Tty.magenta}==>#{Tty.reset} #{Tty.white}#{title}#{Tty.reset}" + puts sput unless sput.empty? end -module Hbc::Utils - def self.which(cmd, path = ENV["PATH"]) - unless File.basename(cmd) == cmd.to_s - # cmd contains a directory element +module Hbc + module Utils + def self.which(cmd, path = ENV["PATH"]) + unless File.basename(cmd) == cmd.to_s + # cmd contains a directory element + cmd_pn = Pathname(cmd) + return nil unless cmd_pn.absolute? + return resolve_executable(cmd_pn) + end + path.split(File::PATH_SEPARATOR).each do |elt| + fq_cmd = Pathname(elt).expand_path.join(cmd) + resolved = resolve_executable fq_cmd + return resolved if resolved + end + nil + end + + def self.resolve_executable(cmd) cmd_pn = Pathname(cmd) - return nil unless cmd_pn.absolute? - return resolve_executable(cmd_pn) + return nil unless cmd_pn.exist? + return nil unless cmd_pn.executable? + begin + cmd_pn = Pathname(cmd_pn.realpath) + rescue RuntimeError + return nil + end + return nil unless cmd_pn.file? + cmd_pn end - path.split(File::PATH_SEPARATOR).each do |elt| - fq_cmd = Pathname(elt).expand_path.join(cmd) - resolved = resolve_executable fq_cmd - return resolved if resolved + + def self.gain_permissions_remove(path, command: SystemCommand) + if path.respond_to?(:rmtree) && path.exist? + gain_permissions(path, ["-R"], command, &:rmtree) + elsif File.symlink?(path) + gain_permissions(path, ["-h"], command, &FileUtils.method(:rm_f)) + end end - nil - end - def self.resolve_executable(cmd) - cmd_pn = Pathname(cmd) - return nil unless cmd_pn.exist? - return nil unless cmd_pn.executable? - begin - cmd_pn = Pathname(cmd_pn.realpath) - rescue RuntimeError - return nil + def self.gain_permissions(path, command_args, command) + tried_permissions = false + tried_ownership = false + begin + yield path + rescue StandardError + # in case of permissions problems + unless tried_permissions + # TODO: Better handling for the case where path is a symlink. + # The -h and -R flags cannot be combined, and behavior is + # dependent on whether the file argument has a trailing + # slash. This should do the right thing, but is fragile. + command.run("/usr/bin/chflags", + must_succeed: false, + args: command_args + ["--", "000", path]) + command.run("/bin/chmod", + must_succeed: false, + args: command_args + ["--", "u+rwx", path]) + command.run("/bin/chmod", + must_succeed: false, + args: command_args + ["-N", path]) + tried_permissions = true + retry # rmtree + end + unless tried_ownership + # in case of ownership problems + # TODO: Further examine files to see if ownership is the problem + # before using sudo+chown + ohai "Using sudo to gain ownership of path '#{path}'" + command.run("/usr/sbin/chown", + args: command_args + ["--", current_user, path], + sudo: true) + tried_ownership = true + # retry chflags/chmod after chown + tried_permissions = false + retry # rmtree + end + end end - return nil unless cmd_pn.file? - cmd_pn - end - def self.gain_permissions_remove(path, command: Hbc::SystemCommand) - if path.respond_to?(:rmtree) && path.exist? - gain_permissions(path, ["-R"], command, &:rmtree) - elsif File.symlink?(path) - gain_permissions(path, ["-h"], command, &FileUtils.method(:rm_f)) + def self.current_user + Etc.getpwuid(Process.euid).name end - end - def self.gain_permissions(path, command_args, command) - tried_permissions = false - tried_ownership = false - begin - yield path - rescue StandardError - # in case of permissions problems - unless tried_permissions - # TODO: Better handling for the case where path is a symlink. - # The -h and -R flags cannot be combined, and behavior is - # dependent on whether the file argument has a trailing - # slash. This should do the right thing, but is fragile. - command.run("/usr/bin/chflags", - must_succeed: false, - args: command_args + ["--", "000", path]) - command.run("/bin/chmod", - must_succeed: false, - args: command_args + ["--", "u+rwx", path]) - command.run("/bin/chmod", - must_succeed: false, - args: command_args + ["-N", path]) - tried_permissions = true - retry # rmtree + # paths that "look" descendant (textually) will still + # return false unless both the given paths exist + def self.file_is_descendant(file, dir) + file = Pathname.new(file) + dir = Pathname.new(dir) + return false unless file.exist? && dir.exist? + unless dir.directory? + onoe "Argument must be a directory: '#{dir}'" + return false end - unless tried_ownership - # in case of ownership problems - # TODO: Further examine files to see if ownership is the problem - # before using sudo+chown - ohai "Using sudo to gain ownership of path '#{path}'" - command.run("/usr/sbin/chown", - args: command_args + ["--", current_user, path], - sudo: true) - tried_ownership = true - # retry chflags/chmod after chown - tried_permissions = false - retry # rmtree + unless file.absolute? && dir.absolute? + onoe "Both arguments must be absolute: '#{file}', '#{dir}'" + return false end + while file.parent != file + return true if File.identical?(file, dir) + file = file.parent + end + false end - end - def self.current_user - Etc.getpwuid(Process.euid).name - end - - # paths that "look" descendant (textually) will still - # return false unless both the given paths exist - def self.file_is_descendant(file, dir) - file = Pathname.new(file) - dir = Pathname.new(dir) - return false unless file.exist? && dir.exist? - unless dir.directory? - onoe "Argument must be a directory: '#{dir}'" - return false - end - unless file.absolute? && dir.absolute? - onoe "Both arguments must be absolute: '#{file}', '#{dir}'" - return false - end - while file.parent != file - return true if File.identical?(file, dir) - file = file.parent + def self.path_occupied?(path) + File.exist?(path) || File.symlink?(path) end - false - end - - def self.path_occupied?(path) - File.exist?(path) || File.symlink?(path) - end - def self.error_message_with_suggestions - <<-EOS.undent - Most likely, this means you have an outdated version of Homebrew-Cask. Please run: + def self.error_message_with_suggestions + <<-EOS.undent + Most likely, this means you have an outdated version of Homebrew-Cask. Please run: - #{Tty.green}#{UPDATE_CMD} + #{Tty.green}#{UPDATE_CMD} - #{Tty.reset}If this doesn’t fix the problem, please report this bug: + #{Tty.reset}If this doesn’t fix the problem, please report this bug: - #{Tty.em}#{ISSUES_URL}#{Tty.reset} + #{Tty.em}#{ISSUES_URL}#{Tty.reset} - EOS - end + EOS + end - def self.method_missing_message(method, token, section = nil) - poo = [] - poo << "Unexpected method '#{method}' called" - poo << "during #{section}" if section - poo << "on Cask #{token}." + def self.method_missing_message(method, token, section = nil) + poo = [] + poo << "Unexpected method '#{method}' called" + poo << "during #{section}" if section + poo << "on Cask #{token}." - opoo(poo.join(" ") + "\n" + error_message_with_suggestions) - end + opoo(poo.join(" ") + "\n" + error_message_with_suggestions) + end - def self.nowstamp_metadata_path(container_path) - @timenow ||= Time.now.gmtime - if container_path.respond_to?(:join) - precision = 3 - timestamp = @timenow.strftime("%Y%m%d%H%M%S") - fraction = format("%.#{precision}f", @timenow.to_f - @timenow.to_i)[1..-1] - timestamp.concat(fraction) - container_path.join(timestamp) + def self.nowstamp_metadata_path(container_path) + @timenow ||= Time.now.gmtime + if container_path.respond_to?(:join) + precision = 3 + timestamp = @timenow.strftime("%Y%m%d%H%M%S") + fraction = format("%.#{precision}f", @timenow.to_f - @timenow.to_i)[1..-1] + timestamp.concat(fraction) + container_path.join(timestamp) + end end - end - def self.size_in_bytes(files) - Array(files).reduce(0) { |a, e| a + (File.size?(e) || 0) } - end + def self.size_in_bytes(files) + Array(files).reduce(0) { |a, e| a + (File.size?(e) || 0) } + end - def self.capture_stderr - previous_stderr = $stderr - $stderr = StringIO.new - yield - $stderr.string - ensure - $stderr = previous_stderr + def self.capture_stderr + previous_stderr = $stderr + $stderr = StringIO.new + yield + $stderr.string + ensure + $stderr = previous_stderr + end end end diff --git a/Library/Homebrew/cask/lib/hbc/utils/file.rb b/Library/Homebrew/cask/lib/hbc/utils/file.rb index 967c6834f..6b80f33ce 100644 --- a/Library/Homebrew/cask/lib/hbc/utils/file.rb +++ b/Library/Homebrew/cask/lib/hbc/utils/file.rb @@ -1,12 +1,14 @@ -module Hbc::Utils - module_function +module Hbc + module Utils + module_function - def file_locked?(file) - unlocked = File.open(file).flock(File::LOCK_EX | File::LOCK_NB) - # revert lock if file was unlocked before check - File.open(file).flock(File::LOCK_UN) if unlocked - !unlocked - rescue - true + def file_locked?(file) + unlocked = File.open(file).flock(File::LOCK_EX | File::LOCK_NB) + # revert lock if file was unlocked before check + File.open(file).flock(File::LOCK_UN) if unlocked + !unlocked + rescue + true + end end end diff --git a/Library/Homebrew/cask/lib/hbc/verify.rb b/Library/Homebrew/cask/lib/hbc/verify.rb index d3c2713e7..dbf3d0e88 100644 --- a/Library/Homebrew/cask/lib/hbc/verify.rb +++ b/Library/Homebrew/cask/lib/hbc/verify.rb @@ -1,33 +1,33 @@ -module Hbc::Verify; end - require "hbc/verify/checksum" require "hbc/verify/gpg" -module Hbc::Verify - module_function +module Hbc + module Verify + module_function - def verifications - [ - Hbc::Verify::Checksum - # TODO: Hbc::Verify::Gpg - ] - end + def verifications + [ + Hbc::Verify::Checksum + # TODO: Hbc::Verify::Gpg + ] + end - def all(cask, downloaded_path) - odebug "Verifying download" - verifications = for_cask(cask) - odebug "#{verifications.size} verifications defined", verifications - verifications.each do |verification| - odebug "Running verification of class #{verification}" - verification.new(cask, downloaded_path).verify + def all(cask, downloaded_path) + odebug "Verifying download" + verifications = for_cask(cask) + odebug "#{verifications.size} verifications defined", verifications + verifications.each do |verification| + odebug "Running verification of class #{verification}" + verification.new(cask, downloaded_path).verify + end end - end - def for_cask(cask) - odebug "Determining which verifications to run for Cask #{cask}" - verifications.select do |verification| - odebug "Checking for verification class #{verification}" - verification.me?(cask) + def for_cask(cask) + odebug "Determining which verifications to run for Cask #{cask}" + verifications.select do |verification| + odebug "Checking for verification class #{verification}" + verification.me?(cask) + end end end end diff --git a/Library/Homebrew/cask/lib/hbc/verify/checksum.rb b/Library/Homebrew/cask/lib/hbc/verify/checksum.rb index 3af6f1667..d079a4446 100644 --- a/Library/Homebrew/cask/lib/hbc/verify/checksum.rb +++ b/Library/Homebrew/cask/lib/hbc/verify/checksum.rb @@ -1,43 +1,47 @@ require "digest" -class Hbc::Verify::Checksum - def self.me?(cask) - return true unless cask.sha256 == :no_check - ohai "No checksum defined for Cask #{cask}, skipping verification" - false - end - - attr_reader :cask, :downloaded_path - - def initialize(cask, downloaded_path) - @cask = cask - @downloaded_path = downloaded_path - end - - def verify - return unless self.class.me?(cask) - ohai "Verifying checksum for Cask #{cask}" - verify_checksum - end - - private - - def expected - @expected ||= cask.sha256 - end - - def computed - @computed ||= Digest::SHA2.file(downloaded_path).hexdigest - end - - def verify_checksum - raise Hbc::CaskSha256MissingError, "sha256 required: sha256 '#{computed}'" if expected.nil? || expected.empty? - - if expected == computed - odebug "SHA256 checksums match" - else - ohai 'Note: running "brew update" may fix sha256 checksum errors' - raise Hbc::CaskSha256MismatchError.new(downloaded_path, expected, computed) +module Hbc + module Verify + class Checksum + def self.me?(cask) + return true unless cask.sha256 == :no_check + ohai "No checksum defined for Cask #{cask}, skipping verification" + false + end + + attr_reader :cask, :downloaded_path + + def initialize(cask, downloaded_path) + @cask = cask + @downloaded_path = downloaded_path + end + + def verify + return unless self.class.me?(cask) + ohai "Verifying checksum for Cask #{cask}" + verify_checksum + end + + private + + def expected + @expected ||= cask.sha256 + end + + def computed + @computed ||= Digest::SHA2.file(downloaded_path).hexdigest + end + + def verify_checksum + raise CaskSha256MissingError, "sha256 required: sha256 '#{computed}'" if expected.nil? || expected.empty? + + if expected == computed + odebug "SHA256 checksums match" + else + ohai 'Note: running "brew update" may fix sha256 checksum errors' + raise CaskSha256MismatchError.new(downloaded_path, expected, computed) + end + end end end end diff --git a/Library/Homebrew/cask/lib/hbc/verify/gpg.rb b/Library/Homebrew/cask/lib/hbc/verify/gpg.rb index 6190f67d1..6eb5fc23b 100644 --- a/Library/Homebrew/cask/lib/hbc/verify/gpg.rb +++ b/Library/Homebrew/cask/lib/hbc/verify/gpg.rb @@ -1,60 +1,64 @@ -class Hbc::Verify::Gpg - def self.me?(cask) - cask.gpg - end +module Hbc + module Verify + class Gpg + def self.me?(cask) + cask.gpg + end - attr_reader :cask, :downloaded_path + attr_reader :cask, :downloaded_path - def initialize(cask, downloaded_path, command = Hbc::SystemCommand) - @command = command - @cask = cask - @downloaded_path = downloaded_path - end + def initialize(cask, downloaded_path, command = Hbc::SystemCommand) + @command = command + @cask = cask + @downloaded_path = downloaded_path + end - def available? - return @available unless @available.nil? - @available = self.class.me?(cask) && installed? - end + def available? + return @available unless @available.nil? + @available = self.class.me?(cask) && installed? + end - def installed? - cmd = @command.run("/usr/bin/type", - args: ["-p", "gpg"]) + def installed? + cmd = @command.run("/usr/bin/type", + args: ["-p", "gpg"]) - # if `gpg` is found, return its absolute path - cmd.success? ? cmd.stdout : false - end + # if `gpg` is found, return its absolute path + cmd.success? ? cmd.stdout : false + end - def fetch_sig(force = false) - unversioned_cask = cask.version.is_a?(Symbol) - cached = cask.metadata_subdir("gpg") unless unversioned_cask + def fetch_sig(force = false) + unversioned_cask = cask.version.is_a?(Symbol) + cached = cask.metadata_subdir("gpg") unless unversioned_cask - meta_dir = cached || cask.metadata_subdir("gpg", :now, true) - sig_path = meta_dir.join("signature.asc") + meta_dir = cached || cask.metadata_subdir("gpg", :now, true) + sig_path = meta_dir.join("signature.asc") - curl(cask.gpg.signature, "-o", sig_path.to_s) unless cached || force + curl(cask.gpg.signature, "-o", sig_path.to_s) unless cached || force - sig_path - end + sig_path + end - def import_key - args = if cask.gpg.key_id - ["--recv-keys", cask.gpg.key_id] - elsif cask.gpg.key_url - ["--fetch-key", cask.gpg.key_url.to_s] - end + def import_key + args = if cask.gpg.key_id + ["--recv-keys", cask.gpg.key_id] + elsif cask.gpg.key_url + ["--fetch-key", cask.gpg.key_url.to_s] + end - @command.run!("gpg", args: args) - end + @command.run!("gpg", args: args) + end - def verify - return unless available? - import_key - sig = fetch_sig + def verify + return unless available? + import_key + sig = fetch_sig - ohai "Verifying GPG signature for #{cask}" + ohai "Verifying GPG signature for #{cask}" - @command.run!("gpg", - args: ["--verify", sig, downloaded_path], - print_stdout: true) + @command.run!("gpg", + args: ["--verify", sig, downloaded_path], + print_stdout: true) + end + end end end diff --git a/Library/Homebrew/cask/lib/hbc/without_source.rb b/Library/Homebrew/cask/lib/hbc/without_source.rb index 6ed826e41..69131d5c7 100644 --- a/Library/Homebrew/cask/lib/hbc/without_source.rb +++ b/Library/Homebrew/cask/lib/hbc/without_source.rb @@ -1,15 +1,17 @@ -class Hbc::WithoutSource < Hbc::Cask - # Override from `Hbc::DSL` because we don't have a cask source file to work - # with, so we don't know the cask's `version`. - def staged_path - (caskroom_path.children - [metadata_master_container_path]).first - end +module Hbc + class WithoutSource < Cask + # Override from `Hbc::DSL` because we don't have a cask source file to work + # with, so we don't know the cask's `version`. + def staged_path + (caskroom_path.children - [metadata_master_container_path]).first + end - def to_s - "#{token} (!)" - end + def to_s + "#{token} (!)" + end - def installed? - caskroom_path.exist? + def installed? + caskroom_path.exist? + end end end diff --git a/Library/Homebrew/cask/spec/cask/cli/cleanup_spec.rb b/Library/Homebrew/cask/spec/cask/cli/cleanup_spec.rb index ab2cd55cc..fe8bb2d4d 100644 --- a/Library/Homebrew/cask/spec/cask/cli/cleanup_spec.rb +++ b/Library/Homebrew/cask/spec/cask/cli/cleanup_spec.rb @@ -12,7 +12,7 @@ describe Hbc::CLI::Cleanup do describe "cleanup" do it "removes cached downloads of given casks" do - cleaned_up_cached_download = 'caffeine' + cleaned_up_cached_download = "caffeine" cached_downloads = [ cache_location.join("#{cleaned_up_cached_download}--latest.zip"), diff --git a/Library/Homebrew/cask/spec/spec_helper.rb b/Library/Homebrew/cask/spec/spec_helper.rb index 6bb13bdcf..aff214745 100644 --- a/Library/Homebrew/cask/spec/spec_helper.rb +++ b/Library/Homebrew/cask/spec/spec_helper.rb @@ -4,13 +4,12 @@ require "rspec/wait" if ENV["HOMEBREW_TESTS_COVERAGE"] require "simplecov" - SimpleCov.command_name "test:cask:rspec" end project_root = Pathname.new(File.expand_path("../..", __FILE__)) # 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")) require "global" @@ -30,7 +29,9 @@ require "mocha/api" require "hbc" -class Hbc::TestCask < Hbc::Cask; end +module Hbc + class TestCask < Cask; end +end TEST_TMPDIR = Dir.mktmpdir("homebrew_cask_tests") at_exit do diff --git a/Library/Homebrew/cask/spec/support/Casks/.rubocop.yml b/Library/Homebrew/cask/spec/support/Casks/.rubocop.yml deleted file mode 120000 index ee5c2b948..000000000 --- a/Library/Homebrew/cask/spec/support/Casks/.rubocop.yml +++ /dev/null @@ -1 +0,0 @@ -../../../Casks/.rubocop.yml
\ No newline at end of file diff --git a/Library/Homebrew/cask/test/cask/accessibility_test.rb b/Library/Homebrew/cask/test/cask/accessibility_test.rb index ee192b4cb..8da8937fe 100644 --- a/Library/Homebrew/cask/test/cask/accessibility_test.rb +++ b/Library/Homebrew/cask/test/cask/accessibility_test.rb @@ -22,8 +22,7 @@ describe "Accessibility Access" do @installer.enable_accessibility_access end end - - it "can enable accessibility access in OS X releases prior to Mavericks" do + it "can enable accessibility access in macOS releases prior to Mavericks" do MacOS.stubs(version: MacOS::Version.new("10.8")) Hbc::FakeSystemCommand.expects_command( @@ -33,6 +32,14 @@ describe "Accessibility Access" do @installer.enable_accessibility_access end end + it "warns about enabling accessibility access on new macOS releases" do + MacOS.stubs(version: MacOS::Version.new("10.12")) + + @installer.stubs(bundle_identifier: "com.example.BasicCask") + + capture_io { @installer.enable_accessibility_access }[1] + .must_match("Warning: Accessibility access cannot be enabled automatically on this version of macOS.") + end end describe "uninstall" do @@ -48,13 +55,21 @@ describe "Accessibility Access" do @installer.disable_accessibility_access end end - it "warns about disabling accessibility access on old OS X releases" do + it "warns about disabling accessibility access on old macOS releases" do MacOS.stubs(version: MacOS::Version.new("10.8")) @installer.stubs(bundle_identifier: "com.example.BasicCask") capture_io { @installer.disable_accessibility_access }[1] - .must_match("Warning: Accessibility access was enabled for with-accessibility-access, but it is not safe to disable") + .must_match("Warning: Accessibility access cannot be disabled automatically on this version of macOS.") + end + it "warns about disabling accessibility access on new macOS releases" do + MacOS.stubs(version: MacOS::Version.new("10.12")) + + @installer.stubs(bundle_identifier: "com.example.BasicCask") + + capture_io { @installer.disable_accessibility_access }[1] + .must_match("Warning: Accessibility access cannot be disabled automatically on this version of macOS.") end 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 index afa4a61aa..47408ab9f 100644 --- a/Library/Homebrew/cask/test/cask/artifact/two_apps_correct_test.rb +++ b/Library/Homebrew/cask/test/cask/artifact/two_apps_correct_test.rb @@ -60,7 +60,6 @@ describe Hbc::Artifact::App do File.exist?(cask.staged_path.join("Caffeine Deluxe.app")).must_equal true end - describe "avoids clobbering an existing app" do let(:cask) { local_two_apps_caffeine } @@ -70,8 +69,8 @@ describe Hbc::Artifact::App do TestHelper.must_output(self, lambda { Hbc::Artifact::App.new(cask).install_phase }, <<-EOS.undent.chomp) - ==> It seems there is already an App at '#{Hbc.appdir.join('Caffeine Mini.app')}'; not moving. - ==> Moving App 'Caffeine Pro.app' to '#{Hbc.appdir.join('Caffeine Pro.app')}' + ==> It seems there is already an App at '#{Hbc.appdir.join("Caffeine Mini.app")}'; not moving. + ==> Moving App 'Caffeine Pro.app' to '#{Hbc.appdir.join("Caffeine Pro.app")}' EOS source_path = cask.staged_path.join("Caffeine Mini.app") @@ -85,8 +84,8 @@ describe Hbc::Artifact::App do TestHelper.must_output(self, lambda { Hbc::Artifact::App.new(cask).install_phase }, <<-EOS.undent.chomp) - ==> Moving App 'Caffeine Mini.app' to '#{Hbc.appdir.join('Caffeine Mini.app')}' - ==> It seems there is already an App at '#{Hbc.appdir.join('Caffeine Pro.app')}'; not moving. + ==> Moving App 'Caffeine Mini.app' to '#{Hbc.appdir.join("Caffeine Mini.app")}' + ==> It seems there is already an App at '#{Hbc.appdir.join("Caffeine Pro.app")}'; not moving. EOS source_path = cask.staged_path.join("Caffeine Pro.app") diff --git a/Library/Homebrew/cask/test/cask/cli/create_test.rb b/Library/Homebrew/cask/test/cask/cli/create_test.rb index cf3cf28a3..efca1a506 100644 --- a/Library/Homebrew/cask/test/cask/cli/create_test.rb +++ b/Library/Homebrew/cask/test/cask/cli/create_test.rb @@ -1,17 +1,21 @@ require "test_helper" # monkeypatch for testing -class Hbc::CLI::Create - def self.exec_editor(*command) - editor_commands << command - end +module Hbc + class CLI + class Create + def self.exec_editor(*command) + editor_commands << command + end - def self.reset! - @editor_commands = [] - end + def self.reset! + @editor_commands = [] + end - def self.editor_commands - @editor_commands ||= [] + def self.editor_commands + @editor_commands ||= [] + end + end end end diff --git a/Library/Homebrew/cask/test/cask/cli/edit_test.rb b/Library/Homebrew/cask/test/cask/cli/edit_test.rb index ebec5f414..3f385eb33 100644 --- a/Library/Homebrew/cask/test/cask/cli/edit_test.rb +++ b/Library/Homebrew/cask/test/cask/cli/edit_test.rb @@ -1,17 +1,21 @@ require "test_helper" # monkeypatch for testing -class Hbc::CLI::Edit - def self.exec_editor(*command) - editor_commands << command - end - - def self.reset! - @editor_commands = [] - end - - def self.editor_commands - @editor_commands ||= [] +module Hbc + class CLI + class Edit + def self.exec_editor(*command) + editor_commands << command + end + + def self.reset! + @editor_commands = [] + end + + def self.editor_commands + @editor_commands ||= [] + end + end end end diff --git a/Library/Homebrew/cask/test/cask/cli/home_test.rb b/Library/Homebrew/cask/test/cask/cli/home_test.rb index 28fd2a391..78302abd1 100644 --- a/Library/Homebrew/cask/test/cask/cli/home_test.rb +++ b/Library/Homebrew/cask/test/cask/cli/home_test.rb @@ -1,17 +1,21 @@ require "test_helper" # monkeypatch for testing -class Hbc::CLI::Home - def self.system(*command) - system_commands << command - end +module Hbc + class CLI + class Home + def self.system(*command) + system_commands << command + end - def self.reset! - @system_commands = [] - end + def self.reset! + @system_commands = [] + end - def self.system_commands - @system_commands ||= [] + def self.system_commands + @system_commands ||= [] + end + end end end diff --git a/Library/Homebrew/cask/test/cask/cli/list_test.rb b/Library/Homebrew/cask/test/cask/cli/list_test.rb index 2189498d4..6831bf0a4 100644 --- a/Library/Homebrew/cask/test/cask/cli/list_test.rb +++ b/Library/Homebrew/cask/test/cask/cli/list_test.rb @@ -79,9 +79,9 @@ describe Hbc::CLI::List do Hbc::CLI::List.run("local-transmission", "local-caffeine") }.must_output <<-EOS.undent ==> Apps - #{Hbc.appdir.join('Transmission.app')} (#{Hbc.appdir.join('Transmission.app').abv}) + #{Hbc.appdir.join("Transmission.app")} (#{Hbc.appdir.join("Transmission.app").abv}) ==> Apps - Missing App: #{Hbc.appdir.join('Caffeine.app')} + Missing App: #{Hbc.appdir.join("Caffeine.app")} EOS end end diff --git a/Library/Homebrew/cask/test/support/Casks/.rubocop.yml b/Library/Homebrew/cask/test/support/Casks/.rubocop.yml deleted file mode 120000 index ee5c2b948..000000000 --- a/Library/Homebrew/cask/test/support/Casks/.rubocop.yml +++ /dev/null @@ -1 +0,0 @@ -../../../Casks/.rubocop.yml
\ No newline at end of file diff --git a/Library/Homebrew/cask/test/support/cleanup.rb b/Library/Homebrew/cask/test/support/cleanup.rb index 0cb9c02fa..c31a74be2 100644 --- a/Library/Homebrew/cask/test/support/cleanup.rb +++ b/Library/Homebrew/cask/test/support/cleanup.rb @@ -1,12 +1,10 @@ -module Hbc::CleanupHooks - def after_teardown - super - Hbc.installed.each do |cask| - Hbc::Installer.new(cask).purge_versioned_files +module MiniTest + class Spec + def after_teardown + super + Hbc.installed.each do |cask| + Hbc::Installer.new(cask).purge_versioned_files + end end end end - -class MiniTest::Spec - include Hbc::CleanupHooks -end diff --git a/Library/Homebrew/cask/test/support/fake_dirs.rb b/Library/Homebrew/cask/test/support/fake_dirs.rb index 89612f850..f8e36bbbb 100644 --- a/Library/Homebrew/cask/test/support/fake_dirs.rb +++ b/Library/Homebrew/cask/test/support/fake_dirs.rb @@ -24,6 +24,8 @@ module FakeDirHooks end end -class MiniTest::Spec - include FakeDirHooks +module MiniTest + class Spec + include FakeDirHooks + end end diff --git a/Library/Homebrew/cask/test/support/fake_fetcher.rb b/Library/Homebrew/cask/test/support/fake_fetcher.rb index a49a89f7f..43483751f 100644 --- a/Library/Homebrew/cask/test/support/fake_fetcher.rb +++ b/Library/Homebrew/cask/test/support/fake_fetcher.rb @@ -1,20 +1,22 @@ -class Hbc::FakeFetcher - def self.fake_response_for(url, response) - @responses[url] = response - end +module Hbc + class FakeFetcher + def self.fake_response_for(url, response) + @responses[url] = response + end - def self.head(url) - @responses ||= {} - raise("no response faked for #{url.inspect}") unless @responses.key?(url) - @responses[url] - end + def self.head(url) + @responses ||= {} + raise("no response faked for #{url.inspect}") unless @responses.key?(url) + @responses[url] + end - def self.init - @responses = {} - end + def self.init + @responses = {} + end - def self.clear - @responses = {} + def self.clear + @responses = {} + end end end @@ -30,6 +32,8 @@ module FakeFetcherHooks end end -class MiniTest::Spec - include FakeFetcherHooks +module MiniTest + class Spec + include FakeFetcherHooks + end end diff --git a/Library/Homebrew/cask/test/support/fake_system_command.rb b/Library/Homebrew/cask/test/support/fake_system_command.rb index e19330fd0..97efd0761 100644 --- a/Library/Homebrew/cask/test/support/fake_system_command.rb +++ b/Library/Homebrew/cask/test/support/fake_system_command.rb @@ -1,61 +1,63 @@ -class Hbc::FakeSystemCommand - def self.responses - @responses ||= {} - end +module Hbc + class FakeSystemCommand + def self.responses + @responses ||= {} + end - def self.expectations - @expectations ||= {} - end + def self.expectations + @expectations ||= {} + end - def self.system_calls - @system_calls ||= Hash.new(0) - end + def self.system_calls + @system_calls ||= Hash.new(0) + end - def self.clear - @responses = nil - @expectations = nil - @system_calls = nil - end + def self.clear + @responses = nil + @expectations = nil + @system_calls = nil + end - def self.stubs_command(command, response = "") - responses[command] = response - end + def self.stubs_command(command, response = "") + responses[command] = response + end - def self.expects_command(command, response = "", times = 1) - stubs_command(command, response) - expectations[command] = times - end + def self.expects_command(command, response = "", times = 1) + stubs_command(command, response) + expectations[command] = times + end - def self.expect_and_pass_through(command, times = 1) - pass_through = ->(cmd, opts) { Hbc::SystemCommand.run(cmd, opts) } - expects_command(command, pass_through, times) - end + def self.expect_and_pass_through(command, times = 1) + pass_through = ->(cmd, opts) { Hbc::SystemCommand.run(cmd, opts) } + expects_command(command, pass_through, times) + end - def self.verify_expectations! - expectations.each do |command, times| - unless system_calls[command] == times - raise("expected #{command.inspect} to be run #{times} times, but got #{system_calls[command]}") + def self.verify_expectations! + expectations.each do |command, times| + unless system_calls[command] == times + raise("expected #{command.inspect} to be run #{times} times, but got #{system_calls[command]}") + end end end - end - def self.run(command_string, options = {}) - command = Hbc::SystemCommand.new(command_string, options).command - unless responses.key?(command) - raise("no response faked for #{command.inspect}, faked responses are: #{responses.inspect}") - end - system_calls[command] += 1 + def self.run(command_string, options = {}) + command = Hbc::SystemCommand.new(command_string, options).command + unless responses.key?(command) + raise("no response faked for #{command.inspect}, faked responses are: #{responses.inspect}") + end + system_calls[command] += 1 - response = responses[command] - if response.respond_to?(:call) - response.call(command_string, options) - else - Hbc::SystemCommand::Result.new(command, response, "", 0) + response = responses[command] + if response.respond_to?(:call) + response.call(command_string, options) + else + Hbc::SystemCommand::Result.new(command, response, "", 0) + end end - end - def self.run!(command, options = {}) - run(command, options.merge(must_succeed: true)) + def self.run!(command, options = {}) + run(command, options.merge(must_succeed: true)) + end end end @@ -68,6 +70,8 @@ module FakeSystemCommandHooks end end -class MiniTest::Spec - include FakeSystemCommandHooks +module MiniTest + class Spec + include FakeSystemCommandHooks + end end diff --git a/Library/Homebrew/cask/test/support/never_sudo_system_command.rb b/Library/Homebrew/cask/test/support/never_sudo_system_command.rb index 50f510a7a..8a370df44 100644 --- a/Library/Homebrew/cask/test/support/never_sudo_system_command.rb +++ b/Library/Homebrew/cask/test/support/never_sudo_system_command.rb @@ -1,5 +1,7 @@ -class Hbc::NeverSudoSystemCommand < Hbc::SystemCommand - def self.run(command, options = {}) - super(command, options.merge(sudo: false)) +module Hbc + class NeverSudoSystemCommand < SystemCommand + def self.run(command, options = {}) + super(command, options.merge(sudo: false)) + end end end diff --git a/Library/Homebrew/cask/test/support/shared_examples.rb b/Library/Homebrew/cask/test/support/shared_examples.rb index e846af404..594ca81c1 100644 --- a/Library/Homebrew/cask/test/support/shared_examples.rb +++ b/Library/Homebrew/cask/test/support/shared_examples.rb @@ -5,14 +5,18 @@ MiniTest::Spec.class_eval do end end -module MiniTest::Spec::SharedExamples - def shared_examples_for(desc, &block) - MiniTest::Spec.shared_examples[desc] = block - 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? + 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 diff --git a/Library/Homebrew/cask/test/test_helper.rb b/Library/Homebrew/cask/test/test_helper.rb index e4fd72170..47c1b4cdb 100644 --- a/Library/Homebrew/cask/test/test_helper.rb +++ b/Library/Homebrew/cask/test/test_helper.rb @@ -4,14 +4,13 @@ require "pathname" if ENV["HOMEBREW_TESTS_COVERAGE"] require "simplecov" - SimpleCov.command_name "test:cask:minitest" end project_root = Pathname.new(File.expand_path("../..", __FILE__)) tap_root = Pathname.new(ENV["HOMEBREW_LIBRARY"]).join("Taps", "caskroom", "homebrew-cask") # 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")) require "global" @@ -39,6 +38,8 @@ 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" @@ -158,7 +159,9 @@ require "tempfile" FileUtils.mkdir_p Hbc.homebrew_prefix.join("bin") # Common superclass for test Casks for when we need to filter them out -class Hbc::TestCask < Hbc::Cask; end +module Hbc + class TestCask < Cask; end +end # jack in some optional utilities FileUtils.ln_s "/usr/local/bin/cabextract", Hbc.homebrew_prefix.join("bin/cabextract") diff --git a/Library/Homebrew/caveats.rb b/Library/Homebrew/caveats.rb index 9c1787f87..a5568cb29 100644 --- a/Library/Homebrew/caveats.rb +++ b/Library/Homebrew/caveats.rb @@ -69,27 +69,34 @@ class Caveats end def bash_completion_caveats - if keg && keg.completion_installed?(:bash) then <<-EOS.undent + return unless keg + return unless keg.completion_installed?(:bash) + + <<-EOS.undent Bash completion has been installed to: #{HOMEBREW_PREFIX}/etc/bash_completion.d - EOS - end + EOS end def zsh_completion_caveats - if keg && keg.completion_installed?(:zsh) then <<-EOS.undent + return unless keg + return unless keg.completion_installed?(:zsh) + + <<-EOS.undent zsh completion has been installed to: #{HOMEBREW_PREFIX}/share/zsh/site-functions - EOS - end + EOS end def fish_completion_caveats - if keg && keg.completion_installed?(:fish) && which("fish") then <<-EOS.undent + return unless keg + return unless keg.completion_installed?(:fish) + return unless which("fish") + + <<-EOS.undent fish completion has been installed to: #{HOMEBREW_PREFIX}/share/fish/vendor_completions.d - EOS - end + EOS end def python_caveats @@ -140,22 +147,24 @@ class Caveats end def app_caveats - if keg && keg.app_installed? - <<-EOS.undent - .app bundles were installed. - Run `brew linkapps #{keg.name}` to symlink these to /Applications. - EOS - end + return unless keg + return unless keg.app_installed? + + <<-EOS.undent + .app bundles were installed. + Run `brew linkapps #{keg.name}` to symlink these to /Applications. + EOS end def elisp_caveats return if f.keg_only? - if keg && keg.elisp_installed? - <<-EOS.undent - Emacs Lisp files have been installed to: - #{HOMEBREW_PREFIX}/share/emacs/site-lisp/#{f.name} - EOS - end + return unless keg + return unless keg.elisp_installed? + + <<-EOS.undent + Emacs Lisp files have been installed to: + #{HOMEBREW_PREFIX}/share/emacs/site-lisp/#{f.name} + EOS end def plist_caveats diff --git a/Library/Homebrew/checksum.rb b/Library/Homebrew/checksum.rb index 6be454efb..1b095ea32 100644 --- a/Library/Homebrew/checksum.rb +++ b/Library/Homebrew/checksum.rb @@ -1,6 +1,6 @@ class Checksum attr_reader :hash_type, :hexdigest - alias_method :to_s, :hexdigest + alias to_s hexdigest TYPES = [:sha256].freeze diff --git a/Library/Homebrew/cleaner.rb b/Library/Homebrew/cleaner.rb index d8a998576..7456e18d6 100644 --- a/Library/Homebrew/cleaner.rb +++ b/Library/Homebrew/cleaner.rb @@ -87,9 +87,9 @@ class Cleaner Find.prune if @f.skip_clean? path - if path.symlink? || path.directory? - next - elsif path.extname == ".la" + next if path.symlink? || path.directory? + + if path.extname == ".la" path.unlink elsif path.basename.to_s == "perllocal.pod" # Both this file & the .packlist one below are completely unnecessary diff --git a/Library/Homebrew/cleanup.rb b/Library/Homebrew/cleanup.rb index 265f06d26..04a976e55 100644 --- a/Library/Homebrew/cleanup.rb +++ b/Library/Homebrew/cleanup.rb @@ -12,7 +12,7 @@ module Homebrew cleanup_logs unless ARGV.dry_run? cleanup_lockfiles - rm_DS_Store + rm_ds_store end end @@ -66,7 +66,7 @@ module Homebrew next unless path.file? file = path - if Pathname::BOTTLE_EXTNAME_RX === file.to_s + if file.to_s =~ Pathname::BOTTLE_EXTNAME_RX version = begin Utils::Bottles.resolve_version(file) rescue @@ -86,7 +86,7 @@ module Homebrew next end - file_is_stale = if PkgVersion === version + file_is_stale = if version.is_a?(PkgVersion) f.pkg_version > version else f.version > version @@ -119,7 +119,7 @@ module Homebrew end end - def self.rm_DS_Store + def self.rm_ds_store paths = Queue.new %w[Cellar Frameworks Library bin etc include lib opt sbin share var] .map { |p| HOMEBREW_PREFIX/p }.each { |p| paths << p if p.exist? } diff --git a/Library/Homebrew/cmd/cleanup.rb b/Library/Homebrew/cmd/cleanup.rb index a9d3fbcde..6e0915c9a 100644 --- a/Library/Homebrew/cmd/cleanup.rb +++ b/Library/Homebrew/cmd/cleanup.rb @@ -22,13 +22,13 @@ module Homebrew ARGV.resolved_formulae.each { |f| Cleanup.cleanup_formula f } end - if Cleanup.disk_cleanup_size > 0 - disk_space = disk_usage_readable(Cleanup.disk_cleanup_size) - if ARGV.dry_run? - ohai "This operation would free approximately #{disk_space} of disk space." - else - ohai "This operation has freed approximately #{disk_space} of disk space." - end + return if Cleanup.disk_cleanup_size.zero? + + disk_space = disk_usage_readable(Cleanup.disk_cleanup_size) + if ARGV.dry_run? + ohai "This operation would free approximately #{disk_space} of disk space." + else + ohai "This operation has freed approximately #{disk_space} of disk space." end end end diff --git a/Library/Homebrew/cmd/diy.rb b/Library/Homebrew/cmd/diy.rb index 8262352f8..95ec7fe35 100644 --- a/Library/Homebrew/cmd/diy.rb +++ b/Library/Homebrew/cmd/diy.rb @@ -31,11 +31,9 @@ module Homebrew def detect_version(path) version = path.version.to_s - if version.empty? - raise "Couldn't determine version, set it with --version=<version>" - else - version - end + raise "Couldn't determine version, set it with --version=<version>" if version.empty? + + version end def detect_name(path, version) diff --git a/Library/Homebrew/cmd/info.rb b/Library/Homebrew/cmd/info.rb index 2474aad57..09c832203 100644 --- a/Library/Homebrew/cmd/info.rb +++ b/Library/Homebrew/cmd/info.rb @@ -54,11 +54,8 @@ module Homebrew end rescue FormulaUnavailableError # No formula with this name, try a blacklist lookup - if (blacklist = blacklisted?(f)) - puts blacklist - else - raise - end + raise unless (blacklist = blacklisted?(f)) + puts blacklist end end end diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb index 50439ccf9..8a8323252 100644 --- a/Library/Homebrew/cmd/install.rb +++ b/Library/Homebrew/cmd/install.rb @@ -203,13 +203,12 @@ module Homebrew # If they haven't updated in 48 hours (172800 seconds), that # might explain the error master = HOMEBREW_REPOSITORY/".git/refs/heads/master" - if master.exist? && (Time.now.to_i - File.mtime(master).to_i) > 172800 - ohai "You haven't updated Homebrew in a while." - puts <<-EOS.undent - A formula for #{e.name} might have been added recently. - Run `brew update` to get the latest Homebrew updates! - EOS - end + return unless master.exist? && (Time.now.to_i - File.mtime(master).to_i) > 172800 + ohai "You haven't updated Homebrew in a while." + puts <<-EOS.undent + A formula for #{e.name} might have been added recently. + Run `brew update` to get the latest Homebrew updates! + EOS end end end @@ -245,11 +244,11 @@ module Homebrew end def check_macports - unless MacOS.macports_or_fink.empty? - opoo "It appears you have MacPorts or Fink installed." - puts "Software installed with other package managers causes known problems for" - puts "Homebrew. If a formula fails to build, uninstall MacPorts/Fink and try again." - end + return if MacOS.macports_or_fink.empty? + + opoo "It appears you have MacPorts or Fink installed." + puts "Software installed with other package managers causes known problems for" + puts "Homebrew. If a formula fails to build, uninstall MacPorts/Fink and try again." end def check_cellar diff --git a/Library/Homebrew/cmd/postinstall.rb b/Library/Homebrew/cmd/postinstall.rb index 71b71b3f5..e0bd8e31b 100644 --- a/Library/Homebrew/cmd/postinstall.rb +++ b/Library/Homebrew/cmd/postinstall.rb @@ -36,7 +36,7 @@ module Homebrew sandbox.allow_write_cellar(formula) sandbox.allow_write_xcode sandbox.allow_write_path HOMEBREW_PREFIX - sandbox.deny_write_homebrew_library + sandbox.deny_write_homebrew_repository sandbox.exec(*args) else exec(*args) diff --git a/Library/Homebrew/cmd/reinstall.rb b/Library/Homebrew/cmd/reinstall.rb index e51aace2a..bda6022bf 100644 --- a/Library/Homebrew/cmd/reinstall.rb +++ b/Library/Homebrew/cmd/reinstall.rb @@ -58,10 +58,11 @@ module Homebrew def restore_backup(keg, formula) path = backup_path(keg) - if path.directory? - path.rename keg - keg.link unless formula.keg_only? - end + + return unless path.directory? + + path.rename keg + keg.link unless formula.keg_only? end def backup_path(path) diff --git a/Library/Homebrew/cmd/search.rb b/Library/Homebrew/cmd/search.rb index 50d9f5f74..aa80ec589 100644 --- a/Library/Homebrew/cmd/search.rb +++ b/Library/Homebrew/cmd/search.rb @@ -150,7 +150,7 @@ module Homebrew names = remote_tap_formulae["#{user}/#{repo}"] user = user.downcase if user == "Homebrew" # special handling for the Homebrew organization - names.select { |name| rx === name }.map { |name| "#{user}/#{repo}/#{name}" } + names.select { |name| name =~ rx }.map { |name| "#{user}/#{repo}/#{name}" } rescue GitHub::HTTPNotFoundError opoo "Failed to search tap: #{user}/#{repo}. Please run `brew update`" [] @@ -171,10 +171,11 @@ module Homebrew rescue canonical_name = canonical_full_name = name end + # Ignore aliases from results when the full name was also found - if aliases.include?(name) && results.include?(canonical_full_name) - next - elsif (HOMEBREW_CELLAR/canonical_name).directory? + next if aliases.include?(name) && results.include?(canonical_full_name) + + if (HOMEBREW_CELLAR/canonical_name).directory? pretty_installed(name) else name diff --git a/Library/Homebrew/cmd/style.rb b/Library/Homebrew/cmd/style.rb index f28d50cc1..db61116be 100644 --- a/Library/Homebrew/cmd/style.rb +++ b/Library/Homebrew/cmd/style.rb @@ -45,7 +45,7 @@ module Homebrew def check_style_impl(files, output_type, options = {}) fix = options[:fix] - Homebrew.install_gem_setup_path! "rubocop", "0.41.2" + Homebrew.install_gem_setup_path! "rubocop", "0.43.0" args = %W[ --force-exclusion @@ -54,20 +54,22 @@ module Homebrew args << "--auto-correct" if fix args += files - case output_type - when :print - args << "--display-cop-names" if ARGV.include? "--display-cop-names" - system "rubocop", "--format", "simple", *args - !$?.success? - when :json - json = Utils.popen_read_text("rubocop", "--format", "json", *args) - # exit status of 1 just means violations were found; other numbers mean execution errors - # exitstatus can also be nil if RuboCop process crashes, e.g. due to - # native extension problems - raise "Error while running RuboCop" if $?.exitstatus.nil? || $?.exitstatus > 1 - RubocopResults.new(Utils::JSON.load(json)) - else - raise "Invalid output_type for check_style_impl: #{output_type}" + HOMEBREW_LIBRARY.cd do + case output_type + when :print + args << "--display-cop-names" if ARGV.include? "--display-cop-names" + system "rubocop", "--format", "simple", *args + !$?.success? + when :json + json = Utils.popen_read_text("rubocop", "--format", "json", *args) + # exit status of 1 just means violations were found; other numbers mean execution errors + # exitstatus can also be nil if RuboCop process crashes, e.g. due to + # native extension problems + raise "Error while running RuboCop" if $?.exitstatus.nil? || $?.exitstatus > 1 + RubocopResults.new(Utils::JSON.load(json)) + else + raise "Invalid output_type for check_style_impl: #{output_type}" + end end end diff --git a/Library/Homebrew/cmd/uninstall.rb b/Library/Homebrew/cmd/uninstall.rb index 6ea45a770..f4ca8ff87 100644 --- a/Library/Homebrew/cmd/uninstall.rb +++ b/Library/Homebrew/cmd/uninstall.rb @@ -25,7 +25,7 @@ module Homebrew versions = rack.subdirs.map(&:basename) verb = versions.length == 1 ? "is" : "are" puts "#{keg.name} #{versions.join(", ")} #{verb} still installed." - puts "Remove them all with `brew uninstall --force #{keg.name}`." + puts "Remove all versions with `brew uninstall --force #{keg.name}`." end end end diff --git a/Library/Homebrew/cmd/update-report.rb b/Library/Homebrew/cmd/update-report.rb index 1e9c8ccd3..18f2f370c 100644 --- a/Library/Homebrew/cmd/update-report.rb +++ b/Library/Homebrew/cmd/update-report.rb @@ -549,11 +549,10 @@ class ReporterHub end end - unless formulae.empty? - # Dump formula list. - ohai title - puts_columns(formulae) - end + return if formulae.empty? + # Dump formula list. + ohai title + puts_columns(formulae) end def installed?(formula) diff --git a/Library/Homebrew/cmd/update.sh b/Library/Homebrew/cmd/update.sh index b57691893..579890820 100644 --- a/Library/Homebrew/cmd/update.sh +++ b/Library/Homebrew/cmd/update.sh @@ -215,7 +215,20 @@ merge_or_rebase() { trap reset_on_interrupt SIGINT - REMOTE_REF="origin/$UPSTREAM_BRANCH" + if [[ "$DIR" = "$HOMEBREW_REPOSITORY" && -z "$HOMEBREW_NO_UPDATE_CLEANUP" ]] + then + UPSTREAM_TAG="$(git tag --list --sort=-version:refname | grep '^[0-9]*\.[0-9]*\.[0-9]*$' | head -n1)" + else + UPSTREAM_TAG="" + fi + + if [ -n "$UPSTREAM_TAG" ] + then + REMOTE_REF="refs/tags/$UPSTREAM_TAG" + UPSTREAM_BRANCH="stable" + else + REMOTE_REF="origin/$UPSTREAM_BRANCH" + fi if [[ -n "$(git status --untracked-files=all --porcelain 2>/dev/null)" ]] then @@ -242,19 +255,13 @@ EOS fi INITIAL_BRANCH="$(git symbolic-ref --short HEAD 2>/dev/null)" - if [[ "$INITIAL_BRANCH" != "$UPSTREAM_BRANCH" && -n "$INITIAL_BRANCH" ]] + if [[ -n "$UPSTREAM_TAG" ]] || + [[ "$INITIAL_BRANCH" != "$UPSTREAM_BRANCH" && -n "$INITIAL_BRANCH" ]] then - - if [[ -z "$HOMEBREW_NO_UPDATE_CLEANUP" ]] - then - echo "Checking out $UPSTREAM_BRANCH in $DIR..." - echo "To checkout $INITIAL_BRANCH in $DIR run:" - echo " 'cd $DIR && git checkout $INITIAL_BRANCH" - fi - # Recreate and check out `#{upstream_branch}` if unable to fast-forward # it to `origin/#{@upstream_branch}`. Otherwise, just check it out. - if git merge-base --is-ancestor "$UPSTREAM_BRANCH" "$REMOTE_REF" &>/dev/null + if [[ -z "$UPSTREAM_TAG" ]] && + git merge-base --is-ancestor "$UPSTREAM_BRANCH" "$REMOTE_REF" &>/dev/null then git checkout --force "$UPSTREAM_BRANCH" "${QUIET_ARGS[@]}" else @@ -290,7 +297,8 @@ EOS if [[ -n "$HOMEBREW_NO_UPDATE_CLEANUP" ]] then - if [[ "$INITIAL_BRANCH" != "$UPSTREAM_BRANCH" && -n "$INITIAL_BRANCH" ]] + if [[ "$INITIAL_BRANCH" != "$UPSTREAM_BRANCH" && -n "$INITIAL_BRANCH" && + ! "$INITIAL_BRANCH" =~ ^v[0-9]+\.[0-9]+\.[0-9]$ ]] then git checkout "$INITIAL_BRANCH" "${QUIET_ARGS[@]}" fi @@ -337,7 +345,7 @@ EOS set -x fi - if [[ -z "$HOMEBREW_UPDATE_CLEANUP" ]] + if [[ -z "$HOMEBREW_UPDATE_CLEANUP" && -z "$HOMEBREW_UPDATE_TO_TAG" ]] then if [[ -n "$HOMEBREW_DEVELOPER" || -n "$HOMEBREW_DEV_CMD_RUN" ]] then @@ -425,6 +433,12 @@ EOS declare UPSTREAM_BRANCH"$TAP_VAR"="$UPSTREAM_BRANCH_DIR" declare PREFETCH_REVISION"$TAP_VAR"="$(git rev-parse -q --verify refs/remotes/origin/"$UPSTREAM_BRANCH_DIR")" + # Force a full update if we don't have any tags. + if [[ "$DIR" = "$HOMEBREW_REPOSITORY" && -z "$(git tag --list)" ]] + then + HOMEBREW_UPDATE_FORCE=1 + fi + if [[ -z "$HOMEBREW_UPDATE_FORCE" ]] then [[ -n "$SKIP_FETCH_BREW_REPOSITORY" && "$DIR" = "$HOMEBREW_REPOSITORY" ]] && continue @@ -480,10 +494,10 @@ EOS if [[ -n "$HOMEBREW_UPDATE_PREINSTALL" ]] then - git fetch --force "${QUIET_ARGS[@]}" origin \ + git fetch --tags --force "${QUIET_ARGS[@]}" origin \ "refs/heads/$UPSTREAM_BRANCH_DIR:refs/remotes/origin/$UPSTREAM_BRANCH_DIR" 2>/dev/null else - if ! git fetch --force "${QUIET_ARGS[@]}" origin \ + if ! git fetch --tags --force "${QUIET_ARGS[@]}" origin \ "refs/heads/$UPSTREAM_BRANCH_DIR:refs/remotes/origin/$UPSTREAM_BRANCH_DIR" then echo "Fetching $DIR failed!" >>"$update_failed_file" diff --git a/Library/Homebrew/compat/dependency_collector.rb b/Library/Homebrew/compat/dependency_collector.rb index 27236ae4b..b18adc490 100644 --- a/Library/Homebrew/compat/dependency_collector.rb +++ b/Library/Homebrew/compat/dependency_collector.rb @@ -1,7 +1,7 @@ require "dependency_collector" class DependencyCollector - alias_method :_parse_symbol_spec, :parse_symbol_spec + alias _parse_symbol_spec parse_symbol_spec def parse_symbol_spec(spec, tags) case spec diff --git a/Library/Homebrew/compat/formula.rb b/Library/Homebrew/compat/formula.rb index 41896d261..853a38706 100644 --- a/Library/Homebrew/compat/formula.rb +++ b/Library/Homebrew/compat/formula.rb @@ -72,8 +72,8 @@ class Formula yield if block_given? PythonRequirement.new end - alias_method :python2, :python - alias_method :python3, :python + alias python2 python + alias python3 python def startup_plist odeprecated "Formula#startup_plist", "Formula#plist" diff --git a/Library/Homebrew/compat/formula_specialties.rb b/Library/Homebrew/compat/formula_specialties.rb index f709bcb5b..ec5e91ce8 100644 --- a/Library/Homebrew/compat/formula_specialties.rb +++ b/Library/Homebrew/compat/formula_specialties.rb @@ -25,7 +25,7 @@ class AmazonWebServicesFormula < Formula libexec.install Dir["*"] bin.install_symlink Dir["#{libexec}/bin/*"] - ["#{libexec}/bin/service"] end - alias_method :standard_install, :install + alias standard_install install # Use this method to generate standard caveats. def standard_instructions(home_name, home_value = libexec) diff --git a/Library/Homebrew/compat/macos.rb b/Library/Homebrew/compat/macos.rb index 957a0b725..6b0166e40 100644 --- a/Library/Homebrew/compat/macos.rb +++ b/Library/Homebrew/compat/macos.rb @@ -136,6 +136,11 @@ module OS odeprecated "MacOS.has_apple_developer_tools?", "DevelopmentTools.installed?" DevelopmentTools.installed? end + + def release + odeprecated "MacOS.release", "MacOS.version" + version + end end end end diff --git a/Library/Homebrew/compilers.rb b/Library/Homebrew/compilers.rb index 940566643..6330db283 100644 --- a/Library/Homebrew/compilers.rb +++ b/Library/Homebrew/compilers.rb @@ -18,7 +18,7 @@ class CompilerFailure # Allows Apple compiler `fails_with` statements to keep using `build` # even though `build` and `version` are the same internally - alias_method :build, :version + alias build version # The cause is no longer used so we need not hold a reference to the string def cause(_); end diff --git a/Library/Homebrew/cxxstdlib.rb b/Library/Homebrew/cxxstdlib.rb index 1f629a8b2..ad859badd 100644 --- a/Library/Homebrew/cxxstdlib.rb +++ b/Library/Homebrew/cxxstdlib.rb @@ -16,7 +16,7 @@ class CxxStdlib if type && ![:libstdcxx, :libcxx].include?(type) raise ArgumentError, "Invalid C++ stdlib type: #{type}" end - klass = GNU_GCC_REGEXP === compiler.to_s ? GnuStdlib : AppleStdlib + klass = compiler.to_s =~ GNU_GCC_REGEXP ? GnuStdlib : AppleStdlib klass.new(type, compiler) end diff --git a/Library/Homebrew/debrew.rb b/Library/Homebrew/debrew.rb index 48d449f4a..1c5047a8c 100644 --- a/Library/Homebrew/debrew.rb +++ b/Library/Homebrew/debrew.rb @@ -14,7 +14,7 @@ module Debrew super(e) unless Debrew.debug(e) == :ignore end - alias_method :fail, :raise + alias fail raise end module Formula @@ -75,7 +75,7 @@ module Debrew end class << self - alias_method :original_raise, :raise + alias original_raise raise end @active = false @@ -118,20 +118,22 @@ module Debrew menu.prompt = "Choose an action: " menu.choice(:raise) { original_raise(e) } - menu.choice(:ignore) { return :ignore } if Ignorable === e + menu.choice(:ignore) { return :ignore } if e.is_a?(Ignorable) menu.choice(:backtrace) { puts e.backtrace } - menu.choice(:irb) do - puts "When you exit this IRB session, execution will continue." - set_trace_func proc { |event, _, _, id, binding, klass| - if klass == Raise && id == :raise && event == "return" - set_trace_func(nil) - synchronize { IRB.start_within(binding) } - end - } - - return :ignore - end if Ignorable === e + if e.is_a?(Ignorable) + menu.choice(:irb) do + puts "When you exit this IRB session, execution will continue." + set_trace_func proc { |event, _, _, id, binding, klass| + if klass == Raise && id == :raise && event == "return" + set_trace_func(nil) + synchronize { IRB.start_within(binding) } + end + } + + return :ignore + end + end menu.choice(:shell) do puts "When you exit this shell, you will return to the menu." diff --git a/Library/Homebrew/dependencies.rb b/Library/Homebrew/dependencies.rb index b55d35c2e..951db078d 100644 --- a/Library/Homebrew/dependencies.rb +++ b/Library/Homebrew/dependencies.rb @@ -22,7 +22,7 @@ class Dependencies @deps * arg end - alias_method :to_ary, :to_a + alias to_ary to_a def optional select(&:optional?) @@ -50,7 +50,7 @@ class Dependencies def ==(other) deps == other.deps end - alias_method :eql?, :== + alias eql? == def inspect "#<#{self.class.name}: #{to_a.inspect}>" @@ -69,7 +69,7 @@ class Requirements end def <<(other) - if Comparable === other + if other.is_a?(Comparable) @reqs.grep(other.class) do |req| return self if req > other @reqs.delete(req) @@ -79,5 +79,5 @@ class Requirements self end - alias_method :to_ary, :to_a + alias to_ary to_a end diff --git a/Library/Homebrew/dependency.rb b/Library/Homebrew/dependency.rb index c280034a8..6b60654e1 100644 --- a/Library/Homebrew/dependency.rb +++ b/Library/Homebrew/dependency.rb @@ -22,7 +22,7 @@ class Dependency def ==(other) instance_of?(other.class) && name == other.name && tags == other.tags end - alias_method :eql?, :== + alias eql? == def hash name.hash ^ tags.hash diff --git a/Library/Homebrew/dependency_collector.rb b/Library/Homebrew/dependency_collector.rb index 08b5fc12b..56463fa29 100644 --- a/Library/Homebrew/dependency_collector.rb +++ b/Library/Homebrew/dependency_collector.rb @@ -49,7 +49,7 @@ class DependencyCollector end def cache_key(spec) - if Resource === spec && spec.download_strategy == CurlDownloadStrategy + if spec.is_a?(Resource) && spec.download_strategy == CurlDownloadStrategy File.extname(spec.url) else spec @@ -57,7 +57,7 @@ class DependencyCollector end def build(spec) - spec, tags = Hash === spec ? spec.first : spec + spec, tags = spec.is_a?(Hash) ? spec.first : spec parse_spec(spec, Array(tags)) end @@ -81,7 +81,7 @@ class DependencyCollector end def parse_string_spec(spec, tags) - if HOMEBREW_TAP_FORMULA_REGEX === spec + if spec =~ HOMEBREW_TAP_FORMULA_REGEX TapDependency.new(spec, tags) elsif tags.empty? Dependency.new(spec, tags) @@ -128,17 +128,15 @@ class DependencyCollector end def parse_class_spec(spec, tags) - if spec < Requirement - spec.new(tags) - else + unless spec < Requirement raise TypeError, "#{spec.inspect} is not a Requirement subclass" end + + spec.new(tags) end def ant_dep(spec, tags) - if MacOS.version >= :mavericks - Dependency.new(spec.to_s, tags) - end + Dependency.new(spec.to_s, tags) end def resource_dep(spec, tags) @@ -167,11 +165,13 @@ class DependencyCollector def parse_url_spec(url, tags) case File.extname(url) - when ".xz" then Dependency.new("xz", tags) + when ".xz" then Dependency.new("xz", tags) when ".lha", ".lzh" then Dependency.new("lha", tags) - when ".lz" then Dependency.new("lzip", tags) - when ".rar" then Dependency.new("unrar", tags) - when ".7z" then Dependency.new("p7zip", tags) + when ".lz" then Dependency.new("lzip", tags) + when ".rar" then Dependency.new("unrar", tags) + when ".7z" then Dependency.new("p7zip", tags) end end end + +require "extend/os/dependency_collector" diff --git a/Library/Homebrew/descriptions.rb b/Library/Homebrew/descriptions.rb index 5e7a5b06c..0ef4316d3 100644 --- a/Library/Homebrew/descriptions.rb +++ b/Library/Homebrew/descriptions.rb @@ -12,9 +12,7 @@ class Descriptions # If the cache file exists, load it into, and return, a hash; otherwise, # return nil. def self.load_cache - if CACHE_FILE.exist? - @cache = Utils::JSON.load(CACHE_FILE.read) - end + @cache = Utils::JSON.load(CACHE_FILE.read) if CACHE_FILE.exist? end # Write the cache to disk after ensuring the existence of the containing @@ -138,6 +136,6 @@ class Descriptions def short_name_counts @short_name_counts ||= - short_names.values.each_with_object(Hash.new(0)) { |name, counts| counts[name] += 1; counts } + short_names.values.each_with_object(Hash.new(0)) { |name, counts| counts[name] += 1 } end end diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index 20e9a8aff..1a6e47dbe 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -83,11 +83,11 @@ module Homebrew end end - unless problem_count.zero? - problems = "problem" + plural(problem_count) - formulae = "formula" + plural(formula_count, "e") - ofail "#{problem_count} #{problems} in #{formula_count} #{formulae}" - end + return if problem_count.zero? + + problems = "problem" + plural(problem_count) + formulae = "formula" + plural(formula_count, "e") + ofail "#{problem_count} #{problems} in #{formula_count} #{formulae}" end end @@ -279,12 +279,13 @@ class FormulaAuditor end end end + if present.include?("head") && present.include?("head block") problem "Should not have both `head` and `head do`" end - if present.include?("bottle modifier") && present.include?("bottle block") - problem "Should not have `bottle :unneeded/:disable` and `bottle do`" - end + + return unless present.include?("bottle modifier") && present.include?("bottle block") + problem "Should not have `bottle :unneeded/:disable` and `bottle do`" end def audit_class @@ -348,9 +349,8 @@ class FormulaAuditor same_name_tap_formulae.delete(full_name) - unless same_name_tap_formulae.empty? - problem "Formula name conflicts with #{same_name_tap_formulae.join ", "}" - end + return if same_name_tap_formulae.empty? + problem "Formula name conflicts with #{same_name_tap_formulae.join ", "}" end def audit_deps @@ -467,7 +467,7 @@ class FormulaAuditor # Make sure the formula name plus description is no longer than 80 characters # Note full_name includes the name of the tap, while name does not - linelength = formula.name.length + ": ".length + desc.length + linelength = "#{formula.name}: #{desc}".length if linelength > 80 problem <<-EOS.undent Description is too long. \"name: desc\" should be less than 80 characters. @@ -483,9 +483,8 @@ class FormulaAuditor problem "Description shouldn't start with an indefinite article (#{$1})" end - if desc.downcase.start_with? "#{formula.name} " - problem "Description shouldn't include the formula name" - end + return unless desc.downcase.start_with? "#{formula.name} " + problem "Description shouldn't include the formula name" end def audit_homepage @@ -562,9 +561,9 @@ class FormulaAuditor end def audit_bottle_spec - if formula.bottle_disabled? && !formula.bottle_disable_reason.valid? - problem "Unrecognized bottle modifier" - end + return unless formula.bottle_disabled? + return if formula.bottle_disable_reason.valid? + problem "Unrecognized bottle modifier" end def audit_github_repository @@ -592,9 +591,8 @@ class FormulaAuditor problem "GitHub repository not notable enough (<20 forks, <20 watchers and <50 stars)" end - if Date.parse(metadata["created_at"]) > (Date.today - 30) - problem "GitHub repository too new (<30 days old)" - end + return if Date.parse(metadata["created_at"]) <= (Date.today - 30) + problem "GitHub repository too new (<30 days old)" end def audit_specs @@ -668,24 +666,26 @@ class FormulaAuditor end revision_map = attributes_map[:revision] - if formula.revision.nonzero? - if formula.stable - if revision_map[formula.stable.version].empty? # check stable spec - problem "'revision #{formula.revision}' should be removed" - end - else # head/devel-only formula + + return if formula.revision.zero? + + if formula.stable + if revision_map[formula.stable.version].empty? # check stable spec problem "'revision #{formula.revision}' should be removed" end + else # head/devel-only formula + problem "'revision #{formula.revision}' should be removed" end end def audit_legacy_patches return unless formula.respond_to?(:patches) legacy_patches = Patch.normalize_legacy_patches(formula.patches).grep(LegacyPatch) - unless legacy_patches.empty? - problem "Use the patch DSL instead of defining a 'patches' method" - legacy_patches.each { |p| audit_patch(p) } - end + + return if legacy_patches.empty? + + problem "Use the patch DSL instead of defining a 'patches' method" + legacy_patches.each { |p| audit_patch(p) } end def audit_patch(patch) @@ -732,9 +732,8 @@ class FormulaAuditor problem "Please set plist_options when using a formula-defined plist." end - if text.include?('require "language/go"') && !text.include?("go_resource") - problem "require \"language/go\" is unnecessary unless using `go_resource`s" - end + return unless text.include?('require "language/go"') && !text.include?("go_resource") + problem "require \"language/go\" is unnecessary unless using `go_resource`s" end def audit_line(line, lineno) @@ -961,61 +960,55 @@ class FormulaAuditor problem "Use Language::Node for npm install args" end - if @strict - if line =~ /system ((["'])[^"' ]*(?:\s[^"' ]*)+\2)/ - bad_system = $1 - unless %w[| < > & ; *].any? { |c| bad_system.include? c } - good_system = bad_system.gsub(" ", "\", \"") - problem "Use `system #{good_system}` instead of `system #{bad_system}` " - end - end + return unless @strict - if line =~ /(require ["']formula["'])/ - problem "`#{$1}` is now unnecessary" + if line =~ /system ((["'])[^"' ]*(?:\s[^"' ]*)+\2)/ + bad_system = $1 + unless %w[| < > & ; *].any? { |c| bad_system.include? c } + good_system = bad_system.gsub(" ", "\", \"") + problem "Use `system #{good_system}` instead of `system #{bad_system}` " end + end - if line =~ %r{#\{share\}/#{Regexp.escape(formula.name)}[/'"]} - problem "Use \#{pkgshare} instead of \#{share}/#{formula.name}" - end + if line =~ /(require ["']formula["'])/ + problem "`#{$1}` is now unnecessary" + end - if line =~ %r{share(\s*[/+]\s*)(['"])#{Regexp.escape(formula.name)}(?:\2|/)} - problem "Use pkgshare instead of (share#{$1}\"#{formula.name}\")" - end + if line =~ %r{#\{share\}/#{Regexp.escape(formula.name)}[/'"]} + problem "Use \#{pkgshare} instead of \#{share}/#{formula.name}" end + + return unless line =~ %r{share(\s*[/+]\s*)(['"])#{Regexp.escape(formula.name)}(?:\2|/)} + problem "Use pkgshare instead of (share#{$1}\"#{formula.name}\")" end def audit_caveats - caveats = formula.caveats.to_s - - if caveats.include?("setuid") - problem "Don't recommend setuid in the caveats, suggest sudo instead." - end + return unless formula.caveats.to_s.include?("setuid") + problem "Don't recommend setuid in the caveats, suggest sudo instead." end def audit_reverse_migration # Only enforce for new formula being re-added to core and official taps return unless @strict return unless formula.tap && formula.tap.official? + return unless formula.tap.tap_migrations.key?(formula.name) - if formula.tap.tap_migrations.key?(formula.name) - problem <<-EOS.undent - #{formula.name} seems to be listed in tap_migrations.json! - Please remove #{formula.name} from present tap & tap_migrations.json - before submitting it to Homebrew/homebrew-#{formula.tap.repo}. - EOS - end + problem <<-EOS.undent + #{formula.name} seems to be listed in tap_migrations.json! + Please remove #{formula.name} from present tap & tap_migrations.json + before submitting it to Homebrew/homebrew-#{formula.tap.repo}. + EOS end def audit_prefix_has_contents return unless formula.prefix.directory? + return unless Keg.new(formula.prefix).empty_installation? - if Keg.new(formula.prefix).empty_installation? - problem <<-EOS.undent - The installation seems to be empty. Please ensure the prefix - is set correctly and expected files are installed. - The prefix configure/make argument may be case-sensitive. - EOS - end + problem <<-EOS.undent + The installation seems to be empty. Please ensure the prefix + is set correctly and expected files are installed. + The prefix configure/make argument may be case-sensitive. + EOS end def audit_conditional_dep(dep, condition, line) @@ -1116,9 +1109,8 @@ class ResourceAuditor problem "version #{version} should not have a leading 'v'" end - if version.to_s =~ /_\d+$/ - problem "version #{version} should not end with an underline and a number" - end + return unless version.to_s =~ /_\d+$/ + problem "version #{version} should not end with an underline and a number" end def audit_checksum @@ -1184,11 +1176,8 @@ class ResourceAuditor end end - using_strategy = DownloadStrategyDetector.detect("", using) - - if url_strategy == using_strategy - problem "Redundant :using value in URL" - end + return unless url_strategy == DownloadStrategyDetector.detect("", using) + problem "Redundant :using value in URL" end def audit_urls diff --git a/Library/Homebrew/dev-cmd/bottle.rb b/Library/Homebrew/dev-cmd/bottle.rb index 9676e374c..b2aa3b2c5 100644 --- a/Library/Homebrew/dev-cmd/bottle.rb +++ b/Library/Homebrew/dev-cmd/bottle.rb @@ -51,10 +51,11 @@ module Homebrew end @put_filenames ||= [] - unless @put_filenames.include? filename - puts "#{Tty.red}#{filename}#{Tty.reset}" - @put_filenames << filename - end + + return if @put_filenames.include? filename + + puts "#{Tty.red}#{filename}#{Tty.reset}" + @put_filenames << filename end result = false @@ -107,9 +108,7 @@ module Homebrew absolute_symlinks_start_with_string = [] keg.find do |pn| next unless pn.symlink? && (link = pn.readlink).absolute? - if link.to_s.start_with?(string) - absolute_symlinks_start_with_string << pn - end + absolute_symlinks_start_with_string << pn if link.to_s.start_with?(string) end if ARGV.verbose? @@ -137,11 +136,11 @@ module Homebrew tap = f.tap unless tap - if ARGV.include?("--force-core-tap") - tap = CoreTap.instance - else + unless ARGV.include?("--force-core-tap") return ofail "Formula not from core or any taps: #{f.full_name}" end + + tap = CoreTap.instance end if f.bottle_disabled? @@ -154,9 +153,7 @@ module Homebrew return ofail "Formula not installed with '--build-bottle': #{f.full_name}" end - unless f.stable - return ofail "Formula has no stable version: #{f.full_name}" - end + return ofail "Formula has no stable version: #{f.full_name}" unless f.stable if ARGV.include?("--no-rebuild") || !f.tap rebuild = 0 @@ -255,7 +252,7 @@ module Homebrew if prefix != prefix_check relocatable = false if keg_contain_absolute_symlink_starting_with?(prefix, keg) end - skip_relocation = relocatable && !keg.require_install_name_tool? + skip_relocation = relocatable && !keg.require_relocation? end puts if !relocatable && ARGV.verbose? rescue Interrupt @@ -323,34 +320,33 @@ module Homebrew puts "./#{filename}" puts output - if ARGV.include? "--json" - json = { - f.full_name => { - "formula" => { - "pkg_version" => f.pkg_version.to_s, - "path" => f.path.to_s.strip_prefix("#{HOMEBREW_REPOSITORY}/"), - }, - "bottle" => { - "root_url" => bottle.root_url, - "prefix" => bottle.prefix, - "cellar" => bottle.cellar.to_s, - "rebuild" => bottle.rebuild, - "tags" => { - Utils::Bottles.tag.to_s => { - "filename" => filename.to_s, - "sha256" => sha256, - }, + return unless ARGV.include? "--json" + json = { + f.full_name => { + "formula" => { + "pkg_version" => f.pkg_version.to_s, + "path" => f.path.to_s.strip_prefix("#{HOMEBREW_REPOSITORY}/"), + }, + "bottle" => { + "root_url" => bottle.root_url, + "prefix" => bottle.prefix, + "cellar" => bottle.cellar.to_s, + "rebuild" => bottle.rebuild, + "tags" => { + Utils::Bottles.tag.to_s => { + "filename" => filename.to_s, + "sha256" => sha256, }, }, - "bintray" => { - "package" => Utils::Bottles::Bintray.package(f.name), - "repository" => Utils::Bottles::Bintray.repository(tap), - }, }, - } - File.open("#{filename.prefix}.bottle.json", "w") do |file| - file.write Utils::JSON.dump json - end + "bintray" => { + "package" => Utils::Bottles::Bintray.package(f.name), + "repository" => Utils::Bottles::Bintray.repository(tap), + }, + }, + } + File.open("#{filename.prefix}.bottle.json", "w") do |file| + file.write Utils::JSON.dump json end end @@ -436,7 +432,7 @@ module Homebrew puts output update_or_add = "add" if s.include? "stable do" - indent = s.slice(/^ +stable do/).length - "stable do".length + indent = s.slice(/^( +)stable do/, 1).length string = s.sub!(/^ {#{indent}}stable do(.|\n)+?^ {#{indent}}end\n/m, '\0' + output + "\n") else string = s.sub!( diff --git a/Library/Homebrew/dev-cmd/bump-formula-pr.rb b/Library/Homebrew/dev-cmd/bump-formula-pr.rb index 38c7559fb..ce10da52a 100644 --- a/Library/Homebrew/dev-cmd/bump-formula-pr.rb +++ b/Library/Homebrew/dev-cmd/bump-formula-pr.rb @@ -27,7 +27,7 @@ require "formula" module Homebrew def inreplace_pairs(path, replacement_pairs) if ARGV.dry_run? - contents = path.open("r") { |f| Formulary.set_encoding(f).read } + contents = path.open("r") { |f| Formulary.ensure_utf8_encoding(f).read } contents.extend(StringInreplaceExtension) replacement_pairs.each do |old, new| unless ARGV.flag?("--quiet") @@ -48,7 +48,7 @@ module Homebrew s.gsub!(old, new) end end - path.open("r") { |f| Formulary.set_encoding(f).read } + path.open("r") { |f| Formulary.ensure_utf8_encoding(f).read } end end diff --git a/Library/Homebrew/dev-cmd/edit.rb b/Library/Homebrew/dev-cmd/edit.rb index f80d05861..2d2a5ec08 100644 --- a/Library/Homebrew/dev-cmd/edit.rb +++ b/Library/Homebrew/dev-cmd/edit.rb @@ -33,9 +33,9 @@ module Homebrew # Don't use ARGV.formulae as that will throw if the file doesn't parse paths = ARGV.named.map do |name| path = Formulary.path(name) - unless path.file? || ARGV.force? - raise FormulaUnavailableError, name - end + + raise FormulaUnavailableError, name unless path.file? || ARGV.force? + path end exec_editor(*paths) diff --git a/Library/Homebrew/dev-cmd/man.rb b/Library/Homebrew/dev-cmd/man.rb index 0627241a3..871fbf46c 100644 --- a/Library/Homebrew/dev-cmd/man.rb +++ b/Library/Homebrew/dev-cmd/man.rb @@ -52,17 +52,12 @@ module Homebrew variables[:commands] = path_glob_commands("#{HOMEBREW_LIBRARY_PATH}/cmd/*.{rb,sh}") variables[:developer_commands] = path_glob_commands("#{HOMEBREW_LIBRARY_PATH}/dev-cmd/*.{rb,sh}") readme = HOMEBREW_REPOSITORY/"README.md" - variables[:lead_maintainer] = readme - .read[/Homebrew's lead maintainer is (.*)\./, 1] - .scan(/\[([^\]]*)\]/).flatten.first - variables[:maintainers] = readme - .read[/Homebrew's current maintainers are (.*)\./, 1] - .scan(/\[([^\]]*)\]/).flatten - former_maintainers = readme - .read[/Former maintainers with significant contributions include (.*)\./, 1] - .scan(/\[([^\]]*)\]/).flatten - variables[:former_maintainers] = former_maintainers[0...-1] - variables[:creator] = former_maintainers.last + variables[:lead_maintainer] = readme.read[/(Homebrew's lead maintainer .*\.)/, 1] + .gsub(/\[([^\]]+)\]\([^)]+\)/, '\1') + variables[:maintainers] = readme.read[/(Homebrew's current maintainers .*\.)/, 1] + .gsub(/\[([^\]]+)\]\([^)]+\)/, '\1') + variables[:former_maintainers] = readme.read[/(Former maintainers .*\.)/, 1] + .gsub(/\[([^\]]+)\]\([^)]+\)/, '\1') ERB.new(template, nil, ">").result(variables.instance_eval { binding }) end diff --git a/Library/Homebrew/dev-cmd/mirror.rb b/Library/Homebrew/dev-cmd/mirror.rb index 162008123..9966163f8 100644 --- a/Library/Homebrew/dev-cmd/mirror.rb +++ b/Library/Homebrew/dev-cmd/mirror.rb @@ -4,9 +4,7 @@ module Homebrew def mirror - if ARGV.named.empty? - odie "This command requires at least formula argument!" - end + odie "This command requires at least formula argument!" if ARGV.named.empty? bintray_user = ENV["BINTRAY_USER"] bintray_key = ENV["BINTRAY_KEY"] diff --git a/Library/Homebrew/dev-cmd/pull.rb b/Library/Homebrew/dev-cmd/pull.rb index 7f027e159..857c55993 100644 --- a/Library/Homebrew/dev-cmd/pull.rb +++ b/Library/Homebrew/dev-cmd/pull.rb @@ -41,12 +41,12 @@ require "pkg_version" module Homebrew def pull - if ARGV[0] == "--rebase" - odie "You meant `git pull --rebase`." - end + odie "You meant `git pull --rebase`." if ARGV[0] == "--rebase" + if ARGV.named.empty? odie "This command requires at least one argument containing a URL or pull request number" end + do_bump = ARGV.include?("--bump") && !ARGV.include?("--clean") # Formulae with affected bottles that were published @@ -429,9 +429,9 @@ module Homebrew # Returns nil if formula is absent or if there was an error reading it def self.lookup(name) json = Utils.popen_read(HOMEBREW_BREW_FILE, "info", "--json=v1", name) - unless $?.success? - return nil - end + + return nil unless $?.success? + Homebrew.force_utf8!(json) FormulaInfoFromJson.new(Utils::JSON.load(json)[0]) end @@ -531,19 +531,19 @@ module Homebrew req = Net::HTTP::Head.new bottle_info.url req.initialize_http_header "User-Agent" => HOMEBREW_USER_AGENT_RUBY res = http.request req - if res.is_a?(Net::HTTPSuccess) - break - elsif res.is_a?(Net::HTTPClientError) - if retry_count >= max_retries - raise "Failed to find published #{f} bottle at #{url}!" - end - print(wrote_dots ? "." : "Waiting on Bintray.") - wrote_dots = true - sleep poll_retry_delay_seconds - retry_count += 1 - else + break if res.is_a?(Net::HTTPSuccess) + + unless res.is_a?(Net::HTTPClientError) raise "Failed to find published #{f} bottle at #{url} (#{res.code} #{res.message})!" end + + if retry_count >= max_retries + raise "Failed to find published #{f} bottle at #{url}!" + end + print(wrote_dots ? "." : "Waiting on Bintray.") + wrote_dots = true + sleep poll_retry_delay_seconds + retry_count += 1 end end diff --git a/Library/Homebrew/dev-cmd/test-bot.rb b/Library/Homebrew/dev-cmd/test-bot.rb deleted file mode 100644 index d20711588..000000000 --- a/Library/Homebrew/dev-cmd/test-bot.rb +++ /dev/null @@ -1,1172 +0,0 @@ -#: @hide_from_man_page -#: * `test-bot` [options] <url|formula>: -#: Tests the full lifecycle of a formula or Homebrew/brew change. -#: -#: If `--dry-run` is passed, print what would be done rather than doing -#: it. -#: -#: If `--local` is passed, perform only local operations (i.e. don't -#: push or create PR). -#: -#: If `--keep-logs` is passed, write and keep log files under -#: `./brewbot/`. -#: -#: If `--cleanup` is passed, clean all state from the Homebrew -#: directory. Use with care! -#: -#: If `--clean-cache` is passed, remove all cached downloads. Use with -#: care! -#: -#: If `--skip-setup` is passed, don't check the local system is setup -#: correctly. -#: -#: If `--skip-homebrew` is passed, don't check Homebrew's files and -#: tests are all valid. -#: -#: If `--junit` is passed, generate a JUnit XML test results file. -#: -#: If `--no-bottle` is passed, run `brew install` without -#: `--build-bottle`. -#: -#: If `--keep-old` is passed, run `brew bottle --keep-old` to build new -#: bottles for a single platform. -#: -#: If `--skip-relocation` is passed, run -#: `brew bottle --skip-relocation` to build new bottles that don't -#: require relocation. -#: -#: If `--HEAD` is passed, run `brew install` with `--HEAD`. -#: -#: If `--local` is passed, ask Homebrew to write verbose logs under -#: `./logs/` and set `$HOME` to `./home/`. -#: -#: If `--tap=<tap>` is passed, use the `git` repository of the given -#: tap. -#: -#: If `--dry-run` is passed, just print commands, don't run them. -#: -#: If `--fail-fast` is passed, immediately exit on a failing step. -#: -#: If `--verbose` is passed, print test step output in real time. Has -#: the side effect of passing output as raw bytes instead of -#: re-encoding in UTF-8. -#: -#: If `--fast` is passed, don't install any packages, but run e.g. -#: `brew audit` anyway. -#: -#: If `--keep-tmp` is passed, keep temporary files written by main -#: installs and tests that are run. -#: -#: If `--no-pull` is passed, don't use `brew pull` when possible. -#: -#: If `--coverage` is passed, generate and uplaod a coverage report. -#: -#: If `--test-default-formula` is passed, use a default testing formula -#: when not building a tap and no other formulae are specified. -#: -#: If `--ci-master` is passed, use the Homebrew master branch CI -#: options. -#: -#: If `--ci-pr` is passed, use the Homebrew pull request CI options. -#: -#: If `--ci-testing` is passed, use the Homebrew testing CI options. -#: -#: If `--ci-auto` is passed, automatically pick one of the Homebrew CI -#: options based on the environment. -#: -#: If `--ci-upload` is passed, use the Homebrew CI bottle upload -#: options. -#: -# -#: Influential environment variables include: -#: `TRAVIS_REPO_SLUG`: same as `--tap` -#: `GIT_URL`: if set to URL of a tap remote, same as `--tap` - -require "formula" -require "utils" -require "date" -require "rexml/document" -require "rexml/xmldecl" -require "rexml/cdata" -require "tap" -require "development_tools" -require "utils/bottles" - -module Homebrew - BYTES_IN_1_MEGABYTE = 1024*1024 - MAX_STEP_OUTPUT_SIZE = BYTES_IN_1_MEGABYTE - (200*1024) # margin of safety - - HOMEBREW_TAP_REGEX = %r{^([\w-]+)/homebrew-([\w-]+)$} - - def fix_encoding!(str) - # Assume we are starting from a "mostly" UTF-8 string - str.force_encoding(Encoding::UTF_8) - return str if str.valid_encoding? - str.encode!(Encoding::UTF_16, invalid: :replace) - str.encode!(Encoding::UTF_8) - end - - def resolve_test_tap - if tap = ARGV.value("tap") - return Tap.fetch(tap) - end - - if (tap = ENV["TRAVIS_REPO_SLUG"]) && (tap =~ HOMEBREW_TAP_REGEX) - return Tap.fetch(tap) - end - - if ENV["UPSTREAM_BOT_PARAMS"] - bot_argv = ENV["UPSTREAM_BOT_PARAMS"].split " " - bot_argv.extend HomebrewArgvExtension - if tap = bot_argv.value("tap") - return Tap.fetch(tap) - end - end - - if git_url = ENV["UPSTREAM_GIT_URL"] || ENV["GIT_URL"] - # Also can get tap from Jenkins GIT_URL. - url_path = git_url.sub(%r{^https?://github\.com/}, "").chomp("/").sub(/\.git$/, "") - begin - return Tap.fetch(url_path) if url_path =~ HOMEBREW_TAP_REGEX - rescue - end - end - end - - # Wraps command invocations. Instantiated by Test#test. - # Handles logging and pretty-printing. - class Step - attr_reader :command, :name, :status, :output - - # Instantiates a Step object. - # @param test [Test] The parent Test object - # @param command [Array<String>] Command to execute and arguments - # @param options [Hash] Recognized options are: - # :puts_output_on_success - # :repository - def initialize(test, command, options = {}) - @test = test - @category = test.category - @command = command - @puts_output_on_success = options[:puts_output_on_success] - @name = command[1].delete("-") - @status = :running - @repository = options[:repository] || HOMEBREW_REPOSITORY - end - - def log_file_path - file = "#{@category}.#{@name}.txt" - root = @test.log_root - root ? root + file : file - end - - def command_short - (@command - %w[brew --force --retry --verbose --build-bottle --json]).join(" ") - end - - def passed? - @status == :passed - end - - def failed? - @status == :failed - end - - def puts_command - if ENV["TRAVIS"] - @@travis_step_num ||= 0 - @travis_fold_id = @command.first(2).join(".") + ".#{@@travis_step_num += 1}" - @travis_timer_id = rand(2**32).to_s(16) - puts "travis_fold:start:#{@travis_fold_id}" - puts "travis_time:start:#{@travis_timer_id}" - end - puts "#{Tty.blue}==>#{Tty.white} #{@command.join(" ")}#{Tty.reset}" - end - - def puts_result - if ENV["TRAVIS"] - travis_start_time = @start_time.to_i*1000000000 - travis_end_time = @end_time.to_i*1000000000 - travis_duration = travis_end_time - travis_start_time - puts "#{Tty.white}==>#{Tty.green} PASSED#{Tty.reset}" if passed? - puts "travis_time:end:#{@travis_timer_id},start=#{travis_start_time},finish=#{travis_end_time},duration=#{travis_duration}" - puts "travis_fold:end:#{@travis_fold_id}" - end - puts "#{Tty.white}==>#{Tty.red} FAILED#{Tty.reset}" if failed? - end - - def output? - @output && !@output.empty? - end - - # The execution time of the task. - # Precondition: Step#run has been called. - # @return [Float] execution time in seconds - def time - @end_time - @start_time - end - - def run - @start_time = Time.now - - puts_command - if ARGV.include? "--dry-run" - @end_time = Time.now - @status = :passed - puts_result - return - end - - verbose = ARGV.verbose? - # Step may produce arbitrary output and we read it bytewise, so must - # buffer it as binary and convert to UTF-8 once complete - output = "".encode!("BINARY") - working_dir = Pathname.new(@command.first == "git" ? @repository : Dir.pwd) - read, write = IO.pipe - - begin - pid = fork do - read.close - $stdout.reopen(write) - $stderr.reopen(write) - write.close - working_dir.cd { exec(*@command) } - end - write.close - while buf = read.readpartial(4096) - if verbose - print buf - $stdout.flush - end - output << buf - end - rescue EOFError - ensure - read.close - end - - Process.wait(pid) - @end_time = Time.now - @status = $?.success? ? :passed : :failed - puts_result - - unless output.empty? - @output = Homebrew.fix_encoding!(output) - puts @output if (failed? || @puts_output_on_success) && !verbose - File.write(log_file_path, @output) if ARGV.include? "--keep-logs" - end - - exit 1 if ARGV.include?("--fail-fast") && failed? - end - end - - class Test - attr_reader :log_root, :category, :name, :steps - - def initialize(argument, options = {}) - @hash = nil - @url = nil - @formulae = [] - @added_formulae = [] - @modified_formula = [] - @steps = [] - @tap = options[:tap] - @repository = @tap ? @tap.path : HOMEBREW_REPOSITORY - @skip_homebrew = options.fetch(:skip_homebrew, false) - - if quiet_system "git", "-C", @repository.to_s, "rev-parse", "--verify", "-q", argument - @hash = argument - elsif url_match = argument.match(HOMEBREW_PULL_OR_COMMIT_URL_REGEX) - @url = url_match[0] - elsif canonical_formula_name = safe_formula_canonical_name(argument) - @formulae = [canonical_formula_name] - else - raise ArgumentError, "#{argument} is not a pull request URL, commit URL or formula name." - end - - @category = __method__ - @brewbot_root = Pathname.pwd + "brewbot" - FileUtils.mkdir_p @brewbot_root - end - - def no_args? - @hash == "HEAD" - end - - def safe_formula_canonical_name(formula_name) - Formulary.factory(formula_name).full_name - rescue TapFormulaUnavailableError => e - raise if e.tap.installed? - test "brew", "tap", e.tap.name - retry unless steps.last.failed? - onoe e - puts e.backtrace if ARGV.debug? - rescue FormulaUnavailableError, TapFormulaAmbiguityError, TapFormulaWithOldnameAmbiguityError => e - onoe e - puts e.backtrace if ARGV.debug? - end - - def git(*args) - @repository.cd { Utils.popen_read("git", *args) } - end - - def download - def shorten_revision(revision) - git("rev-parse", "--short", revision).strip - end - - def current_sha1 - shorten_revision "HEAD" - end - - def current_branch - git("symbolic-ref", "HEAD").gsub("refs/heads/", "").strip - end - - def single_commit?(start_revision, end_revision) - git("rev-list", "--count", "#{start_revision}..#{end_revision}").to_i == 1 - end - - def diff_formulae(start_revision, end_revision, path, filter) - return unless @tap - git( - "diff-tree", "-r", "--name-only", "--diff-filter=#{filter}", - start_revision, end_revision, "--", path - ).lines.map do |line| - file = Pathname.new line.chomp - next unless @tap.formula_file?(file) - @tap.formula_file_to_name(file) - end.compact - end - - @category = __method__ - @start_branch = current_branch - - travis_pr = ENV["TRAVIS_PULL_REQUEST"] && ENV["TRAVIS_PULL_REQUEST"] != "false" - - # Use Jenkins GitHub Pull Request Builder plugin variables for - # pull request jobs. - if ENV["ghprbPullLink"] - @url = ENV["ghprbPullLink"] - @hash = nil - test "git", "checkout", "origin/master" - elsif ENV["GIT_URL"] && ENV["GIT_BRANCH"] - git_url = ENV["GIT_URL"].chomp("/").chomp(".git") - %r{origin/pr/(\d+)/(merge|head)} =~ ENV["GIT_BRANCH"] - pr = $1 - @url = "#{git_url}/pull/#{pr}" - @hash = nil - # Use Travis CI pull-request variables for pull request jobs. - elsif travis_pr - @url = "https://github.com/#{ENV["TRAVIS_REPO_SLUG"]}/pull/#{ENV["TRAVIS_PULL_REQUEST"]}" - @hash = nil - end - - # Use Jenkins Git plugin variables for master branch jobs. - if ENV["GIT_PREVIOUS_COMMIT"] && ENV["GIT_COMMIT"] - diff_start_sha1 = ENV["GIT_PREVIOUS_COMMIT"] - diff_end_sha1 = ENV["GIT_COMMIT"] - # Use Travis CI Git variables for master or branch jobs. - elsif ENV["TRAVIS_COMMIT_RANGE"] - diff_start_sha1, diff_end_sha1 = ENV["TRAVIS_COMMIT_RANGE"].split "..." - # Otherwise just use the current SHA-1 (which may be overriden later) - else - diff_end_sha1 = diff_start_sha1 = current_sha1 - end - - diff_start_sha1 = git("merge-base", diff_start_sha1, diff_end_sha1).strip - - # Handle no arguments being passed on the command-line e.g. `brew test-bot`. - if no_args? - if diff_start_sha1 == diff_end_sha1 || \ - single_commit?(diff_start_sha1, diff_end_sha1) - @name = diff_end_sha1 - else - @name = "#{diff_start_sha1}-#{diff_end_sha1}" - end - # Handle formulae arguments being passed on the command-line e.g. `brew test-bot wget fish`. - elsif !@formulae.empty? - @name = "#{@formulae.first}-#{diff_end_sha1}" - diff_start_sha1 = diff_end_sha1 - # Handle a hash being passed on the command-line e.g. `brew test-bot 1a2b3c`. - elsif @hash - test "git", "checkout", @hash - diff_start_sha1 = "#{@hash}^" - diff_end_sha1 = @hash - @name = @hash - # Handle a URL being passed on the command-line or through Jenkins/Travis - # environment variables e.g. - # `brew test-bot https://github.com/Homebrew/homebrew-core/pull/678`. - elsif @url - # TODO: in future Travis CI may need to also use `brew pull` to e.g. push - # the right commit to BrewTestBot. - if !travis_pr && !ARGV.include?("--no-pull") - diff_start_sha1 = current_sha1 - test "brew", "pull", "--clean", @url - diff_end_sha1 = current_sha1 - end - @short_url = @url.gsub("https://github.com/", "") - if @short_url.include? "/commit/" - # 7 characters should be enough for a commit (not 40). - @short_url.gsub!(%r{(commit/\w{7}).*/}, '\1') - @name = @short_url - else - @name = "#{@short_url}-#{diff_end_sha1}" - end - else - raise "Cannot set @name: invalid command-line arguments!" - end - - @log_root = @brewbot_root + @name - FileUtils.mkdir_p @log_root - - return unless diff_start_sha1 != diff_end_sha1 - return if @url && steps.last && !steps.last.passed? - - if @tap - formula_path = @tap.formula_dir.to_s - @added_formulae += diff_formulae(diff_start_sha1, diff_end_sha1, formula_path, "A") - @modified_formula += diff_formulae(diff_start_sha1, diff_end_sha1, formula_path, "M")\ - elsif @formulae.empty? && ARGV.include?("--test-default-formula") - # Build the default test formula. - HOMEBREW_CACHE_FORMULA.mkpath - testbottest = "#{HOMEBREW_LIBRARY}/Homebrew/test/testbottest.rb" - FileUtils.cp testbottest, HOMEBREW_CACHE_FORMULA - @test_default_formula = true - @added_formulae = [testbottest] - end - - @formulae += @added_formulae + @modified_formula - end - - def skip(formula_name) - puts "#{Tty.blue}==>#{Tty.white} SKIPPING: #{formula_name}#{Tty.reset}" - end - - def satisfied_requirements?(formula, spec, dependency = nil) - requirements = formula.send(spec).requirements - - unsatisfied_requirements = requirements.reject do |requirement| - satisfied = false - satisfied ||= requirement.satisfied? - satisfied ||= requirement.optional? - if !satisfied && requirement.default_formula? - default = Formula[requirement.default_formula] - satisfied = satisfied_requirements?(default, :stable, formula.full_name) - end - satisfied - end - - if unsatisfied_requirements.empty? - true - else - name = formula.full_name - name += " (#{spec})" unless spec == :stable - name += " (#{dependency} dependency)" if dependency - skip name - puts unsatisfied_requirements.map(&:message) - false - end - end - - def setup - @category = __method__ - return if ARGV.include? "--skip-setup" - if !ENV["TRAVIS"] && HOMEBREW_PREFIX.to_s == "/usr/local" - test "brew", "doctor" - end - test "brew", "--env" - test "brew", "config" - end - - def formula(formula_name) - @category = "#{__method__}.#{formula_name}" - - test "brew", "uses", formula_name - - formula = Formulary.factory(formula_name) - - installed_gcc = false - - deps = [] - reqs = [] - - fetch_args = [formula_name] - fetch_args << "--build-bottle" if !ARGV.include?("--fast") && !ARGV.include?("--no-bottle") && !formula.bottle_disabled? - fetch_args << "--force" if ARGV.include? "--cleanup" - - audit_args = [formula_name] - audit_args << "--new-formula" if @added_formulae.include? formula_name - - if formula.stable - unless satisfied_requirements?(formula, :stable) - test "brew", "fetch", "--retry", *fetch_args - test "brew", "audit", *audit_args - return - end - - deps |= formula.stable.deps.to_a.reject(&:optional?) - reqs |= formula.stable.requirements.to_a.reject(&:optional?) - elsif formula.devel - unless satisfied_requirements?(formula, :devel) - test "brew", "fetch", "--retry", "--devel", *fetch_args - test "brew", "audit", "--devel", *audit_args - return - end - end - - if formula.devel && !ARGV.include?("--HEAD") - deps |= formula.devel.deps.to_a.reject(&:optional?) - reqs |= formula.devel.requirements.to_a.reject(&:optional?) - end - - begin - deps.each { |d| d.to_formula.recursive_dependencies } - rescue TapFormulaUnavailableError => e - raise if e.tap.installed? - safe_system "brew", "tap", e.tap.name - retry - end - - begin - deps.each do |dep| - CompilerSelector.select_for(dep.to_formula) - end - CompilerSelector.select_for(formula) - rescue CompilerSelectionError => e - unless installed_gcc - run_as_not_developer { test "brew", "install", "gcc" } - installed_gcc = true - DevelopmentTools.clear_version_cache - retry - end - skip formula_name - puts e.message - return - end - - conflicts = formula.conflicts - formula.recursive_dependencies.each do |dependency| - conflicts += dependency.to_formula.conflicts - end - - conflicts.each do |conflict| - confict_formula = Formulary.factory(conflict.name) - - if confict_formula.installed? && confict_formula.linked_keg.exist? - test "brew", "unlink", "--force", conflict.name - end - end - - installed = Utils.popen_read("brew", "list").split("\n") - dependencies = Utils.popen_read("brew", "deps", "--include-build", formula_name).split("\n") - - (installed & dependencies).each do |installed_dependency| - installed_dependency_formula = Formulary.factory(installed_dependency) - if installed_dependency_formula.installed? && - !installed_dependency_formula.keg_only? && - !installed_dependency_formula.linked_keg.exist? - test "brew", "link", installed_dependency - end - end - - dependencies -= installed - unchanged_dependencies = dependencies - @formulae - changed_dependences = dependencies - unchanged_dependencies - - runtime_dependencies = Utils.popen_read("brew", "deps", formula_name).split("\n") - build_dependencies = dependencies - runtime_dependencies - unchanged_build_dependencies = build_dependencies - @formulae - - dependents = Utils.popen_read("brew", "uses", formula_name).split("\n") - dependents -= @formulae - dependents = dependents.map { |d| Formulary.factory(d) } - - bottled_dependents = dependents.select(&:bottled?) - testable_dependents = dependents.select { |d| d.bottled? && d.test_defined? } - - if (deps | reqs).any? { |d| d.name == "mercurial" && d.build? } - run_as_not_developer { test "brew", "install", "mercurial" } - end - - test "brew", "fetch", "--retry", *unchanged_dependencies unless unchanged_dependencies.empty? - - unless changed_dependences.empty? - test "brew", "fetch", "--retry", "--build-bottle", *changed_dependences - unless ARGV.include?("--fast") - # Install changed dependencies as new bottles so we don't have checksum problems. - test "brew", "install", "--build-bottle", *changed_dependences - # Run postinstall on them because the tested formula might depend on - # this step - test "brew", "postinstall", *changed_dependences - end - end - test "brew", "fetch", "--retry", *fetch_args - test "brew", "uninstall", "--force", formula_name if formula.installed? - - # shared_*_args are applied to both the main and --devel spec - shared_install_args = ["--verbose"] - shared_install_args << "--keep-tmp" if ARGV.keep_tmp? - # install_args is just for the main (stable, or devel if in a devel-only tap) spec - install_args = [] - install_args << "--build-bottle" if !ARGV.include?("--fast") && !ARGV.include?("--no-bottle") && !formula.bottle_disabled? - install_args << "--HEAD" if ARGV.include? "--HEAD" - - # Pass --devel or --HEAD to install in the event formulae lack stable. Supports devel-only/head-only. - # head-only should not have devel, but devel-only can have head. Stable can have all three. - if devel_only_tap? formula - install_args << "--devel" - formula_bottled = false - elsif head_only_tap? formula - install_args << "--HEAD" - formula_bottled = false - else - formula_bottled = formula.bottled? - end - - install_args.concat(shared_install_args) - install_args << formula_name - # Don't care about e.g. bottle failures for dependencies. - install_passed = false - run_as_not_developer do - if !ARGV.include?("--fast") || formula_bottled || formula.bottle_unneeded? - test "brew", "install", "--only-dependencies", *install_args unless dependencies.empty? - test "brew", "install", *install_args - install_passed = steps.last.passed? - end - end - test "brew", "audit", *audit_args - if install_passed - if formula.stable? && !ARGV.include?("--fast") && !ARGV.include?("--no-bottle") && !formula.bottle_disabled? - bottle_args = ["--verbose", "--json", formula_name] - bottle_args << "--keep-old" if ARGV.include? "--keep-old" - bottle_args << "--skip-relocation" if ARGV.include? "--skip-relocation" - bottle_args << "--force-core-tap" if @test_default_formula - test "brew", "bottle", *bottle_args - bottle_step = steps.last - if bottle_step.passed? && bottle_step.output? - bottle_filename = - bottle_step.output.gsub(%r{.*(\./\S+#{Utils::Bottles.native_regex}).*}m, '\1') - bottle_json_filename = bottle_filename.gsub(/\.(\d+\.)?tar\.gz$/, ".json") - bottle_merge_args = ["--merge", "--write", "--no-commit", bottle_json_filename] - bottle_merge_args << "--keep-old" if ARGV.include? "--keep-old" - test "brew", "bottle", *bottle_merge_args - test "brew", "uninstall", "--force", formula_name - FileUtils.ln bottle_filename, HOMEBREW_CACHE/bottle_filename, force: true - @formulae.delete(formula_name) - unless unchanged_build_dependencies.empty? - test "brew", "uninstall", "--force", *unchanged_build_dependencies - unchanged_dependencies -= unchanged_build_dependencies - end - test "brew", "install", bottle_filename - end - end - shared_test_args = ["--verbose"] - shared_test_args << "--keep-tmp" if ARGV.keep_tmp? - test "brew", "test", formula_name, *shared_test_args if formula.test_defined? - bottled_dependents.each do |dependent| - unless dependent.installed? - test "brew", "fetch", "--retry", dependent.name - next if steps.last.failed? - conflicts = dependent.conflicts.map { |c| Formulary.factory(c.name) }.select(&:installed?) - dependent.recursive_dependencies.each do |dependency| - conflicts += dependency.to_formula.conflicts.map { |c| Formulary.factory(c.name) }.select(&:installed?) - end - conflicts.each do |conflict| - test "brew", "unlink", conflict.name - end - unless ARGV.include?("--fast") - run_as_not_developer { test "brew", "install", dependent.name } - next if steps.last.failed? - end - end - next unless dependent.installed? - test "brew", "linkage", "--test", dependent.name - if testable_dependents.include? dependent - test "brew", "test", "--verbose", dependent.name - end - end - test "brew", "uninstall", "--force", formula_name - end - - if formula.devel && formula.stable? \ - && !ARGV.include?("--HEAD") && !ARGV.include?("--fast") \ - && satisfied_requirements?(formula, :devel) - test "brew", "fetch", "--retry", "--devel", *fetch_args - run_as_not_developer do - test "brew", "install", "--devel", formula_name, *shared_install_args - end - devel_install_passed = steps.last.passed? - test "brew", "audit", "--devel", *audit_args - if devel_install_passed - test "brew", "test", "--devel", formula_name, *shared_test_args if formula.test_defined? - test "brew", "uninstall", "--devel", "--force", formula_name - end - end - test "brew", "uninstall", "--force", *unchanged_dependencies unless unchanged_dependencies.empty? - end - - def homebrew - @category = __method__ - return if @skip_homebrew - - if !@tap && (@formulae.empty? || @test_default_formula) - # TODO: try to fix this on Linux at some stage. - if OS.mac? - # test update from origin/master to current commit. - test "brew", "update-test" - # test no-op update from current commit (to current commit, a no-op). - test "brew", "update-test", "--commit=HEAD" - end - - test "brew", "style" - test "brew", "readall", "--syntax" - - coverage_args = [] - if ARGV.include?("--coverage") - if ENV["JENKINS_HOME"] - if OS.mac? && MacOS.version == :sierra - coverage_args << "--coverage" - end - else - coverage_args << "--coverage" - end - end - - test "brew", "tests", "--no-compat" - test "brew", "tests", "--generic" - test "brew", "tests", "--official-cmd-taps", *coverage_args - - if OS.mac? - run_as_not_developer { test "brew", "tap", "caskroom/cask" } - test "brew", "cask-tests", *coverage_args - end - elsif @tap - if @tap.name == "homebrew/core" - test "brew", "style", @tap.name - end - test "brew", "readall", "--aliases", @tap.name - end - end - - def cleanup_git - git "gc", "--auto" - test "git", "clean", "-ffdx", "--exclude=Library/Taps" - - Tap.names.each do |tap| - next if tap == "homebrew/core" - next if tap == @tap.to_s - safe_system "brew", "untap", tap - end - - Formula.installed.each do |formula| - safe_system "brew", "uninstall", "--force", formula - end - safe_system "brew", "prune" - - unless @repository == HOMEBREW_REPOSITORY - HOMEBREW_REPOSITORY.cd do - safe_system "git", "checkout", "-f", "master" - safe_system "git", "reset", "--hard", "origin/master" - safe_system "git", "clean", "-ffdx", "--exclude=Library/Taps" - end - end - - Pathname.glob("#{HOMEBREW_LIBRARY}/Taps/*/*").each do |git_repo| - next if @repository == git_repo - git_repo.cd do - safe_system "git", "checkout", "-f", "master" - safe_system "git", "reset", "--hard", "origin/master" - end - end - end - - def cleanup_before - @category = __method__ - return unless ARGV.include? "--cleanup" - git "stash" - git "am", "--abort" - git "rebase", "--abort" - unless ARGV.include? "--no-pull" - git "checkout", "-f", "master" - git "reset", "--hard", "origin/master" - end - - cleanup_git - - pr_locks = "#{@repository}/.git/refs/remotes/*/pr/*/*.lock" - Dir.glob(pr_locks) { |lock| FileUtils.rm_rf lock } - end - - def cleanup_after - @category = __method__ - - if @start_branch && !@start_branch.empty? && \ - (ARGV.include?("--cleanup") || @url || @hash) - checkout_args = [@start_branch] - checkout_args << "-f" if ARGV.include? "--cleanup" - test "git", "checkout", *checkout_args - end - - if ARGV.include? "--cleanup" - git "reset", "--hard", "origin/master" - git "stash", "pop" - test "brew", "cleanup", "--prune=7" - - cleanup_git - - if ARGV.include? "--local" - FileUtils.rm_rf ENV["HOMEBREW_HOME"] - FileUtils.rm_rf ENV["HOMEBREW_LOGS"] - end - end - - FileUtils.rm_rf @brewbot_root unless ARGV.include? "--keep-logs" - end - - def test(*args) - options = args.last.is_a?(Hash) ? args.pop : {} - options[:repository] = @repository - step = Step.new self, args, options - step.run - steps << step - step - end - - def check_results - steps.all? do |step| - case step.status - when :passed then true - when :running then raise - when :failed then false - end - end - end - - def formulae - changed_formulae_dependents = {} - - @formulae.each do |formula| - formula_dependencies = Utils.popen_read("brew", "deps", "--full-name", "--include-build", formula).split("\n") - unchanged_dependencies = formula_dependencies - @formulae - changed_dependences = formula_dependencies - unchanged_dependencies - changed_dependences.each do |changed_formula| - changed_formulae_dependents[changed_formula] ||= 0 - changed_formulae_dependents[changed_formula] += 1 - end - end - - changed_formulae = changed_formulae_dependents.sort do |a1, a2| - a2[1].to_i <=> a1[1].to_i - end - changed_formulae.map!(&:first) - unchanged_formulae = @formulae - changed_formulae - changed_formulae + unchanged_formulae - end - - def head_only_tap?(formula) - formula.head && formula.devel.nil? && formula.stable.nil? && formula.tap == "homebrew/homebrew-head-only" - end - - def devel_only_tap?(formula) - formula.devel && formula.stable.nil? && formula.tap == "homebrew/homebrew-devel-only" - end - - def run - cleanup_before - begin - download - setup - homebrew - formulae.each do |f| - formula(f) - end - ensure - cleanup_after - end - check_results - end - end - - def test_ci_upload(tap) - # Don't trust formulae we're uploading - ENV["HOMEBREW_DISABLE_LOAD_FORMULA"] = "1" - - bintray_user = ENV["BINTRAY_USER"] - bintray_key = ENV["BINTRAY_KEY"] - if !bintray_user || !bintray_key - raise "Missing BINTRAY_USER or BINTRAY_KEY variables!" - end - - # Don't pass keys/cookies to subprocesses - ENV["BINTRAY_KEY"] = nil - ENV["HUDSON_SERVER_COOKIE"] = nil - ENV["JENKINS_SERVER_COOKIE"] = nil - ENV["HUDSON_COOKIE"] = nil - ENV["COVERALLS_REPO_TOKEN"] = nil - - ARGV << "--verbose" - - bottles = Dir["*.bottle*.*"] - if bottles.empty? - jenkins = ENV["JENKINS_HOME"] - job = ENV["UPSTREAM_JOB_NAME"] - id = ENV["UPSTREAM_BUILD_ID"] - raise "Missing Jenkins variables!" if !jenkins || !job || !id - - bottles = Dir["#{jenkins}/jobs/#{job}/configurations/axis-version/*/builds/#{id}/archive/*.bottle*.*"] - return if bottles.empty? - - FileUtils.cp bottles, Dir.pwd, verbose: true - end - - json_files = Dir.glob("*.bottle.json") - bottles_hash = json_files.reduce({}) do |hash, json_file| - deep_merge_hashes hash, Utils::JSON.load(IO.read(json_file)) - end - - first_formula_name = bottles_hash.keys.first - tap = Tap.fetch(first_formula_name.rpartition("/").first.chuzzle || "homebrew/core") - - ENV["GIT_AUTHOR_NAME"] = ENV["GIT_COMMITTER_NAME"] = "BrewTestBot" - ENV["GIT_AUTHOR_EMAIL"] = ENV["GIT_COMMITTER_EMAIL"] = "brew-test-bot@googlegroups.com" - ENV["GIT_WORK_TREE"] = tap.path - ENV["GIT_DIR"] = "#{ENV["GIT_WORK_TREE"]}/.git" - - quiet_system "git", "am", "--abort" - quiet_system "git", "rebase", "--abort" - safe_system "git", "checkout", "-f", "master" - safe_system "git", "reset", "--hard", "origin/master" - safe_system "brew", "update" - - if (pr = ENV["UPSTREAM_PULL_REQUEST"]) - pull_pr = "https://github.com/#{tap.user}/homebrew-#{tap.repo}/pull/#{pr}" - safe_system "brew", "pull", "--clean", pull_pr - end - - if ENV["UPSTREAM_BOTTLE_KEEP_OLD"] || ENV["BOT_PARAMS"].to_s.include?("--keep-old") - system "brew", "bottle", "--merge", "--write", "--keep-old", *json_files - else - system "brew", "bottle", "--merge", "--write", *json_files - end - - remote = "git@github.com:BrewTestBot/homebrew-#{tap.repo}.git" - git_tag = if pr - "pr-#{pr}" - elsif (upstream_number = ENV["UPSTREAM_BUILD_NUMBER"]) - "testing-#{upstream_number}" - elsif (number = ENV["BUILD_NUMBER"]) - "other-#{number}" - end - if git_tag - safe_system "git", "push", "--force", remote, "master:master", ":refs/tags/#{git_tag}" - end - - formula_packaged = {} - - bottles_hash.each do |formula_name, bottle_hash| - version = bottle_hash["formula"]["pkg_version"] - bintray_package = bottle_hash["bintray"]["package"] - bintray_repo = bottle_hash["bintray"]["repository"] - bintray_repo_url = "https://api.bintray.com/packages/homebrew/#{bintray_repo}" - - bottle_hash["bottle"]["tags"].each do |_tag, tag_hash| - filename = tag_hash["filename"] - if system "curl", "-I", "--silent", "--fail", "--output", "/dev/null", - "#{BottleSpecification::DEFAULT_DOMAIN}/#{bintray_repo}/#{filename}" - raise <<-EOS.undent - #{filename} is already published. Please remove it manually from - https://bintray.com/homebrew/#{bintray_repo}/#{bintray_package}/view#files - EOS - end - - unless formula_packaged[formula_name] - package_url = "#{bintray_repo_url}/#{bintray_package}" - unless system "curl", "--silent", "--fail", "--output", "/dev/null", package_url - package_blob = <<-EOS.undent - {"name": "#{bintray_package}", - "public_download_numbers": true, - "public_stats": true} - EOS - curl "--silent", "--fail", "-u#{bintray_user}:#{bintray_key}", - "-H", "Content-Type: application/json", - "-d", package_blob, bintray_repo_url - puts - end - formula_packaged[formula_name] = true - end - - content_url = "https://api.bintray.com/content/homebrew" - content_url += "/#{bintray_repo}/#{bintray_package}/#{version}/#{filename}" - content_url += "?override=1" - curl "--silent", "--fail", "-u#{bintray_user}:#{bintray_key}", - "-T", filename, content_url - puts - end - end - - if git_tag - safe_system "git", "tag", "--force", git_tag - safe_system "git", "push", "--force", remote, "master:master", "refs/tags/#{git_tag}" - end - end - - def sanitize_argv_and_env - if Pathname.pwd == HOMEBREW_PREFIX && ARGV.include?("--cleanup") - odie "cannot use --cleanup from HOMEBREW_PREFIX as it will delete all output." - end - - ENV["HOMEBREW_DEVELOPER"] = "1" - ENV["HOMEBREW_SANDBOX"] = "1" - ENV["HOMEBREW_NO_EMOJI"] = "1" - ENV["HOMEBREW_FAIL_LOG_LINES"] = "150" - ENV["HOMEBREW_EXPERIMENTAL_FILTER_FLAGS_ON_DEPS"] = "1" - ENV["PATH"] = "#{HOMEBREW_PREFIX}/bin:#{HOMEBREW_PREFIX}/sbin:#{ENV["PATH"]}" - - travis = !ENV["TRAVIS"].nil? - if travis - ARGV << "--verbose" - ENV["HOMEBREW_VERBOSE_USING_DOTS"] = "1" - end - - # Only report coverage if build runs on macOS and this is indeed Homebrew, - # as we don't want this to be averaged with inferior Linux test coverage. - if OS.mac? && (ENV["COVERALLS_REPO_TOKEN"] || ENV["CODECOV_TOKEN"]) - ARGV << "--coverage" - end - - travis_pr = ENV["TRAVIS_PULL_REQUEST"] && ENV["TRAVIS_PULL_REQUEST"] != "false" - jenkins_pr = !ENV["ghprbPullLink"].nil? - jenkins_branch = !ENV["GIT_COMMIT"].nil? - - if ARGV.include?("--ci-auto") - if travis_pr || jenkins_pr - ARGV << "--ci-pr" - elsif travis || jenkins_branch - ARGV << "--ci-master" - else - ARGV << "--ci-testing" - end - end - - if ARGV.include?("--ci-master") || ARGV.include?("--ci-pr") \ - || ARGV.include?("--ci-testing") - ARGV << "--cleanup" if ENV["JENKINS_HOME"] - ARGV << "--junit" << "--local" << "--test-default-formula" - end - - if ARGV.include? "--ci-master" - ARGV << "--fast" - end - - if ARGV.include? "--local" - ENV["HOMEBREW_CACHE"] = "#{ENV["HOME"]}/Library/Caches/Homebrew" - mkdir_p ENV["HOMEBREW_CACHE"] - ENV["HOMEBREW_HOME"] = ENV["HOME"] = "#{Dir.pwd}/home" - mkdir_p ENV["HOME"] - ENV["HOMEBREW_LOGS"] = "#{Dir.pwd}/logs" - end - end - - def test_bot - sanitize_argv_and_env - - tap = resolve_test_tap - # Tap repository if required, this is done before everything else - # because Formula parsing and/or git commit hash lookup depends on it. - # At the same time, make sure Tap is not a shallow clone. - # bottle rebuild and bottle upload rely on full clone. - safe_system "brew", "tap", tap.name, "--full" if tap - - if ARGV.include? "--ci-upload" - return test_ci_upload(tap) - end - - tests = [] - any_errors = false - skip_homebrew = ARGV.include?("--skip-homebrew") - if ARGV.named.empty? - # With no arguments just build the most recent commit. - current_test = Test.new("HEAD", tap: tap, skip_homebrew: skip_homebrew) - any_errors = !current_test.run - tests << current_test - else - ARGV.named.each do |argument| - test_error = false - begin - current_test = Test.new(argument, tap: tap, skip_homebrew: skip_homebrew) - skip_homebrew = true - rescue ArgumentError => e - test_error = true - ofail e.message - else - test_error = !current_test.run - tests << current_test - end - any_errors ||= test_error - end - end - - if ARGV.include? "--junit" - xml_document = REXML::Document.new - xml_document << REXML::XMLDecl.new - testsuites = xml_document.add_element "testsuites" - - tests.each do |test| - testsuite = testsuites.add_element "testsuite" - testsuite.add_attribute "name", "brew-test-bot.#{Utils::Bottles.tag}" - testsuite.add_attribute "tests", test.steps.count - - test.steps.each do |step| - testcase = testsuite.add_element "testcase" - testcase.add_attribute "name", step.command_short - testcase.add_attribute "status", step.status - testcase.add_attribute "time", step.time - - next unless step.output? - output = sanitize_output_for_xml(step.output) - cdata = REXML::CData.new output - - if step.passed? - elem = testcase.add_element "system-out" - else - elem = testcase.add_element "failure" - elem.add_attribute "message", "#{step.status}: #{step.command.join(" ")}" - end - - elem << cdata - end - end - - open("brew-test-bot.xml", "w") do |xml_file| - pretty_print_indent = 2 - xml_document.write(xml_file, pretty_print_indent) - end - end - ensure - if ARGV.include? "--clean-cache" - HOMEBREW_CACHE.children.each(&:rmtree) - else - Dir.glob("*.bottle*.tar.gz") do |bottle_file| - FileUtils.rm_f HOMEBREW_CACHE/bottle_file - end - end - - Homebrew.failed = any_errors - end - - def sanitize_output_for_xml(output) - unless output.empty? - # Remove invalid XML CData characters from step output. - invalid_xml_pat = /[^\x09\x0A\x0D\x20-\uD7FF\uE000-\uFFFD\u{10000}-\u{10FFFF}]/ - output = output.gsub(invalid_xml_pat, "\uFFFD") - - # Truncate to 1MB to avoid hitting CI limits - if output.bytesize > MAX_STEP_OUTPUT_SIZE - output = truncate_text_to_approximate_size(output, MAX_STEP_OUTPUT_SIZE, front_weight: 0.0) - output = "truncated output to 1MB:\n" + output - end - end - output - end -end diff --git a/Library/Homebrew/dev-cmd/test.rb b/Library/Homebrew/dev-cmd/test.rb index a80fa5e4f..c20edf804 100644 --- a/Library/Homebrew/dev-cmd/test.rb +++ b/Library/Homebrew/dev-cmd/test.rb @@ -1,5 +1,5 @@ #: * `test` [`--devel`|`--HEAD`] [`--debug`] [`--keep-tmp`] <formula>: -#: A few formulae provide a test method. `brew test` <formula> runs this +#: Most formulae provide a test method. `brew test` <formula> runs this #: test method. There is no standard output or return code, but it should #: generally indicate to the user if something is wrong with the installed #: formula. diff --git a/Library/Homebrew/dev-cmd/tests.rb b/Library/Homebrew/dev-cmd/tests.rb index aa2a3bff9..9b15f9f3e 100644 --- a/Library/Homebrew/dev-cmd/tests.rb +++ b/Library/Homebrew/dev-cmd/tests.rb @@ -6,7 +6,7 @@ require "tap" module Homebrew def tests - (HOMEBREW_LIBRARY/"Homebrew/test").cd do + (HOMEBREW_LIBRARY/"Homebrew").cd do ENV["HOMEBREW_NO_ANALYTICS_THIS_RUN"] = "1" ENV["HOMEBREW_DEVELOPER"] = "1" ENV["TESTOPTS"] = "-v" if ARGV.verbose? @@ -19,9 +19,11 @@ module Homebrew if ARGV.include? "--coverage" ENV["HOMEBREW_TESTS_COVERAGE"] = "1" - FileUtils.rm_f "coverage/.resultset.json" + FileUtils.rm_f "test/coverage/.resultset.json" end + ENV["BUNDLE_GEMFILE"] = "#{Dir.pwd}/test/Gemfile" + # Override author/committer as global settings might be invalid and thus # will cause silent failure during the setup of dummy Git repositories. %w[AUTHOR COMMITTER].each do |role| @@ -37,16 +39,26 @@ module Homebrew # Make it easier to reproduce test runs. ENV["SEED"] = ARGV.next if ARGV.include? "--seed" + files = Dir["test/test_*.rb"] + files -= Dir["test/test_os_mac_*.rb"] unless OS.mac? + + opts = [] + opts << "--serialize-stdout" if ENV["CI"] + args = [] args << "--trace" if ARGV.include? "--trace" + if ARGV.value("only") ENV["HOMEBREW_TESTS_ONLY"] = "1" test_name, test_method = ARGV.value("only").split("/", 2) - args << "TEST=test_#{test_name}.rb" - args << "TESTOPTS=--name=test_#{test_method}" if test_method + files = ["test/test_#{test_name}.rb"] + args << "--name=test_#{test_method}" if test_method end + args += ARGV.named.select { |v| v[/^TEST(OPTS)?=/] } - system "bundle", "exec", "rake", "test", *args + + system "bundle", "exec", "parallel_test", *opts, + "--", *args, "--", *files Homebrew.failed = !$?.success? diff --git a/Library/Homebrew/dev-cmd/update-test.rb b/Library/Homebrew/dev-cmd/update-test.rb index bcf8020e4..18980b691 100644 --- a/Library/Homebrew/dev-cmd/update-test.rb +++ b/Library/Homebrew/dev-cmd/update-test.rb @@ -1,9 +1,9 @@ -#: * `update-test` [`--commit=<sha1>`] [`--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=<sha1>` is passed, use `<sha1>` 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 #: start commit. @@ -14,18 +14,18 @@ module Homebrew def update_test cd HOMEBREW_REPOSITORY - start_sha1 = if commit = ARGV.value("commit") + start_commit = if commit = ARGV.value("commit") commit elsif date = ARGV.value("before") Utils.popen_read("git", "rev-list", "-n1", "--before=#{date}", "origin/master").chomp else Utils.popen_read("git", "rev-parse", "origin/master").chomp end - start_sha1 = Utils.popen_read("git", "rev-parse", start_sha1).chomp - end_sha1 = Utils.popen_read("git", "rev-parse", "HEAD").chomp + start_commit = Utils.popen_read("git", "rev-parse", start_commit).chomp + end_commit = Utils.popen_read("git", "rev-parse", "HEAD").chomp - puts "Start commit: #{start_sha1}" - puts "End commit: #{end_sha1}" + puts "Start commit: #{start_commit}" + puts "End commit: #{end_commit}" mktemp("update-test") do |staging| staging.retain! if ARGV.keep_tmp? @@ -39,12 +39,12 @@ module Homebrew safe_system "git", "clone", "--local", "--bare", "#{HOMEBREW_REPOSITORY}/.git", "remote.git" safe_system "git", "config", "remote.origin.url", "#{curdir}/remote.git" - # force push origin to end_sha1 - safe_system "git", "checkout", "-B", "master", end_sha1 + # force push origin to end_commit + safe_system "git", "checkout", "-B", "master", end_commit safe_system "git", "push", "--force", "origin", "master" - # set test copy to start_sha1 - safe_system "git", "reset", "--hard", start_sha1 + # set test copy to start_commit + safe_system "git", "reset", "--hard", start_commit # update ENV["PATH"] ENV["PATH"] = "#{curdir}/bin:/usr/local/bin:/usr/bin:/bin" @@ -52,13 +52,13 @@ module Homebrew # run brew update oh1 "Running brew update..." safe_system "brew", "update", "--verbose" - actual_end_sha1 = Utils.popen_read("git", "rev-parse", "master").chomp - if start_sha1 != end_sha1 && start_sha1 == actual_end_sha1 + actual_end_commit = Utils.popen_read("git", "rev-parse", "master").chomp + if start_commit != end_commit && start_commit == actual_end_commit raise <<-EOS.undent brew update didn't update master! - Start commit: #{start_sha1} - Expected end commit: #{end_sha1} - Actual end commit: #{actual_end_sha1} + Start commit: #{start_commit} + Expected end commit: #{end_commit} + Actual end commit: #{actual_end_commit} EOS end end diff --git a/Library/Homebrew/development_tools.rb b/Library/Homebrew/development_tools.rb index 14e1a07f7..7221e5b52 100644 --- a/Library/Homebrew/development_tools.rb +++ b/Library/Homebrew/development_tools.rb @@ -22,8 +22,7 @@ class DevelopmentTools def installation_instructions "Install Clang or brew install gcc" end - alias_method :custom_installation_instructions, - :installation_instructions + alias custom_installation_instructions installation_instructions def default_cc cc = DevelopmentTools.locate "cc" @@ -48,7 +47,7 @@ class DevelopmentTools `#{path} --version 2>/dev/null`[/build (\d{4,})/, 1].to_i end end - alias_method :gcc_4_0_build_version, :gcc_40_build_version + alias gcc_4_0_build_version gcc_40_build_version def gcc_42_build_version @gcc_42_build_version ||= @@ -59,7 +58,7 @@ class DevelopmentTools end end end - alias_method :gcc_build_version, :gcc_42_build_version + alias gcc_build_version gcc_42_build_version def clang_version @clang_version ||= diff --git a/Library/Homebrew/diagnostic.rb b/Library/Homebrew/diagnostic.rb index 650ff3eab..743c653d2 100644 --- a/Library/Homebrew/diagnostic.rb +++ b/Library/Homebrew/diagnostic.rb @@ -39,15 +39,11 @@ module Homebrew vols = get_mounts path # no volume found - if vols.empty? - return -1 - end + return -1 if vols.empty? vol_index = @volumes.index(vols[0]) # volume not found in volume list - if vol_index.nil? - return -1 - end + return -1 if vol_index.nil? vol_index end @@ -82,8 +78,8 @@ module Homebrew end end - def inject_file_list(list, str) - list.inject(str) { |s, f| s << " #{f}\n" } + def inject_file_list(list, string) + list.inject(string) { |a, e| a << " #{e}\n" } end ############# END HELPERS @@ -599,7 +595,7 @@ module Homebrew EOS end - def check_DYLD_vars + def check_dyld_vars dyld_vars = ENV.keys.grep(/^DYLD_/) return if dyld_vars.empty? @@ -758,7 +754,7 @@ module Homebrew cd #{HOMEBREW_REPOSITORY} git remote add origin https://github.com/Homebrew/brew.git EOS - elsif origin !~ /Homebrew\/brew(\.git)?$/ + elsif origin !~ %r{Homebrew/brew(\.git)?$} <<-EOS.undent Suspicious git origin remote found. diff --git a/Library/Homebrew/download_strategy.rb b/Library/Homebrew/download_strategy.rb index cabb22c22..1775e4e38 100644 --- a/Library/Homebrew/download_strategy.rb +++ b/Library/Homebrew/download_strategy.rb @@ -158,14 +158,13 @@ class VCSDownloadStrategy < AbstractDownloadStrategy version.update_commit(last_commit) if head? - if @ref_type == :tag && @revision && current_revision - unless current_revision == @revision - raise <<-EOS.undent - #{@ref} tag should be #{@revision} - but is actually #{current_revision} - EOS - end - end + return unless @ref_type == :tag + return unless @revision && current_revision + return if current_revision == @revision + raise <<-EOS.undent + #{@ref} tag should be #{@revision} + but is actually #{current_revision} + EOS end def fetch_last_commit @@ -336,14 +335,14 @@ class CurlDownloadStrategy < AbstractFileDownloadStrategy rescue ErrorDuringExecution # 33 == range not supported # try wiping the incomplete download and retrying once - if $?.exitstatus == 33 && had_incomplete_download - ohai "Trying a full download" - temporary_path.unlink - had_incomplete_download = false - retry - else + unless $?.exitstatus == 33 && had_incomplete_download raise CurlDownloadStrategyError, @url end + + ohai "Trying a full download" + temporary_path.unlink + had_incomplete_download = false + retry end ignore_interrupts { temporary_path.rename(cached_location) } end @@ -561,7 +560,7 @@ class SubversionDownloadStrategy < VCSDownloadStrategy Utils.popen_read("svn", "info", cached_location.to_s).strip[/^URL: (.+)$/, 1] end - def get_externals + def externals Utils.popen_read("svn", "propget", "svn:externals", @url).chomp.each_line do |line| name, url = line.split(/\s+/) yield name, url @@ -601,14 +600,14 @@ class SubversionDownloadStrategy < VCSDownloadStrategy main_revision = @ref[:trunk] fetch_repo cached_location, @url, main_revision, true - get_externals do |external_name, external_url| + externals do |external_name, external_url| fetch_repo cached_location+external_name, external_url, @ref[external_name], true end else fetch_repo cached_location, @url end end - alias_method :update, :clone_repo + alias update clone_repo end class GitDownloadStrategy < VCSDownloadStrategy @@ -663,19 +662,19 @@ class GitDownloadStrategy < VCSDownloadStrategy @shallow && support_depth? end - def is_shallow_clone? + def shallow_dir? git_dir.join("shallow").exist? end def support_depth? - @ref_type != :revision && SHALLOW_CLONE_WHITELIST.any? { |rx| rx === @url } + @ref_type != :revision && SHALLOW_CLONE_WHITELIST.any? { |regex| @url =~ regex } end def git_dir cached_location.join(".git") end - def has_ref? + def ref? quiet_system "git", "--git-dir", git_dir, "rev-parse", "-q", "--verify", "#{@ref}^{commit}" end @@ -696,7 +695,8 @@ class GitDownloadStrategy < VCSDownloadStrategy args << "--depth" << "1" if shallow_clone? case @ref_type - when :branch, :tag then args << "--branch" << @ref + when :branch, :tag + args << "--branch" << @ref end args << @url << cached_location @@ -716,12 +716,12 @@ class GitDownloadStrategy < VCSDownloadStrategy end def update_repo - if @ref_type == :branch || !has_ref? - if !shallow_clone? && is_shallow_clone? - quiet_safe_system "git", "fetch", "origin", "--unshallow" - else - quiet_safe_system "git", "fetch", "origin" - end + return unless @ref_type == :branch || !ref? + + if !shallow_clone? && shallow_dir? + quiet_safe_system "git", "fetch", "origin", "--unshallow" + else + quiet_safe_system "git", "fetch", "origin" end end @@ -741,9 +741,11 @@ class GitDownloadStrategy < VCSDownloadStrategy def reset_args ref = case @ref_type - when :branch then "origin/#{@ref}" - when :revision, :tag then @ref - end + when :branch + "origin/#{@ref}" + when :revision, :tag + @ref + end %W[reset --hard #{ref}] end @@ -795,10 +797,10 @@ end class GitHubGitDownloadStrategy < GitDownloadStrategy def initialize(name, resource) super - if @url =~ %r{^https?://github\.com/([^/]+)/([^/]+)\.git$} - @user = $1 - @repo = $2 - end + + return unless %r{^https?://github\.com/(?<user>[^/]+)/(?<repo>[^/]+)\.git$} =~ @url + @user = user + @repo = repo end def github_last_commit @@ -1021,9 +1023,9 @@ class DownloadStrategyDetector def self.detect(url, strategy = nil) if strategy.nil? detect_from_url(url) - elsif Class === strategy && strategy < AbstractDownloadStrategy + elsif strategy.is_a?(Class) && strategy < AbstractDownloadStrategy strategy - elsif Symbol === strategy + elsif strategy.is_a?(Symbol) detect_from_symbol(strategy) else raise TypeError, diff --git a/Library/Homebrew/emoji.rb b/Library/Homebrew/emoji.rb index ade330947..8c58ca895 100644 --- a/Library/Homebrew/emoji.rb +++ b/Library/Homebrew/emoji.rb @@ -17,7 +17,7 @@ module Emoji def enabled? !ENV["HOMEBREW_NO_EMOJI"] end - alias_method :generic_enabled?, :enabled? + alias generic_enabled? enabled? end end diff --git a/Library/Homebrew/extend/ARGV.rb b/Library/Homebrew/extend/ARGV.rb index d9f599877..c217ed8a5 100644 --- a/Library/Homebrew/extend/ARGV.rb +++ b/Library/Homebrew/extend/ARGV.rb @@ -30,7 +30,7 @@ module HomebrewArgvExtension if f.any_version_installed? tab = Tab.for_formula(f) resolved_spec = spec(nil) || tab.spec - f.set_active_spec(resolved_spec) if f.send(resolved_spec) + f.active_spec = resolved_spec if f.send(resolved_spec) f.build = tab if f.head? && tab.tabfile k = Keg.new(tab.tabfile.parent) @@ -88,11 +88,11 @@ module HomebrewArgvExtension Formulary.from_rack(rack) end - if (prefix = f.installed_prefix).directory? - Keg.new(prefix) - else + unless (prefix = f.installed_prefix).directory? raise MultipleVersionsInstalledError, rack.basename end + + Keg.new(prefix) end rescue FormulaUnavailableError raise <<-EOS.undent @@ -216,7 +216,7 @@ module HomebrewArgvExtension end def build_all_from_source? - !!ENV["HOMEBREW_BUILD_FROM_SOURCE"] + !ENV["HOMEBREW_BUILD_FROM_SOURCE"].nil? end # Whether a given formula should be built from source during the current diff --git a/Library/Homebrew/extend/ENV/shared.rb b/Library/Homebrew/extend/ENV/shared.rb index 447e4dd29..909dc4f94 100644 --- a/Library/Homebrew/extend/ENV/shared.rb +++ b/Library/Homebrew/extend/ENV/shared.rb @@ -289,12 +289,11 @@ module SharedEnvExtension EOS end - unless gcc_formula.opt_prefix.exist? - raise <<-EOS.undent - The requested Homebrew GCC was not installed. You must: - brew install #{gcc_formula.full_name} - EOS - end + return if gcc_formula.opt_prefix.exist? + raise <<-EOS.undent + The requested Homebrew GCC was not installed. You must: + brew install #{gcc_formula.full_name} + EOS end def permit_arch_flags; end @@ -328,9 +327,8 @@ module SharedEnvExtension end def check_for_compiler_universal_support - if homebrew_cc =~ GNU_GCC_REGEXP - raise "Non-Apple GCC can't build universal binaries" - end + return unless homebrew_cc =~ GNU_GCC_REGEXP + raise "Non-Apple GCC can't build universal binaries" end def gcc_with_cxx11_support?(cc) diff --git a/Library/Homebrew/extend/ENV/std.rb b/Library/Homebrew/extend/ENV/std.rb index a9b2358b1..27dc95d29 100644 --- a/Library/Homebrew/extend/ENV/std.rb +++ b/Library/Homebrew/extend/ENV/std.rb @@ -42,18 +42,17 @@ module Stdenv end # Os is the default Apple uses for all its stuff so let's trust them - set_cflags "-Os #{SAFE_CFLAGS_FLAGS}" + define_cflags "-Os #{SAFE_CFLAGS_FLAGS}" append "LDFLAGS", "-Wl,-headerpad_max_install_names" send(compiler) - if cc =~ GNU_GCC_REGEXP - gcc_formula = gcc_version_formula($&) - append_path "PATH", gcc_formula.opt_bin.to_s - end + return unless cc =~ GNU_GCC_REGEXP + gcc_formula = gcc_version_formula($&) + append_path "PATH", gcc_formula.opt_bin.to_s end - alias_method :generic_setup_build_environment, :setup_build_environment + alias generic_setup_build_environment setup_build_environment def homebrew_extra_pkg_config_paths [] @@ -84,7 +83,7 @@ module Stdenv old end - alias_method :j1, :deparallelize + alias j1 deparallelize # These methods are no-ops for compatibility. %w[fast O4 Og].each { |opt| define_method(opt) {} } @@ -112,13 +111,13 @@ module Stdenv super set_cpu_cflags "-march=nocona -mssse3" end - alias_method :gcc_4_0_1, :gcc_4_0 + alias gcc_4_0_1 gcc_4_0 def gcc super set_cpu_cflags end - alias_method :gcc_4_2, :gcc + alias gcc_4_2 gcc GNU_GCC_VERSIONS.each do |n| define_method(:"gcc-#{n}") do @@ -137,21 +136,21 @@ module Stdenv end def minimal_optimization - set_cflags "-Os #{SAFE_CFLAGS_FLAGS}" + define_cflags "-Os #{SAFE_CFLAGS_FLAGS}" end - alias_method :generic_minimal_optimization, :minimal_optimization + alias generic_minimal_optimization minimal_optimization def no_optimization - set_cflags SAFE_CFLAGS_FLAGS + define_cflags SAFE_CFLAGS_FLAGS end - alias_method :generic_no_optimization, :no_optimization + alias generic_no_optimization no_optimization def libxml2 end def x11 end - alias_method :libpng, :x11 + alias libpng x11 # we've seen some packages fail to build when warnings are disabled! def enable_warnings @@ -174,10 +173,10 @@ module Stdenv append_to_cflags Hardware::CPU.universal_archs.as_arch_flags append "LDFLAGS", Hardware::CPU.universal_archs.as_arch_flags - if compiler != :clang && Hardware.is_32_bit? - # Can't mix "-march" for a 32-bit CPU with "-arch x86_64" - replace_in_cflags(/-march=\S*/, "-Xarch_#{Hardware::CPU.arch_32_bit} \\0") - end + return if compiler == :clang + return unless Hardware.is_32_bit? + # Can't mix "-march" for a 32-bit CPU with "-arch x86_64" + replace_in_cflags(/-march=\S*/, "-Xarch_#{Hardware::CPU.arch_32_bit} \\0") end def cxx11 @@ -192,15 +191,11 @@ module Stdenv end def libcxx - if compiler == :clang - append "CXX", "-stdlib=libc++" - end + append "CXX", "-stdlib=libc++" if compiler == :clang end def libstdcxx - if compiler == :clang - append "CXX", "-stdlib=libstdc++" - end + append "CXX", "-stdlib=libstdc++" if compiler == :clang end # @private @@ -211,7 +206,7 @@ module Stdenv end # Convenience method to set all C compiler flags in one shot. - def set_cflags(val) + def define_cflags(val) CC_FLAG_VARS.each { |key| self[key] = val } end @@ -228,7 +223,7 @@ module Stdenv append flags, xarch unless xarch.empty? append flags, map.fetch(effective_arch, default) end - alias_method :generic_set_cpu_flags, :set_cpu_flags + alias generic_set_cpu_flags set_cpu_flags # @private def effective_arch diff --git a/Library/Homebrew/extend/ENV/super.rb b/Library/Homebrew/extend/ENV/super.rb index 4169905df..a3837c695 100644 --- a/Library/Homebrew/extend/ENV/super.rb +++ b/Library/Homebrew/extend/ENV/super.rb @@ -18,7 +18,7 @@ module Superenv attr_accessor :keg_only_deps, :deps attr_accessor :x11 - alias_method :x11?, :x11 + alias x11? x11 def self.extended(base) base.keg_only_deps = [] @@ -64,9 +64,7 @@ module Superenv self["HOMEBREW_INCLUDE_PATHS"] = determine_include_paths self["HOMEBREW_LIBRARY_PATHS"] = determine_library_paths self["HOMEBREW_DEPENDENCIES"] = determine_dependencies - unless formula.nil? - self["HOMEBREW_FORMULA_PREFIX"] = formula.prefix - end + self["HOMEBREW_FORMULA_PREFIX"] = formula.prefix unless formula.nil? # The HOMEBREW_CCCFG ENV variable is used by the ENV/cc tool to control # compiler flag stripping. It consists of a string of characters which act @@ -84,7 +82,7 @@ module Superenv # s - apply fix for sed's Unicode support # a - apply fix for apr-1-config path end - alias_method :generic_setup_build_environment, :setup_build_environment + alias generic_setup_build_environment setup_build_environment private @@ -265,7 +263,7 @@ module Superenv old end - alias_method :j1, :deparallelize + alias j1 deparallelize def make_jobs self["MAKEFLAGS"] =~ /-\w*j(\d+)/ @@ -278,12 +276,12 @@ module Superenv self["HOMEBREW_ARCHFLAGS"] = Hardware::CPU.universal_archs.as_arch_flags # GCC doesn't accept "-march" for a 32-bit CPU with "-arch x86_64" - if compiler != :clang && Hardware::CPU.is_32_bit? - self["HOMEBREW_OPTFLAGS"] = self["HOMEBREW_OPTFLAGS"].sub( - /-march=\S*/, - "-Xarch_#{Hardware::CPU.arch_32_bit} \\0" - ) - end + return if compiler == :clang + return unless Hardware::CPU.is_32_bit? + self["HOMEBREW_OPTFLAGS"] = self["HOMEBREW_OPTFLAGS"].sub( + /-march=\S*/, + "-Xarch_#{Hardware::CPU.arch_32_bit} \\0" + ) end def permit_arch_flags @@ -336,18 +334,18 @@ module Superenv # These methods are no longer necessary under superenv, but are needed to # maintain an interface compatible with stdenv. - alias_method :fast, :noop - alias_method :O4, :noop - alias_method :Og, :noop - alias_method :libxml2, :noop - alias_method :set_cpu_flags, :noop + alias fast noop + alias O4 noop + alias Og noop + alias libxml2 noop + alias set_cpu_flags noop # These methods provide functionality that has not yet been ported to # superenv. - alias_method :gcc_4_0_1, :noop - alias_method :minimal_optimization, :noop - alias_method :no_optimization, :noop - alias_method :enable_warnings, :noop + alias gcc_4_0_1 noop + alias minimal_optimization noop + alias no_optimization noop + alias enable_warnings noop end class Array diff --git a/Library/Homebrew/extend/fileutils.rb b/Library/Homebrew/extend/fileutils.rb index 3a2b32481..4f20d36a3 100644 --- a/Library/Homebrew/extend/fileutils.rb +++ b/Library/Homebrew/extend/fileutils.rb @@ -84,15 +84,14 @@ module FileUtils end # @private - alias_method :old_mkdir, :mkdir + alias old_mkdir mkdir # A version of mkdir that also changes to that folder in a block. def mkdir(name, &_block) mkdir_p(name) - if block_given? - chdir name do - yield - end + return unless block_given? + chdir name do + yield end end module_function :mkdir @@ -122,7 +121,7 @@ module FileUtils if method_defined?(:ruby) # @private - alias_method :old_ruby, :ruby + alias old_ruby ruby end # Run the `ruby` Homebrew is using rather than whatever is in the `PATH`. diff --git a/Library/Homebrew/extend/os/blacklist.rb b/Library/Homebrew/extend/os/blacklist.rb index f72c7c643..932040f82 100644 --- a/Library/Homebrew/extend/os/blacklist.rb +++ b/Library/Homebrew/extend/os/blacklist.rb @@ -1,5 +1,2 @@ require "blacklist" - -if OS.mac? - require "extend/os/mac/blacklist" -end +require "extend/os/mac/blacklist" if OS.mac? diff --git a/Library/Homebrew/extend/os/bottles.rb b/Library/Homebrew/extend/os/bottles.rb index aff9300de..146b807a4 100644 --- a/Library/Homebrew/extend/os/bottles.rb +++ b/Library/Homebrew/extend/os/bottles.rb @@ -1,5 +1,2 @@ require "utils/bottles" - -if OS.mac? - require "extend/os/mac/utils/bottles" -end +require "extend/os/mac/utils/bottles" if OS.mac? diff --git a/Library/Homebrew/extend/os/cleaner.rb b/Library/Homebrew/extend/os/cleaner.rb index 868ff2d33..6b94cdf5a 100644 --- a/Library/Homebrew/extend/os/cleaner.rb +++ b/Library/Homebrew/extend/os/cleaner.rb @@ -1,5 +1,2 @@ require "cleaner" - -if OS.mac? - require "extend/os/mac/cleaner" -end +require "extend/os/mac/cleaner" if OS.mac? diff --git a/Library/Homebrew/extend/os/dependency_collector.rb b/Library/Homebrew/extend/os/dependency_collector.rb new file mode 100644 index 000000000..56fcad31d --- /dev/null +++ b/Library/Homebrew/extend/os/dependency_collector.rb @@ -0,0 +1,2 @@ +require "dependency_collector" +require "extend/os/mac/dependency_collector" if OS.mac? diff --git a/Library/Homebrew/extend/os/development_tools.rb b/Library/Homebrew/extend/os/development_tools.rb index 7b590dc8b..5bd5cb81a 100644 --- a/Library/Homebrew/extend/os/development_tools.rb +++ b/Library/Homebrew/extend/os/development_tools.rb @@ -1,5 +1,2 @@ require "development_tools" - -if OS.mac? - require "extend/os/mac/development_tools" -end +require "extend/os/mac/development_tools" if OS.mac? diff --git a/Library/Homebrew/extend/os/diagnostic.rb b/Library/Homebrew/extend/os/diagnostic.rb index 0c844743b..f8f53b1f4 100644 --- a/Library/Homebrew/extend/os/diagnostic.rb +++ b/Library/Homebrew/extend/os/diagnostic.rb @@ -1,5 +1,2 @@ require "diagnostic" - -if OS.mac? - require "extend/os/mac/diagnostic" -end +require "extend/os/mac/diagnostic" if OS.mac? diff --git a/Library/Homebrew/extend/os/emoji.rb b/Library/Homebrew/extend/os/emoji.rb index fe3e7f44e..8fd99e1d3 100644 --- a/Library/Homebrew/extend/os/emoji.rb +++ b/Library/Homebrew/extend/os/emoji.rb @@ -1,6 +1,3 @@ require "os" require "emoji" - -if OS.mac? - require "extend/os/mac/emoji" -end +require "extend/os/mac/emoji" if OS.mac? diff --git a/Library/Homebrew/extend/os/extend/ENV/shared.rb b/Library/Homebrew/extend/os/extend/ENV/shared.rb index 676159b37..e9574eb58 100644 --- a/Library/Homebrew/extend/os/extend/ENV/shared.rb +++ b/Library/Homebrew/extend/os/extend/ENV/shared.rb @@ -1,5 +1,2 @@ require "extend/ENV/shared" - -if OS.mac? - require "extend/os/mac/extend/ENV/shared" -end +require "extend/os/mac/extend/ENV/shared" if OS.mac? diff --git a/Library/Homebrew/extend/os/extend/ENV/std.rb b/Library/Homebrew/extend/os/extend/ENV/std.rb index 320f9981f..8e6b13a61 100644 --- a/Library/Homebrew/extend/os/extend/ENV/std.rb +++ b/Library/Homebrew/extend/os/extend/ENV/std.rb @@ -1,5 +1,2 @@ require "extend/ENV/std" - -if OS.mac? - require "extend/os/mac/extend/ENV/std" -end +require "extend/os/mac/extend/ENV/std" if OS.mac? diff --git a/Library/Homebrew/extend/os/extend/ENV/super.rb b/Library/Homebrew/extend/os/extend/ENV/super.rb index fd4e93c22..27c49eb84 100644 --- a/Library/Homebrew/extend/os/extend/ENV/super.rb +++ b/Library/Homebrew/extend/os/extend/ENV/super.rb @@ -1,5 +1,2 @@ require "extend/ENV/super" - -if OS.mac? - require "extend/os/mac/extend/ENV/super" -end +require "extend/os/mac/extend/ENV/super" if OS.mac? diff --git a/Library/Homebrew/extend/os/formula_cellar_checks.rb b/Library/Homebrew/extend/os/formula_cellar_checks.rb index 4e30cd791..66b5b80d3 100644 --- a/Library/Homebrew/extend/os/formula_cellar_checks.rb +++ b/Library/Homebrew/extend/os/formula_cellar_checks.rb @@ -1,5 +1,2 @@ require "formula_cellar_checks" - -if OS.mac? - require "extend/os/mac/formula_cellar_checks" -end +require "extend/os/mac/formula_cellar_checks" if OS.mac? diff --git a/Library/Homebrew/extend/os/keg_relocate.rb b/Library/Homebrew/extend/os/keg_relocate.rb index 2fde45d93..25a74286a 100644 --- a/Library/Homebrew/extend/os/keg_relocate.rb +++ b/Library/Homebrew/extend/os/keg_relocate.rb @@ -1,5 +1,2 @@ require "keg_relocate" - -if OS.mac? - require "extend/os/mac/keg_relocate" -end +require "extend/os/mac/keg_relocate" if OS.mac? diff --git a/Library/Homebrew/extend/os/linux/hardware/cpu.rb b/Library/Homebrew/extend/os/linux/hardware/cpu.rb index 2e5b3d07d..2472c60ed 100644 --- a/Library/Homebrew/extend/os/linux/hardware/cpu.rb +++ b/Library/Homebrew/extend/os/linux/hardware/cpu.rb @@ -81,7 +81,7 @@ module Hardware %w[aes altivec avx avx2 lm sse3 ssse3 sse4 sse4_2].each do |flag| define_method(flag + "?") { flags.include? flag } end - alias_method :is_64_bit?, :lm? + alias is_64_bit? lm? def bits is_64_bit? ? 64 : 32 diff --git a/Library/Homebrew/extend/os/mac/dependency_collector.rb b/Library/Homebrew/extend/os/mac/dependency_collector.rb new file mode 100644 index 000000000..ee98045b6 --- /dev/null +++ b/Library/Homebrew/extend/os/mac/dependency_collector.rb @@ -0,0 +1,6 @@ +class DependencyCollector + def ant_dep(spec, tags) + return if MacOS.version < :mavericks + Dependency.new(spec.to_s, tags) + end +end diff --git a/Library/Homebrew/extend/os/mac/development_tools.rb b/Library/Homebrew/extend/os/mac/development_tools.rb index b9c9d8e43..381b26e66 100644 --- a/Library/Homebrew/extend/os/mac/development_tools.rb +++ b/Library/Homebrew/extend/os/mac/development_tools.rb @@ -3,7 +3,7 @@ require "os/mac/xcode" # @private class DevelopmentTools class << self - alias_method :original_locate, :locate + alias original_locate locate def locate(tool) (@locate ||= {}).fetch(tool) do |key| @locate[key] = if (located_tool = original_locate(tool)) diff --git a/Library/Homebrew/extend/os/mac/diagnostic.rb b/Library/Homebrew/extend/os/mac/diagnostic.rb index 15dd3328f..063558f19 100644 --- a/Library/Homebrew/extend/os/mac/diagnostic.rb +++ b/Library/Homebrew/extend/os/mac/diagnostic.rb @@ -14,7 +14,7 @@ module Homebrew end def fatal_development_tools_checks - if MacOS.prerelease? + if MacOS.version >= :sierra && ENV["CI"].nil? %w[ check_xcode_up_to_date check_clt_up_to_date diff --git a/Library/Homebrew/extend/os/mac/extend/ENV/shared.rb b/Library/Homebrew/extend/os/mac/extend/ENV/shared.rb index 866204024..67a3944c3 100644 --- a/Library/Homebrew/extend/os/mac/extend/ENV/shared.rb +++ b/Library/Homebrew/extend/os/mac/extend/ENV/shared.rb @@ -2,13 +2,8 @@ module SharedEnvExtension def no_weak_imports_support? return false unless compiler == :clang - if MacOS::Xcode.version && MacOS::Xcode.version < "8.0" - return false - end - - if MacOS::CLT.version && MacOS::CLT.version < "8.0" - return false - end + return false if MacOS::Xcode.version && MacOS::Xcode.version < "8.0" + return false if MacOS::CLT.version && MacOS::CLT.version < "8.0" true end diff --git a/Library/Homebrew/extend/os/mac/extend/ENV/std.rb b/Library/Homebrew/extend/os/mac/extend/ENV/std.rb index 8efbd3bc9..4853ecf0c 100644 --- a/Library/Homebrew/extend/os/mac/extend/ENV/std.rb +++ b/Library/Homebrew/extend/os/mac/extend/ENV/std.rb @@ -20,14 +20,13 @@ module Stdenv # Leopard's ld needs some convincing that it's building 64-bit # See: https://github.com/mistydemeo/tigerbrew/issues/59 - if MacOS.version == :leopard && MacOS.prefer_64_bit? - append "LDFLAGS", "-arch #{Hardware::CPU.arch_64_bit}" + return unless MacOS.version == :leopard && MacOS.prefer_64_bit? + append "LDFLAGS", "-arch #{Hardware::CPU.arch_64_bit}" - # Many, many builds are broken thanks to Leopard's buggy ld. - # Our ld64 fixes many of those builds, though of course we can't - # depend on it already being installed to build itself. - ld64 if Formula["ld64"].installed? - end + # Many, many builds are broken thanks to Leopard's buggy ld. + # Our ld64 fixes many of those builds, though of course we can't + # depend on it already being installed to build itself. + ld64 if Formula["ld64"].installed? end def homebrew_extra_pkg_config_paths @@ -65,19 +64,18 @@ module Stdenv delete("CPATH") remove "LDFLAGS", "-L#{HOMEBREW_PREFIX}/lib" - if (sdk = MacOS.sdk_path(version)) && !MacOS::CLT.installed? - delete("SDKROOT") - remove_from_cflags "-isysroot #{sdk}" - remove "CPPFLAGS", "-isysroot #{sdk}" - remove "LDFLAGS", "-isysroot #{sdk}" - if HOMEBREW_PREFIX.to_s == "/usr/local" - delete("CMAKE_PREFIX_PATH") - else - # It was set in setup_build_environment, so we have to restore it here. - self["CMAKE_PREFIX_PATH"] = HOMEBREW_PREFIX.to_s - end - remove "CMAKE_FRAMEWORK_PATH", "#{sdk}/System/Library/Frameworks" + return unless (sdk = MacOS.sdk_path(version)) && !MacOS::CLT.installed? + delete("SDKROOT") + remove_from_cflags "-isysroot #{sdk}" + remove "CPPFLAGS", "-isysroot #{sdk}" + remove "LDFLAGS", "-isysroot #{sdk}" + if HOMEBREW_PREFIX.to_s == "/usr/local" + delete("CMAKE_PREFIX_PATH") + else + # It was set in setup_build_environment, so we have to restore it here. + self["CMAKE_PREFIX_PATH"] = HOMEBREW_PREFIX.to_s end + remove "CMAKE_FRAMEWORK_PATH", "#{sdk}/System/Library/Frameworks" end def macosxsdk(version = MacOS.version) @@ -89,20 +87,19 @@ module Stdenv self["CPATH"] = "#{HOMEBREW_PREFIX}/include" prepend "LDFLAGS", "-L#{HOMEBREW_PREFIX}/lib" - if (sdk = MacOS.sdk_path(version)) && !MacOS::CLT.installed? - # Extra setup to support Xcode 4.3+ without CLT. - self["SDKROOT"] = sdk - # Tell clang/gcc where system include's are: - append_path "CPATH", "#{sdk}/usr/include" - # The -isysroot is needed, too, because of the Frameworks - append_to_cflags "-isysroot #{sdk}" - append "CPPFLAGS", "-isysroot #{sdk}" - # And the linker needs to find sdk/usr/lib - append "LDFLAGS", "-isysroot #{sdk}" - # Needed to build cmake itself and perhaps some cmake projects: - append_path "CMAKE_PREFIX_PATH", "#{sdk}/usr" - append_path "CMAKE_FRAMEWORK_PATH", "#{sdk}/System/Library/Frameworks" - end + return unless (sdk = MacOS.sdk_path(version)) && !MacOS::CLT.installed? + # Extra setup to support Xcode 4.3+ without CLT. + self["SDKROOT"] = sdk + # Tell clang/gcc where system include's are: + append_path "CPATH", "#{sdk}/usr/include" + # The -isysroot is needed, too, because of the Frameworks + append_to_cflags "-isysroot #{sdk}" + append "CPPFLAGS", "-isysroot #{sdk}" + # And the linker needs to find sdk/usr/lib + append "LDFLAGS", "-isysroot #{sdk}" + # Needed to build cmake itself and perhaps some cmake projects: + append_path "CMAKE_PREFIX_PATH", "#{sdk}/usr" + append_path "CMAKE_FRAMEWORK_PATH", "#{sdk}/System/Library/Frameworks" end # Some configure scripts won't find libxml2 without help diff --git a/Library/Homebrew/extend/os/mac/extend/ENV/super.rb b/Library/Homebrew/extend/os/mac/extend/ENV/super.rb index 78e36251c..38a81488f 100644 --- a/Library/Homebrew/extend/os/mac/extend/ENV/super.rb +++ b/Library/Homebrew/extend/os/mac/extend/ENV/super.rb @@ -118,6 +118,6 @@ module Superenv # These methods are no longer necessary under superenv, but are needed to # maintain an interface compatible with stdenv. - alias_method :macosxsdk, :noop - alias_method :remove_macosxsdk, :noop + alias macosxsdk noop + alias remove_macosxsdk noop end diff --git a/Library/Homebrew/extend/os/mac/formula_cellar_checks.rb b/Library/Homebrew/extend/os/mac/formula_cellar_checks.rb index b3f8250ee..8bc42ad35 100644 --- a/Library/Homebrew/extend/os/mac/formula_cellar_checks.rb +++ b/Library/Homebrew/extend/os/mac/formula_cellar_checks.rb @@ -64,13 +64,12 @@ module FormulaCellarChecks keg = Keg.new(formula.prefix) checker = LinkageChecker.new(keg, formula) - if checker.broken_dylibs? - audit_check_output <<-EOS.undent - The installation was broken. - Broken dylib links found: - #{checker.broken_dylibs.to_a * "\n "} - EOS - end + return unless checker.broken_dylibs? + audit_check_output <<-EOS.undent + The installation was broken. + Broken dylib links found: + #{checker.broken_dylibs.to_a * "\n "} + EOS end def audit_installed diff --git a/Library/Homebrew/extend/os/mac/keg_relocate.rb b/Library/Homebrew/extend/os/mac/keg_relocate.rb index 61d54ba97..33ee149ce 100644 --- a/Library/Homebrew/extend/os/mac/keg_relocate.rb +++ b/Library/Homebrew/extend/os/mac/keg_relocate.rb @@ -124,7 +124,7 @@ class Keg end def self.file_linked_libraries(file, string) - # Check dynamic library linkage. Importantly, do not run otool on static + # Check dynamic library linkage. Importantly, do not perform for static # libraries, which will falsely report "linkage" to themselves. if file.mach_o_executable? || file.dylib? || file.mach_o_bundle? file.dynamically_linked_libraries.select { |lib| lib.include? string } diff --git a/Library/Homebrew/extend/os/mac/utils/bottles.rb b/Library/Homebrew/extend/os/mac/utils/bottles.rb index 6b83ad6c4..0dd7341ea 100644 --- a/Library/Homebrew/extend/os/mac/utils/bottles.rb +++ b/Library/Homebrew/extend/os/mac/utils/bottles.rb @@ -21,7 +21,7 @@ module Utils class Collector private - alias_method :original_find_matching_tag, :find_matching_tag + alias original_find_matching_tag find_matching_tag def find_matching_tag(tag) original_find_matching_tag(tag) || find_altivec_tag(tag) || find_or_later_tag(tag) end @@ -31,10 +31,9 @@ module Utils # sometimes a formula has just :tiger_altivec, other times it has # :tiger_g4, :tiger_g5, etc. def find_altivec_tag(tag) - if tag.to_s =~ /(\w+)_(g4|g4e|g5)$/ - altivec_tag = "#{$1}_altivec".to_sym - altivec_tag if key?(altivec_tag) - end + return unless tag.to_s =~ /(\w+)_(g4|g4e|g5)$/ + altivec_tag = "#{$1}_altivec".to_sym + altivec_tag if key?(altivec_tag) end # Allows a bottle tag to specify a specific OS or later, diff --git a/Library/Homebrew/extend/os/system_config.rb b/Library/Homebrew/extend/os/system_config.rb index cf7b69cb6..edc007166 100644 --- a/Library/Homebrew/extend/os/system_config.rb +++ b/Library/Homebrew/extend/os/system_config.rb @@ -1,5 +1,2 @@ require "system_config" - -if OS.mac? - require "extend/os/mac/system_config" -end +require "extend/os/mac/system_config" if OS.mac? diff --git a/Library/Homebrew/extend/pathname.rb b/Library/Homebrew/extend/pathname.rb index 5dce906b9..3f73b6a1c 100644 --- a/Library/Homebrew/extend/pathname.rb +++ b/Library/Homebrew/extend/pathname.rb @@ -71,13 +71,13 @@ class Pathname when Array if src.empty? opoo "tried to install empty array to #{self}" - return + break end src.each { |s| install_p(s, File.basename(s)) } when Hash if src.empty? opoo "tried to install empty hash to #{self}" - return + break end src.each { |s, new_basename| install_p(s, new_basename) } else @@ -132,7 +132,7 @@ class Pathname if method_defined?(:write) # @private - alias_method :old_write, :write + alias old_write write end # we assume this pathname object is a file obviously @@ -212,7 +212,7 @@ class Pathname end # @private - alias_method :extname_old, :extname + alias extname_old extname # extended to support common double extensions def extname(path = to_s) @@ -322,7 +322,7 @@ class Pathname end # FIXME: eliminate the places where we rely on this method - alias_method :to_str, :to_s unless method_defined?(:to_str) + alias to_str to_s unless method_defined?(:to_str) def cd Dir.chdir(self) { yield } diff --git a/Library/Homebrew/extend/string.rb b/Library/Homebrew/extend/string.rb index 1d9c2e036..162666d2d 100644 --- a/Library/Homebrew/extend/string.rb +++ b/Library/Homebrew/extend/string.rb @@ -13,7 +13,7 @@ class String # sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt # mollit anim id est laborum. # EOS - alias_method :undent_________________________________________________________72, :undent + alias undent_________________________________________________________72 undent # String.chomp, but if result is empty: returns nil instead. # Allows `chuzzle || foo` short-circuits. @@ -59,9 +59,8 @@ module StringInreplaceExtension # Looks for Makefile style variable defintions and replaces the # value with "new_value", or removes the definition entirely. def change_make_var!(flag, new_value) - unless gsub!(/^#{Regexp.escape(flag)}[ \t]*=[ \t]*(.*)$/, "#{flag}=#{new_value}", false) - errors << "expected to change #{flag.inspect} to #{new_value.inspect}" - end + return if gsub!(/^#{Regexp.escape(flag)}[ \t]*=[ \t]*(.*)$/, "#{flag}=#{new_value}", false) + errors << "expected to change #{flag.inspect} to #{new_value.inspect}" end # Removes variable assignments completely. diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index 4cff28d8e..4d3c143dc 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -162,7 +162,7 @@ class Formula # Defaults to true. # @return [Boolean] attr_accessor :follow_installed_alias - alias_method :follow_installed_alias?, :follow_installed_alias + alias follow_installed_alias? follow_installed_alias # @private def initialize(name, path, spec, alias_path: nil) @@ -179,12 +179,12 @@ class Formula Tap.fetch($1, $2) end - @full_name = get_full_name(name) - @full_alias_name = get_full_name(@alias_name) + @full_name = full_name_with_optional_tap(name) + @full_alias_name = full_name_with_optional_tap(@alias_name) - set_spec :stable - set_spec :devel - set_spec :head + spec_eval :stable + spec_eval :devel + spec_eval :head @active_spec = determine_active_spec(spec) @active_spec_sym = if head? @@ -201,7 +201,7 @@ class Formula end # @private - def set_active_spec(spec_sym) + def active_spec=(spec_sym) spec = send(spec_sym) raise FormulaSpecificationError, "#{spec_sym} spec is not available for #{full_name}" unless spec @active_spec = spec @@ -214,7 +214,7 @@ class Formula # Allow full name logic to be re-used between names, aliases, # and installed aliases. - def get_full_name(name) + def full_name_with_optional_tap(name) if name.nil? || @tap.nil? || @tap.core_tap? name else @@ -222,12 +222,11 @@ class Formula end end - def set_spec(name) + def spec_eval(name) spec = self.class.send(name) - if spec.url - spec.owner = self - instance_variable_set("@#{name}", spec) - end + return unless spec.url + spec.owner = self + instance_variable_set("@#{name}", spec) end def determine_active_spec(requested) @@ -246,9 +245,8 @@ class Formula end val = version.respond_to?(:to_str) ? version.to_str : version - if val.nil? || val.empty? || val =~ /\s/ - raise FormulaValidationError.new(full_name, :version, val) - end + return unless val.nil? || val.empty? || val =~ /\s/ + raise FormulaValidationError.new(full_name, :version, val) end public @@ -266,7 +264,7 @@ class Formula end def full_installed_alias_name - get_full_name(installed_alias_name) + full_name_with_optional_tap(installed_alias_name) end # The path that was specified to find this formula. @@ -395,9 +393,7 @@ class Formula def oldname @oldname ||= if tap formula_renames = tap.formula_renames - if formula_renames.value?(name) - formula_renames.to_a.rassoc(name).first - end + formula_renames.to_a.rassoc(name).first if formula_renames.value?(name) end end @@ -1052,7 +1048,7 @@ class Formula self.class.link_overwrite_paths.any? do |p| p == to_check || to_check.start_with?(p.chomp("/") + "/") || - /^#{Regexp.escape(p).gsub('\*', ".*?")}$/ === to_check + to_check =~ /^#{Regexp.escape(p).gsub('\*', ".*?")}$/ end end @@ -1067,10 +1063,9 @@ class Formula # @private def patch - unless patchlist.empty? - ohai "Patching" - patchlist.each(&:apply) - end + return if patchlist.empty? + ohai "Patching" + patchlist.each(&:apply) end # yields |self,staging| with current working directory set to the uncompressed tarball @@ -1096,10 +1091,11 @@ class Formula def lock @lock = FormulaLock.new(name) @lock.lock - if oldname && (oldname_rack = HOMEBREW_CELLAR/oldname).exist? && oldname_rack.resolved_path == rack - @oldname_lock = FormulaLock.new(oldname) - @oldname_lock.lock - end + return unless oldname + return unless (oldname_rack = HOMEBREW_CELLAR/oldname).exist? + return unless oldname_rack.resolved_path == rack + @oldname_lock = FormulaLock.new(oldname) + @oldname_lock.lock end # @private @@ -1237,7 +1233,7 @@ class Formula name == other.name && active_spec == other.active_spec end - alias_method :eql?, :== + alias eql? == # @private def hash @@ -1246,7 +1242,7 @@ class Formula # @private def <=>(other) - return unless Formula === other + return unless other.is_a?(Formula) name <=> other.name end @@ -1266,7 +1262,7 @@ class Formula # Note: there isn't a std_autotools variant because autotools is a lot # less consistent and the standard parameters are more memorable. def std_cmake_args - %W[ + args = %W[ -DCMAKE_C_FLAGS_RELEASE=-DNDEBUG -DCMAKE_CXX_FLAGS_RELEASE=-DNDEBUG -DCMAKE_INSTALL_PREFIX=#{prefix} @@ -1275,6 +1271,14 @@ class Formula -DCMAKE_VERBOSE_MAKEFILE=ON -Wno-dev ] + + # Avoid false positives for clock_gettime support on 10.11. + # CMake cache entries for other weak symbols may be added here as needed. + if MacOS.version == "10.11" && MacOS::Xcode.installed? && MacOS::Xcode.version >= "8.0" + args << "-DHAVE_CLOCK_GETTIME:INTERNAL=0" + end + + args end # an array of all core {Formula} names @@ -1421,10 +1425,9 @@ class Formula # @private def print_tap_action(options = {}) - if tap? - verb = options[:verb] || "Installing" - ohai "#{verb} #{name} from #{tap}" - end + return unless tap? + verb = options[:verb] || "Installing" + ohai "#{verb} #{name} from #{tap}" end # @private @@ -1662,7 +1665,7 @@ class Formula @exec_count ||= 0 @exec_count += 1 - logfn = "#{logs}/#{active_log_prefix}%02d.%s" % [@exec_count, File.basename(cmd).split(" ").first] + logfn = format("#{logs}/#{active_log_prefix}%02d.%s", @exec_count, File.basename(cmd).split(" ").first) logs.mkpath File.open(logfn, "w") do |log| @@ -1768,9 +1771,7 @@ class Formula ENV["HOMEBREW_CC_LOG_PATH"] = logfn # TODO: system "xcodebuild" is deprecated, this should be removed soon. - if cmd.to_s.start_with? "xcodebuild" - ENV.remove_cc_etc - end + ENV.remove_cc_etc if cmd.to_s.start_with? "xcodebuild" # Turn on argument filtering in the superenv compiler wrapper. # We should probably have a better mechanism for this than adding @@ -1778,9 +1779,7 @@ class Formula if cmd == "python" setup_py_in_args = %w[setup.py build.py].include?(args.first) setuptools_shim_in_args = args.any? { |a| a.to_s.start_with? "import setuptools" } - if setup_py_in_args || setuptools_shim_in_args - ENV.refurbish_args - end + ENV.refurbish_args if setup_py_in_args || setuptools_shim_in_args end $stdout.reopen(out) @@ -2218,7 +2217,7 @@ class Formula # If this formula conflicts with another one. # <pre>conflicts_with "imagemagick", :because => "because this is just a stupid example"</pre> def conflicts_with(*names) - opts = Hash === names.last ? names.pop : {} + opts = names.last.is_a?(Hash) ? names.pop : {} names.each { |name| conflicts << FormulaConflict.new(name, opts[:because]) } end diff --git a/Library/Homebrew/formula_cellar_checks.rb b/Library/Homebrew/formula_cellar_checks.rb index 3805d0f45..7db5e748b 100644 --- a/Library/Homebrew/formula_cellar_checks.rb +++ b/Library/Homebrew/formula_cellar_checks.rb @@ -1,7 +1,7 @@ require "utils/shell" module FormulaCellarChecks - def check_PATH(bin) + def check_env_path(bin) # warn the user if stuff was installed outside of their PATH return unless bin.directory? return if bin.children.empty? @@ -166,7 +166,7 @@ module FormulaCellarChecks audit_check_output(check_elisp_dirname(formula.share, formula.name)) audit_check_output(check_elisp_root(formula.share, formula.name)) end - alias_method :generic_audit_installed, :audit_installed + alias generic_audit_installed audit_installed private diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb index f64b77026..3738c3784 100644 --- a/Library/Homebrew/formula_installer.rb +++ b/Library/Homebrew/formula_installer.rb @@ -24,7 +24,9 @@ class FormulaInstaller private(*names) names.each do |name| predicate = "#{name}?" - define_method(predicate) { !!send(name) } + define_method(predicate) do + send(name) ? true : false + end private(predicate) end end @@ -71,7 +73,8 @@ class FormulaInstaller end def build_bottle? - !!@build_bottle && !formula.bottle_disabled? + return false unless @build_bottle + !formula.bottle_disabled? end def pour_bottle?(install_bottle_options = { warn: false }) @@ -130,12 +133,10 @@ class FormulaInstaller begin compute_dependencies rescue TapFormulaUnavailableError => e - if e.tap.installed? - raise - else - e.tap.install - retry - end + raise if e.tap.installed? + + e.tap.install + retry end rescue FormulaUnavailableError => e e.dependent = formula.full_name @@ -145,23 +146,24 @@ class FormulaInstaller def check_install_sanity raise FormulaInstallationAlreadyAttemptedError, formula if @@attempted.include?(formula) - unless skip_deps_check? - recursive_deps = formula.recursive_dependencies - unlinked_deps = recursive_deps.map(&:to_formula).select do |dep| - dep.installed? && !dep.keg_only? && !dep.linked_keg.directory? - end - raise CannotInstallFormulaError, - "You must `brew link #{unlinked_deps*" "}` before #{formula.full_name} can be installed" unless unlinked_deps.empty? + return if skip_deps_check? - pinned_unsatisfied_deps = recursive_deps.select do |dep| - dep.to_formula.pinned? && !dep.satisfied?(inherited_options_for(dep)) - end + recursive_deps = formula.recursive_dependencies + unlinked_deps = recursive_deps.map(&:to_formula).select do |dep| + dep.installed? && !dep.keg_only? && !dep.linked_keg.directory? + end - unless pinned_unsatisfied_deps.empty? - raise CannotInstallFormulaError, - "You must `brew unpin #{pinned_unsatisfied_deps*" "}` as installing #{formula.full_name} requires the latest version of pinned dependencies" - end + unless unlinked_deps.empty? + raise CannotInstallFormulaError, "You must `brew link #{unlinked_deps*" "}` before #{formula.full_name} can be installed" + end + + pinned_unsatisfied_deps = recursive_deps.select do |dep| + dep.to_formula.pinned? && !dep.satisfied?(inherited_options_for(dep)) end + + return if pinned_unsatisfied_deps.empty? + raise CannotInstallFormulaError, + "You must `brew unpin #{pinned_unsatisfied_deps*" "}` as installing #{formula.full_name} requires the latest version of pinned dependencies" end def build_bottle_preinstall @@ -254,9 +256,7 @@ class FormulaInstaller unless @poured_bottle not_pouring = !pour_bottle || @pour_failed - if not_pouring && !ignore_deps? - compute_and_install_dependencies - end + compute_and_install_dependencies if not_pouring && !ignore_deps? build clean end @@ -284,11 +284,10 @@ class FormulaInstaller #{formula}: #{e.message} 'conflicts_with \"#{c.name}\"' should be removed from #{formula.path.basename}. EOS - if ARGV.homebrew_developer? - raise - else - $stderr.puts "Please report this to the #{formula.tap} tap!" - end + + raise if ARGV.homebrew_developer? + + $stderr.puts "Please report this to the #{formula.tap} tap!" false else f.linked_keg.exist? && f.opt_prefix.exist? @@ -491,10 +490,9 @@ class FormulaInstaller c = Caveats.new(formula) - unless c.empty? - @show_summary_heading = true - ohai "Caveats", c.caveats - end + return if c.empty? + @show_summary_heading = true + ohai "Caveats", c.caveats end def finish @@ -543,7 +541,7 @@ class FormulaInstaller @build_time ||= Time.now - @start_time if @start_time && !interactive? end - def sanitized_ARGV_options + def sanitized_argv_options args = [] args << "--ignore-dependencies" if ignore_deps? @@ -582,7 +580,7 @@ class FormulaInstaller end def build_argv - sanitized_ARGV_options + options.as_flags + sanitized_argv_options + options.as_flags end def build @@ -705,13 +703,12 @@ class FormulaInstaller raise end - unless link_overwrite_backup.empty? - opoo "These files were overwritten during `brew link` step:" - puts link_overwrite_backup.keys - puts - puts "They have been backed up in #{backup_dir}" - @show_summary_heading = true - end + return if link_overwrite_backup.empty? + opoo "These files were overwritten during `brew link` step:" + puts link_overwrite_backup.keys + puts + puts "They have been backed up in #{backup_dir}" + @show_summary_heading = true end def install_plist @@ -803,15 +800,14 @@ class FormulaInstaller end def audit_check_output(output) - if output - opoo output - @show_summary_heading = true - end + return unless output + opoo output + @show_summary_heading = true end def audit_installed - audit_check_output(check_PATH(formula.bin)) - audit_check_output(check_PATH(formula.sbin)) + audit_check_output(check_env_path(formula.bin)) + audit_check_output(check_env_path(formula.sbin)) super end @@ -822,22 +818,20 @@ class FormulaInstaller end def lock - if (@@locked ||= []).empty? - formula.recursive_dependencies.each do |dep| - @@locked << dep.to_formula - end unless ignore_deps? - @@locked.unshift(formula) - @@locked.uniq! - @@locked.each(&:lock) - @hold_locks = true - end + return unless (@@locked ||= []).empty? + formula.recursive_dependencies.each do |dep| + @@locked << dep.to_formula + end unless ignore_deps? + @@locked.unshift(formula) + @@locked.uniq! + @@locked.each(&:lock) + @hold_locks = true end def unlock - if hold_locks? - @@locked.each(&:unlock) - @@locked.clear - @hold_locks = false - end + return unless hold_locks? + @@locked.each(&:unlock) + @@locked.clear + @hold_locks = false end end diff --git a/Library/Homebrew/formula_lock.rb b/Library/Homebrew/formula_lock.rb index 1ce62b328..bf747fea2 100644 --- a/Library/Homebrew/formula_lock.rb +++ b/Library/Homebrew/formula_lock.rb @@ -8,18 +8,16 @@ class FormulaLock end def lock - HOMEBREW_LOCK_DIR.mkpath - @lockfile = get_or_create_lockfile - unless @lockfile.flock(File::LOCK_EX | File::LOCK_NB) - raise OperationInProgressError, @name - end + @path.parent.mkpath + create_lockfile + return if @lockfile.flock(File::LOCK_EX | File::LOCK_NB) + raise OperationInProgressError, @name end def unlock - unless @lockfile.nil? || @lockfile.closed? - @lockfile.flock(File::LOCK_UN) - @lockfile.close - end + return if @lockfile.nil? || @lockfile.closed? + @lockfile.flock(File::LOCK_UN) + @lockfile.close end def with_lock @@ -31,13 +29,9 @@ class FormulaLock private - def get_or_create_lockfile - if @lockfile.nil? || @lockfile.closed? - @lockfile = @path.open(File::RDWR | File::CREAT) - @lockfile.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) - @lockfile - else - @lockfile - end + def create_lockfile + return unless @lockfile.nil? || @lockfile.closed? + @lockfile = @path.open(File::RDWR | File::CREAT) + @lockfile.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) end end diff --git a/Library/Homebrew/formula_versions.rb b/Library/Homebrew/formula_versions.rb index ec2e2a459..81e15d314 100644 --- a/Library/Homebrew/formula_versions.rb +++ b/Library/Homebrew/formula_versions.rb @@ -52,9 +52,7 @@ class FormulaVersions rev_list(branch) do |rev| formula_at_revision(rev) do |f| bottle = f.bottle_specification - unless bottle.checksums.empty? - map[f.pkg_version] << bottle.rebuild - end + map[f.pkg_version] << bottle.rebuild unless bottle.checksums.empty? end end map diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb index 74f669413..5ce09f6ba 100644 --- a/Library/Homebrew/formulary.rb +++ b/Library/Homebrew/formulary.rb @@ -37,18 +37,18 @@ class Formulary end def self.load_formula_from_path(name, path) - contents = path.open("r") { |f| set_encoding(f).read } + contents = path.open("r") { |f| ensure_utf8_encoding(f).read } namespace = "FormulaNamespace#{Digest::MD5.hexdigest(path.to_s)}" klass = load_formula(name, path, contents, namespace) FORMULAE[path] = klass end if IO.method_defined?(:set_encoding) - def self.set_encoding(io) + def self.ensure_utf8_encoding(io) io.set_encoding(Encoding::UTF_8) end else - def self.set_encoding(io) + def self.ensure_utf8_encoding(io) io end end @@ -301,9 +301,7 @@ class Formulary return TapLoader.new(ref) end - if File.extname(ref) == ".rb" - return FromPathLoader.new(ref) - end + return FromPathLoader.new(ref) if File.extname(ref) == ".rb" formula_with_that_name = core_path(ref) if formula_with_that_name.file? @@ -311,14 +309,14 @@ class Formulary end possible_alias = CoreTap.instance.alias_dir/ref - if possible_alias.file? - return AliasLoader.new(possible_alias) - end + return AliasLoader.new(possible_alias) if possible_alias.file? possible_tap_formulae = tap_paths(ref) if possible_tap_formulae.size > 1 raise TapFormulaAmbiguityError.new(ref, possible_tap_formulae) - elsif possible_tap_formulae.size == 1 + end + + if possible_tap_formulae.size == 1 path = possible_tap_formulae.first.resolved_path name = path.basename(".rb").to_s return FormulaLoader.new(name, path) @@ -340,7 +338,9 @@ class Formulary if possible_tap_newname_formulae.size > 1 raise TapFormulaWithOldnameAmbiguityError.new(ref, possible_tap_newname_formulae) - elsif !possible_tap_newname_formulae.empty? + end + + unless possible_tap_newname_formulae.empty? return TapLoader.new(possible_tap_newname_formulae.first) end @@ -372,7 +372,9 @@ class Formulary possible_pinned_tap_formulae = tap_paths(ref, Dir["#{HOMEBREW_LIBRARY}/PinnedTaps/*/*/"]).map(&:realpath) if possible_pinned_tap_formulae.size > 1 raise TapFormulaAmbiguityError.new(ref, possible_pinned_tap_formulae) - elsif possible_pinned_tap_formulae.size == 1 + end + + if possible_pinned_tap_formulae.size == 1 selected_formula = factory(possible_pinned_tap_formulae.first, spec) if core_path(ref).file? opoo <<-EOS.undent diff --git a/Library/Homebrew/global.rb b/Library/Homebrew/global.rb index 91692c146..0cd0d57e6 100644 --- a/Library/Homebrew/global.rb +++ b/Library/Homebrew/global.rb @@ -43,10 +43,10 @@ module Homebrew extend self attr_accessor :failed - alias_method :failed?, :failed + alias failed? failed attr_accessor :raise_deprecation_exceptions - alias_method :raise_deprecation_exceptions?, :raise_deprecation_exceptions + alias raise_deprecation_exceptions? raise_deprecation_exceptions end HOMEBREW_PULL_API_REGEX = %r{https://api\.github\.com/repos/([\w-]+)/([\w-]+)?/pulls/(\d+)} diff --git a/Library/Homebrew/keg.rb b/Library/Homebrew/keg.rb index ecbc4c6e0..d2c9e12e8 100644 --- a/Library/Homebrew/keg.rb +++ b/Library/Homebrew/keg.rb @@ -62,12 +62,17 @@ class Keg end # locale-specific directories have the form language[_territory][.codeset][@modifier] - LOCALEDIR_RX = /(locale|man)\/([a-z]{2}|C|POSIX)(_[A-Z]{2})?(\.[a-zA-Z\-0-9]+(@.+)?)?/ + LOCALEDIR_RX = %r{(locale|man)/([a-z]{2}|C|POSIX)(_[A-Z]{2})?(\.[a-zA-Z\-0-9]+(@.+)?)?} INFOFILE_RX = %r{info/([^.].*?\.info|dir)$} TOP_LEVEL_DIRECTORIES = %w[bin etc include lib sbin share var Frameworks].freeze ALL_TOP_LEVEL_DIRECTORIES = (TOP_LEVEL_DIRECTORIES + %w[lib/pkgconfig share/locale share/man opt]).freeze - PRUNEABLE_DIRECTORIES = %w[bin etc include lib sbin share Frameworks LinkedKegs var/homebrew/linked].map do |d| - case d when "LinkedKegs" then HOMEBREW_LIBRARY/d else HOMEBREW_PREFIX/d end + PRUNEABLE_DIRECTORIES = %w[bin etc include lib sbin share Frameworks LinkedKegs var/homebrew/linked].map do |dir| + case dir + when "LinkedKegs" + HOMEBREW_LIBRARY/dir + else + HOMEBREW_PREFIX/dir + end end # These paths relative to the keg's share directory should always be real @@ -113,9 +118,9 @@ class Keg end if Pathname.method_defined?(:to_path) - alias_method :to_path, :to_s + alias to_path to_s else - alias_method :to_str, :to_s + alias to_str to_s end def inspect @@ -125,7 +130,7 @@ class Keg def ==(other) instance_of?(other.class) && path == other.path end - alias_method :eql?, :== + alias eql? == def hash path.hash @@ -249,10 +254,10 @@ class Keg def completion_installed?(shell) dir = case shell - when :bash then path.join("etc", "bash_completion.d") - when :zsh then path.join("share", "zsh", "site-functions") - when :fish then path.join("share", "fish", "vendor_completions.d") - end + when :bash then path.join("etc", "bash_completion.d") + when :zsh then path.join("share", "zsh", "site-functions") + when :fish then path.join("share", "fish", "vendor_completions.d") + end dir && dir.directory? && !dir.children.empty? end @@ -318,13 +323,13 @@ class Keg when "locale/locale.alias" then :skip_file when INFOFILE_RX then :info when LOCALEDIR_RX then :mkpath - when /^icons\/.*\/icon-theme\.cache$/ then :skip_file + when %r{^icons/.*/icon-theme\.cache$} then :skip_file # all icons subfolders should also mkpath - when /^icons\// then :mkpath + when %r{^icons/} then :mkpath when /^zsh/ then :mkpath when /^fish/ then :mkpath # Lua, Lua51, Lua53 all need the same handling. - when /^lua\// then :mkpath + when %r{^lua/} then :mkpath when %r{^guile/} then :mkpath when *SHARE_PATHS then :mkpath else :link @@ -362,7 +367,7 @@ class Keg # the :link strategy. However, for Foo.framework and # Foo.framework/Versions we have to use :mkpath so that multiple formulae # can link their versions into it and `brew [un]link` works. - if relative_path.to_s =~ /[^\/]*\.framework(\/Versions)?$/ + if relative_path.to_s =~ %r{[^/]*\.framework(/Versions)?$} :mkpath else :link @@ -389,10 +394,9 @@ class Keg opt_record.delete if opt_record.symlink? || opt_record.exist? make_relative_symlink(opt_record, path, mode) - if oldname_opt_record - oldname_opt_record.delete - make_relative_symlink(oldname_opt_record, path, mode) - end + return unless oldname_opt_record + oldname_opt_record.delete + make_relative_symlink(oldname_opt_record, path, mode) end def delete_pyc_files! @@ -418,18 +422,19 @@ class Keg return end - if stat.directory? - begin - keg = Keg.for(src) - rescue NotAKegError - puts "Won't resolve conflicts for symlink #{dst} as it doesn't resolve into the Cellar" if ARGV.verbose? - return + return unless stat.directory? + begin + keg = Keg.for(src) + rescue NotAKegError + if ARGV.verbose? + puts "Won't resolve conflicts for symlink #{dst} as it doesn't resolve into the Cellar" end - - dst.unlink unless mode.dry_run - keg.link_dir(src, mode) { :mkpath } - return true + return end + + dst.unlink unless mode.dry_run + keg.link_dir(src, mode) { :mkpath } + true end def make_relative_symlink(dst, src, mode) @@ -457,9 +462,8 @@ class Keg dst.delete if mode.overwrite && (dst.exist? || dst.symlink?) dst.make_relative_symlink(src) rescue Errno::EEXIST => e - if dst.exist? - raise ConflictError.new(self, src.relative_path_from(path), dst, e) - elsif dst.symlink? + raise ConflictError.new(self, src.relative_path_from(path), dst, e) if dst.exist? + if dst.symlink? dst.unlink retry end diff --git a/Library/Homebrew/keg_relocate.rb b/Library/Homebrew/keg_relocate.rb index 04f589984..3f0f4c8ed 100644 --- a/Library/Homebrew/keg_relocate.rb +++ b/Library/Homebrew/keg_relocate.rb @@ -13,7 +13,7 @@ class Keg end end end - alias_method :generic_fix_dynamic_linkage, :fix_dynamic_linkage + alias generic_fix_dynamic_linkage fix_dynamic_linkage def relocate_dynamic_linkage(_old_prefix, _new_prefix, _old_cellar, _new_cellar) [] diff --git a/Library/Homebrew/language/haskell.rb b/Library/Homebrew/language/haskell.rb index b5d0e1220..4b7f88a99 100644 --- a/Library/Homebrew/language/haskell.rb +++ b/Library/Homebrew/language/haskell.rb @@ -79,19 +79,16 @@ module Language # if we have build flags, we have to pass them to cabal install to resolve the necessary # dependencies, and call cabal configure afterwards to set the flags again for compile - flags = "" - if options[:flags] - flags = "--flags=#{options[:flags].join(" ")}" - end + flags = "--flags=#{options[:flags].join(" ")}" if options[:flags] args_and_flags = args - args_and_flags << flags unless flags.empty? + args_and_flags << flags unless flags.nil? # install dependencies in the sandbox cabal_install "--only-dependencies", *args_and_flags # call configure if build flags are set - cabal_configure flags unless flags.empty? + cabal_configure flags unless flags.nil? # install the main package in the destination dir cabal_install "--prefix=#{prefix}", *args diff --git a/Library/Homebrew/manpages/brew-cask.1.md b/Library/Homebrew/manpages/brew-cask.1.md index fc14d54d1..4e160b527 100644 --- a/Library/Homebrew/manpages/brew-cask.1.md +++ b/Library/Homebrew/manpages/brew-cask.1.md @@ -19,10 +19,10 @@ names, and other aspects of this manual are still subject to change. ## FREQUENTLY USED COMMANDS - * `install [--force] [--skip-cask-deps] [--require-sha]` <token> [ <token> ... ]: + * `install` [--force] [--skip-cask-deps] [--require-sha] <token> [ <token> ... ]: Install Cask identified by <token>. - * `uninstall [--force]` <token> [ <token> ... ]: + * `uninstall` [--force] <token> [ <token> ... ]: Uninstall Cask identified by <token>. * `search` <text> | /<regexp>/: @@ -69,7 +69,7 @@ names, and other aspects of this manual are still subject to change. * `info` or `abv` <token> [ <token> ... ]: Display information about the given Cask. - * `install [--force] [--skip-cask-deps] [--require-sha]` <token> [ <token> ... ]: + * `install` [--force] [--skip-cask-deps] [--require-sha] <token> [ <token> ... ]: Install the given Cask. With `--force`, re-install even if the Cask appears to be already present. With `--skip-cask-deps`, skip any Cask dependencies. `--require-sha` will abort installation if the Cask does not @@ -78,42 +78,29 @@ names, and other aspects of this manual are still subject to change. <token> is usually the ID of a Cask as returned by `brew cask search`, but see [OTHER WAYS TO SPECIFY A CASK][] for variations. - * `list` or `ls` [-1 | -l] [ <token> ... ]: + * `list` or `ls` [-1] [--versions] [ <token> ... ]: Without any arguments, list all installed Casks. With `-1`, always - format the output in a single column. With `-l`, give a more detailed - listing. + format the output in a single column. With `--versions`, show all installed + versions. If <token> is given, summarize the staged files associated with the given Cask. - * `search` or `-S`: - Display all Casks available for install. - - * `search` or `-S` <text> | /<regexp>/: - Perform a substring search of known Cask tokens for <text>. If the text - is delimited by slashes, it is interpreted as a Ruby regular expression. + * `search` or `-S` [<text> | /<regexp>/]: + Without 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. - * `uninstall [--force]` or `rm` or `remove` <token> [ <token> ... ]: + * `uninstall` or `rm` or `remove` [--force] <token> [ <token> ... ]: Uninstall the given Cask. With `--force`, uninstall even if the Cask does not appear to be present. - Note that `uninstall --force` is currently imperfect. It will follow - the `uninstall` instructions from *newest* Cask definition, even if - the given Cask has changed since you installed it. The result is that - `uninstall --force` will always succeed in removing relevant files - under `<Caskroom_path>`, but will sometimes fail to remove relevant - installed files outside of it. This issue is being - addressed. - - `uninstall` without `--force` is also imperfect. It may be unable to - perform an `uninstall` operation if the given Cask has changed since you - installed it. This issue is being addressed. - * `update`: For convenience. `brew cask update` is a synonym for `brew update`. diff --git a/Library/Homebrew/manpages/brew.1.md.erb b/Library/Homebrew/manpages/brew.1.md.erb index e44dc2658..bc2140b40 100644 --- a/Library/Homebrew/manpages/brew.1.md.erb +++ b/Library/Homebrew/manpages/brew.1.md.erb @@ -255,11 +255,11 @@ Homebrew Documentation: <https://github.com/Homebrew/brew/blob/master/docs/> ## AUTHORS -Homebrew's lead maintainer is <%= lead_maintainer %>. +<%= lead_maintainer.concat("\n") %> -Homebrew's current maintainers are <%= maintainers[0...-1].join(", ") %> and <%= maintainers[-1] %>. +<%= maintainers.concat("\n") %> -Former maintainers with significant contributions include <%= former_maintainers.join(", ") %> and Homebrew's creator: <%= creator %>. +<%= former_maintainers.concat("\n") %> ## BUGS diff --git a/Library/Homebrew/migrator.rb b/Library/Homebrew/migrator.rb index d31025119..4f8cba1ce 100644 --- a/Library/Homebrew/migrator.rb +++ b/Library/Homebrew/migrator.rb @@ -101,7 +101,7 @@ class Migrator @new_cellar = HOMEBREW_CELLAR/formula.name - if @old_linked_keg = get_linked_old_linked_keg + if @old_linked_keg = linked_old_linked_keg @old_linked_keg_record = old_linked_keg.linked_keg_record if old_linked_keg.linked? @old_opt_record = old_linked_keg.opt_record if old_linked_keg.optlinked? @new_linked_keg_record = HOMEBREW_CELLAR/"#{newname}/#{File.basename(old_linked_keg)}" @@ -137,7 +137,7 @@ class Migrator end end - def get_linked_old_linked_keg + def linked_old_linked_keg kegs = old_cellar.subdirs.map { |d| Keg.new(d) } kegs.detect(&:linked?) || kegs.detect(&:optlinked?) end @@ -182,22 +182,21 @@ class Migrator end def repin - if pinned? - # old_pin_record is a relative symlink and when we try to to read it - # from <dir> we actually try to find file - # <dir>/../<...>/../Cellar/name/version. - # To repin formula we need to update the link thus that it points to - # the right directory. - # NOTE: old_pin_record.realpath.sub(oldname, newname) is unacceptable - # here, because it resolves every symlink for old_pin_record and then - # substitutes oldname with newname. It breaks things like - # Pathname#make_relative_symlink, where Pathname#relative_path_from - # is used to find relative path from source to destination parent and - # it assumes no symlinks. - src_oldname = old_pin_record.dirname.join(old_pin_link_record).expand_path - new_pin_record.make_relative_symlink(src_oldname.sub(oldname, newname)) - old_pin_record.delete - end + return unless pinned? + # old_pin_record is a relative symlink and when we try to to read it + # from <dir> we actually try to find file + # <dir>/../<...>/../Cellar/name/version. + # To repin formula we need to update the link thus that it points to + # the right directory. + # NOTE: old_pin_record.realpath.sub(oldname, newname) is unacceptable + # here, because it resolves every symlink for old_pin_record and then + # substitutes oldname with newname. It breaks things like + # Pathname#make_relative_symlink, where Pathname#relative_path_from + # is used to find relative path from source to destination parent and + # it assumes no symlinks. + src_oldname = old_pin_record.dirname.join(old_pin_link_record).expand_path + new_pin_record.make_relative_symlink(src_oldname.sub(oldname, newname)) + old_pin_record.delete end def unlink_oldname @@ -254,10 +253,9 @@ class Migrator # Link keg to opt if it was linked before migrating. def link_oldname_opt - if old_opt_record - old_opt_record.delete if old_opt_record.symlink? - old_opt_record.make_relative_symlink(new_linked_keg_record) - end + return unless old_opt_record + old_opt_record.delete if old_opt_record.symlink? + old_opt_record.make_relative_symlink(new_linked_keg_record) end # After migtaion every INSTALL_RECEIPT.json has wrong path to the formula @@ -316,30 +314,27 @@ class Migrator end end - unless old_linked_keg.nil? - # The keg used to be linked and when we backup everything we restore - # Cellar/oldname, the target also gets restored, so we are able to - # create a keg using its old path - if old_linked_keg_record - begin - old_linked_keg.link - rescue Keg::LinkError - old_linked_keg.unlink - raise - rescue Keg::AlreadyLinkedError - old_linked_keg.unlink - retry - end - else - old_linked_keg.optlink + return if old_linked_keg.nil? + # The keg used to be linked and when we backup everything we restore + # Cellar/oldname, the target also gets restored, so we are able to + # create a keg using its old path + if old_linked_keg_record + begin + old_linked_keg.link + rescue Keg::LinkError + old_linked_keg.unlink + raise + rescue Keg::AlreadyLinkedError + old_linked_keg.unlink + retry end + else + old_linked_keg.optlink end end def backup_oldname_cellar - unless old_cellar.exist? - FileUtils.mv(new_cellar, old_cellar) - end + FileUtils.mv(new_cellar, old_cellar) unless old_cellar.exist? end def backup_old_tabs diff --git a/Library/Homebrew/official_taps.rb b/Library/Homebrew/official_taps.rb index 53f3640d1..a220c9239 100644 --- a/Library/Homebrew/official_taps.rb +++ b/Library/Homebrew/official_taps.rb @@ -18,5 +18,6 @@ OFFICIAL_TAPS = %w[ OFFICIAL_CMD_TAPS = { "homebrew/bundle" => ["bundle"], + "homebrew/test-bot" => ["test-bot"], "homebrew/services" => ["services"], }.freeze diff --git a/Library/Homebrew/options.rb b/Library/Homebrew/options.rb index 1d92fbf47..08f459b24 100644 --- a/Library/Homebrew/options.rb +++ b/Library/Homebrew/options.rb @@ -14,14 +14,14 @@ class Option end def <=>(other) - return unless Option === other + return unless other.is_a?(Option) name <=> other.name end def ==(other) instance_of?(other.class) && name == other.name end - alias_method :eql?, :== + alias eql? == def hash name.hash @@ -51,7 +51,7 @@ class DeprecatedOption def ==(other) instance_of?(other.class) && old == other.old && current == other.current end - alias_method :eql?, :== + alias eql? == end class Options @@ -106,7 +106,7 @@ class Options any? { |opt| opt == o || opt.name == o || opt.flag == o } end - alias_method :to_ary, :to_a + alias to_ary to_a def inspect "#<#{self.class.name}: #{to_a.inspect}>" diff --git a/Library/Homebrew/os/mac.rb b/Library/Homebrew/os/mac.rb index f121cbbd3..029c761f7 100644 --- a/Library/Homebrew/os/mac.rb +++ b/Library/Homebrew/os/mac.rb @@ -45,26 +45,6 @@ module OS @language ||= Utils.popen_read("defaults", "read", ".GlobalPreferences", "AppleLanguages").delete(" \n\"()").sub(/,.*/, "") end - # Locates a (working) copy of install_name_tool, guaranteed to function - # whether the user has developer tools installed or not. - def install_name_tool - if (path = HOMEBREW_PREFIX/"opt/cctools/bin/install_name_tool").executable? - path - else - DevelopmentTools.locate("install_name_tool") - end - end - - # Locates a (working) copy of otool, guaranteed to function whether the user - # has developer tools installed or not. - def otool - if (path = HOMEBREW_PREFIX/"opt/cctools/bin/otool").executable? - path - else - DevelopmentTools.locate("otool") - end - end - def active_developer_dir @active_developer_dir ||= Utils.popen_read("/usr/bin/xcode-select", "-print-path").strip end diff --git a/Library/Homebrew/os/mac/cctools_keg.rb b/Library/Homebrew/os/mac/cctools_keg.rb deleted file mode 100644 index cd928f522..000000000 --- a/Library/Homebrew/os/mac/cctools_keg.rb +++ /dev/null @@ -1,21 +0,0 @@ -module CctoolsKeg - def install_name_tool(*args) - @require_install_name_tool = true - tool = MacOS.install_name_tool - system(tool, *args) || raise(ErrorDuringExecution.new(tool, args)) - end - - def require_install_name_tool? - !!@require_install_name_tool - end - - def change_dylib_id(id, file) - puts "Changing dylib ID of #{file}\n from #{file.dylib_id}\n to #{id}" if ARGV.debug? - install_name_tool("-id", id, file) - end - - def change_install_name(old, new, file) - puts "Changing install name in #{file}\n from #{old}\n to #{new}" if ARGV.debug? - install_name_tool("-change", old, new, file) - end -end diff --git a/Library/Homebrew/os/mac/cctools_mach.rb b/Library/Homebrew/os/mac/cctools_mach.rb deleted file mode 100644 index 7e8b96b83..000000000 --- a/Library/Homebrew/os/mac/cctools_mach.rb +++ /dev/null @@ -1,99 +0,0 @@ -module CctoolsMachO - # @private - OTOOL_RX = /\t(.*) \(compatibility version (?:\d+\.)*\d+, current version (?:\d+\.)*\d+\)/ - - # Mach-O binary methods, see: - # /usr/include/mach-o/loader.h - # /usr/include/mach-o/fat.h - # @private - def mach_data - @mach_data ||= begin - offsets = [] - mach_data = [] - - header = read(8).unpack("N2") - case header[0] - when 0xcafebabe # universal - header[1].times do |i| - # header[1] is the number of struct fat_arch in the file. - # Each struct fat_arch is 20 bytes, and the 'offset' member - # begins 8 bytes into the struct, with an additional 8 byte - # offset due to the struct fat_header at the beginning of - # the file. - offsets << read(4, 20*i + 16).unpack("N")[0] - end - when 0xcefaedfe, 0xcffaedfe, 0xfeedface, 0xfeedfacf # Single arch - offsets << 0 - else - raise "Not a Mach-O binary." - end - - offsets.each do |offset| - arch = case read(8, offset).unpack("N2") - when [0xcefaedfe, 0x07000000] then :i386 - when [0xcffaedfe, 0x07000001] then :x86_64 - when [0xfeedface, 0x00000012] then :ppc7400 - when [0xfeedfacf, 0x01000012] then :ppc64 - else :dunno - end - - type = case read(4, offset + 12).unpack("N")[0] - when 0x00000002, 0x02000000 then :executable - when 0x00000006, 0x06000000 then :dylib - when 0x00000008, 0x08000000 then :bundle - else :dunno - end - - mach_data << { arch: arch, type: type } - end - mach_data - rescue - [] - end - end - - # @private - class Metadata - attr_reader :path, :dylib_id, :dylibs - - def initialize(path) - @path = path - @dylib_id, @dylibs = parse_otool_L_output - end - - def parse_otool_L_output - args = ["-L", path.expand_path.to_s] - libs = Utils.popen_read(OS::Mac.otool, *args).split("\n") - unless $?.success? - raise ErrorDuringExecution.new(OS::Mac.otool, args) - end - - libs.shift # first line is the filename - - id = libs.shift[OTOOL_RX, 1] if path.dylib? - libs.map! { |lib| lib[OTOOL_RX, 1] }.compact! - - [id, libs] - end - end - - # @private - def mach_metadata - @mach_metadata ||= Metadata.new(self) - end - - # Returns an array containing all dynamically-linked libraries, based on the - # output of otool. This returns the install names, so these are not guaranteed - # to be absolute paths. - # Returns an empty array both for software that links against no libraries, - # and for non-mach objects. - # @private - def dynamically_linked_libraries - mach_metadata.dylibs - end - - # @private - def dylib_id - mach_metadata.dylib_id - end -end diff --git a/Library/Homebrew/os/mac/keg.rb b/Library/Homebrew/os/mac/keg.rb index 201c57b50..b2a769849 100644 --- a/Library/Homebrew/os/mac/keg.rb +++ b/Library/Homebrew/os/mac/keg.rb @@ -1,9 +1,31 @@ class Keg - if !ENV["HOMEBREW_NO_RUBY_MACHO"] - require "os/mac/ruby_keg" - include RubyKeg - else - require "os/mac/cctools_keg" - include CctoolsKeg + def change_dylib_id(id, file) + @require_relocation = true + puts "Changing dylib ID of #{file}\n from #{file.dylib_id}\n to #{id}" if ARGV.debug? + MachO::Tools.change_dylib_id(file, id, strict: false) + rescue MachO::MachOError + onoe <<-EOS.undent + Failed changing dylib ID of #{file} + from #{file.dylib_id} + to #{id} + EOS + raise + end + + def change_install_name(old, new, file) + @require_relocation = true + puts "Changing install name in #{file}\n from #{old}\n to #{new}" if ARGV.debug? + MachO::Tools.change_install_name(file, old, new, strict: false) + rescue MachO::MachOError + onoe <<-EOS.undent + Failed changing install name in #{file} + from #{old} + to #{new} + EOS + raise + end + + def require_relocation? + @require_relocation end end diff --git a/Library/Homebrew/os/mac/ruby_mach.rb b/Library/Homebrew/os/mac/mach.rb index 5d0e75c31..07598a23d 100644 --- a/Library/Homebrew/os/mac/ruby_mach.rb +++ b/Library/Homebrew/os/mac/mach.rb @@ -1,6 +1,7 @@ require "vendor/macho/macho" +require "os/mac/architecture_list" -module RubyMachO +module MachO # @private def macho @macho ||= begin @@ -57,4 +58,51 @@ module RubyMachO def dylib_id macho.dylib_id end + + def archs + mach_data.map { |m| m.fetch :arch }.extend(ArchitectureListExtension) + end + + def arch + case archs.length + when 0 then :dunno + when 1 then archs.first + else :universal + end + end + + def universal? + arch == :universal + end + + def i386? + arch == :i386 + end + + def x86_64? + arch == :x86_64 + end + + def ppc7400? + arch == :ppc7400 + end + + def ppc64? + arch == :ppc64 + end + + # @private + def dylib? + mach_data.any? { |m| m.fetch(:type) == :dylib } + end + + # @private + def mach_o_executable? + mach_data.any? { |m| m.fetch(:type) == :executable } + end + + # @private + def mach_o_bundle? + mach_data.any? { |m| m.fetch(:type) == :bundle } + end end diff --git a/Library/Homebrew/os/mac/pathname.rb b/Library/Homebrew/os/mac/pathname.rb index b76c4333a..9b65d7ac0 100644 --- a/Library/Homebrew/os/mac/pathname.rb +++ b/Library/Homebrew/os/mac/pathname.rb @@ -1,13 +1,5 @@ -require "os/mac/shared_mach" +require "os/mac/mach" class Pathname - if !ENV["HOMEBREW_NO_RUBY_MACHO"] - require "os/mac/ruby_mach" - include RubyMachO - else - require "os/mac/cctools_mach" - include CctoolsMachO - end - - include SharedMachO + include MachO end diff --git a/Library/Homebrew/os/mac/ruby_keg.rb b/Library/Homebrew/os/mac/ruby_keg.rb deleted file mode 100644 index e476b174f..000000000 --- a/Library/Homebrew/os/mac/ruby_keg.rb +++ /dev/null @@ -1,33 +0,0 @@ -require "vendor/macho/macho" - -module RubyKeg - def change_dylib_id(id, file) - @require_install_name_tool = true - puts "Changing dylib ID of #{file}\n from #{file.dylib_id}\n to #{id}" if ARGV.debug? - MachO::Tools.change_dylib_id(file, id, strict: false) - rescue MachO::MachOError - onoe <<-EOS.undent - Failed changing dylib ID of #{file} - from #{file.dylib_id} - to #{id} - EOS - raise - end - - def change_install_name(old, new, file) - @require_install_name_tool = true - puts "Changing install name in #{file}\n from #{old}\n to #{new}" if ARGV.debug? - MachO::Tools.change_install_name(file, old, new, strict: false) - rescue MachO::MachOError - onoe <<-EOS.undent - Failed changing install name in #{file} - from #{old} - to #{new} - EOS - raise - end - - def require_install_name_tool? - !!@require_install_name_tool - end -end diff --git a/Library/Homebrew/os/mac/shared_mach.rb b/Library/Homebrew/os/mac/shared_mach.rb deleted file mode 100644 index aa8baa92e..000000000 --- a/Library/Homebrew/os/mac/shared_mach.rb +++ /dev/null @@ -1,50 +0,0 @@ -require "os/mac/architecture_list" - -module SharedMachO - def archs - mach_data.map { |m| m.fetch :arch }.extend(ArchitectureListExtension) - end - - def arch - case archs.length - when 0 then :dunno - when 1 then archs.first - else :universal - end - end - - def universal? - arch == :universal - end - - def i386? - arch == :i386 - end - - def x86_64? - arch == :x86_64 - end - - def ppc7400? - arch == :ppc7400 - end - - def ppc64? - arch == :ppc64 - end - - # @private - def dylib? - mach_data.any? { |m| m.fetch(:type) == :dylib } - end - - # @private - def mach_o_executable? - mach_data.any? { |m| m.fetch(:type) == :executable } - end - - # @private - def mach_o_bundle? - mach_data.any? { |m| m.fetch(:type) == :bundle } - end -end diff --git a/Library/Homebrew/os/mac/xcode.rb b/Library/Homebrew/os/mac/xcode.rb index f487a6997..0f78e4412 100644 --- a/Library/Homebrew/os/mac/xcode.rb +++ b/Library/Homebrew/os/mac/xcode.rb @@ -15,15 +15,13 @@ module OS when "10.8" then "5.1.1" when "10.9" then "6.2" when "10.10" then "7.2.1" - when "10.11" then "7.3.1" + when "10.11" then "8.0" when "10.12" then "8.0" else + raise "macOS '#{MacOS.version}' is invalid" unless OS::Mac.prerelease? + # Default to newest known version of Xcode for unreleased macOS versions. - if OS::Mac.prerelease? - "8.0" - else - raise "macOS '#{MacOS.version}' is invalid" - end + "8.0" end end @@ -175,7 +173,7 @@ module OS # Returns true even if outdated tools are installed, e.g. # tools from Xcode 4.x on 10.9 def installed? - !!detect_version + !detect_version.nil? end def update_instructions @@ -193,6 +191,9 @@ module OS end def latest_version + # As of Xcode 8 CLT releases are no longer in sync with Xcode releases + # on the older supported platform for that Xcode release, i.e there's no + # CLT package for 10.11 that contains the Clang version from Xcode 8. case MacOS.version when "10.12" then "800.0.38" when "10.11" then "703.0.31" @@ -206,9 +207,9 @@ module OS def outdated? if MacOS.version >= :mavericks - version = `#{MAVERICKS_PKG_PATH}/usr/bin/clang --version` + version = Utils.popen_read("#{MAVERICKS_PKG_PATH}/usr/bin/clang --version") else - version = `/usr/bin/clang --version` + version = Utils.popen_read("/usr/bin/clang --version") end version = version[/clang-(\d+\.\d+\.\d+(\.\d+)?)/, 1] || "0" version < latest_version diff --git a/Library/Homebrew/patch.rb b/Library/Homebrew/patch.rb index 1148389cf..1b7751ba3 100644 --- a/Library/Homebrew/patch.rb +++ b/Library/Homebrew/patch.rb @@ -89,7 +89,7 @@ class DATAPatch < EmbeddedPatch path.open("rb") do |f| begin line = f.gets - end until line.nil? || /^__END__$/ === line + end until line.nil? || line =~ /^__END__$/ data << line while line = f.gets end data @@ -130,14 +130,13 @@ class ExternalPatch patch_dir = Pathname.pwd if patch_files.empty? children = patch_dir.children - if children.length == 1 && children.first.file? - patch_files << children.first.basename - else + if children.length != 1 || !children.first.file? raise MissingApplyError, <<-EOS.undent There should be exactly one patch file in the staging directory unless the "apply" method was used one or more times in the patch-do block. EOS end + patch_files << children.first.basename end dir.cd do patch_files.each do |patch_file| diff --git a/Library/Homebrew/pkg_version.rb b/Library/Homebrew/pkg_version.rb index 4bf701f35..761a349fd 100644 --- a/Library/Homebrew/pkg_version.rb +++ b/Library/Homebrew/pkg_version.rb @@ -29,13 +29,13 @@ class PkgVersion version.to_s end end - alias_method :to_str, :to_s + alias to_str to_s def <=>(other) - return unless PkgVersion === other + return unless other.is_a?(PkgVersion) (version <=> other.version).nonzero? || revision <=> other.revision end - alias_method :eql?, :== + alias eql? == def hash version.hash ^ revision.hash diff --git a/Library/Homebrew/readall.rb b/Library/Homebrew/readall.rb index 61222e015..3dd7075ec 100644 --- a/Library/Homebrew/readall.rb +++ b/Library/Homebrew/readall.rb @@ -1,7 +1,6 @@ require "formula" require "tap" require "thread" -require "readall" module Readall class << self diff --git a/Library/Homebrew/requirement.rb b/Library/Homebrew/requirement.rb index 4ea15774d..89487fec3 100644 --- a/Library/Homebrew/requirement.rb +++ b/Library/Homebrew/requirement.rb @@ -56,7 +56,7 @@ class Requirement def satisfied? result = self.class.satisfy.yielder { |p| instance_eval(&p) } @satisfied_result = result - !!result + result ? true : false end # Overriding #fatal? is deprecated. @@ -83,12 +83,11 @@ class Requirement # 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. - if Pathname === @satisfied_result - parent = @satisfied_result.parent - unless ENV["PATH"].split(File::PATH_SEPARATOR).include?(parent.to_s) - ENV.append_path("PATH", parent) - end - end + return unless @satisfied_result.is_a?(Pathname) + parent = @satisfied_result.parent + + return if ENV["PATH"].split(File::PATH_SEPARATOR).include?(parent.to_s) + ENV.append_path("PATH", parent) end def env @@ -102,7 +101,7 @@ class Requirement def ==(other) instance_of?(other.class) && name == other.name && tags == other.tags end - alias_method :eql?, :== + alias eql? == def hash name.hash ^ tags.hash @@ -115,7 +114,7 @@ class Requirement def to_dependency f = self.class.default_formula raise "No default formula defined for #{inspect}" if f.nil? - if HOMEBREW_TAP_FORMULA_REGEX === f + 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) @@ -199,11 +198,8 @@ class Requirement formulae.each do |f| f.requirements.each do |req| - if prune?(f, req, &block) - next - else - reqs << req - end + next if prune?(f, req, &block) + reqs << req end end diff --git a/Library/Homebrew/requirements.rb b/Library/Homebrew/requirements.rb index 68d21a2b7..274ba5c9b 100644 --- a/Library/Homebrew/requirements.rb +++ b/Library/Homebrew/requirements.rb @@ -22,7 +22,7 @@ class XcodeRequirement < Requirement satisfy(build_env: false) { xcode_installed_version } def initialize(tags) - @version = tags.find { |t| tags.delete(t) if /(\d\.)+\d/ === t } + @version = tags.find { |tag| tags.delete(tag) if tag =~ /(\d\.)+\d/ } super end @@ -39,11 +39,11 @@ class XcodeRequirement < Requirement Installing just the Command Line Tools is not sufficient. EOS if MacOS.version >= :lion - message += <<-EOS.undent + message + <<-EOS.undent Xcode can be installed from the App Store. EOS else - message += <<-EOS.undent + message + <<-EOS.undent Xcode can be installed from https://developer.apple.com/xcode/downloads/ EOS end diff --git a/Library/Homebrew/requirements/python_requirement.rb b/Library/Homebrew/requirements/python_requirement.rb index 5d79f2a18..696b9c800 100644 --- a/Library/Homebrew/requirements/python_requirement.rb +++ b/Library/Homebrew/requirements/python_requirement.rb @@ -50,7 +50,7 @@ class PythonRequirement < Requirement end # Deprecated - alias_method :to_s, :python_binary + alias to_s python_binary end class Python3Requirement < PythonRequirement diff --git a/Library/Homebrew/sandbox.rb b/Library/Homebrew/sandbox.rb index 9392b7122..4d0709cb4 100644 --- a/Library/Homebrew/sandbox.rb +++ b/Library/Homebrew/sandbox.rb @@ -3,8 +3,12 @@ require "tempfile" class Sandbox SANDBOX_EXEC = "/usr/bin/sandbox-exec".freeze - SANDBOXED_TAPS = [ - "homebrew/core", + SANDBOXED_TAPS = %w[ + homebrew/core + homebrew/dupes + homebrew/fuse + homebrew/devel-only + homebrew/tex ].freeze def self.available? @@ -73,17 +77,21 @@ class Sandbox # Xcode projects expect access to certain cache/archive dirs. def allow_write_xcode - allow_write_path "/Users/#{ENV["USER"]}/Library/Developer/Xcode/DerivedData/" + allow_write_path "/Users/#{ENV["USER"]}/Library/Developer" end def allow_write_log(formula) allow_write_path formula.logs end - def deny_write_homebrew_library - deny_write_path HOMEBREW_LIBRARY - deny_write_path HOMEBREW_REPOSITORY/".git" + def deny_write_homebrew_repository deny_write HOMEBREW_BREW_FILE + if HOMEBREW_PREFIX.to_s != HOMEBREW_REPOSITORY.to_s + deny_write_path HOMEBREW_REPOSITORY + else + deny_write_path HOMEBREW_LIBRARY + deny_write_path HOMEBREW_REPOSITORY/".git" + end end def exec(*args) diff --git a/Library/Homebrew/software_spec.rb b/Library/Homebrew/software_spec.rb index 986dc5354..bb432e2dd 100644 --- a/Library/Homebrew/software_spec.rb +++ b/Library/Homebrew/software_spec.rb @@ -65,11 +65,12 @@ class SoftwareSpec end def bottle_unneeded? - !!@bottle_disable_reason && @bottle_disable_reason.unneeded? + return false unless @bottle_disable_reason + @bottle_disable_reason.unneeded? end def bottle_disabled? - !!@bottle_disable_reason + @bottle_disable_reason ? true : false end attr_reader :bottle_disable_reason @@ -116,12 +117,12 @@ class SoftwareSpec def option(name, description = "") opt = PREDEFINED_OPTIONS.fetch(name) do - if Symbol === name + if name.is_a?(Symbol) opoo "Passing arbitrary symbols to `option` is deprecated: #{name.inspect}" puts "Symbols are reserved for future use, please pass a string instead" name = name.to_s end - unless String === name + unless name.is_a?(String) raise ArgumentError, "option name must be string or symbol; got a #{name.class}: #{name}" end raise ArgumentError, "option name is required" if name.empty? @@ -227,7 +228,7 @@ class Bottle def to_s prefix + suffix end - alias_method :to_str, :to_s + alias to_str to_s def prefix "#{name}-#{version}.#{tag}" @@ -318,7 +319,7 @@ class BottleSpecification end def tag?(tag) - !!checksum_for(tag) + checksum_for(tag) ? true : false end # Checksum methods in the DSL's bottle block optionally take diff --git a/Library/Homebrew/system_config.rb b/Library/Homebrew/system_config.rb index a8b4ee1ff..555493c0d 100644 --- a/Library/Homebrew/system_config.rb +++ b/Library/Homebrew/system_config.rb @@ -152,7 +152,7 @@ class SystemConfig f.puts "Ruby: #{describe_ruby}" f.puts "Java: #{describe_java}" end - alias_method :dump_generic_verbose_config, :dump_verbose_config + alias dump_generic_verbose_config dump_verbose_config end end diff --git a/Library/Homebrew/tab.rb b/Library/Homebrew/tab.rb index 12b23cc73..379f2e8a4 100644 --- a/Library/Homebrew/tab.rb +++ b/Library/Homebrew/tab.rb @@ -328,9 +328,9 @@ class Tab < OpenStruct else s << "Built from source" end - if time - s << Time.at(time).strftime("on %Y-%m-%d at %H:%M:%S") - end + + s << Time.at(time).strftime("on %Y-%m-%d at %H:%M:%S") if time + unless used_options.empty? s << "with:" s << used_options.to_a.join(" ") diff --git a/Library/Homebrew/tap.rb b/Library/Homebrew/tap.rb index ecf81ca37..c73e3f7a7 100644 --- a/Library/Homebrew/tap.rb +++ b/Library/Homebrew/tap.rb @@ -130,9 +130,8 @@ class Tap # The issues URL of this {Tap}. # e.g. `https://github.com/user/homebrew-repo/issues` def issues_url - if official? || !custom_remote? - "https://github.com/#{user}/homebrew-#{repo}/issues" - end + return unless official? || !custom_remote? + "https://github.com/#{user}/homebrew-#{repo}/issues" end def to_s @@ -236,15 +235,16 @@ class Tap puts "Tapped #{formula_count} formula#{plural(formula_count, "e")} (#{path.abv})" unless quiet Descriptions.cache_formulae(formula_names) - if !options[:clone_target] && private? && !quiet - puts <<-EOS.undent - It looks like you tapped a private repository. To avoid entering your - credentials each time you update, you can use git HTTP credential - caching or issue the following command: - cd #{path} - git remote set-url origin git@github.com:#{user}/homebrew-#{repo}.git - EOS - end + return if options[:clone_target] + return unless private? + return if quiet + puts <<-EOS.undent + It looks like you tapped a private repository. To avoid entering your + credentials each time you update, you can use git HTTP credential + caching or issue the following command: + cd #{path} + git remote set-url origin git@github.com:#{user}/homebrew-#{repo}.git + EOS end def link_manpages diff --git a/Library/Homebrew/test/Gemfile b/Library/Homebrew/test/Gemfile index b7666e551..0a84f8dc2 100644 --- a/Library/Homebrew/test/Gemfile +++ b/Library/Homebrew/test/Gemfile @@ -3,15 +3,17 @@ source "https://rubygems.org" gem "mocha", "~> 1.1" gem "minitest", "~> 5.3" gem "rake", "~> 10.3" +gem "parallel_tests", "~> 2.9" group :coverage do - # This is SimpleCov v0.12.0 with one PR merged on top, that finally resolves + # 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. See pull request - # <https://github.com/Homebrew/legacy-homebrew/pull/48250> for full details. + # 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", # commit 257e26394c464c4ab388631b4eff1aa98c37d3f1 + branch: "master", # commit 83d8031ddde0927f87ef9327200a98583ca18d77 require: false gem "codecov", require: false end diff --git a/Library/Homebrew/test/Gemfile.lock b/Library/Homebrew/test/Gemfile.lock index ceb11128d..ba639d70f 100644 --- a/Library/Homebrew/test/Gemfile.lock +++ b/Library/Homebrew/test/Gemfile.lock @@ -1,6 +1,6 @@ GIT remote: https://github.com/colszowka/simplecov.git - revision: 257e26394c464c4ab388631b4eff1aa98c37d3f1 + revision: 83d8031ddde0927f87ef9327200a98583ca18d77 branch: master specs: simplecov (0.12.0) @@ -21,6 +21,9 @@ GEM minitest (5.9.0) mocha (1.1.0) metaclass (~> 0.0.1) + parallel (1.9.0) + parallel_tests (2.9.0) + parallel rake (10.5.0) simplecov-html (0.10.0) url (0.3.2) @@ -32,8 +35,9 @@ DEPENDENCIES codecov minitest (~> 5.3) mocha (~> 1.1) + parallel_tests (~> 2.9) rake (~> 10.3) simplecov (= 0.12.0)! BUNDLED WITH - 1.12.5 + 1.13.1 diff --git a/Library/Homebrew/test/Rakefile b/Library/Homebrew/test/Rakefile deleted file mode 100644 index a2db861f2..000000000 --- a/Library/Homebrew/test/Rakefile +++ /dev/null @@ -1,29 +0,0 @@ -require "rake" -require "rake/testtask" - -def mac? - return false if ENV["HOMEBREW_TEST_GENERIC_OS"] - RUBY_PLATFORM.to_s.downcase.include? "darwin" -end - -TEST_DIRECTORY = File.dirname(File.expand_path(__FILE__)) -TEST_FILES = Dir["#{TEST_DIRECTORY}/test_*.rb"].reject do |f| - f.include?("/test_os_mac_") && !mac? -end - -task default: :test - -Rake::TestTask.new(:test) do |t| - t.libs << TEST_DIRECTORY - t.test_files = TEST_FILES -end - -namespace :test do - TEST_FILES.each do |file| - name = file[/test_(.+)\.rb/, 1] - Rake::TestTask.new(name) do |t| - t.libs << TEST_DIRECTORY - t.test_files = [file] - end - end -end diff --git a/Library/Homebrew/test/test_cmd_testbot.rb b/Library/Homebrew/test/test_cmd_testbot.rb deleted file mode 100644 index d762448d1..000000000 --- a/Library/Homebrew/test/test_cmd_testbot.rb +++ /dev/null @@ -1,99 +0,0 @@ -require "pathname" - -require "testing_env" -require "dev-cmd/test-bot" - -class TestbotCommandTests < Homebrew::TestCase - def test_resolve_test_tap - tap = Homebrew.resolve_test_tap - assert_nil tap, "Should return nil if no tap slug provided" - - slug = "spam/homebrew-eggs" - url = "https://github.com/#{slug}.git" - environments = [ - { "TRAVIS_REPO_SLUG" => slug }, - { "UPSTREAM_BOT_PARAMS" => "--tap=#{slug}" }, - { "UPSTREAM_BOT_PARAMS" => "--tap=spam/eggs" }, - { "UPSTREAM_GIT_URL" => url }, - { "GIT_URL" => url }, - ] - - predicate = proc do |message| - tap = Homebrew.resolve_test_tap - assert_kind_of Tap, tap, message - assert_equal tap.user, "spam", message - assert_equal tap.repo, "eggs", message - end - - environments.each do |pair| - with_environment(pair) do - predicate.call pair.to_s - end - end - - ARGV.expects(:value).with("tap").returns(slug) - predicate.call "ARGV" - end -end - -class TestbotStepTests < Homebrew::TestCase - def run - [nil, "1"].each do |travis| - with_environment("TRAVIS" => travis) { super } - end - self - end - - def teardown - unless passed? - raise "INFO: Previous test failed with ENV['TRAVIS'] = #{ENV["TRAVIS"].inspect}" - end - end - - def stub_test_instance - stub( - category: "stub", - log_root: Pathname.pwd - ) - end - - def test_step_run_measures_execution_time - step = Homebrew::Step.new stub_test_instance, %w[sleep 0.1] - shutup do - step.run - end - assert_operator step.time, :>, 0.1 - assert_operator step.time, :<, 1 - assert_equal step.passed?, true - end - - def test_step_run_observes_failure - step = Homebrew::Step.new stub_test_instance, ["false", ""] - shutup do - step.run - end - assert_equal step.passed?, false - assert_equal step.failed?, true - end - - def test_step_dry_run_is_dry_and_always_succeeds - step = Homebrew::Step.new stub_test_instance, ["false", ""] - ARGV.expects(:include?).with("--dry-run").returns(true) - step.stubs(:fork).raises("Dry run isn't dry!") - shutup do - step.run - end - assert_equal step.passed?, true - end - - def test_step_fail_fast_exits_on_failure - step = Homebrew::Step.new stub_test_instance, ["false", ""] - ARGV.stubs(:include?).returns(false) - ARGV.expects(:include?).with("--fail-fast").returns(true) - step.expects(:exit).with(1).returns(nil) - shutup do - step.run - end - assert_equal step.passed?, false - end -end diff --git a/Library/Homebrew/test/test_dependency_collector.rb b/Library/Homebrew/test/test_dependency_collector.rb index a94b4959e..4e87c8515 100644 --- a/Library/Homebrew/test/test_dependency_collector.rb +++ b/Library/Homebrew/test/test_dependency_collector.rb @@ -76,6 +76,11 @@ class DependencyCollectorTests < Homebrew::TestCase assert_predicate dep, :optional? end + def test_ant_dep + @d.add ant: :build + assert_equal find_dependency("ant"), Dependency.new("ant", [:build]) + end + def test_raises_typeerror_for_unknown_classes assert_raises(TypeError) { @d.add(Class.new) } end diff --git a/Library/Homebrew/test/test_diagnostic.rb b/Library/Homebrew/test/test_diagnostic.rb index 5d0f5f386..37f56e961 100644 --- a/Library/Homebrew/test/test_diagnostic.rb +++ b/Library/Homebrew/test/test_diagnostic.rb @@ -154,7 +154,7 @@ class DiagnosticChecksTest < Homebrew::TestCase def test_check_dyld_vars ENV["DYLD_INSERT_LIBRARIES"] = "foo" assert_match "Setting DYLD_INSERT_LIBRARIES", - @checks.check_DYLD_vars + @checks.check_dyld_vars end def test_check_for_symlinked_cellar diff --git a/Library/Homebrew/test/test_download_strategies.rb b/Library/Homebrew/test/test_download_strategies.rb index d107d14e8..87218fb12 100644 --- a/Library/Homebrew/test/test_download_strategies.rb +++ b/Library/Homebrew/test/test_download_strategies.rb @@ -118,7 +118,7 @@ class GitDownloadStrategyTests < Homebrew::TestCase def test_source_modified_time setup_git_repo - assert_equal 1242860651, @strategy.source_modified_time.to_i + assert_equal 1_242_860_651, @strategy.source_modified_time.to_i end def test_last_commit diff --git a/Library/Homebrew/test/test_formula.rb b/Library/Homebrew/test/test_formula.rb index 9207f8ead..37d3f0f59 100644 --- a/Library/Homebrew/test/test_formula.rb +++ b/Library/Homebrew/test/test_formula.rb @@ -467,7 +467,7 @@ class FormulaTests < Homebrew::TestCase assert_version_equal "HEAD", f.head.version end - def test_formula_set_active_spec + def test_formula_active_spec= f = formula do url "foo" version "1.0" @@ -481,11 +481,11 @@ class FormulaTests < Homebrew::TestCase 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.set_active_spec(:devel) + 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.set_active_spec(:head) } + assert_raises(FormulaSpecificationError) { f.active_spec = :head } end def test_path diff --git a/Library/Homebrew/test/test_inreplace.rb b/Library/Homebrew/test/test_inreplace.rb index 91d57f942..0e62f9d3f 100644 --- a/Library/Homebrew/test/test_inreplace.rb +++ b/Library/Homebrew/test/test_inreplace.rb @@ -91,26 +91,29 @@ class InreplaceTest < Homebrew::TestCase end def test_inreplace_errors + require "tempfile" extend(Utils::Inreplace) - open("test", "w") { |f| f.write "a\nb\nc\n" } + file = Tempfile.new("test") + + file.write "a\nb\nc\n" assert_raises(Utils::InreplaceError) do - inreplace "test", "d", "f" + 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("test") { |s| s.gsub!("d", "f") } # rubocop:disable Performance/StringReplacement + inreplace(file.path) { |s| s.gsub!("d", "f") } # rubocop:disable Performance/StringReplacement end assert_raises(Utils::InreplaceError) do - inreplace("test") do |s| + inreplace(file.path) do |s| s.change_make_var! "VAR", "value" s.remove_make_var! "VAR2" end end ensure - File.unlink("test") + file.unlink end end diff --git a/Library/Homebrew/test/test_integration_cmds.rb b/Library/Homebrew/test/test_integration_cmds.rb index 11eb6c69d..35ad04e7a 100644 --- a/Library/Homebrew/test/test_integration_cmds.rb +++ b/Library/Homebrew/test/test_integration_cmds.rb @@ -39,9 +39,8 @@ class IntegrationCommandTests < Homebrew::TestCase end def needs_test_cmd_taps - unless ENV["HOMEBREW_TEST_OFFICIAL_CMD_TAPS"] - skip "HOMEBREW_TEST_OFFICIAL_CMD_TAPS is not set" - end + return if ENV["HOMEBREW_TEST_OFFICIAL_CMD_TAPS"] + skip "HOMEBREW_TEST_OFFICIAL_CMD_TAPS is not set" end def needs_macos @@ -274,8 +273,8 @@ class IntegrationCommandTests < Homebrew::TestCase cmd("help", "cat")) # Internal command (documented, Ruby). assert_match(/^brew update /, cmd("help", "update")) # Internal command (documented, Shell). - assert_match(/^brew test-bot /, - cmd("help", "test-bot")) # Internal developer command (documented, Ruby). + assert_match(/^brew update-test /, + cmd("help", "update-test")) # Internal developer command (documented, Ruby). end def test_config diff --git a/Library/Homebrew/test/test_os_mac_dependency_collector.rb b/Library/Homebrew/test/test_os_mac_dependency_collector.rb index 37b619101..05b466c94 100644 --- a/Library/Homebrew/test/test_os_mac_dependency_collector.rb +++ b/Library/Homebrew/test/test_os_mac_dependency_collector.rb @@ -2,6 +2,10 @@ 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 @@ -19,4 +23,16 @@ class OSMacDependencyCollectorTests < Homebrew::TestCase 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 end diff --git a/Library/Homebrew/test/test_pathname.rb b/Library/Homebrew/test/test_pathname.rb index bc13241a7..2f6360719 100644 --- a/Library/Homebrew/test/test_pathname.rb +++ b/Library/Homebrew/test/test_pathname.rb @@ -26,7 +26,7 @@ class PathnameTests < Homebrew::TestCase mkdir_p @dir/"a-directory" touch @dir/".DS_Store" touch @dir/"a-file" - File.truncate(@dir/"a-file", 1048576) + 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 diff --git a/Library/Homebrew/test/test_versions.rb b/Library/Homebrew/test/test_versions.rb index 2a1a33a59..21bf324a3 100644 --- a/Library/Homebrew/test/test_versions.rb +++ b/Library/Homebrew/test/test_versions.rb @@ -63,6 +63,8 @@ class VersionComparisonTests < Homebrew::TestCase end def test_comparing_alpha_versions + assert_operator version("1.2.3alpha"), :<, version("1.2.3") + assert_operator version("1.2.3"), :<, version("1.2.3a") assert_operator version("1.2.3alpha4"), :==, version("1.2.3a4") assert_operator version("1.2.3alpha4"), :==, version("1.2.3A4") assert_operator version("1.2.3alpha4"), :>, version("1.2.3alpha3") @@ -203,6 +205,10 @@ class VersionParsingTests < Homebrew::TestCase assert_version_detected "0.7.1", "https://codeload.github.com/gsamokovarov/jump/tar.gz/v0.7.1" end + def test_elasticsearch_alpha_style + assert_version_detected "5.0.0-alpha5", "https://download.elastic.co/elasticsearch/release/org/elasticsearch/distribution/tar/elasticsearch/5.0.0-alpha5/elasticsearch-5.0.0-alpha5.tar.gz" + end + def test_gloox_beta_style assert_version_detected "1.0-beta7", "http://camaya.net/download/gloox-1.0-beta7.tar.bz2" end diff --git a/Library/Homebrew/test/testing_env.rb b/Library/Homebrew/test/testing_env.rb index 164c812ea..02264aa39 100644 --- a/Library/Homebrew/test/testing_env.rb +++ b/Library/Homebrew/test/testing_env.rb @@ -15,6 +15,7 @@ TEST_DIRECTORY = File.dirname(File.expand_path(__FILE__)) begin require "rubygems" require "minitest/autorun" + require "parallel_tests/test/runtime_logger" require "mocha/setup" rescue LoadError abort "Run `bundle install` or install the mocha and minitest gems before running the tests" @@ -42,7 +43,7 @@ module Homebrew module FSLeakLogger def self.included(klass) require "find" - @@log = File.open("fs_leak_log", "w") + @@log = File.open("#{__dir__}/fs_leak_log", "w") klass.make_my_diffs_pretty! end @@ -56,9 +57,8 @@ module Homebrew super files_after_test = [] Find.find(TEST_TMPDIR) { |f| files_after_test << f.sub(TEST_TMPDIR, "") } - if @__files_before_test != files_after_test - @@log.puts location, diff(@__files_before_test, files_after_test) - end + return if @__files_before_test == files_after_test + @@log.puts location, diff(@__files_before_test, files_after_test) end end diff --git a/Library/Homebrew/utils.rb b/Library/Homebrew/utils.rb index e466f8a08..58083fe1b 100644 --- a/Library/Homebrew/utils.rb +++ b/Library/Homebrew/utils.rb @@ -218,13 +218,9 @@ def interactive_shell(f = nil) Process.wait fork { exec ENV["SHELL"] } - if $?.success? - return - elsif $?.exited? - raise "Aborted due to non-zero exit status (#{$?.exitstatus})" - else - raise $?.inspect - end + return if $?.success? + raise "Aborted due to non-zero exit status (#{$?.exitstatus})" if $?.exited? + raise $?.inspect end module Homebrew @@ -248,15 +244,6 @@ module Homebrew _system(cmd, *args) end - def self.homebrew_version_string - if pretty_revision = HOMEBREW_REPOSITORY.git_short_head - last_commit = HOMEBREW_REPOSITORY.git_last_commit_date - "#{HOMEBREW_VERSION} (git revision #{pretty_revision}; last commit #{last_commit})" - else - "#{HOMEBREW_VERSION} (no git repository)" - end - end - def self.core_tap_version_string require "tap" tap = CoreTap.instance @@ -334,13 +321,12 @@ module Homebrew end end - if $times.nil? - $times = {} - at_exit do - col_width = [$times.keys.map(&:size).max + 2, 15].max - $times.sort_by { |_k, v| v }.each do |method, time| - puts format("%-*s %0.4f sec", col_width, "#{method}:", time) - end + return unless $times.nil? + $times = {} + at_exit do + col_width = [$times.keys.map(&:size).max + 2, 15].max + $times.sort_by { |_k, v| v }.each do |method, time| + puts format("%-*s %0.4f sec", col_width, "#{method}:", time) end end end @@ -617,14 +603,14 @@ def link_src_dst_dirs(src_dir, dst_dir, command, link_dir: false) dst_dir.parent.mkpath dst.make_relative_symlink(src) end - unless conflicts.empty? - onoe <<-EOS.undent - Could not link: - #{conflicts.join("\n")} - Please delete these paths and run `#{command}`. - EOS - end + return if conflicts.empty? + onoe <<-EOS.undent + Could not link: + #{conflicts.join("\n")} + + Please delete these paths and run `#{command}`. + EOS end def link_path_manpages(path, command) diff --git a/Library/Homebrew/utils/git.rb b/Library/Homebrew/utils/git.rb index 837cc22e4..dfe47f890 100644 --- a/Library/Homebrew/utils/git.rb +++ b/Library/Homebrew/utils/git.rb @@ -22,9 +22,7 @@ module Utils return if git_available? # we cannot install brewed git if homebrew/core is unavailable. - unless CoreTap.instance.installed? - raise "Git is unavailable" - end + raise "Git is unavailable" unless CoreTap.instance.installed? begin oh1 "Installing git" diff --git a/Library/Homebrew/utils/github.rb b/Library/Homebrew/utils/github.rb index 654272363..b7ec538f9 100644 --- a/Library/Homebrew/utils/github.rb +++ b/Library/Homebrew/utils/github.rb @@ -2,7 +2,8 @@ require "uri" require "tempfile" module GitHub - extend self + module_function + ISSUES_URI = URI.parse("https://api.github.com/search/issues") Error = Class.new(RuntimeError) diff --git a/Library/Homebrew/utils/json.rb b/Library/Homebrew/utils/json.rb index 8a8cb6847..19d32a1e1 100644 --- a/Library/Homebrew/utils/json.rb +++ b/Library/Homebrew/utils/json.rb @@ -2,7 +2,7 @@ require "vendor/okjson" module Utils module JSON - extend self + module_function Error = Class.new(StandardError) diff --git a/Library/Homebrew/utils/popen.rb b/Library/Homebrew/utils/popen.rb index 76e67b3a9..350d9a09f 100644 --- a/Library/Homebrew/utils/popen.rb +++ b/Library/Homebrew/utils/popen.rb @@ -14,11 +14,8 @@ module Utils def self.popen(args, mode) IO.popen("-", mode) do |pipe| if pipe - if block_given? - yield pipe - else - return pipe.read - end + return pipe.read unless block_given? + yield pipe else $stderr.reopen("/dev/null", "w") exec(*args) diff --git a/Library/Homebrew/version.rb b/Library/Homebrew/version.rb index 520db6626..60a833609 100644 --- a/Library/Homebrew/version.rb +++ b/Library/Homebrew/version.rb @@ -95,7 +95,7 @@ class Version end class AlphaToken < CompositeToken - PATTERN = /a(?:lpha)?[0-9]*/i + PATTERN = /alpha[0-9]*|a[0-9]+/i def <=>(other) case other @@ -108,7 +108,7 @@ class Version end class BetaToken < CompositeToken - PATTERN = /b(?:eta)?[0-9]*/i + PATTERN = /beta[0-9]*|b[0-9]+/i def <=>(other) case other @@ -192,11 +192,10 @@ class Version end def initialize(val) - if val.respond_to?(:to_str) - @version = val.to_str - else + unless val.respond_to?(:to_str) raise TypeError, "Version value must be a string; got a #{val.class} (#{val})" end + @version = val.to_str end def detected_from_url? @@ -208,7 +207,7 @@ class Version end def <=>(other) - return unless Version === other + return unless other.is_a?(Version) return 0 if version == other.version return 1 if head? && !other.head? return -1 if !head? && other.head? @@ -242,7 +241,7 @@ class Version 0 end - alias_method :eql?, :== + alias eql? == def hash version.hash @@ -251,7 +250,7 @@ class Version def to_s version.dup end - alias_method :to_str, :to_s + alias to_str to_s protected @@ -340,8 +339,8 @@ class Version m = /-((?:\d+\.)*\d+(?:[abc]|rc|RC)\d*)$/.match(stem) return m.captures.first unless m.nil? - # e.g. foobar-4.5.0-beta1, or foobar-4.50-beta - m = /-((?:\d+\.)*\d+-beta\d*)$/.match(stem) + # e.g. foobar-4.5.0-alpha5, foobar-4.5.0-beta1, or foobar-4.50-beta + m = /-((?:\d+\.)*\d+-(?:alpha|beta|rc)\d*)$/.match(stem) return m.captures.first unless m.nil? # e.g. http://ftpmirror.gnu.org/libidn/libidn-1.29-win64.zip @@ -386,7 +385,7 @@ class Version # e.g. http://mirrors.jenkins-ci.org/war/1.486/jenkins.war # e.g. https://github.com/foo/bar/releases/download/0.10.11/bar.phar - m = /\/(\d\.\d+(\.\d+)?)\//.match(spec_s) + m = %r{/(\d\.\d+(\.\d+)?)}.match(spec_s) return m.captures.first unless m.nil? # e.g. http://www.ijg.org/files/jpegsrc.v8d.tar.gz |
