aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Muschol2017-09-27 16:36:10 -0400
committerGitHub2017-09-27 16:36:10 -0400
commit2d6bd0400785b5fb061f793f70736f12e6ec8231 (patch)
treefd0abc8937fc85fb49714ad9dc4a3735fa58242f
parentfe5c885da0b8b69a5de74647e4181b137acb835f (diff)
parentcb139ca381cb7f00a4dfdc21482515f103aed417 (diff)
downloadbrew-2d6bd0400785b5fb061f793f70736f12e6ec8231.tar.bz2
Merge branch 'master' into check-for-master-no-refactor
-rw-r--r--.travis.yml7
-rw-r--r--Library/.rubocop.yml23
-rw-r--r--Library/Homebrew/.rubocop.yml4
-rw-r--r--Library/Homebrew/.rubocop_todo.yml9
-rw-r--r--Library/Homebrew/brew.rb20
-rw-r--r--Library/Homebrew/brew.sh11
-rw-r--r--Library/Homebrew/build.rb4
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact.rb9
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/abstract_artifact.rb (renamed from Library/Homebrew/cask/lib/hbc/artifact/base.rb)43
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/abstract_flight_block.rb46
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/abstract_uninstall.rb (renamed from Library/Homebrew/cask/lib/hbc/artifact/uninstall_base.rb)141
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/artifact.rb31
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/binary.rb6
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/installer.rb97
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/moved.rb52
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/nested_container.rb28
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/pkg.rb61
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/prefpane.rb2
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/qlplugin.rb20
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/relocated.rb82
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/stage_only.rb20
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/suite.rb4
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/symlinked.rb58
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/uninstall.rb8
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/zap.rb8
-rw-r--r--Library/Homebrew/cask/lib/hbc/audit.rb8
-rw-r--r--Library/Homebrew/cask/lib/hbc/cask.rb10
-rw-r--r--Library/Homebrew/cask/lib/hbc/cask_loader.rb19
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/abstract_command.rb47
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/cat.rb4
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/edit.rb19
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/fetch.rb4
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/info.rb12
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/install.rb4
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb26
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/internal_dump.rb4
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb74
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/list.rb14
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/reinstall.rb2
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/search.rb21
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/uninstall.rb4
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/zap.rb4
-rw-r--r--Library/Homebrew/cask/lib/hbc/container/naked.rb2
-rw-r--r--Library/Homebrew/cask/lib/hbc/dsl.rb131
-rw-r--r--Library/Homebrew/cask/lib/hbc/dsl/installer.rb32
-rw-r--r--Library/Homebrew/cask/lib/hbc/dsl/version.rb2
-rw-r--r--Library/Homebrew/cask/lib/hbc/installer.rb24
-rw-r--r--Library/Homebrew/cask/lib/hbc/staged.rb2
-rw-r--r--Library/Homebrew/cask/lib/hbc/system_command.rb2
-rw-r--r--Library/Homebrew/caveats.rb2
-rw-r--r--Library/Homebrew/cleanup.rb8
-rw-r--r--Library/Homebrew/cmd/irb.rb8
-rw-r--r--Library/Homebrew/cmd/list.rb10
-rw-r--r--Library/Homebrew/cmd/prune.rb2
-rw-r--r--Library/Homebrew/cmd/search.rb2
-rw-r--r--Library/Homebrew/cmd/style.rb4
-rw-r--r--Library/Homebrew/cmd/tap-info.rb4
-rw-r--r--Library/Homebrew/cmd/unlinkapps.rb2
-rw-r--r--Library/Homebrew/cmd/update-report.rb3
-rw-r--r--Library/Homebrew/cmd/update.sh6
-rw-r--r--Library/Homebrew/cmd/vendor-install.sh21
-rw-r--r--Library/Homebrew/compat/ENV/shared.rb4
-rw-r--r--Library/Homebrew/compat/formula_specialties.rb2
-rw-r--r--Library/Homebrew/constants.rb6
-rw-r--r--Library/Homebrew/debrew.rb2
-rw-r--r--Library/Homebrew/debrew/irb.rb2
-rw-r--r--Library/Homebrew/dependency.rb2
-rw-r--r--Library/Homebrew/dev-cmd/audit.rb164
-rw-r--r--Library/Homebrew/dev-cmd/bottle.rb6
-rw-r--r--Library/Homebrew/dev-cmd/bump-formula-pr.rb15
-rw-r--r--Library/Homebrew/dev-cmd/pull.rb6
-rw-r--r--Library/Homebrew/dev-cmd/release-notes.rb4
-rw-r--r--Library/Homebrew/development_tools.rb2
-rw-r--r--Library/Homebrew/diagnostic.rb4
-rw-r--r--Library/Homebrew/download_strategy.rb12
-rw-r--r--Library/Homebrew/exceptions.rb2
-rw-r--r--Library/Homebrew/extend/ARGV.rb6
-rw-r--r--Library/Homebrew/extend/ENV.rb2
-rw-r--r--Library/Homebrew/extend/ENV/shared.rb4
-rw-r--r--Library/Homebrew/extend/ENV/std.rb4
-rw-r--r--Library/Homebrew/extend/os/mac/development_tools.rb17
-rw-r--r--Library/Homebrew/extend/os/mac/diagnostic.rb5
-rw-r--r--Library/Homebrew/extend/os/mac/extend/ENV/super.rb10
-rw-r--r--Library/Homebrew/extend/os/mac/hardware/cpu.rb2
-rw-r--r--Library/Homebrew/extend/string.rb2
-rw-r--r--Library/Homebrew/formula.rb28
-rw-r--r--Library/Homebrew/formula_installer.rb13
-rw-r--r--Library/Homebrew/global.rb6
-rw-r--r--Library/Homebrew/gpg.rb23
-rw-r--r--Library/Homebrew/install_renamed.rb8
-rw-r--r--Library/Homebrew/keg.rb2
-rw-r--r--Library/Homebrew/keg_relocate.rb2
-rw-r--r--Library/Homebrew/language/python.rb2
-rw-r--r--Library/Homebrew/locale.rb2
-rw-r--r--Library/Homebrew/manpages/brew-cask.1.md13
-rw-r--r--Library/Homebrew/missing_formula.rb4
-rw-r--r--Library/Homebrew/options.rb24
-rw-r--r--Library/Homebrew/os/mac.rb12
-rw-r--r--Library/Homebrew/os/mac/linkage_checker.rb19
-rw-r--r--Library/Homebrew/os/mac/version.rb1
-rw-r--r--Library/Homebrew/os/mac/xcode.rb2
-rw-r--r--Library/Homebrew/pkg_version.rb2
-rw-r--r--Library/Homebrew/requirements/gpg2_requirement.rb6
-rw-r--r--Library/Homebrew/requirements/java_requirement.rb4
-rw-r--r--Library/Homebrew/requirements/ruby_requirement.rb4
-rw-r--r--Library/Homebrew/rubocops.rb1
-rw-r--r--Library/Homebrew/rubocops/class_cop.rb41
-rw-r--r--Library/Homebrew/rubocops/components_order_cop.rb4
-rw-r--r--Library/Homebrew/rubocops/conflicts_cop.rb2
-rw-r--r--Library/Homebrew/rubocops/extend/formula_cop.rb44
-rw-r--r--Library/Homebrew/rubocops/lines_cop.rb67
-rw-r--r--Library/Homebrew/sandbox.rb2
-rw-r--r--Library/Homebrew/software_spec.rb2
-rw-r--r--Library/Homebrew/system_config.rb2
-rw-r--r--Library/Homebrew/tab.rb2
-rw-r--r--Library/Homebrew/tap.rb7
-rw-r--r--Library/Homebrew/test/cask/artifact/alt_target_spec.rb2
-rw-r--r--Library/Homebrew/test/cask/artifact/app_spec.rb21
-rw-r--r--Library/Homebrew/test/cask/artifact/binary_spec.rb21
-rw-r--r--Library/Homebrew/test/cask/artifact/generic_artifact_spec.rb12
-rw-r--r--Library/Homebrew/test/cask/artifact/nested_container_spec.rb3
-rw-r--r--Library/Homebrew/test/cask/artifact/pkg_spec.rb8
-rw-r--r--Library/Homebrew/test/cask/artifact/postflight_block_spec.rb6
-rw-r--r--Library/Homebrew/test/cask/artifact/preflight_block_spec.rb6
-rw-r--r--Library/Homebrew/test/cask/artifact/suite_spec.rb4
-rw-r--r--Library/Homebrew/test/cask/artifact/two_apps_correct_spec.rb2
-rw-r--r--Library/Homebrew/test/cask/artifact/uninstall_no_zap_spec.rb2
-rw-r--r--Library/Homebrew/test/cask/artifact/uninstall_zap_shared_examples.rb26
-rw-r--r--Library/Homebrew/test/cask/audit_spec.rb9
-rw-r--r--Library/Homebrew/test/cask/cask_spec.rb34
-rw-r--r--Library/Homebrew/test/cask/cli/audit_spec.rb4
-rw-r--r--Library/Homebrew/test/cask/cli/cat_spec.rb3
-rw-r--r--Library/Homebrew/test/cask/cli/create_spec.rb2
-rw-r--r--Library/Homebrew/test/cask/cli/edit_spec.rb2
-rw-r--r--Library/Homebrew/test/cask/cli/fetch_spec.rb2
-rw-r--r--Library/Homebrew/test/cask/cli/info_spec.rb10
-rw-r--r--Library/Homebrew/test/cask/cli/install_spec.rb18
-rw-r--r--Library/Homebrew/test/cask/cli/list_spec.rb23
-rw-r--r--Library/Homebrew/test/cask/cli/search_spec.rb53
-rw-r--r--Library/Homebrew/test/cask/cli/uninstall_spec.rb9
-rw-r--r--Library/Homebrew/test/cask/cli/zap_spec.rb3
-rw-r--r--Library/Homebrew/test/cask/conflicts_with_spec.rb2
-rw-r--r--Library/Homebrew/test/cask/depends_on_spec.rb2
-rw-r--r--Library/Homebrew/test/cask/dsl_spec.rb24
-rw-r--r--Library/Homebrew/test/cleanup_spec.rb132
-rw-r--r--Library/Homebrew/test/cmd/commands_spec.rb2
-rw-r--r--Library/Homebrew/test/cmd/home_spec.rb6
-rw-r--r--Library/Homebrew/test/cmd/search_remote_tap_spec.rb3
-rw-r--r--Library/Homebrew/test/dependency_expansion_spec.rb2
-rw-r--r--Library/Homebrew/test/dev-cmd/audit_spec.rb64
-rw-r--r--Library/Homebrew/test/os/mac/diagnostic_spec.rb11
-rw-r--r--Library/Homebrew/test/pathname_spec.rb2
-rw-r--r--Library/Homebrew/test/requirement_spec.rb4
-rw-r--r--Library/Homebrew/test/rubocops/class_cop_spec.rb81
-rw-r--r--Library/Homebrew/test/rubocops/conflicts_cop_spec.rb4
-rw-r--r--Library/Homebrew/test/rubocops/formula_desc_cop_spec.rb12
-rw-r--r--Library/Homebrew/test/rubocops/lines_cop_spec.rb312
-rw-r--r--Library/Homebrew/test/support/fixtures/third-party/Casks/third-party-cask.rb9
-rw-r--r--Library/Homebrew/test/support/helper/spec/shared_context/homebrew_cask.rb8
-rw-r--r--Library/Homebrew/test/utils/analytics_spec.rb88
-rw-r--r--Library/Homebrew/test/utils/git_spec.rb150
-rw-r--r--Library/Homebrew/test/utils/github_spec.rb2
-rw-r--r--Library/Homebrew/test/utils/svn_spec.rb39
-rw-r--r--Library/Homebrew/test/utils_spec.rb29
-rw-r--r--Library/Homebrew/test/version_spec.rb14
-rw-r--r--Library/Homebrew/utils.rb14
-rw-r--r--Library/Homebrew/utils/analytics.rb5
-rw-r--r--Library/Homebrew/utils/curl.rb5
-rw-r--r--Library/Homebrew/utils/git.rb23
-rw-r--r--Library/Homebrew/utils/github.rb14
-rw-r--r--Library/Homebrew/utils/popen.rb14
-rw-r--r--Library/Homebrew/utils/ruby.sh13
-rw-r--r--Library/Homebrew/utils/shell.rb4
-rw-r--r--Library/Homebrew/utils/svn.rb4
-rw-r--r--Library/Homebrew/vendor/portable-ruby-version2
-rw-r--r--README.md4
-rw-r--r--completions/zsh/_brew10
-rw-r--r--docs/Analytics.md4
-rw-r--r--docs/Installation.md2
-rw-r--r--manpages/brew-cask.12
180 files changed, 2247 insertions, 1133 deletions
diff --git a/.travis.yml b/.travis.yml
index 9cdebda83..94b83fc11 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -15,26 +15,27 @@ matrix:
rvm: system
- os: linux
sudo: false
- rvm: 2.0.0
+ rvm: 2.3.3
before_install:
- export HOMEBREW_NO_AUTO_UPDATE=1
- export HOMEBREW_DEVELOPER=1
- - git clone --depth=1 https://github.com/Homebrew/homebrew-test-bot Library/Taps/homebrew/homebrew-test-bot
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then
+ git clone --depth=1 https://github.com/Homebrew/homebrew-test-bot Library/Taps/homebrew/homebrew-test-bot;
HOMEBREW_REPOSITORY="$(brew --repo)";
sudo chown -R "$USER" "$HOMEBREW_REPOSITORY/Library/Taps";
mv "$HOMEBREW_REPOSITORY/Library/Taps" "$PWD/Library";
sudo rm -rf "$HOMEBREW_REPOSITORY";
sudo ln -s "$PWD" "$HOMEBREW_REPOSITORY";
else
+ umask 022;
+ git clone --depth=1 https://github.com/Homebrew/homebrew-test-bot Library/Taps/homebrew/homebrew-test-bot;
git fetch --unshallow;
export PATH="$PWD/bin:$PATH";
HOMEBREW_CORE_TAP_DIR="$(brew --repo "homebrew/core")";
mkdir -p "$HOMEBREW_CORE_TAP_DIR";
HOMEBREW_TEST_BOT_TAP_DIR="$(brew --repo "homebrew/test-bot")";
ln -s "$HOMEBREW_TEST_BOT_TAP_DIR/.git" "$HOMEBREW_TEST_BOT_TAP_DIR/Formula" "$HOMEBREW_CORE_TAP_DIR";
- umask 022;
fi
script:
diff --git a/Library/.rubocop.yml b/Library/.rubocop.yml
index cb065a1a4..dd6e039b0 100644
--- a/Library/.rubocop.yml
+++ b/Library/.rubocop.yml
@@ -1,5 +1,5 @@
AllCops:
- TargetRubyVersion: 2.0
+ TargetRubyVersion: 2.3
Exclude:
- '**/Casks/**/*'
- '**/vendor/**/*'
@@ -119,7 +119,7 @@ Style/Encoding:
Enabled: true
# dashes in filenames are typical
-Style/FileName:
+Naming/FileName:
Regex: !ruby/regexp /^[\w\@\-\+\.]+(\.rb)?$/
# falsely flags e.g. curl formatting arguments as format strings
@@ -189,8 +189,25 @@ Style/TrailingCommaInArguments:
EnforcedStyleForMultiline: comma
# we have too many variables like sha256 where this harms readability
-Style/VariableNumber:
+Naming/VariableNumber:
Enabled: false
Style/WordArray:
MinSize: 4
+
+# we want to add this slowly and manually
+Style/FrozenStringLiteralComment:
+ Enabled: false
+
+# generally rescuing StandardError is fine
+Lint/RescueWithoutErrorClass:
+ Enabled: false
+
+# implicitly allow EOS as we use it everywhere
+Naming/HeredocDelimiterNaming:
+ Blacklist:
+ - END, EOD, EOF
+
+# we output how to use interpolated strings too often
+Lint/InterpolationCheck:
+ Enabled: false
diff --git a/Library/Homebrew/.rubocop.yml b/Library/Homebrew/.rubocop.yml
index 26c944529..dc4406527 100644
--- a/Library/Homebrew/.rubocop.yml
+++ b/Library/Homebrew/.rubocop.yml
@@ -42,12 +42,12 @@ Style/HashSyntax:
EnforcedStyle: ruby19_no_mixed_keys
# we won't change backward compatible method names
-Style/MethodName:
+Naming/MethodName:
Exclude:
- 'compat/**/*'
# we won't change backward compatible predicate names
-Style/PredicateName:
+Naming/PredicateName:
Exclude:
- 'compat/**/*'
NameWhitelist: is_32_bit?, is_64_bit?
diff --git a/Library/Homebrew/.rubocop_todo.yml b/Library/Homebrew/.rubocop_todo.yml
index 37518a5f0..96c2f3676 100644
--- a/Library/Homebrew/.rubocop_todo.yml
+++ b/Library/Homebrew/.rubocop_todo.yml
@@ -81,7 +81,7 @@ Security/MarshalLoad:
- 'utils/fork.rb'
# Offense count: 1
-Style/AccessorMethodName:
+Naming/AccessorMethodName:
Exclude:
- 'extend/ENV/super.rb'
@@ -136,10 +136,3 @@ Style/MutableConstant:
- 'formulary.rb'
- 'tab.rb'
- 'tap.rb'
-
-# Offense count: 8
-Style/OpMethod:
- Exclude:
- - 'dependencies.rb'
- - 'install_renamed.rb'
- - 'options.rb'
diff --git a/Library/Homebrew/brew.rb b/Library/Homebrew/brew.rb
index ec86bd794..2906fd93d 100644
--- a/Library/Homebrew/brew.rb
+++ b/Library/Homebrew/brew.rb
@@ -105,18 +105,16 @@ begin
possible_tap = OFFICIAL_CMD_TAPS.find { |_, cmds| cmds.include?(cmd) }
possible_tap = Tap.fetch(possible_tap.first) if possible_tap
- if possible_tap && !possible_tap.installed?
- brew_uid = HOMEBREW_BREW_FILE.stat.uid
- tap_commands = []
- if Process.uid.zero? && !brew_uid.zero?
- tap_commands += %W[/usr/bin/sudo -u ##{brew_uid}]
- end
- tap_commands += %W[#{HOMEBREW_BREW_FILE} tap #{possible_tap}]
- safe_system(*tap_commands)
- exec HOMEBREW_BREW_FILE, cmd, *ARGV
- else
- odie "Unknown command: #{cmd}"
+ odie "Unknown command: #{cmd}" if !possible_tap || possible_tap.installed?
+
+ brew_uid = HOMEBREW_BREW_FILE.stat.uid
+ tap_commands = []
+ if Process.uid.zero? && !brew_uid.zero?
+ tap_commands += %W[/usr/bin/sudo -u ##{brew_uid}]
end
+ tap_commands += %W[#{HOMEBREW_BREW_FILE} tap #{possible_tap}]
+ safe_system(*tap_commands)
+ exec HOMEBREW_BREW_FILE, cmd, *ARGV
end
rescue UsageError => e
require "cmd/help"
diff --git a/Library/Homebrew/brew.sh b/Library/Homebrew/brew.sh
index c40ce8bf7..b2859c927 100644
--- a/Library/Homebrew/brew.sh
+++ b/Library/Homebrew/brew.sh
@@ -23,7 +23,7 @@ HOMEBREW_VERSION="$(git -C "$HOMEBREW_REPOSITORY" describe --tags --dirty --abbr
HOMEBREW_USER_AGENT_VERSION="$HOMEBREW_VERSION"
if [[ -z "$HOMEBREW_VERSION" ]]
then
- HOMEBREW_VERSION=">1.2.0 (no git repository)"
+ HOMEBREW_VERSION=">1.2.0 (shallow or no git repository)"
HOMEBREW_USER_AGENT_VERSION="1.X.Y"
fi
@@ -105,7 +105,14 @@ then
HOMEBREW_OS_USER_AGENT_VERSION="Mac OS X $HOMEBREW_MACOS_VERSION"
printf -v HOMEBREW_MACOS_VERSION_NUMERIC "%02d%02d%02d" ${HOMEBREW_MACOS_VERSION//./ }
- if [[ "$HOMEBREW_MACOS_VERSION_NUMERIC" -lt "100900" &&
+ if [[ "$HOMEBREW_MACOS_VERSION_NUMERIC" -lt "101000" ]]
+ then
+ HOMEBREW_SYSTEM_CURL_TOO_OLD="1"
+ fi
+
+ # The system Curl is too old for some modern HTTPS certificates on
+ # older macOS versions.
+ if [[ -n "$HOMEBREW_SYSTEM_CURL_TOO_OLD" &&
-x "$HOMEBREW_PREFIX/opt/curl/bin/curl" ]]
then
HOMEBREW_CURL="$HOMEBREW_PREFIX/opt/curl/bin/curl"
diff --git a/Library/Homebrew/build.rb b/Library/Homebrew/build.rb
index 8dd4fb245..cd2fa4c02 100644
--- a/Library/Homebrew/build.rb
+++ b/Library/Homebrew/build.rb
@@ -112,6 +112,10 @@ class Build
formula.extend(Debrew::Formula) if ARGV.debug?
formula.brew do |_formula, staging|
+ # For head builds, HOMEBREW_FORMULA_PREFIX should include the commit,
+ # which is not known until after the formula has been staged.
+ ENV["HOMEBREW_FORMULA_PREFIX"] = formula.prefix
+
staging.retain! if ARGV.keep_tmp?
formula.patch
diff --git a/Library/Homebrew/cask/lib/hbc/artifact.rb b/Library/Homebrew/cask/lib/hbc/artifact.rb
index 074d15017..cb15ec051 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact.rb
@@ -33,7 +33,7 @@ module Hbc
# We want to extract nested containers before we
# handle any other artifacts.
#
- TYPES = [
+ CLASSES = [
PreflightBlock,
Uninstall,
NestedContainer,
@@ -60,12 +60,9 @@ module Hbc
Zap,
].freeze
- def self.for_cask(cask, options = {})
+ def self.for_cask(cask)
odebug "Determining which artifacts are present in Cask #{cask}"
-
- TYPES
- .select { |klass| klass.me?(cask) }
- .map { |klass| klass.new(cask, options) }
+ CLASSES.flat_map { |klass| klass.for_cask(cask) }
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/base.rb b/Library/Homebrew/cask/lib/hbc/artifact/abstract_artifact.rb
index ae15552a4..1b18cc6e7 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/base.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/abstract_artifact.rb
@@ -1,34 +1,28 @@
module Hbc
module Artifact
- class Base
+ class AbstractArtifact
extend Predicable
- def self.artifact_name
- @artifact_name ||= name.sub(/^.*:/, "").gsub(/(.)([A-Z])/, '\1_\2').downcase
+ def self.english_name
+ @english_name ||= name.sub(/^.*:/, "").gsub(/(.)([A-Z])/, '\1 \2')
end
- def self.artifact_english_name
- @artifact_english_name ||= name.sub(/^.*:/, "").gsub(/(.)([A-Z])/, '\1 \2')
+ def self.english_article
+ @english_article ||= (english_name =~ /^[aeiou]/i) ? "an" : "a"
end
- def self.artifact_english_article
- @artifact_english_article ||= (artifact_english_name =~ /^[aeiou]/i) ? "an" : "a"
+ def self.dsl_key
+ @dsl_key ||= name.sub(/^.*:/, "").gsub(/(.)([A-Z])/, '\1_\2').downcase.to_sym
end
- def self.artifact_dsl_key
- @artifact_dsl_key ||= artifact_name.to_sym
+ def self.dirmethod
+ @dirmethod ||= "#{dsl_key}dir".to_sym
end
- def self.artifact_dirmethod
- @artifact_dirmethod ||= "#{artifact_name}dir".to_sym
+ def self.for_cask(cask)
+ cask.artifacts[dsl_key].to_a
end
- def self.me?(cask)
- cask.artifacts[artifact_dsl_key].any?
- end
-
- attr_reader :force
-
# 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)
@@ -63,17 +57,14 @@ module Hbc
[executable, arguments]
end
- def summary
- {}
- end
+ attr_reader :cask
- attr_predicate :force?, :verbose?
-
- def initialize(cask, command: SystemCommand, force: false, verbose: false)
+ def initialize(cask)
@cask = cask
- @command = command
- @force = force
- @verbose = verbose
+ end
+
+ def to_s
+ "#{summarize} (#{self.class.english_name})"
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 be3050acb..4e8edbc11 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/abstract_flight_block.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/abstract_flight_block.rb
@@ -1,39 +1,51 @@
-require "hbc/artifact/base"
+require "hbc/artifact/abstract_artifact"
module Hbc
module Artifact
- class AbstractFlightBlock < Base
- def self.artifact_dsl_key
+ class AbstractFlightBlock < AbstractArtifact
+ def self.dsl_key
super.to_s.sub(/_block$/, "").to_sym
end
- def self.uninstall_artifact_dsl_key
- artifact_dsl_key.to_s.prepend("uninstall_").to_sym
+ def self.uninstall_dsl_key
+ 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}")
+ def self.for_cask(cask)
+ [dsl_key, uninstall_dsl_key].flat_map do |key|
+ [*cask.artifacts[key]].map { |block| new(cask, key => block) }
+ end
end
- def self.me?(cask)
- cask.artifacts[artifact_dsl_key].any? ||
- cask.artifacts[uninstall_artifact_dsl_key].any?
+ attr_reader :directives
+
+ def initialize(cask, **directives)
+ super(cask)
+ @directives = directives
end
- def install_phase
- abstract_phase(self.class.artifact_dsl_key)
+ def install_phase(**)
+ abstract_phase(self.class.dsl_key)
end
- def uninstall_phase
- abstract_phase(self.class.uninstall_artifact_dsl_key)
+ def uninstall_phase(**)
+ abstract_phase(self.class.uninstall_dsl_key)
end
private
+ def class_for_dsl_key(dsl_key)
+ namespace = self.class.name.to_s.sub(/::.*::.*$/, "")
+ self.class.const_get("#{namespace}::DSL::#{dsl_key.to_s.split("_").collect(&:capitalize).join}")
+ end
+
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
+ return if (block = directives[dsl_key]).nil?
+ class_for_dsl_key(dsl_key).new(cask).instance_eval(&block)
+ end
+
+ def summarize
+ directives.keys.map(&:to_s).join(", ")
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/uninstall_base.rb b/Library/Homebrew/cask/lib/hbc/artifact/abstract_uninstall.rb
index d92644150..badd549ce 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/uninstall_base.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/abstract_uninstall.rb
@@ -1,11 +1,11 @@
require "pathname"
require "timeout"
-require "hbc/artifact/base"
+require "hbc/artifact/abstract_artifact"
module Hbc
module Artifact
- class UninstallBase < Base
+ class AbstractUninstall < AbstractArtifact
ORDERED_DIRECTIVES = [
:early_script,
:launchctl,
@@ -20,26 +20,42 @@ module Hbc
:rmdir,
].freeze
- def dispatch_uninstall_directives
- directives_set = @cask.artifacts[stanza]
+ def self.from_args(cask, **directives)
+ new(cask, directives)
+ end
+
+ attr_reader :directives
+
+ def initialize(cask, directives)
+ super(cask)
+ directives[:signal] = [*directives[:signal]].flatten.each_slice(2).to_a
+ @directives = directives
+ end
+
+ def to_h
+ directives.to_h
+ end
+
+ def summarize
+ to_h.map { |key, val| [*val].map { |v| "#{key.inspect} => #{v.inspect}" }.join(", ") }.join(", ")
+ end
+
+ private
+
+ def dispatch_uninstall_directives(**options)
ohai "Running #{stanza} process for #{@cask}; your password may be necessary"
- directives_set.each do |directives|
- warn_for_unknown_directives(directives)
- end
+ warn_for_unknown_directives(directives)
ORDERED_DIRECTIVES.each do |directive_sym|
- directives_set.select { |h| h.key?(directive_sym) }.each do |directives|
- args = directives[directive_sym]
- send("uninstall_#{directive_sym}", *(args.is_a?(Hash) ? [args] : args))
- end
+ next unless directives.key?(directive_sym)
+ args = directives[directive_sym]
+ send("uninstall_#{directive_sym}", *(args.is_a?(Hash) ? [args] : args), **options)
end
end
- private
-
def stanza
- self.class.artifact_dsl_key
+ self.class.dsl_key
end
def warn_for_unknown_directives(directives)
@@ -51,18 +67,18 @@ module Hbc
# 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)
+ def uninstall_early_script(directives, **options)
+ uninstall_script(directives, directive_name: :early_script, **options)
end
# :launchctl must come before :quit/:signal for cases where app would instantly re-launch
- def uninstall_launchctl(*services)
+ def uninstall_launchctl(*services, command: nil, **_)
services.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
+ plist_status = command.run("/bin/launchctl", args: ["list", service], sudo: with_sudo, print_stderr: false).stdout
if plist_status =~ /^\{/
- @command.run!("/bin/launchctl", args: ["remove", service], sudo: with_sudo)
+ command.run!("/bin/launchctl", args: ["remove", service], sudo: with_sudo)
sleep 1
end
paths = ["/Library/LaunchAgents/#{service}.plist",
@@ -70,38 +86,38 @@ module Hbc
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)
+ 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)
+ 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
- def running_processes(bundle_id)
- @command.run!("/bin/launchctl", args: ["list"]).stdout.lines
- .map { |line| line.chomp.split("\t") }
- .map { |pid, state, id| [pid.to_i, state.to_i, id] }
- .select do |fields|
- next if fields[0].zero?
- fields[2] =~ /^#{Regexp.escape(bundle_id)}($|\.\d+)/
- end
+ def running_processes(bundle_id, command: nil)
+ command.run!("/bin/launchctl", args: ["list"]).stdout.lines
+ .map { |line| line.chomp.split("\t") }
+ .map { |pid, state, id| [pid.to_i, state.to_i, id] }
+ .select do |fields|
+ next if fields[0].zero?
+ fields[2] =~ /^#{Regexp.escape(bundle_id)}($|\.\d+)/
+ end
end
# :quit/:signal must come before :kext so the kext will not be in use by a running process
- def uninstall_quit(*bundle_ids)
+ def uninstall_quit(*bundle_ids, command: nil, **_)
bundle_ids.each do |bundle_id|
ohai "Quitting application ID #{bundle_id}"
- next if running_processes(bundle_id).empty?
- @command.run!("/usr/bin/osascript", args: ["-e", %Q(tell application id "#{bundle_id}" to quit)], sudo: true)
+ next if running_processes(bundle_id, command: command).empty?
+ command.run!("/usr/bin/osascript", args: ["-e", %Q(tell application id "#{bundle_id}" to quit)], sudo: true)
begin
Timeout.timeout(3) do
Kernel.loop do
- break if running_processes(bundle_id).empty?
+ break if running_processes(bundle_id, command: command).empty?
end
end
rescue Timeout::Error
@@ -111,15 +127,15 @@ module Hbc
end
# :signal should come after :quit so it can be used as a backup when :quit fails
- def uninstall_signal(*signals)
- signals.flatten.each_slice(2) do |pair|
+ def uninstall_signal(*signals, command: nil, **_)
+ signals.each do |pair|
unless pair.size == 2
- raise CaskInvalidError.new(@cask, "Each #{stanza} :signal must consist of 2 elements.")
+ raise CaskInvalidError.new(cask, "Each #{stanza} :signal must consist of 2 elements.")
end
signal, bundle_id = pair
ohai "Signalling '#{signal}' to application ID '#{bundle_id}'"
- pids = running_processes(bundle_id).map(&:first)
+ pids = running_processes(bundle_id, command: command).map(&:first)
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
@@ -133,10 +149,10 @@ module Hbc
end
end
- def uninstall_login_item(*login_items)
+ def uninstall_login_item(*login_items, command: nil, **_)
login_items.each do |name|
ohai "Removing login item #{name}"
- @command.run!("/usr/bin/osascript",
+ 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
@@ -144,23 +160,24 @@ module Hbc
end
# :kext should be unloaded before attempting to delete the relevant file
- def uninstall_kext(*kexts)
+ def uninstall_kext(*kexts, command: nil, **_)
kexts.each do |kext|
ohai "Unloading kernel extension #{kext}"
- is_loaded = @command.run!("/usr/sbin/kextstat", args: ["-l", "-b", kext], sudo: true).stdout
+ 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)
+ command.run!("/sbin/kextunload", args: ["-b", kext], sudo: true)
sleep 1
end
- @command.run!("/usr/sbin/kextfind", args: ["-b", kext], sudo: true).stdout.chomp.lines.each do |kext_path|
+ command.run!("/usr/sbin/kextfind", args: ["-b", kext], sudo: true).stdout.chomp.lines.each do |kext_path|
ohai "Removing kernel extension #{kext_path}"
- @command.run!("/bin/rm", args: ["-rf", kext_path], sudo: true)
+ command.run!("/bin/rm", args: ["-rf", kext_path], sudo: true)
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)
+ def uninstall_script(directives, directive_name: :script, force: false, command: nil, **_)
+ # TODO: Create a common `Script` class to run this and Artifact::Installer.
executable, script_arguments = self.class.read_script_arguments(directives,
"uninstall",
{ must_succeed: true, sudo: false },
@@ -168,25 +185,25 @@ module Hbc
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)
+ raise CaskInvalidError.new(cask, "#{stanza} :#{directive_name} without :executable.") if executable.nil?
+ executable_path = cask.staged_path.join(executable)
unless executable_path.exist?
message = "uninstall script #{executable} does not exist"
- raise CaskError, "#{message}." unless force?
+ raise CaskError, "#{message}." unless force
opoo "#{message}, skipping."
return
end
- @command.run("/bin/chmod", args: ["--", "+x", executable_path])
- @command.run(executable_path, script_arguments)
+ command.run("/bin/chmod", args: ["--", "+x", executable_path])
+ command.run(executable_path, script_arguments)
sleep 1
end
- def uninstall_pkgutil(*pkgs)
+ def uninstall_pkgutil(*pkgs, command: nil, **_)
ohai "Uninstalling packages:"
pkgs.each do |regex|
- Hbc::Pkg.all_matching(regex, @command).each do |pkg|
+ Hbc::Pkg.all_matching(regex, command).each do |pkg|
puts pkg.package_id
pkg.uninstall
end
@@ -215,28 +232,28 @@ module Hbc
end
end
- def uninstall_delete(*paths)
+ def uninstall_delete(*paths, command: nil, **_)
return if paths.empty?
ohai "Removing files:"
each_resolved_path(:delete, paths) do |path, resolved_paths|
puts path
- @command.run!("/usr/bin/xargs", args: ["-0", "--", "/bin/rm", "-r", "-f", "--"], input: resolved_paths.join("\0"), sudo: true)
+ command.run!("/usr/bin/xargs", args: ["-0", "--", "/bin/rm", "-r", "-f", "--"], input: resolved_paths.join("\0"), sudo: true)
end
end
- def uninstall_trash(*paths)
+ def uninstall_trash(*paths, **options)
return if paths.empty?
resolved_paths = each_resolved_path(:trash, paths).to_a
ohai "Trashing files:"
puts resolved_paths.map(&:first)
- trash_paths(*resolved_paths.flat_map(&:last))
+ trash_paths(*resolved_paths.flat_map(&:last), **options)
end
- def trash_paths(*paths)
- @command.run!("/usr/bin/osascript", args: ["-e", <<-'EOS'.undent, *paths])
+ def trash_paths(*paths, command: nil, **_)
+ command.run!("/usr/bin/osascript", args: ["-e", <<-'EOS'.undent, *paths])
on run argv
repeat with i from 1 to (count argv)
set item i of argv to (item i of argv as POSIX file)
@@ -260,7 +277,7 @@ module Hbc
EOS
end
- def uninstall_rmdir(*directories)
+ def uninstall_rmdir(*directories, command: nil, **_)
return if directories.empty?
ohai "Removing directories if empty:"
@@ -268,10 +285,10 @@ module Hbc
puts path
resolved_paths.select(&:directory?).each do |resolved_path|
if (ds_store = resolved_path.join(".DS_Store")).exist?
- @command.run!("/bin/rm", args: ["-f", "--", ds_store], sudo: true, print_stderr: false)
+ command.run!("/bin/rm", args: ["-f", "--", ds_store], sudo: true, print_stderr: false)
end
- @command.run("/bin/rmdir", args: ["--", resolved_path], sudo: true, print_stderr: false)
+ command.run("/bin/rmdir", args: ["--", resolved_path], sudo: true, print_stderr: false)
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/artifact.rb b/Library/Homebrew/cask/lib/hbc/artifact/artifact.rb
index b42db877d..0f37afade 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/artifact.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/artifact.rb
@@ -5,21 +5,32 @@ require "hbc/utils/hash_validator"
module Hbc
module Artifact
class Artifact < Moved
- def self.artifact_english_name
+ def self.english_name
"Generic Artifact"
end
- def self.artifact_dirmethod
- :appdir
- end
+ def self.from_args(cask, *args)
+ source_string, target_hash = args
+
+ if source_string.nil?
+ raise CaskInvalidError.new(cask.token, "no source given for #{english_name}")
+ end
+
+ unless target_hash.is_a?(Hash)
+ raise CaskInvalidError.new(cask.token, "target required for #{english_name} '#{source_string}'")
+ end
- 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.extend(HashValidator).assert_valid_keys(:target)
- @target = Pathname.new(target_hash[:target])
+
+ new(cask, source_string, **target_hash)
+ end
+
+ def self.resolve_target(target)
+ Pathname(target)
+ end
+
+ def initialize(cask, source, target: nil)
+ super(cask, source, target: target)
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/binary.rb b/Library/Homebrew/cask/lib/hbc/artifact/binary.rb
index 7178c2af6..68f4b074d 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/binary.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/binary.rb
@@ -3,13 +3,13 @@ require "hbc/artifact/symlinked"
module Hbc
module Artifact
class Binary < Symlinked
- def link
- super
+ def link(command: nil, **options)
+ super(command: command, **options)
return if source.executable?
if source.writable?
FileUtils.chmod "+x", source
else
- @command.run!("/bin/chmod", args: ["+x", source], sudo: true)
+ command.run!("/bin/chmod", args: ["+x", source], sudo: true)
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/installer.rb b/Library/Homebrew/cask/lib/hbc/artifact/installer.rb
index be857696e..588bcabd5 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/installer.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/installer.rb
@@ -1,29 +1,82 @@
-require "hbc/artifact/base"
+require "hbc/artifact/abstract_artifact"
module Hbc
module Artifact
- class Installer < Base
- 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)}'
-
- EOS
- else
- executable, script_arguments = self.class.read_script_arguments(artifact.script,
- self.class.artifact_dsl_key.to_s,
- { must_succeed: true, sudo: false },
- 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)
+ class Installer < AbstractArtifact
+ VALID_KEYS = Set.new [
+ :manual,
+ :script,
+ ]
+
+ module ManualInstaller
+ def install_phase(**)
+ puts <<-EOS.undent
+ To complete the installation of Cask #{cask}, you must also
+ run the installer at
+
+ '#{path}'
+ EOS
+ end
+ end
+
+ module ScriptInstaller
+ def install_phase(command: nil, **_)
+ ohai "Running #{self.class.dsl_key} script '#{path.relative_path_from(cask.staged_path)}'"
+ FileUtils.chmod "+x", path unless path.executable?
+ command.run(path, **args)
+ end
+ end
+
+ def self.from_args(cask, **args)
+ raise CaskInvalidError.new(cask, "'installer' stanza requires an argument.") if args.empty?
+
+ if args.key?(:script) && !args[:script].respond_to?(:key?)
+ if args.key?(:executable)
+ raise CaskInvalidError.new(cask, "'installer' stanza gave arguments for both :script and :executable.")
end
+
+ args[:executable] = args[:script]
+ args.delete(:script)
+ args = { script: args }
+ end
+
+ unless args.keys.count == 1
+ raise CaskInvalidError.new(cask, "invalid 'installer' stanza: Only one of #{VALID_KEYS.inspect} is permitted.")
+ end
+
+ args.extend(HashValidator).assert_valid_keys(*VALID_KEYS)
+ new(cask, **args)
+ end
+
+ attr_reader :path, :args
+
+ def initialize(cask, **args)
+ super(cask)
+
+ if args.key?(:manual)
+ @path = cask.staged_path.join(args[:manual])
+ @args = []
+ extend(ManualInstaller)
+ return
+ end
+
+ path, @args = self.class.read_script_arguments(
+ args[:script], self.class.dsl_key.to_s, { must_succeed: true, sudo: false }, print_stdout: true
+ )
+ raise CaskInvalidError.new(cask, "#{self.class.dsl_key} missing executable") if path.nil?
+
+ path = Pathname(path)
+ @path = path.absolute? ? path : cask.staged_path.join(path)
+ extend(ScriptInstaller)
+ end
+
+ def summarize
+ path.relative_path_from(cask.staged_path).to_s
+ end
+
+ def to_h
+ { path: path.relative_path_from(cask.staged_path).to_s }.tap do |h|
+ h[:args] = args unless is_a?(ManualInstaller)
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/moved.rb b/Library/Homebrew/cask/lib/hbc/artifact/moved.rb
index 3fe969c0c..ba1c8e907 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/moved.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/moved.rb
@@ -4,63 +4,61 @@ module Hbc
module Artifact
class Moved < Relocated
def self.english_description
- "#{artifact_english_name}s"
+ "#{english_name}s"
end
- def install_phase
- each_artifact(&method(:move))
+ def install_phase(**options)
+ move(**options)
end
- def uninstall_phase
- each_artifact(&method(:delete))
+ def uninstall_phase(**options)
+ delete(**options)
+ end
+
+ def summarize_installed
+ if target.exist?
+ "#{printable_target} (#{target.abv})"
+ else
+ Formatter.error(printable_target, label: "Missing #{self.class.english_name}")
+ end
end
private
- def move
+ def move(force: false, command: nil, **options)
if Utils.path_occupied?(target)
- message = "It seems there is already #{self.class.artifact_english_article} #{self.class.artifact_english_name} at '#{target}'"
- raise CaskError, "#{message}." unless force?
+ message = "It seems there is already #{self.class.english_article} #{self.class.english_name} at '#{target}'"
+ raise CaskError, "#{message}." unless force
opoo "#{message}; overwriting."
- delete
+ delete(force: force, command: command, **options)
end
unless source.exist?
- raise CaskError, "It seems the #{self.class.artifact_english_name} source '#{source}' is not there."
+ raise CaskError, "It seems the #{self.class.english_name} source '#{source}' is not there."
end
- ohai "Moving #{self.class.artifact_english_name} '#{source.basename}' to '#{target}'."
+ ohai "Moving #{self.class.english_name} '#{source.basename}' to '#{target}'."
target.dirname.mkpath
if target.parent.writable?
FileUtils.move(source, target)
else
- SystemCommand.run("/bin/mv", args: [source, target], sudo: true)
+ command.run("/bin/mv", args: [source, target], sudo: true)
end
- add_altname_metadata target, source.basename.to_s
+ add_altname_metadata(target, source.basename, command: command)
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 delete(force: false, command: nil, **_)
+ ohai "Removing #{self.class.english_name} '#{target}'."
+ raise CaskError, "Cannot remove undeletable #{self.class.english_name}." if MacOS.undeletable?(target)
return unless Utils.path_occupied?(target)
if target.parent.writable? && !force
target.rmtree
else
- Utils.gain_permissions_remove(target, command: @command)
- end
- end
-
- def summarize_artifact(artifact_spec)
- load_specification artifact_spec
-
- if target.exist?
- "#{printable_target} (#{target.abv})"
- else
- Formatter.error(printable_target, label: "Missing #{self.class.artifact_english_name}")
+ Utils.gain_permissions_remove(target, command: command)
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 84253ea30..81adf9029 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/nested_container.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/nested_container.rb
@@ -1,23 +1,31 @@
-require "hbc/artifact/base"
+require "hbc/artifact/abstract_artifact"
module Hbc
module Artifact
- class NestedContainer < Base
- def install_phase
- @cask.artifacts[:nested_container].each { |container| extract(container) }
+ class NestedContainer < AbstractArtifact
+ attr_reader :path
+
+ def initialize(cask, path)
+ super(cask)
+ @path = cask.staged_path.join(path)
+ end
+
+ def install_phase(**options)
+ extract(**options)
end
- def extract(container_relative_path)
- source = @cask.staged_path.join(container_relative_path)
- container = Container.for_path(source, @command)
+ private
+
+ def extract(command: nil, verbose: nil, **_)
+ container = Container.for_path(path, command)
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, verbose: verbose?).extract
- FileUtils.remove_entry_secure(source)
+ ohai "Extracting nested container #{path.relative_path_from(cask.staged_path)}"
+ container.new(cask, path, command, verbose: verbose).extract
+ FileUtils.remove_entry_secure(path)
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/pkg.rb b/Library/Homebrew/cask/lib/hbc/artifact/pkg.rb
index be0a6be71..0967fd99d 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/pkg.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/pkg.rb
@@ -1,4 +1,4 @@
-require "hbc/artifact/base"
+require "hbc/artifact/abstract_artifact"
require "hbc/utils/hash_validator"
@@ -6,62 +6,57 @@ require "vendor/plist/plist"
module Hbc
module Artifact
- class Pkg < Base
+ class Pkg < AbstractArtifact
attr_reader :pkg_relative_path
- def self.artifact_dsl_key
- :pkg
+ def self.from_args(cask, path, **options)
+ options.extend(HashValidator).assert_valid_keys(:allow_untrusted, :choices)
+ new(cask, path, **options)
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.extend(HashValidator).assert_valid_keys(:allow_untrusted, :choices)
- elsif @pkg_install_opts
- raise
- end
- raise if pkg_description.nil?
- rescue StandardError
- raise CaskInvalidError.new(@cask, "Bad pkg stanza")
- end
+ attr_reader :path, :options
+
+ def initialize(cask, path, **options)
+ super(cask)
+ @path = cask.staged_path.join(path)
+ @options = options
end
- def pkg_install_opts(opt)
- @pkg_install_opts[opt] if @pkg_install_opts.respond_to?(:keys)
+ def summarize
+ path.relative_path_from(cask.staged_path).to_s
end
- def install_phase
- @cask.artifacts[:pkg].each { |pkg_description| run_installer(pkg_description) }
+ def install_phase(**options)
+ run_installer(**options)
end
- def run_installer(pkg_description)
- load_pkg_description pkg_description
- ohai "Running installer for #{@cask}; your password may be necessary."
+ private
+
+ def run_installer(command: nil, verbose: false, **options)
+ 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}'"
+ unless path.exist?
+ raise CaskError, "pkg source file not found: '#{path.relative_path_from(cask.staged_path)}'"
end
args = [
- "-pkg", source,
+ "-pkg", path,
"-target", "/"
]
- args << "-verboseR" if verbose?
- args << "-allowUntrusted" if pkg_install_opts :allow_untrusted
+ args << "-verboseR" if verbose
+ args << "-allowUntrusted" if options.fetch(:allow_untrusted, false)
with_choices_file do |choices_path|
args << "-applyChoiceChangesXML" << choices_path if choices_path
- @command.run!("/usr/sbin/installer", sudo: true, args: args, print_stdout: true)
+ command.run!("/usr/sbin/installer", sudo: true, args: args, print_stdout: true)
end
end
def with_choices_file
- return yield nil unless pkg_install_opts(:choices)
+ choices = options.fetch(:choices, {})
+ return yield nil if choices.empty?
Tempfile.open(["choices", ".xml"]) do |file|
begin
- file.write Plist::Emit.dump(pkg_install_opts(:choices))
+ file.write Plist::Emit.dump(choices)
file.close
yield file.path
ensure
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/prefpane.rb b/Library/Homebrew/cask/lib/hbc/artifact/prefpane.rb
index a44f8ae3a..87f120934 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/prefpane.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/prefpane.rb
@@ -3,7 +3,7 @@ require "hbc/artifact/moved"
module Hbc
module Artifact
class Prefpane < Moved
- def self.artifact_english_name
+ def self.english_name
"Preference Pane"
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/qlplugin.rb b/Library/Homebrew/cask/lib/hbc/artifact/qlplugin.rb
index ee41de2fe..298714d89 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/qlplugin.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/qlplugin.rb
@@ -3,22 +3,24 @@ require "hbc/artifact/moved"
module Hbc
module Artifact
class Qlplugin < Moved
- def self.artifact_english_name
+ def self.english_name
"QuickLook Plugin"
end
- def install_phase
- super
- reload_quicklook
+ def install_phase(**options)
+ super(**options)
+ reload_quicklook(**options)
end
- def uninstall_phase
- super
- reload_quicklook
+ def uninstall_phase(**options)
+ super(**options)
+ reload_quicklook(**options)
end
- def reload_quicklook
- @command.run!("/usr/bin/qlmanage", args: ["-r"])
+ private
+
+ def reload_quicklook(command: nil, **_)
+ command.run!("/usr/bin/qlmanage", args: ["-r"])
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/relocated.rb b/Library/Homebrew/cask/lib/hbc/artifact/relocated.rb
index 4dba46c9d..540699630 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/relocated.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/relocated.rb
@@ -1,65 +1,79 @@
-require "hbc/artifact/base"
+require "hbc/artifact/abstract_artifact"
require "hbc/utils/hash_validator"
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,
- }
+ class Relocated < AbstractArtifact
+ def self.from_args(cask, *args)
+ source_string, target_hash = args
+
+ if target_hash
+ raise CaskInvalidError unless target_hash.respond_to?(:keys)
+ target_hash.extend(HashValidator).assert_valid_keys(:target)
+ end
+
+ target_hash ||= {}
+
+ new(cask, source_string, **target_hash)
+ end
+
+ def self.resolve_target(target)
+ Hbc.public_send(dirmethod).join(target)
end
attr_reader :source, :target
- def printable_target
- target.to_s.sub(/^#{ENV['HOME']}(#{File::SEPARATOR}|$)/, "~/")
+ def initialize(cask, source, target: nil)
+ super(cask)
+
+ @source_string = source.to_s
+ @target_string = target.to_s
+ source = cask.staged_path.join(source)
+ @source = source
+ target ||= source.basename
+ @target = self.class.resolve_target(target)
end
+ def to_a
+ [@source_string].tap do |ary|
+ ary << { target: @target_string } unless @target_string.empty?
+ end
+ end
+
+ def summarize
+ target_string = @target_string.empty? ? "" : " -> #{@target_string}"
+ "#{@source_string}#{target_string}"
+ end
+
+ private
+
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?
+ def add_altname_metadata(file, altname, command: nil)
+ return if altname.to_s.casecmp(file.basename.to_s).zero?
odebug "Adding #{ALT_NAME_ATTRIBUTE} metadata"
- altnames = @command.run("/usr/bin/xattr",
- args: ["-p", ALT_NAME_ATTRIBUTE, file.to_s],
+ altnames = command.run("/usr/bin/xattr",
+ args: ["-p", ALT_NAME_ATTRIBUTE, file],
print_stderr: false).stdout.sub(/\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+rw", file, file.realpath])
+ # Some packages are shipped as u=rx (e.g. Bitcoin Core)
+ command.run!("/bin/chmod", args: ["--", "u+rw", file, file.realpath])
- @command.run!("/usr/bin/xattr",
+ command.run!("/usr/bin/xattr",
args: ["-w", ALT_NAME_ATTRIBUTE, altnames, file],
print_stderr: false)
end
- def each_artifact
- @cask.artifacts[self.class.artifact_dsl_key].each do |artifact|
- load_specification(artifact)
- yield
- end
- 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.extend(HashValidator).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
+ def printable_target
+ target.to_s.sub(/^#{ENV['HOME']}(#{File::SEPARATOR}|$)/, "~/")
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 1122c1d02..8c32a52d0 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/stage_only.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/stage_only.rb
@@ -1,10 +1,22 @@
-require "hbc/artifact/base"
+require "hbc/artifact/abstract_artifact"
module Hbc
module Artifact
- class StageOnly < Base
- def self.artifact_dsl_key
- :stage_only
+ class StageOnly < AbstractArtifact
+ def self.from_args(cask, *args)
+ if args != [true]
+ raise CaskInvalidError.new(cask.token, "'stage_only' takes only a single argument: true")
+ end
+
+ new(cask)
+ end
+
+ def initialize(cask)
+ super(cask)
+ end
+
+ def to_a
+ [true]
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/suite.rb b/Library/Homebrew/cask/lib/hbc/artifact/suite.rb
index 35251f70c..59ae58cf1 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/suite.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/suite.rb
@@ -3,11 +3,11 @@ require "hbc/artifact/moved"
module Hbc
module Artifact
class Suite < Moved
- def self.artifact_english_name
+ def self.english_name
"App Suite"
end
- def self.artifact_dirmethod
+ def self.dirmethod
:appdir
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/symlinked.rb b/Library/Homebrew/cask/lib/hbc/artifact/symlinked.rb
index 16715fe81..3726ebb5c 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/symlinked.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/symlinked.rb
@@ -8,58 +8,56 @@ module Hbc
end
def self.english_description
- "#{artifact_english_name} #{link_type_english_name}s"
+ "#{english_name} #{link_type_english_name}s"
end
- def install_phase
- each_artifact(&method(:link))
+ def install_phase(**options)
+ link(**options)
end
- def uninstall_phase
- each_artifact(&method(:unlink))
+ def uninstall_phase(**options)
+ unlink(**options)
+ end
+
+ def summarize_installed
+ if target.symlink? && target.exist? && target.readlink.exist?
+ "#{printable_target} -> #{target.readlink} (#{target.readlink.abv})"
+ else
+ string = if target.symlink?
+ "#{printable_target} -> #{target.readlink}"
+ else
+ printable_target
+ end
+
+ Formatter.error(string, label: "Broken Link")
+ end
end
private
- def link
+ def link(**options)
unless source.exist?
raise CaskError, "It seems the #{self.class.link_type_english_name.downcase} source '#{source}' is not there."
end
if target.exist? && !target.symlink?
- raise CaskError, "It seems there is already #{self.class.artifact_english_article} #{self.class.artifact_english_name} at '#{target}'; not linking."
+ raise CaskError, "It seems there is already #{self.class.english_article} #{self.class.english_name} at '#{target}'; not linking."
end
- ohai "Linking #{self.class.artifact_english_name} '#{source.basename}' to '#{target}'."
- create_filesystem_link(source, target)
+ ohai "Linking #{self.class.english_name} '#{source.basename}' to '#{target}'."
+ create_filesystem_link(**options)
end
- def unlink
+ def unlink(**)
return unless target.symlink?
- ohai "Unlinking #{self.class.artifact_english_name} '#{target}'."
+ ohai "Unlinking #{self.class.english_name} '#{target}'."
target.delete
end
- def create_filesystem_link(source, target)
+ def create_filesystem_link(command: nil, **_)
target.dirname.mkpath
- @command.run!("/bin/ln", args: ["-h", "-f", "-s", "--", source, target])
- add_altname_metadata source, target.basename.to_s
- end
-
- def summarize_artifact(artifact_spec)
- load_specification artifact_spec
-
- if target.symlink? && target.exist? && target.readlink.exist?
- "#{printable_target} -> #{target.readlink} (#{target.readlink.abv})"
- else
- string = if target.symlink?
- "#{printable_target} -> #{target.readlink}"
- else
- printable_target
- end
-
- Formatter.error(string, label: "Broken Link")
- end
+ command.run!("/bin/ln", args: ["-h", "-f", "-s", "--", source, target])
+ add_altname_metadata(source, target.basename, command: command)
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/uninstall.rb b/Library/Homebrew/cask/lib/hbc/artifact/uninstall.rb
index 5a3dc098d..2bbf82862 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/uninstall.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/uninstall.rb
@@ -1,10 +1,10 @@
-require "hbc/artifact/uninstall_base"
+require "hbc/artifact/abstract_uninstall"
module Hbc
module Artifact
- class Uninstall < UninstallBase
- def uninstall_phase
- dispatch_uninstall_directives
+ class Uninstall < AbstractUninstall
+ def uninstall_phase(**options)
+ dispatch_uninstall_directives(**options)
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/zap.rb b/Library/Homebrew/cask/lib/hbc/artifact/zap.rb
index cdfe2531d..31ff54d20 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/zap.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/zap.rb
@@ -1,10 +1,10 @@
-require "hbc/artifact/uninstall_base"
+require "hbc/artifact/abstract_uninstall"
module Hbc
module Artifact
- class Zap < UninstallBase
- def zap_phase
- dispatch_uninstall_directives
+ class Zap < AbstractUninstall
+ def zap_phase(**options)
+ dispatch_uninstall_directives(**options)
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/audit.rb b/Library/Homebrew/cask/lib/hbc/audit.rb
index b8bb6ab81..03d8cce82 100644
--- a/Library/Homebrew/cask/lib/hbc/audit.rb
+++ b/Library/Homebrew/cask/lib/hbc/audit.rb
@@ -214,12 +214,10 @@ module Hbc
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
+ cask.artifacts[:artifact].each do |artifact|
+ unless artifact.target.absolute?
+ add_error "target must be absolute path for #{artifact.class.english_name} #{artifact.source}"
end
- add_error "target must be absolute path for generic artifact #{source}" unless Pathname.new(target_hash[:target]).absolute?
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/cask.rb b/Library/Homebrew/cask/lib/hbc/cask.rb
index 6d89a997c..72a23066f 100644
--- a/Library/Homebrew/cask/lib/hbc/cask.rb
+++ b/Library/Homebrew/cask/lib/hbc/cask.rb
@@ -17,7 +17,7 @@ module Hbc
@token = token
@sourcefile_path = sourcefile_path
@tap = tap
- @dsl = DSL.new(@token)
+ @dsl = DSL.new(self)
return unless block_given?
@dsl.instance_eval(&block)
@dsl.language_eval
@@ -41,6 +41,14 @@ module Hbc
.reverse
end
+ def full_name
+ if @tap.nil? || @tap == Hbc.default_tap
+ token
+ else
+ "#{@tap}/#{token}"
+ end
+ end
+
def installed?
!versions.empty?
end
diff --git a/Library/Homebrew/cask/lib/hbc/cask_loader.rb b/Library/Homebrew/cask/lib/hbc/cask_loader.rb
index dd9c61089..8fce9636a 100644
--- a/Library/Homebrew/cask/lib/hbc/cask_loader.rb
+++ b/Library/Homebrew/cask/lib/hbc/cask_loader.rb
@@ -56,7 +56,7 @@ module Hbc
class FromURILoader < FromPathLoader
def self.can_load?(ref)
- ref.to_s.match?(::URI.regexp)
+ ref.to_s.match?(::URI::DEFAULT_PARSER.make_regexp)
end
attr_reader :url
@@ -116,6 +116,22 @@ module Hbc
end
end
+ class FromInstanceLoader
+ attr_reader :cask
+
+ def self.can_load?(ref)
+ ref.is_a?(Cask)
+ end
+
+ def initialize(cask)
+ @cask = cask
+ end
+
+ def load
+ cask
+ end
+ end
+
class NullLoader < FromPathLoader
def self.can_load?(*)
true
@@ -149,6 +165,7 @@ module Hbc
def self.for(ref)
[
+ FromInstanceLoader,
FromURILoader,
FromTapLoader,
FromTapPathLoader,
diff --git a/Library/Homebrew/cask/lib/hbc/cli/abstract_command.rb b/Library/Homebrew/cask/lib/hbc/cli/abstract_command.rb
index 77f85301e..001a9623b 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/abstract_command.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/abstract_command.rb
@@ -42,41 +42,32 @@ module Hbc
@args = process_arguments(*args)
end
- def self.warn_unavailable_with_suggestion(cask_token, e)
- exact_match, partial_matches = Search.search(cask_token)
- error_message = e.message
- if exact_match
- error_message.concat(" Did you mean:\n#{exact_match}")
- elsif !partial_matches.empty?
- error_message.concat(" Did you mean one of:\n")
- .concat(Formatter.columns(partial_matches.take(20)))
- end
- onoe error_message
- end
-
private
def casks(alternative: -> { [] })
- return to_enum(:casks, alternative: alternative) unless block_given?
-
- count = 0
-
+ return @casks if defined?(@casks)
casks = args.empty? ? alternative.call : args
+ @casks = casks.map { |cask| CaskLoader.load(cask) }
+ rescue CaskUnavailableError => e
+ reason = [e.reason, suggestion_message(e.token)].join(" ")
+ raise e.class.new(e.token, reason)
+ end
+
+ def suggestion_message(cask_token)
+ exact_match, partial_matches = Search.search(cask_token)
- casks.each do |cask_or_token|
- begin
- yield cask_or_token.respond_to?(:token) ? cask_or_token : CaskLoader.load(cask_or_token)
- count += 1
- rescue CaskUnavailableError => e
- cask_token = cask_or_token
- self.class.warn_unavailable_with_suggestion cask_token, e
- rescue CaskError => e
- onoe e.message
- end
+ if exact_match.nil? && partial_matches.count == 1
+ exact_match = partial_matches.first
end
- return :empty if casks.length.zero?
- (count == casks.length) ? :complete : :incomplete
+ if exact_match
+ "Did you mean “#{exact_match}”?"
+ elsif !partial_matches.empty?
+ "Did you mean one of these?\n"
+ .concat(Formatter.columns(partial_matches.take(20)))
+ else
+ ""
+ 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 d08c87bea..043080556 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/cat.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/cat.rb
@@ -7,10 +7,6 @@ module Hbc
end
def run
- raise CaskError, "Cat incomplete." if cat_casks == :incomplete
- end
-
- def cat_casks
casks.each do |cask|
puts File.open(cask.sourcefile_path, &:read)
end
diff --git a/Library/Homebrew/cask/lib/hbc/cli/edit.rb b/Library/Homebrew/cask/lib/hbc/cli/edit.rb
index b9485886c..8bce81c52 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/edit.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/edit.rb
@@ -4,21 +4,18 @@ module Hbc
def initialize(*)
super
raise CaskUnspecifiedError if args.empty?
- raise ArgumentError, "Only one Cask can be created at a time." if args.count > 1
+ raise ArgumentError, "Only one Cask can be edited at a time." if args.count > 1
end
def run
- cask_token = args.first
- cask_path = begin
- CaskLoader.load(cask_token).sourcefile_path
- rescue CaskUnavailableError => e
- reason = e.reason.empty? ? "" : "#{e.reason} "
- reason.concat("Run #{Formatter.identifier("brew cask create #{e.token}")} to create a new Cask.")
- raise e.class.new(e.token, reason)
- end
-
- odebug "Opening editor for Cask #{cask_token}"
+ cask = casks.first
+ cask_path = cask.sourcefile_path
+ odebug "Opening editor for Cask #{cask.token}"
exec_editor cask_path
+ rescue CaskUnavailableError => e
+ reason = e.reason.empty? ? "" : "#{e.reason} "
+ reason.concat("Run #{Formatter.identifier("brew cask create #{e.token}")} to create a new Cask.")
+ raise e.class.new(e.token, reason)
end
def self.help
diff --git a/Library/Homebrew/cask/lib/hbc/cli/fetch.rb b/Library/Homebrew/cask/lib/hbc/cli/fetch.rb
index e31b1a17c..12c794f5f 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/fetch.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/fetch.rb
@@ -9,10 +9,6 @@ module Hbc
end
def run
- raise CaskError, "Fetch incomplete." if fetch_casks == :incomplete
- end
-
- def fetch_casks
casks.each do |cask|
ohai "Downloading external files for Cask #{cask}"
downloaded_path = Download.new(cask, force: force?).perform
diff --git a/Library/Homebrew/cask/lib/hbc/cli/info.rb b/Library/Homebrew/cask/lib/hbc/cli/info.rb
index d26747e17..9cdada62e 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/info.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/info.rb
@@ -69,13 +69,11 @@ module Hbc
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
+ DSL::ORDINARY_ARTIFACT_CLASSES.flat_map { |klass| klass.for_cask(cask) }
+ .select { |artifact| artifact.respond_to?(:install_phase) }
+ .each do |artifact|
+ puts artifact.to_s
+ 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 0f1a5dd34..9a2116e6a 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/install.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/install.rb
@@ -10,10 +10,6 @@ module Hbc
end
def run
- raise CaskError, "Install incomplete." if install_casks == :incomplete
- end
-
- def install_casks
casks.each do |cask|
begin
Installer.new(cask, binaries: binaries?,
diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb
index cd2679782..a538ffd8c 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/internal_appcast_checkpoint.rb
@@ -12,7 +12,7 @@ module Hbc
if args.all? { |t| t =~ %r{^https?://} && t !~ /\.rb$/ }
self.class.appcask_checkpoint_for_url(args)
else
- self.class.appcask_checkpoint(args, calculate?)
+ self.class.appcask_checkpoint(casks, calculate?)
end
end
@@ -23,33 +23,27 @@ module Hbc
end
end
- def self.appcask_checkpoint(cask_tokens, calculate)
- count = 0
-
- cask_tokens.each do |cask_token|
- cask = CaskLoader.load(cask_token)
-
+ def self.appcask_checkpoint(casks, calculate)
+ casks.each do |cask|
if cask.appcast.nil?
opoo "Cask '#{cask}' is missing an `appcast` stanza."
else
- if calculate
+ checkpoint = if calculate
result = cask.appcast.calculate_checkpoint
-
- checkpoint = result[:checkpoint]
+ result[:checkpoint]
else
- checkpoint = cask.appcast.checkpoint
+ cask.appcast.checkpoint
end
- if checkpoint.nil?
+ if calculate && checkpoint.nil?
onoe "Could not retrieve `appcast` checkpoint for cask '#{cask}': #{result[:command_result].stderr}"
+ elsif casks.count > 1
+ puts "#{checkpoint} #{cask}"
else
- puts((cask_tokens.count > 1) ? "#{checkpoint} #{cask}" : checkpoint)
- count += 1
+ puts checkpoint
end
end
end
-
- count == cask_tokens.count
end
def self.help
diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_dump.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_dump.rb
index e21ce86b6..8a38ce1be 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/internal_dump.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/internal_dump.rb
@@ -7,10 +7,6 @@ module Hbc
end
def run
- raise CaskError, "Dump incomplete." if dump_casks == :incomplet
- end
-
- def dump_casks
casks.each(&:dumpcask)
end
diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb
index 4515fe931..c04619798 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb
@@ -3,7 +3,7 @@ module Hbc
class InternalStanza < AbstractInternalCommand
# Syntax
#
- # brew cask _stanza <stanza_name> [ --table | --yaml | --inspect | --quiet ] [ <cask_token> ... ]
+ # brew cask _stanza <stanza_name> [ --quiet ] [ --table | --yaml ] [ <cask_token> ... ]
#
# If no tokens are given, then data for all Casks is returned.
#
@@ -14,41 +14,16 @@ module Hbc
# 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
+ # brew cask _stanza app --table alfred google-chrome adium vagrant
+ # brew cask _stanza url --table alfred google-chrome adium vagrant
+ # brew cask _stanza version --table alfred google-chrome adium vagrant
+ # brew cask _stanza artifacts --table alfred google-chrome adium vagrant
+ # brew cask _stanza artifacts --table --yaml alfred google-chrome adium vagrant
#
- # TODO: this should be retrievable from Hbc::DSL
- ARTIFACTS = Set.new [
- :app,
- :suite,
- :artifact,
- :prefpane,
- :qlplugin,
- :dictionary,
- :font,
- :service,
- :colorpicker,
- :binary,
- :input_method,
- :internet_plugin,
- :audio_unit_plugin,
- :vst_plugin,
- :vst3_plugin,
- :screen_saver,
- :pkg,
- :installer,
- :stage_only,
- :nested_container,
- :uninstall,
- :preflight,
- :postflight,
- :uninstall_preflight,
- :uninstall_postflight,
- ]
+ ARTIFACTS =
+ DSL::ORDINARY_ARTIFACT_CLASSES.map(&:dsl_key) +
+ DSL::ARTIFACT_BLOCK_CLASSES.map(&:dsl_key)
option "--table", :table, false
option "--quiet", :quiet, false
@@ -68,16 +43,9 @@ module Hbc
@stanza = args.shift.to_sym
@format = :to_yaml if yaml?
- @format = :inspect if inspect?
end
def run
- return unless print_stanzas == :incomplete
- exit 1 if quiet?
- raise CaskError, "Print incomplete."
- end
-
- def print_stanzas
if ARTIFACTS.include?(stanza)
artifact_name = stanza
@stanza = :artifacts
@@ -93,7 +61,7 @@ module Hbc
end
begin
- value = cask.send(@stanza)
+ value = cask.send(stanza)
rescue StandardError
opoo "failure calling '#{stanza}' on Cask '#{cask}'" unless quiet?
puts ""
@@ -106,11 +74,25 @@ module Hbc
next
end
- value = value.fetch(artifact_name).to_a.flatten if artifact_name
+ if stanza == :artifacts
+ value = Hash[
+ value.map do |k, v|
+ v = v.map do |a|
+ next a.to_a if a.respond_to?(:to_a)
+ next a.to_h if a.respond_to?(:to_h)
+ a
+ end
+
+ [k, v]
+ end
+ ]
+
+ value = value.fetch(artifact_name) if artifact_name
+ end
- if @format
- puts value.send(@format)
- elsif artifact_name || value.is_a?(Symbol)
+ if format
+ puts value.send(format)
+ elsif value.is_a?(Symbol)
puts value.inspect
else
puts value.to_s
diff --git a/Library/Homebrew/cask/lib/hbc/cli/list.rb b/Library/Homebrew/cask/lib/hbc/cli/list.rb
index 9d978360e..32415af8a 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/list.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/list.rb
@@ -3,6 +3,7 @@ module Hbc
class List < AbstractCommand
option "-1", :one, false
option "--versions", :versions, false
+ option "--full-name", :full_name, false
option "-l", (lambda do |*|
one = true # rubocop:disable Lint/UselessAssignment
@@ -10,8 +11,7 @@ module Hbc
end)
def run
- retval = args.any? ? list : list_installed
- raise CaskError, "Listing incomplete." if retval == :incomplete
+ args.any? ? list : list_installed
end
def list
@@ -30,9 +30,9 @@ module Hbc
end
def self.list_artifacts(cask)
- Artifact.for_cask(cask).each do |artifact|
- summary = artifact.summary
- ohai summary[:english_description], summary[:contents] unless summary.empty?
+ Artifact.for_cask(cask).group_by(&:class).each do |klass, artifacts|
+ next unless klass.respond_to?(:english_description)
+ ohai klass.english_description, artifacts.map(&:summarize_installed)
end
end
@@ -43,11 +43,11 @@ module Hbc
puts installed_casks.map(&:to_s)
elsif versions?
puts installed_casks.map(&self.class.method(:format_versioned))
+ elsif full_name?
+ puts installed_casks.map(&:full_name).sort &tap_and_name_comparison
elsif !installed_casks.empty?
puts Formatter.columns(installed_casks.map(&:to_s))
end
-
- installed_casks.empty? ? :empty : :complete
end
def self.format_versioned(cask)
diff --git a/Library/Homebrew/cask/lib/hbc/cli/reinstall.rb b/Library/Homebrew/cask/lib/hbc/cli/reinstall.rb
index 337a2eb9d..408be134d 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/reinstall.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/reinstall.rb
@@ -1,7 +1,7 @@
module Hbc
class CLI
class Reinstall < Install
- def install_casks
+ def run
casks.each do |cask|
Installer.new(cask, binaries: binaries?,
verbose: verbose?,
diff --git a/Library/Homebrew/cask/lib/hbc/cli/search.rb b/Library/Homebrew/cask/lib/hbc/cli/search.rb
index e89dced92..d56d0c81f 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/search.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/search.rb
@@ -2,8 +2,12 @@ module Hbc
class CLI
class Search < AbstractCommand
def run
- results = self.class.search(*args)
- self.class.render_results(*results)
+ if args.empty?
+ puts Formatter.columns(CLI.nice_listing(Hbc.all_tokens))
+ else
+ results = self.class.search(*args)
+ self.class.render_results(*results)
+ end
end
def self.extract_regexp(string)
@@ -15,8 +19,17 @@ module Hbc
end
def self.search_remote(query)
- matches = GitHub.search_code(user: "caskroom", path: "Casks",
- filename: query, extension: "rb")
+ matches = begin
+ GitHub.search_code(
+ user: "caskroom",
+ path: "Casks",
+ filename: query,
+ extension: "rb",
+ )
+ rescue GitHub::Error => error
+ opoo "Error searching on GitHub: #{error}\n"
+ []
+ end
matches.map do |match|
tap = Tap.fetch(match["repository"]["full_name"])
next if tap.installed?
diff --git a/Library/Homebrew/cask/lib/hbc/cli/uninstall.rb b/Library/Homebrew/cask/lib/hbc/cli/uninstall.rb
index c0697c808..7e55db5f1 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/uninstall.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/uninstall.rb
@@ -9,10 +9,6 @@ module Hbc
end
def run
- raise CaskError, "Uninstall incomplete." if uninstall_casks == :incomplete
- end
-
- def uninstall_casks
casks.each do |cask|
odebug "Uninstalling Cask #{cask}"
diff --git a/Library/Homebrew/cask/lib/hbc/cli/zap.rb b/Library/Homebrew/cask/lib/hbc/cli/zap.rb
index e709f4191..7f5e6785d 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/zap.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/zap.rb
@@ -9,10 +9,6 @@ module Hbc
end
def run
- raise CaskError, "Zap incomplete." if zap_casks == :incomplete
- end
-
- def zap_casks
casks.each do |cask|
odebug "Zapping Cask #{cask}"
Installer.new(cask, verbose: verbose?, force: force?).zap
diff --git a/Library/Homebrew/cask/lib/hbc/container/naked.rb b/Library/Homebrew/cask/lib/hbc/container/naked.rb
index 375d62f7a..dc265c402 100644
--- a/Library/Homebrew/cask/lib/hbc/container/naked.rb
+++ b/Library/Homebrew/cask/lib/hbc/container/naked.rb
@@ -16,7 +16,7 @@ module Hbc
def target_file
return @path.basename if @nested
- URI.decode(File.basename(@cask.url.path))
+ CGI.unescape(File.basename(@cask.url.path))
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/dsl.rb b/Library/Homebrew/cask/lib/hbc/dsl.rb
index 8ad206c2f..3824b9761 100644
--- a/Library/Homebrew/cask/lib/hbc/dsl.rb
+++ b/Library/Homebrew/cask/lib/hbc/dsl.rb
@@ -1,6 +1,8 @@
require "set"
require "locale"
+require "hbc/artifact"
+
require "hbc/dsl/appcast"
require "hbc/dsl/base"
require "hbc/dsl/caveats"
@@ -8,7 +10,6 @@ require "hbc/dsl/conflicts_with"
require "hbc/dsl/container"
require "hbc/dsl/depends_on"
require "hbc/dsl/gpg"
-require "hbc/dsl/installer"
require "hbc/dsl/postflight"
require "hbc/dsl/preflight"
require "hbc/dsl/stanza_proxy"
@@ -18,39 +19,35 @@ require "hbc/dsl/version"
module Hbc
class DSL
- ORDINARY_ARTIFACT_TYPES = [
- :app,
- :artifact,
- :audio_unit_plugin,
- :binary,
- :colorpicker,
- :dictionary,
- :font,
- :input_method,
- :internet_plugin,
- :pkg,
- :prefpane,
- :qlplugin,
- :screen_saver,
- :service,
- :stage_only,
- :suite,
- :vst_plugin,
- :vst3_plugin,
+ ORDINARY_ARTIFACT_CLASSES = [
+ Artifact::Installer,
+ Artifact::App,
+ Artifact::Artifact,
+ Artifact::AudioUnitPlugin,
+ Artifact::Binary,
+ Artifact::Colorpicker,
+ Artifact::Dictionary,
+ Artifact::Font,
+ Artifact::InputMethod,
+ Artifact::InternetPlugin,
+ Artifact::Pkg,
+ Artifact::Prefpane,
+ Artifact::Qlplugin,
+ Artifact::ScreenSaver,
+ Artifact::Service,
+ Artifact::StageOnly,
+ Artifact::Suite,
+ Artifact::VstPlugin,
+ Artifact::Vst3Plugin,
+ Artifact::Uninstall,
+ Artifact::Zap,
].freeze
- ACTIVATABLE_ARTIFACT_TYPES = ([:installer, *ORDINARY_ARTIFACT_TYPES] - [:stage_only]).freeze
-
- SPECIAL_ARTIFACT_TYPES = [
- :uninstall,
- :zap,
- ].freeze
+ ACTIVATABLE_ARTIFACT_TYPES = (ORDINARY_ARTIFACT_CLASSES.map(&:dsl_key) - [:stage_only]).freeze
- ARTIFACT_BLOCK_TYPES = [
- :preflight,
- :postflight,
- :uninstall_preflight,
- :uninstall_postflight,
+ ARTIFACT_BLOCK_CLASSES = [
+ Artifact::PreflightBlock,
+ Artifact::PostflightBlock,
].freeze
DSL_METHODS = Set.new [
@@ -72,15 +69,15 @@ module Hbc
:url,
:version,
:appdir,
- *ORDINARY_ARTIFACT_TYPES,
+ *ORDINARY_ARTIFACT_CLASSES.map(&:dsl_key),
*ACTIVATABLE_ARTIFACT_TYPES,
- *SPECIAL_ARTIFACT_TYPES,
- *ARTIFACT_BLOCK_TYPES,
+ *ARTIFACT_BLOCK_CLASSES.flat_map { |klass| [klass.dsl_key, klass.uninstall_dsl_key] },
].freeze
- attr_reader :token
- def initialize(token)
- @token = token
+ attr_reader :token, :cask
+ def initialize(cask)
+ @cask = cask
+ @token = cask.token
end
def name(*args)
@@ -93,12 +90,14 @@ module Hbc
return instance_variable_get("@#{stanza}") if should_return
if instance_variable_defined?("@#{stanza}")
- raise CaskInvalidError.new(token, "'#{stanza}' stanza may only appear once")
+ raise CaskInvalidError.new(cask, "'#{stanza}' stanza may only appear once.")
end
instance_variable_set("@#{stanza}", yield)
+ rescue CaskInvalidError
+ raise
rescue StandardError => e
- raise CaskInvalidError.new(token, "'#{stanza}' stanza failed with: #{e}")
+ raise CaskInvalidError.new(cask, "'#{stanza}' stanza failed with: #{e}")
end
def homepage(homepage = nil)
@@ -113,7 +112,7 @@ module Hbc
return unless default
unless @language_blocks.default.nil?
- raise CaskInvalidError.new(token, "Only one default language may be defined")
+ raise CaskInvalidError.new(cask, "Only one default language may be defined.")
end
@language_blocks.default = block
@@ -162,8 +161,8 @@ module Hbc
begin
DSL::Container.new(*args).tap do |container|
# TODO: remove this backward-compatibility section after removing nested_container
- if container && container.nested
- artifacts[:nested_container] << container.nested
+ if container&.nested
+ artifacts[:nested_container] << Artifact::NestedContainer.new(cask, container.nested)
end
end
end
@@ -173,7 +172,7 @@ module Hbc
def version(arg = nil)
set_unique_stanza(:version, arg.nil?) do
if !arg.is_a?(String) && arg != :latest
- raise CaskInvalidError.new(token, "invalid 'version' value: '#{arg.inspect}'")
+ raise CaskInvalidError.new(cask, "invalid 'version' value: '#{arg.inspect}'")
end
DSL::Version.new(arg)
end
@@ -182,7 +181,7 @@ module Hbc
def sha256(arg = nil)
set_unique_stanza(:sha256, arg.nil?) do
if !arg.is_a?(String) && arg != :no_check
- raise CaskInvalidError.new(token, "invalid 'sha256' value: '#{arg.inspect}'")
+ raise CaskInvalidError.new(cask, "invalid 'sha256' value: '#{arg.inspect}'")
end
arg
end
@@ -195,7 +194,7 @@ module Hbc
begin
@depends_on.load(*args)
rescue RuntimeError => e
- raise CaskInvalidError.new(token, e)
+ raise CaskInvalidError.new(cask, e)
end
@depends_on
end
@@ -237,39 +236,29 @@ module Hbc
set_unique_stanza(:auto_updates, auto_updates.nil?) { auto_updates }
end
- ORDINARY_ARTIFACT_TYPES.each do |type|
+ ORDINARY_ARTIFACT_CLASSES.each do |klass|
+ type = klass.dsl_key
+
define_method(type) do |*args|
- if type == :stage_only
- if args != [true]
- raise CaskInvalidError.new(token, "'stage_only' takes a single argument: true")
+ begin
+ if [*artifacts.keys, type].include?(:stage_only) && (artifacts.keys & ACTIVATABLE_ARTIFACT_TYPES).any?
+ raise CaskInvalidError.new(cask, "'stage_only' must be the only activatable artifact.")
end
- unless (artifacts.keys & ACTIVATABLE_ARTIFACT_TYPES).empty?
- raise CaskInvalidError.new(token, "'stage_only' must be the only activatable artifact")
- end
+ artifacts[type].add(klass.from_args(cask, *args))
+ rescue CaskInvalidError
+ raise
+ rescue StandardError => e
+ raise CaskInvalidError.new(cask, "invalid '#{klass.dsl_key}' stanza: #{e}")
end
-
- artifacts[type].add(args)
end
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)
- end
- end
-
- ARTIFACT_BLOCK_TYPES.each do |type|
- define_method(type) do |&block|
- artifacts[type] << block
+ ARTIFACT_BLOCK_CLASSES.each do |klass|
+ [klass.dsl_key, klass.uninstall_dsl_key].each do |dsl_key|
+ define_method(dsl_key) do |&block|
+ artifacts[dsl_key] << block
+ end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/dsl/installer.rb b/Library/Homebrew/cask/lib/hbc/dsl/installer.rb
deleted file mode 100644
index b01b28d76..000000000
--- a/Library/Homebrew/cask/lib/hbc/dsl/installer.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-module Hbc
- class DSL
- class Installer
- VALID_KEYS = Set.new [
- :manual,
- :script,
- ]
-
- attr_accessor(*VALID_KEYS)
-
- 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
- end
- end
-end
diff --git a/Library/Homebrew/cask/lib/hbc/dsl/version.rb b/Library/Homebrew/cask/lib/hbc/dsl/version.rb
index d73205f52..9605feb57 100644
--- a/Library/Homebrew/cask/lib/hbc/dsl/version.rb
+++ b/Library/Homebrew/cask/lib/hbc/dsl/version.rb
@@ -49,7 +49,7 @@ module Hbc
end
end
- DIVIDERS.keys.each do |divider|
+ DIVIDERS.each_key do |divider|
define_divider_methods(divider)
end
diff --git a/Library/Homebrew/cask/lib/hbc/installer.rb b/Library/Homebrew/cask/lib/hbc/installer.rb
index 37cc4e561..01aae935d 100644
--- a/Library/Homebrew/cask/lib/hbc/installer.rb
+++ b/Library/Homebrew/cask/lib/hbc/installer.rb
@@ -159,7 +159,7 @@ module Hbc
odebug "Extracting primary container"
FileUtils.mkdir_p @cask.staged_path
- container = if @cask.container && @cask.container.type
+ container = if @cask.container&.type
Container.from_type(@cask.container.type)
else
Container.for_path(@downloaded_path, @command)
@@ -177,7 +177,7 @@ module Hbc
already_installed_artifacts = []
odebug "Installing artifacts"
- artifacts = Artifact.for_cask(@cask, command: @command, verbose: verbose?, force: force?)
+ artifacts = Artifact.for_cask(@cask)
odebug "#{artifacts.length} artifact/s defined", artifacts
artifacts.each do |artifact|
@@ -188,7 +188,7 @@ module Hbc
next unless binaries?
end
- artifact.install_phase
+ artifact.install_phase(command: @command, verbose: verbose?, force: force?)
already_installed_artifacts.unshift(artifact)
end
rescue StandardError => e
@@ -196,7 +196,7 @@ module Hbc
already_installed_artifacts.each do |artifact|
next unless artifact.respond_to?(:uninstall_phase)
odebug "Reverting installation of artifact of class #{artifact.class}"
- artifact.uninstall_phase
+ artifact.uninstall_phase(command: @command, verbose: verbose?, force: force?)
end
ensure
purge_versioned_files
@@ -361,7 +361,7 @@ module Hbc
savedir = @cask.metadata_subdir("Casks", timestamp: :now, create: true)
FileUtils.copy @cask.sourcefile_path, savedir
- old_savedir.rmtree unless old_savedir.nil?
+ old_savedir&.rmtree
end
def uninstall
@@ -374,25 +374,27 @@ module Hbc
def uninstall_artifacts
odebug "Un-installing artifacts"
- artifacts = Artifact.for_cask(@cask, command: @command, verbose: verbose?, force: force?)
+ artifacts = Artifact.for_cask(@cask)
odebug "#{artifacts.length} artifact/s defined", artifacts
artifacts.each do |artifact|
next unless artifact.respond_to?(:uninstall_phase)
odebug "Un-installing artifact of class #{artifact.class}"
- artifact.uninstall_phase
+ artifact.uninstall_phase(command: @command, verbose: verbose?, force: force?)
end
end
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
+ if (zap_stanzas = Artifact::Zap.for_cask(@cask)).empty?
opoo "No zap stanza present for Cask '#{@cask}'"
+ else
+ ohai "Dispatching zap stanza"
+ zap_stanzas.each do |stanza|
+ stanza.zap_phase(command: @command, verbose: verbose?, force: force?)
+ end
end
ohai "Removing all staged versions of Cask '#{@cask}'"
purge_caskroom_path
diff --git a/Library/Homebrew/cask/lib/hbc/staged.rb b/Library/Homebrew/cask/lib/hbc/staged.rb
index c1aa01b29..dc21279de 100644
--- a/Library/Homebrew/cask/lib/hbc/staged.rb
+++ b/Library/Homebrew/cask/lib/hbc/staged.rb
@@ -4,7 +4,7 @@ module Hbc
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")
+ @cask.artifacts[:app].to_a.at(index).target.join("Contents", "Info.plist")
end
def plist_exec(cmd)
diff --git a/Library/Homebrew/cask/lib/hbc/system_command.rb b/Library/Homebrew/cask/lib/hbc/system_command.rb
index b735ae4f9..be083c29e 100644
--- a/Library/Homebrew/cask/lib/hbc/system_command.rb
+++ b/Library/Homebrew/cask/lib/hbc/system_command.rb
@@ -61,7 +61,7 @@ module Hbc
end
def assert_success
- return if processed_status && processed_status.success?
+ return if processed_status&.success?
raise CaskCommandFailedError.new(command, processed_output[:stdout], processed_output[:stderr], processed_status)
end
diff --git a/Library/Homebrew/caveats.rb b/Library/Homebrew/caveats.rb
index 578b292fa..1849ea79b 100644
--- a/Library/Homebrew/caveats.rb
+++ b/Library/Homebrew/caveats.rb
@@ -163,7 +163,7 @@ class Caveats
def plist_caveats
s = []
- if f.plist || (keg && keg.plist_installed?)
+ if f.plist || (keg&.plist_installed?)
plist_domain = f.plist_path.basename(".plist")
# we readlink because this path probably doesn't exist since caveats
diff --git a/Library/Homebrew/cleanup.rb b/Library/Homebrew/cleanup.rb
index d1f0b2516..340161204 100644
--- a/Library/Homebrew/cleanup.rb
+++ b/Library/Homebrew/cleanup.rb
@@ -6,6 +6,10 @@ module Homebrew
module Cleanup
@disk_cleanup_size = 0
+ class << self
+ attr_reader :disk_cleanup_size
+ end
+
module_function
def cleanup
@@ -21,10 +25,6 @@ module Homebrew
@disk_cleanup_size += path_size
end
- def disk_cleanup_size
- @disk_cleanup_size
- end
-
def unremovable_kegs
@unremovable_kegs ||= []
end
diff --git a/Library/Homebrew/cmd/irb.rb b/Library/Homebrew/cmd/irb.rb
index cba8a5b82..4cd3d4c9e 100644
--- a/Library/Homebrew/cmd/irb.rb
+++ b/Library/Homebrew/cmd/irb.rb
@@ -19,15 +19,13 @@ class String
end
end
-def cask
- $LOAD_PATH.unshift("#{HOMEBREW_LIBRARY_PATH}/cask/lib")
- require "hbc"
-end
-
module Homebrew
module_function
def irb
+ $LOAD_PATH.unshift("#{HOMEBREW_LIBRARY_PATH}/cask/lib")
+ require "hbc"
+
if ARGV.include? "--examples"
puts "'v8'.f # => instance of the v8 formula"
puts ":hub.f.installed?"
diff --git a/Library/Homebrew/cmd/list.rb b/Library/Homebrew/cmd/list.rb
index f5c4e68ac..436fc1f97 100644
--- a/Library/Homebrew/cmd/list.rb
+++ b/Library/Homebrew/cmd/list.rb
@@ -39,15 +39,7 @@ module Homebrew
filtered_list
elsif ARGV.named.empty?
if ARGV.include? "--full-name"
- full_names = Formula.installed.map(&:full_name).sort do |a, b|
- if a.include?("/") && !b.include?("/")
- 1
- elsif !a.include?("/") && b.include?("/")
- -1
- else
- a <=> b
- end
- end
+ full_names = Formula.installed.map(&:full_name).sort &tap_and_name_comparison
return if full_names.empty?
puts Formatter.columns(full_names)
else
diff --git a/Library/Homebrew/cmd/prune.rb b/Library/Homebrew/cmd/prune.rb
index 9fc6dbcd9..7ec2838ba 100644
--- a/Library/Homebrew/cmd/prune.rb
+++ b/Library/Homebrew/cmd/prune.rb
@@ -55,7 +55,7 @@ module Homebrew
else
n, d = ObserverPathnameExtension.counts
print "Pruned #{n} symbolic links "
- print "and #{d} directories " if d > 0
+ print "and #{d} directories " if d.positive?
puts "from #{HOMEBREW_PREFIX}"
end
end
diff --git a/Library/Homebrew/cmd/search.rb b/Library/Homebrew/cmd/search.rb
index acee9817f..c01a11c10 100644
--- a/Library/Homebrew/cmd/search.rb
+++ b/Library/Homebrew/cmd/search.rb
@@ -67,7 +67,7 @@ module Homebrew
ohai "Searching blacklisted, migrated and deleted formulae..."
if reason = Homebrew::MissingFormula.reason(query, silent: true)
- if count > 0
+ if count.positive?
puts
puts "If you meant #{query.inspect} specifically:"
end
diff --git a/Library/Homebrew/cmd/style.rb b/Library/Homebrew/cmd/style.rb
index b0f46fadc..e816db5dc 100644
--- a/Library/Homebrew/cmd/style.rb
+++ b/Library/Homebrew/cmd/style.rb
@@ -119,10 +119,10 @@ module Homebrew
when :print
args << "--display-cop-names" if ARGV.include? "--display-cop-names"
args << "--format" << "simple" if files
- system(cache_env, "rubocop", *args)
+ system(cache_env, "rubocop", "_#{HOMEBREW_RUBOCOP_VERSION}_", *args)
!$CHILD_STATUS.success?
when :json
- json, _, status = Open3.capture3(cache_env, "rubocop", "--format", "json", *args)
+ json, _, status = Open3.capture3(cache_env, "rubocop", "_#{HOMEBREW_RUBOCOP_VERSION}_", "--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
diff --git a/Library/Homebrew/cmd/tap-info.rb b/Library/Homebrew/cmd/tap-info.rb
index af087645d..cb0e0b387 100644
--- a/Library/Homebrew/cmd/tap-info.rb
+++ b/Library/Homebrew/cmd/tap-info.rb
@@ -64,10 +64,10 @@ module Homebrew
if tap.installed?
info += tap.pinned? ? "pinned" : "unpinned"
info += ", private" if tap.private?
- if (formula_count = tap.formula_files.size) > 0
+ if (formula_count = tap.formula_files.size).positive?
info += ", #{Formatter.pluralize(formula_count, "formula")}"
end
- if (command_count = tap.command_files.size) > 0
+ if (command_count = tap.command_files.size).positive?
info += ", #{Formatter.pluralize(command_count, "command")}"
end
info += ", no formulae/commands" if (formula_count + command_count).zero?
diff --git a/Library/Homebrew/cmd/unlinkapps.rb b/Library/Homebrew/cmd/unlinkapps.rb
index 7cae97e27..56dba3603 100644
--- a/Library/Homebrew/cmd/unlinkapps.rb
+++ b/Library/Homebrew/cmd/unlinkapps.rb
@@ -77,7 +77,7 @@ module Homebrew
def unlinkapps_unlink?(target_app, opts = {})
# Skip non-symlinks and symlinks that don't point into the Homebrew prefix.
app = target_app.readlink.to_s if target_app.symlink?
- return false unless app && app.start_with?(*UNLINKAPPS_PREFIXES)
+ return false unless app&.start_with?(*UNLINKAPPS_PREFIXES)
if opts.fetch(:prune, false)
!File.exist?(app) # Remove only broken symlinks in prune mode.
diff --git a/Library/Homebrew/cmd/update-report.rb b/Library/Homebrew/cmd/update-report.rb
index ea915f99c..781ee8808 100644
--- a/Library/Homebrew/cmd/update-report.rb
+++ b/Library/Homebrew/cmd/update-report.rb
@@ -124,7 +124,7 @@ module Homebrew
return if ENV["HOMEBREW_UPDATE_TEST"]
core_tap = CoreTap.instance
return if core_tap.installed?
- CoreTap.ensure_installed! quiet: false
+ CoreTap.ensure_installed!
revision = core_tap.git_head
ENV["HOMEBREW_UPDATE_BEFORE_HOMEBREW_HOMEBREW_CORE"] = revision
ENV["HOMEBREW_UPDATE_AFTER_HOMEBREW_HOMEBREW_CORE"] = revision
@@ -203,6 +203,7 @@ module Homebrew
end
new_homebrew_repository = Pathname.new "/usr/local/Homebrew"
+ new_homebrew_repository.rmdir_if_possible
if new_homebrew_repository.exist?
ofail <<-EOS.undent
#{new_homebrew_repository} already exists.
diff --git a/Library/Homebrew/cmd/update.sh b/Library/Homebrew/cmd/update.sh
index fb6a3459c..e8211e4dd 100644
--- a/Library/Homebrew/cmd/update.sh
+++ b/Library/Homebrew/cmd/update.sh
@@ -385,6 +385,12 @@ EOS
if ! git --version >/dev/null 2>&1
then
+ # we need a new enough curl to install git
+ if [[ -n "$HOMEBREW_SYSTEM_CURL_TOO_OLD" &&
+ ! -x "$HOMEBREW_PREFIX/opt/curl/bin/curl" ]]
+ then
+ brew install curl
+ fi
# we cannot install brewed git if homebrew/core is unavailable.
[[ -d "$HOMEBREW_LIBRARY/Taps/homebrew/homebrew-core" ]] && brew install git
unset GIT_EXECUTABLE
diff --git a/Library/Homebrew/cmd/vendor-install.sh b/Library/Homebrew/cmd/vendor-install.sh
index fe7e26dd4..6d16a297d 100644
--- a/Library/Homebrew/cmd/vendor-install.sh
+++ b/Library/Homebrew/cmd/vendor-install.sh
@@ -13,16 +13,16 @@ if [[ -n "$HOMEBREW_MACOS" ]]
then
if [[ "$HOMEBREW_PROCESSOR" = "Intel" ]]
then
- ruby_URL="https://homebrew.bintray.com/bottles-portable/portable-ruby-2.0.0-p648.leopard_64.bottle.tar.gz"
- ruby_SHA="5c1240abe4be91c9774a0089c2a38a8ccfff87c009e8e5786730c659d5e633f7"
+ ruby_URL="https://homebrew.bintray.com/bottles-portable/portable-ruby-2.3.3.leopard_64.bottle.1.tar.gz"
+ ruby_SHA="34ce9e4c9c1be28db564d744165aa29291426f8a3d2ef806ba4f0b9175aedb2b"
else
ruby_URL=""
ruby_SHA=""
fi
elif [[ -n "$HOMEBREW_LINUX" ]]
then
- ruby_URL="https://homebrew.bintray.com/bottles-portable/portable-ruby-2.0.0-p648.x86_64_linux.bottle.tar.gz"
- ruby_SHA="dbb5118a22a6a75cc77e62544a3d8786d383fab1bdaf8c154951268807357bf0"
+ ruby_URL="https://homebrew.bintray.com/bottles-portable/portable-ruby-2.3.3.x86_64_linux.bottle.tar.gz"
+ ruby_SHA="543c18bd33a300e6c16671437b1e0f17b03bb64e6a485fc15ff7de1eb1a0bc2a"
fi
fetch() {
@@ -45,20 +45,25 @@ fetch() {
curl_args[${#curl_args[*]}]="--progress-bar"
fi
+ if [[ "$HOMEBREW_MACOS_VERSION_NUMERIC" -lt "100600" ]]
+ then
+ curl_args[${#curl_args[*]}]="--insecure"
+ fi
+
temporary_path="$CACHED_LOCATION.incomplete"
mkdir -p "$HOMEBREW_CACHE"
- [[ -n "$HOMEBREW_QUIET" ]] || echo "==> Downloading $VENDOR_URL"
+ [[ -n "$HOMEBREW_QUIET" ]] || echo "==> Downloading $VENDOR_URL" >&2
if [[ -f "$CACHED_LOCATION" ]]
then
- [[ -n "$HOMEBREW_QUIET" ]] || echo "Already downloaded: $CACHED_LOCATION"
+ [[ -n "$HOMEBREW_QUIET" ]] || echo "Already downloaded: $CACHED_LOCATION" >&2
else
if [[ -f "$temporary_path" ]]
then
"$HOMEBREW_CURL" "${curl_args[@]}" -C - "$VENDOR_URL" -o "$temporary_path"
if [[ $? -eq 33 ]]
then
- [[ -n "$HOMEBREW_QUIET" ]] || echo "Trying a full download"
+ [[ -n "$HOMEBREW_QUIET" ]] || echo "Trying a full download" >&2
rm -f "$temporary_path"
"$HOMEBREW_CURL" "${curl_args[@]}" "$VENDOR_URL" -o "$temporary_path"
fi
@@ -135,7 +140,7 @@ install() {
fi
safe_cd "$VENDOR_DIR"
- [[ -n "$HOMEBREW_QUIET" ]] || echo "==> Unpacking $(basename "$VENDOR_URL")"
+ [[ -n "$HOMEBREW_QUIET" ]] || echo "==> Pouring $(basename "$VENDOR_URL")" >&2
tar "$tar_args" "$CACHED_LOCATION"
safe_cd "$VENDOR_DIR/portable-$VENDOR_NAME"
diff --git a/Library/Homebrew/compat/ENV/shared.rb b/Library/Homebrew/compat/ENV/shared.rb
index 200e7b132..c700b1e00 100644
--- a/Library/Homebrew/compat/ENV/shared.rb
+++ b/Library/Homebrew/compat/ENV/shared.rb
@@ -3,4 +3,8 @@ module SharedEnvExtension
odeprecated "ENV.j1", "ENV.deparallelize"
deparallelize
end
+
+ def java_cache
+ # odeprecated "ENV.java_cache"
+ end
end
diff --git a/Library/Homebrew/compat/formula_specialties.rb b/Library/Homebrew/compat/formula_specialties.rb
index ec5e91ce8..78966625e 100644
--- a/Library/Homebrew/compat/formula_specialties.rb
+++ b/Library/Homebrew/compat/formula_specialties.rb
@@ -16,7 +16,7 @@ end
# This formula serves as the base class for several very similar
# formulae for Amazon Web Services related tools.
class AmazonWebServicesFormula < Formula
- # Use this method to peform a standard install for Java-based tools,
+ # Use this method to perform a standard install for Java-based tools,
# keeping the .jars out of HOMEBREW_PREFIX/lib
def install
odeprecated "AmazonWebServicesFormula#install", "Formula#install"
diff --git a/Library/Homebrew/constants.rb b/Library/Homebrew/constants.rb
index 23be70bcc..b122946c8 100644
--- a/Library/Homebrew/constants.rb
+++ b/Library/Homebrew/constants.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# RuboCop version used for `brew style` and `brew cask style`
-HOMEBREW_RUBOCOP_VERSION = "0.49.1".freeze
-HOMEBREW_RUBOCOP_CASK_VERSION = "~> 0.13.1".freeze # has to be updated when RuboCop version changes
+HOMEBREW_RUBOCOP_VERSION = "0.50.0"
+HOMEBREW_RUBOCOP_CASK_VERSION = "~> 0.14.2" # has to be updated when RuboCop version changes
diff --git a/Library/Homebrew/debrew.rb b/Library/Homebrew/debrew.rb
index c2662c9ee..5bc3d2daa 100644
--- a/Library/Homebrew/debrew.rb
+++ b/Library/Homebrew/debrew.rb
@@ -57,7 +57,7 @@ module Debrew
input.chomp!
i = input.to_i
- if i > 0
+ if i.positive?
choice = menu.entries[i - 1]
else
possible = menu.entries.find_all { |e| e.name.start_with?(input) }
diff --git a/Library/Homebrew/debrew/irb.rb b/Library/Homebrew/debrew/irb.rb
index f97403782..069dbe676 100644
--- a/Library/Homebrew/debrew/irb.rb
+++ b/Library/Homebrew/debrew/irb.rb
@@ -16,7 +16,7 @@ module IRB
workspace = WorkSpace.new(binding)
irb = Irb.new(workspace)
- @CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC]
+ @CONF[:IRB_RC]&.call(irb.context)
@CONF[:MAIN_CONTEXT] = irb.context
trap("SIGINT") do
diff --git a/Library/Homebrew/dependency.rb b/Library/Homebrew/dependency.rb
index d7d5ec59c..0fbc2625b 100644
--- a/Library/Homebrew/dependency.rb
+++ b/Library/Homebrew/dependency.rb
@@ -51,7 +51,7 @@ class Dependency
end
def modify_build_environment
- env_proc.call unless env_proc.nil?
+ env_proc&.call
end
def inspect
diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb
index 2c9336481..a7d498c0d 100644
--- a/Library/Homebrew/dev-cmd/audit.rb
+++ b/Library/Homebrew/dev-cmd/audit.rb
@@ -54,6 +54,7 @@ module Homebrew
def audit
Homebrew.inject_dump_stats!(FormulaAuditor, /^audit_/) if ARGV.switch? "D"
+ Homebrew.auditing = true
formula_count = 0
problem_count = 0
@@ -201,19 +202,24 @@ class FormulaAuditor
@specs = %w[stable devel head].map { |s| formula.send(s) }.compact
end
- def self.check_http_content(url, name, user_agents: [:default])
+ def self.check_http_content(url, user_agents: [:default], check_content: false, strict: false, require_http: false)
return unless url.start_with? "http"
details = nil
user_agent = nil
- hash_needed = url.start_with?("http:") && name != "curl"
+ hash_needed = url.start_with?("http:") && !require_http
user_agents.each do |ua|
details = http_content_headers_and_checksum(url, hash_needed: hash_needed, user_agent: ua)
user_agent = ua
break if details[:status].to_s.start_with?("2")
end
- return "The URL #{url} is not reachable" unless details[:status]
+ unless details[:status]
+ # Hack around https://github.com/Homebrew/brew/issues/3199
+ return if MacOS.version == :el_capitan
+ return "The URL #{url} is not reachable"
+ end
+
unless details[:status].start_with? "2"
return "The URL #{url} is not reachable (HTTP status code #{details[:status]})"
end
@@ -236,8 +242,32 @@ class FormulaAuditor
details[:content_length] == secure_details[:content_length]
file_match = details[:file_hash] == secure_details[:file_hash]
- return if !etag_match && !content_length_match && !file_match
- "The URL #{url} could use HTTPS rather than HTTP"
+ if etag_match || content_length_match || file_match
+ return "The URL #{url} should use HTTPS rather than HTTP"
+ end
+
+ return unless check_content
+
+ no_protocol_file_contents = %r{https?:\\?/\\?/}
+ details[:file] = details[:file].gsub(no_protocol_file_contents, "/")
+ secure_details[:file] = secure_details[:file].gsub(no_protocol_file_contents, "/")
+
+ # Check for the same content after removing all protocols
+ if details[:file] == secure_details[:file]
+ return "The URL #{url} should use HTTPS rather than HTTP"
+ end
+
+ return unless strict
+
+ # Same size, different content after normalization
+ # (typical causes: Generated ID, Timestamp, Unix time)
+ if details[:file].length == secure_details[:file].length
+ return "The URL #{url} may be able to use HTTPS rather than HTTP. Please verify it in a browser."
+ end
+
+ lenratio = (100 * secure_details[:file].length / details[:file].length).to_i
+ return unless (90..110).cover?(lenratio)
+ "The URL #{url} may be able to use HTTPS rather than HTTP. Please verify it in a browser."
end
def self.http_content_headers_and_checksum(url, hash_needed: false, user_agent: :default)
@@ -260,6 +290,7 @@ class FormulaAuditor
etag: headers[%r{ETag: ([wW]\/)?"(([^"]|\\")*)"}, 2],
content_length: headers[/Content-Length: (\d+)/, 1],
file_hash: output_hash,
+ file: output,
}
end
@@ -327,7 +358,7 @@ class FormulaAuditor
end
valid_alias_names = [alias_name_major, alias_name_major_minor]
- if formula.tap && !formula.tap.core_tap?
+ unless formula.tap&.core_tap?
versioned_aliases.map! { |a| "#{formula.tap}/#{a}" }
valid_alias_names.map! { |a| "#{formula.tap}/#{a}" }
end
@@ -356,21 +387,6 @@ class FormulaAuditor
end
end
- def audit_class
- if @strict
- unless formula.test_defined?
- problem "A `test do` test block should be added"
- end
- end
-
- classes = %w[GithubGistFormula ScriptFileFormula AmazonWebServicesFormula]
- klass = classes.find do |c|
- Object.const_defined?(c) && formula.class < Object.const_get(c)
- end
-
- problem "#{klass} is deprecated, use Formula instead" if klass
- end
-
# core aliases + tap alias names + tap alias full name
@@aliases ||= Formula.aliases + Formula.tap_aliases
@@ -403,6 +419,7 @@ class FormulaAuditor
@@local_official_taps_name_map ||= Tap.select(&:official?).flat_map(&:formula_names)
.each_with_object({}) do |tap_formula_full_name, name_map|
+ next if tap_formula_full_name.start_with?("homebrew/science/")
tap_formula_name = tap_formula_full_name.split("/").last
name_map[tap_formula_name] ||= []
name_map[tap_formula_name] << tap_formula_full_name
@@ -413,6 +430,7 @@ class FormulaAuditor
if @online
Homebrew.search_taps(name, silent: true).each do |tap_formula_full_name|
+ next if tap_formula_full_name.start_with?("homebrew/science/")
tap_formula_name = tap_formula_full_name.split("/").last
next if tap_formula_name != name
same_name_tap_formulae << tap_formula_full_name
@@ -563,10 +581,11 @@ class FormulaAuditor
return unless @online
- return unless DevelopmentTools.curl_handles_most_https_homepages?
+ return unless DevelopmentTools.curl_handles_most_https_certificates?
if http_content_problem = FormulaAuditor.check_http_content(homepage,
- formula.name,
- user_agents: [:browser, :default])
+ user_agents: [:browser, :default],
+ check_content: true,
+ strict: @strict)
problem http_content_problem
end
end
@@ -616,13 +635,14 @@ class FormulaAuditor
end
%w[Stable Devel HEAD].each do |name|
- next unless spec = formula.send(name.downcase)
+ spec_name = name.downcase.to_sym
+ next unless spec = formula.send(spec_name)
- ra = ResourceAuditor.new(spec, online: @online, strict: @strict).audit
+ ra = ResourceAuditor.new(spec, spec_name, online: @online, strict: @strict).audit
problems.concat ra.problems.map { |problem| "#{name}: #{problem}" }
spec.resources.each_value do |resource|
- ra = ResourceAuditor.new(resource, online: @online, strict: @strict).audit
+ ra = ResourceAuditor.new(resource, spec_name, online: @online, strict: @strict).audit
problems.concat ra.problems.map { |problem|
"#{name} resource #{resource.name.inspect}: #{problem}"
}
@@ -687,7 +707,7 @@ class FormulaAuditor
end
stable = formula.stable
- case stable && stable.url
+ case stable&.url
when /[\d\._-](alpha|beta|rc\d)/
matched = Regexp.last_match(1)
version_prefix = stable.version.to_s.sub(/\d+$/, "")
@@ -865,8 +885,8 @@ class FormulaAuditor
problem "Use spaces instead of tabs for indentation" if line =~ /^[ ]*\t/
- if line.include?("ENV.x11")
- problem "Use \"depends_on :x11\" instead of \"ENV.x11\""
+ if line.include?("ENV.java_cache")
+ problem "In-formula ENV.java_cache usage has been deprecated & should be removed."
end
# Avoid hard-coding compilers
@@ -882,14 +902,6 @@ class FormulaAuditor
problem "Use ENV instead of invoking '#{Regexp.last_match(1)}' to modify the environment"
end
- if formula.name != "wine" && line =~ /ENV\.universal_binary/
- problem "macOS has been 64-bit only since 10.6 so ENV.universal_binary is deprecated."
- end
-
- if line =~ /build\.universal\?/
- problem "macOS has been 64-bit only so build.universal? is deprecated."
- end
-
if line =~ /version == ['"]HEAD['"]/
problem "Use 'build.head?' instead of inspecting 'version'"
end
@@ -930,12 +942,6 @@ class FormulaAuditor
problem "Use build instead of ARGV to check options"
end
- problem "Use new-style option definitions" if line.include?("def options")
-
- if line.end_with?("def test")
- problem "Use new-style test definitions (test do)"
- end
-
if line.include?("MACOS_VERSION")
problem "Use MacOS.version instead of MACOS_VERSION"
end
@@ -949,11 +955,6 @@ class FormulaAuditor
problem "\"#{$&}\" is deprecated, use a comparison to MacOS.version instead"
end
- if line =~ /skip_clean\s+:all/
- problem "`skip_clean :all` is deprecated; brew no longer strips symbols\n" \
- "\tPass explicit paths to prevent Homebrew from removing empty folders."
- end
-
if line =~ /depends_on [A-Z][\w:]+\.new$/
problem "`depends_on` can take requirement classes instead of instances"
end
@@ -992,30 +993,6 @@ class FormulaAuditor
problem "Use `assert_match` instead of `assert ...include?`"
end
- if line.include?('system "npm", "install"') && !line.include?("Language::Node") &&
- formula.name !~ /^kibana(\@\d+(\.\d+)?)?$/
- problem "Use Language::Node for npm install args"
- end
-
- if line.include?("fails_with :llvm")
- problem "'fails_with :llvm' is now a no-op so should be removed"
- end
-
- if line =~ /system\s+['"](otool|install_name_tool|lipo)/ && formula.name != "cctools"
- problem "Use ruby-macho instead of calling #{Regexp.last_match(1)}"
- end
-
- if formula.tap.to_s == "homebrew/core"
- ["OS.mac?", "OS.linux?"].each do |check|
- next unless line.include?(check)
- problem "Don't use #{check}; Homebrew/core only supports macOS"
- end
- end
-
- if line =~ /((revision|version_scheme)\s+0)/
- problem "'#{Regexp.last_match(1)}' should be removed"
- end
-
return unless @strict
problem "`#{Regexp.last_match(1)}` in formulae is deprecated" if line =~ /(env :(std|userpaths))/
@@ -1041,7 +1018,7 @@ class FormulaAuditor
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&.official?
return unless formula.tap.tap_migrations.key?(formula.name)
problem <<-EOS.undent
@@ -1116,10 +1093,10 @@ class FormulaAuditor
end
class ResourceAuditor
- attr_reader :problems
- attr_reader :version, :checksum, :using, :specs, :url, :mirrors, :name
+ attr_reader :name, :version, :checksum, :url, :mirrors, :using, :specs, :owner
+ attr_reader :spec_name, :problems
- def initialize(resource, options = {})
+ def initialize(resource, spec_name, options = {})
@name = resource.name
@version = resource.version
@checksum = resource.checksum
@@ -1127,9 +1104,11 @@ class ResourceAuditor
@mirrors = resource.mirrors
@using = resource.using
@specs = resource.specs
- @online = options[:online]
- @strict = options[:strict]
- @problems = []
+ @owner = resource.owner
+ @spec_name = spec_name
+ @online = options[:online]
+ @strict = options[:strict]
+ @problems = []
end
def audit
@@ -1203,11 +1182,29 @@ class ResourceAuditor
problem "Redundant :using value in URL"
end
+ def self.curl_openssl_and_deps
+ @curl_openssl_and_deps ||= begin
+ formulae_names = ["curl", "openssl"]
+ formulae_names += formulae_names.flat_map do |f|
+ Formula[f].recursive_dependencies.map(&:name)
+ end
+ formulae_names.uniq
+ rescue FormulaUnavailableError
+ []
+ end
+ end
+
def audit_urls
urls = [url] + mirrors
- if name == "curl" && !urls.find { |u| u.start_with?("http://") }
- problem "should always include at least one HTTP url"
+ curl_openssl_or_deps = ResourceAuditor.curl_openssl_and_deps.include?(owner.name)
+
+ if spec_name == :stable && curl_openssl_or_deps
+ problem "should not use xz tarballs" if url.end_with?(".xz")
+
+ unless urls.find { |u| u.start_with?("http://") }
+ problem "should always include at least one HTTP mirror"
+ end
end
return unless @online
@@ -1219,7 +1216,7 @@ class ResourceAuditor
# A `brew mirror`'ed URL is usually not yet reachable at the time of
# pull request.
next if url =~ %r{^https://dl.bintray.com/homebrew/mirror/}
- if http_content_problem = FormulaAuditor.check_http_content(url, name)
+ if http_content_problem = FormulaAuditor.check_http_content(url, require_http: curl_openssl_or_deps)
problem http_content_problem
end
elsif strategy <= GitDownloadStrategy
@@ -1228,6 +1225,7 @@ class ResourceAuditor
end
elsif strategy <= SubversionDownloadStrategy
next unless DevelopmentTools.subversion_handles_most_https_certificates?
+ next unless Utils.svn_available?
unless Utils.svn_remote_exists url
problem "The URL #{url} is not a valid svn URL"
end
diff --git a/Library/Homebrew/dev-cmd/bottle.rb b/Library/Homebrew/dev-cmd/bottle.rb
index d8aefc4c0..8dfd0d12c 100644
--- a/Library/Homebrew/dev-cmd/bottle.rb
+++ b/Library/Homebrew/dev-cmd/bottle.rb
@@ -47,7 +47,7 @@ BOTTLE_ERB = <<-EOS.freeze
<% elsif cellar != BottleSpecification::DEFAULT_CELLAR %>
cellar "<%= cellar %>"
<% end %>
- <% if rebuild > 0 %>
+ <% if rebuild.positive? %>
rebuild <%= rebuild %>
<% end %>
<% checksums.each do |checksum_type, checksum_values| %>
@@ -186,7 +186,7 @@ module Homebrew
ohai "Determining #{f.full_name} bottle rebuild..."
versions = FormulaVersions.new(f)
rebuilds = versions.bottle_version_map("origin/master")[f.pkg_version]
- rebuilds.pop if rebuilds.last.to_i > 0
+ rebuilds.pop if rebuilds.last.to_i.positive?
rebuild = rebuilds.empty? ? 0 : rebuilds.max.to_i + 1
end
@@ -283,7 +283,7 @@ module Homebrew
raise
ensure
ignore_interrupts do
- original_tab.write if original_tab
+ original_tab&.write
unless ARGV.include? "--skip-relocation"
keg.replace_placeholders_with_locations changed_files
end
diff --git a/Library/Homebrew/dev-cmd/bump-formula-pr.rb b/Library/Homebrew/dev-cmd/bump-formula-pr.rb
index e9e98d450..87d8274cc 100644
--- a/Library/Homebrew/dev-cmd/bump-formula-pr.rb
+++ b/Library/Homebrew/dev-cmd/bump-formula-pr.rb
@@ -89,7 +89,8 @@ module Homebrew
def check_for_duplicate_pull_requests(formula)
pull_requests = fetch_pull_requests(formula)
- return unless pull_requests && !pull_requests.empty?
+ return unless pull_requests
+ return if pull_requests.empty?
duplicates_message = <<-EOS.undent
These open pull requests may be duplicates:
#{pull_requests.map { |pr| "#{pr["title"]} #{pr["html_url"]}" }.join("\n")}
@@ -124,7 +125,7 @@ module Homebrew
Formula.each do |f|
if is_devel && f.devel && f.devel.url && f.devel.url.match(base_url)
guesses << f
- elsif f.stable && f.stable.url && f.stable.url.match(base_url)
+ elsif f.stable&.url && f.stable.url.match(base_url)
guesses << f
end
end
@@ -296,9 +297,7 @@ module Homebrew
ohai "git fetch --unshallow origin" if shallow
ohai "git checkout --no-track -b #{branch} origin/master"
ohai "git commit --no-edit --verbose --message='#{formula.name} #{new_formula_version}#{devel_message}' -- #{formula.path}"
- ohai "hub fork --no-remote"
- ohai "hub fork"
- ohai "hub fork (to read $HUB_REMOTE)"
+ ohai "hub fork # read $HUB_REMOTE"
ohai "git push --set-upstream $HUB_REMOTE #{branch}:#{branch}"
ohai "hub pull-request --browse -m '#{formula.name} #{new_formula_version}#{devel_message}'"
ohai "git checkout -"
@@ -308,9 +307,9 @@ module Homebrew
safe_system "git", "commit", "--no-edit", "--verbose",
"--message=#{formula.name} #{new_formula_version}#{devel_message}",
"--", formula.path
- safe_system "hub", "fork", "--no-remote"
- quiet_system "hub", "fork"
- remote = Utils.popen_read("hub fork 2>&1")[/fatal: remote (.+) already exists\./, 1]
+ remote = Utils.popen_read("hub fork 2>&1")[/remote:? (\S+)/, 1]
+ # repeat for hub 2.2 backwards compatibility:
+ remote = Utils.popen_read("hub fork 2>&1")[/remote:? (\S+)/, 1] if remote.to_s.empty?
odie "cannot get remote from 'hub'!" if remote.to_s.empty?
safe_system "git", "push", "--set-upstream", remote, "#{branch}:#{branch}"
pr_message = <<-EOS.undent
diff --git a/Library/Homebrew/dev-cmd/pull.rb b/Library/Homebrew/dev-cmd/pull.rb
index a8f35531f..cd0d6fbd0 100644
--- a/Library/Homebrew/dev-cmd/pull.rb
+++ b/Library/Homebrew/dev-cmd/pull.rb
@@ -69,13 +69,13 @@ module Homebrew
tap = nil
ARGV.named.each do |arg|
- if arg.to_i > 0
+ if arg.to_i.positive?
issue = arg
url = "https://github.com/Homebrew/homebrew-core/pull/#{arg}"
tap = CoreTap.instance
elsif (testing_match = arg.match %r{/job/Homebrew.*Testing/(\d+)/})
tap = ARGV.value("tap")
- tap = if tap && tap.start_with?("homebrew/")
+ tap = if tap&.start_with?("homebrew/")
Tap.fetch("homebrew", tap.strip_prefix("homebrew/"))
elsif tap
odie "Tap option did not start with \"homebrew/\": #{tap}"
@@ -350,7 +350,7 @@ module Homebrew
files << Regexp.last_match(1) if line =~ %r{^\+\+\+ b/(.*)}
end
files.each do |file|
- if tap && tap.formula_file?(file)
+ if tap&.formula_file?(file)
formula_name = File.basename(file, ".rb")
formulae << formula_name unless formulae.include?(formula_name)
else
diff --git a/Library/Homebrew/dev-cmd/release-notes.rb b/Library/Homebrew/dev-cmd/release-notes.rb
index e578869bf..496023956 100644
--- a/Library/Homebrew/dev-cmd/release-notes.rb
+++ b/Library/Homebrew/dev-cmd/release-notes.rb
@@ -10,10 +10,8 @@ module Homebrew
def release_notes
previous_tag = ARGV.named.first
- unless previous_tag
- previous_tag = Utils.popen_read("git tag --list --sort=-version:refname")
+ previous_tag ||= Utils.popen_read("git tag --list --sort=-version:refname")
.lines.first.chomp
- end
odie "Could not find any previous tags!" unless previous_tag
end_ref = ARGV.named[1] || "origin/master"
diff --git a/Library/Homebrew/development_tools.rb b/Library/Homebrew/development_tools.rb
index 996dea87c..b7787d849 100644
--- a/Library/Homebrew/development_tools.rb
+++ b/Library/Homebrew/development_tools.rb
@@ -114,7 +114,7 @@ class DevelopmentTools
@non_apple_gcc_version = {}
end
- def curl_handles_most_https_homepages?
+ def curl_handles_most_https_certificates?
true
end
diff --git a/Library/Homebrew/diagnostic.rb b/Library/Homebrew/diagnostic.rb
index f42fb95e2..020594f0c 100644
--- a/Library/Homebrew/diagnostic.rb
+++ b/Library/Homebrew/diagnostic.rb
@@ -522,7 +522,7 @@ module Homebrew
homebrew_owned = @found.all? do |path|
Pathname.new(path).realpath.to_s.start_with? "#{HOMEBREW_CELLAR}/gettext"
end
- return if gettext && gettext.linked_keg.directory? && homebrew_owned
+ return if gettext&.linked_keg&.directory? && homebrew_owned
inject_file_list @found, <<-EOS.undent
gettext files detected at a system prefix.
@@ -540,7 +540,7 @@ module Homebrew
rescue
nil
end
- if libiconv && libiconv.linked_keg.directory?
+ if libiconv&.linked_keg&.directory?
unless libiconv.keg_only?
<<-EOS.undent
A libiconv formula is installed and linked.
diff --git a/Library/Homebrew/download_strategy.rb b/Library/Homebrew/download_strategy.rb
index adeb0a02a..7012fccc8 100644
--- a/Library/Homebrew/download_strategy.rb
+++ b/Library/Homebrew/download_strategy.rb
@@ -331,20 +331,10 @@ class CurlDownloadStrategy < AbstractFileDownloadStrategy
if cached_location.exist?
puts "Already downloaded: #{cached_location}"
else
- had_incomplete_download = temporary_path.exist?
begin
_fetch
rescue ErrorDuringExecution
- # 33 == range not supported
- # try wiping the incomplete download and retrying once
- unless $CHILD_STATUS.exitstatus == 33 && had_incomplete_download
- raise CurlDownloadStrategyError, @url
- end
-
- ohai "Trying a full download"
- temporary_path.unlink
- had_incomplete_download = false
- retry
+ raise CurlDownloadStrategyError, @url
end
ignore_interrupts { temporary_path.rename(cached_location) }
end
diff --git a/Library/Homebrew/exceptions.rb b/Library/Homebrew/exceptions.rb
index 8b4cddc59..5418f9331 100644
--- a/Library/Homebrew/exceptions.rb
+++ b/Library/Homebrew/exceptions.rb
@@ -416,7 +416,7 @@ class BuildError < RuntimeError
puts
- if issues && !issues.empty?
+ unless issues&.empty?
puts "These open issues may also help:"
puts issues.map { |i| "#{i["title"]} #{i["html_url"]}" }.join("\n")
end
diff --git a/Library/Homebrew/extend/ARGV.rb b/Library/Homebrew/extend/ARGV.rb
index c6cb54f5d..63a0f3e40 100644
--- a/Library/Homebrew/extend/ARGV.rb
+++ b/Library/Homebrew/extend/ARGV.rb
@@ -144,10 +144,10 @@ module HomebrewArgvExtension
def value(name)
arg_prefix = "--#{name}="
flag_with_value = find { |arg| arg.start_with?(arg_prefix) }
- flag_with_value.strip_prefix(arg_prefix) if flag_with_value
+ flag_with_value&.strip_prefix(arg_prefix)
end
- # Returns an array of values that were given as a comma-seperated list.
+ # Returns an array of values that were given as a comma-separated list.
# @see value
def values(name)
return unless val = value(name)
@@ -236,7 +236,7 @@ module HomebrewArgvExtension
def bottle_arch
arch = value "bottle-arch"
- arch.to_sym if arch
+ arch&.to_sym
end
def build_from_source?
diff --git a/Library/Homebrew/extend/ENV.rb b/Library/Homebrew/extend/ENV.rb
index 283e90b69..ea1b99501 100644
--- a/Library/Homebrew/extend/ENV.rb
+++ b/Library/Homebrew/extend/ENV.rb
@@ -28,7 +28,7 @@ module EnvActivation
end
def clear_sensitive_environment!
- ENV.keys.each do |key|
+ ENV.each_key do |key|
next unless /(cookie|key|token)/i =~ key
ENV.delete key
end
diff --git a/Library/Homebrew/extend/ENV/shared.rb b/Library/Homebrew/extend/ENV/shared.rb
index b51ade48b..15488ee19 100644
--- a/Library/Homebrew/extend/ENV/shared.rb
+++ b/Library/Homebrew/extend/ENV/shared.rb
@@ -260,10 +260,6 @@ module SharedEnvExtension
set_cpu_flags(flags)
end
- def java_cache
- append "_JAVA_OPTIONS", "-Duser.home=#{HOMEBREW_CACHE}/java_cache"
- end
-
# ld64 is a newer linker provided for Xcode 2.5
# @private
def ld64
diff --git a/Library/Homebrew/extend/ENV/std.rb b/Library/Homebrew/extend/ENV/std.rb
index a2e800803..4e5d0683a 100644
--- a/Library/Homebrew/extend/ENV/std.rb
+++ b/Library/Homebrew/extend/ENV/std.rb
@@ -233,8 +233,8 @@ module Stdenv
def make_jobs
# '-j' requires a positive integral argument
- if self["HOMEBREW_MAKE_JOBS"].to_i > 0
- self["HOMEBREW_MAKE_JOBS"].to_i
+ if (jobs = self["HOMEBREW_MAKE_JOBS"].to_i).positive?
+ jobs
else
Hardware::CPU.cores
end
diff --git a/Library/Homebrew/extend/os/mac/development_tools.rb b/Library/Homebrew/extend/os/mac/development_tools.rb
index caa85ffca..1931b398d 100644
--- a/Library/Homebrew/extend/os/mac/development_tools.rb
+++ b/Library/Homebrew/extend/os/mac/development_tools.rb
@@ -9,7 +9,7 @@ class DevelopmentTools
@locate[key] = if (located_tool = original_locate(tool))
located_tool
elsif MacOS.version > :tiger
- path = Utils.popen_read("/usr/bin/xcrun", "-no-cache", "-find", tool).chomp
+ path = Utils.popen_read("/usr/bin/xcrun", "-no-cache", "-find", tool, err: :close).chomp
Pathname.new(path) if File.executable?(path)
end
end
@@ -43,11 +43,16 @@ class DevelopmentTools
end
def custom_installation_instructions
- if MacOS.version > :tiger
+ if MacOS.version > :leopard
<<-EOS.undent
Install GNU's GCC
brew install gcc
EOS
+ elsif MacOS.version > :tiger
+ <<-EOS.undent
+ Install GNU's GCC
+ brew install gcc@4.6
+ EOS
else
# Tiger doesn't ship with apple-gcc42, and this is required to build
# some software that doesn't build properly with FSF GCC.
@@ -55,7 +60,7 @@ class DevelopmentTools
Install Apple's GCC
brew install apple-gcc42
or GNU's GCC
- brew install gcc
+ brew install gcc@4.6
EOS
end
end
@@ -77,10 +82,10 @@ class DevelopmentTools
end
end
- def curl_handles_most_https_homepages?
- # The system Curl is too old for some modern HTTPS homepages on
+ def curl_handles_most_https_certificates?
+ # The system Curl is too old for some modern HTTPS certificates on
# older macOS versions.
- MacOS.version >= :el_capitan
+ ENV["HOMEBREW_SYSTEM_CURL_TOO_OLD"].nil?
end
def subversion_handles_most_https_certificates?
diff --git a/Library/Homebrew/extend/os/mac/diagnostic.rb b/Library/Homebrew/extend/os/mac/diagnostic.rb
index 0cdd7b115..9f7b18b49 100644
--- a/Library/Homebrew/extend/os/mac/diagnostic.rb
+++ b/Library/Homebrew/extend/os/mac/diagnostic.rb
@@ -195,8 +195,9 @@ module Homebrew
end
def check_ruby_version
- ruby_version = "2.0"
- return if RUBY_VERSION[/\d\.\d/] == ruby_version
+ ruby_version = "2.3.3"
+ return if RUBY_VERSION == ruby_version
+ return if ARGV.homebrew_developer? && OS::Mac.prerelease?
<<-EOS.undent
Ruby version #{RUBY_VERSION} is unsupported on #{MacOS.version}. Homebrew
diff --git a/Library/Homebrew/extend/os/mac/extend/ENV/super.rb b/Library/Homebrew/extend/os/mac/extend/ENV/super.rb
index 9c20cc7c6..5872c2264 100644
--- a/Library/Homebrew/extend/os/mac/extend/ENV/super.rb
+++ b/Library/Homebrew/extend/os/mac/extend/ENV/super.rb
@@ -96,9 +96,13 @@ module Superenv
self["SDKROOT"] = MacOS.sdk_path
end
- # Filter out symbols known not to be defined on 10.11 since GNU Autotools
- # can't reliably figure this out with Xcode 8 on its own yet.
- if MacOS.version == "10.11" && MacOS::Xcode.installed? && MacOS::Xcode.version >= "8.0"
+ # Filter out symbols known not to be defined since GNU Autotools can't
+ # reliably figure this out with Xcode 8 and above.
+ if MacOS.version == "10.12" && MacOS::Xcode.installed? && MacOS::Xcode.version >= "9.0"
+ %w[fmemopen futimens open_memstream utimensat].each do |s|
+ ENV["ac_cv_func_#{s}"] = "no"
+ end
+ elsif MacOS.version == "10.11" && MacOS::Xcode.installed? && MacOS::Xcode.version >= "8.0"
%w[basename_r clock_getres clock_gettime clock_settime dirname_r
getentropy mkostemp mkostemps timingsafe_bcmp].each do |s|
ENV["ac_cv_func_#{s}"] = "no"
diff --git a/Library/Homebrew/extend/os/mac/hardware/cpu.rb b/Library/Homebrew/extend/os/mac/hardware/cpu.rb
index 22d118e1a..b97c280cd 100644
--- a/Library/Homebrew/extend/os/mac/hardware/cpu.rb
+++ b/Library/Homebrew/extend/os/mac/hardware/cpu.rb
@@ -50,6 +50,8 @@ module Hardware
:broadwell
when 0x37fc219f # Skylake
:skylake
+ when 0x0f817246 # Kaby Lake
+ :kabylake
else
:dunno
end
diff --git a/Library/Homebrew/extend/string.rb b/Library/Homebrew/extend/string.rb
index ae7a209db..b96f12994 100644
--- a/Library/Homebrew/extend/string.rb
+++ b/Library/Homebrew/extend/string.rb
@@ -60,7 +60,7 @@ module StringInreplaceExtension
result
end
- # Looks for Makefile style variable defintions and replaces the
+ # Looks for Makefile style variable definitions and replaces the
# value with "new_value", or removes the definition entirely.
def change_make_var!(flag, new_value)
return if gsub!(/^#{Regexp.escape(flag)}[ \t]*=[ \t]*(.*)$/, "#{flag}=#{new_value}", false)
diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb
index 8cea85a99..d999b9c5f 100644
--- a/Library/Homebrew/formula.rb
+++ b/Library/Homebrew/formula.rb
@@ -472,7 +472,7 @@ class Formula
return true if devel && tab.devel_version && tab.devel_version < devel.version
if options[:fetch_head]
- return false unless head && head.downloader.is_a?(VCSDownloadStrategy)
+ return false unless head&.downloader.is_a?(VCSDownloadStrategy)
downloader = head.downloader
downloader.shutup! unless ARGV.verbose?
downloader.commit_outdated?(version.version.commit)
@@ -1115,8 +1115,8 @@ class Formula
# @private
def unlock
- @lock.unlock unless @lock.nil?
- @oldname_lock.unlock unless @oldname_lock.nil?
+ @lock&.unlock
+ @oldname_lock&.unlock
end
def migration_needed?
@@ -1182,7 +1182,8 @@ class Formula
# Returns false if the formula wasn't installed with an alias.
def installed_alias_target_changed?
target = current_installed_alias_target
- target && target.name != name
+ return false unless target
+ target.name != name
end
# Is this formula the target of an alias used to install an old formula?
@@ -1440,13 +1441,14 @@ class Formula
# True if this formula is provided by Homebrew itself
# @private
def core_formula?
- tap && tap.core_tap?
+ tap&.core_tap?
end
# True if this formula is provided by external Tap
# @private
def tap?
- tap && !tap.core_tap?
+ return false unless tap
+ !tap.core_tap?
end
# @private
@@ -1525,10 +1527,10 @@ class Formula
"oldname" => oldname,
"aliases" => aliases,
"versions" => {
- "stable" => (stable.version.to_s if stable),
+ "stable" => stable&.version.to_s,
"bottle" => bottle ? true : false,
- "devel" => (devel.version.to_s if devel),
- "head" => (head.version.to_s if head),
+ "devel" => devel&.version.to_s,
+ "head" => head&.version.to_s,
},
"revision" => revision,
"version_scheme" => version_scheme,
@@ -1570,7 +1572,7 @@ class Formula
"root_url" => bottle_spec.root_url,
}
bottle_info["files"] = {}
- bottle_spec.collector.keys.each do |os|
+ bottle_spec.collector.keys.each do |os| # rubocop:disable Performance/HashEachMethods
checksum = bottle_spec.collector[os]
bottle_info["files"][os] = {
"url" => "#{bottle_spec.root_url}/#{Bottle::Filename.create(self, os, bottle_spec.rebuild)}",
@@ -1613,6 +1615,7 @@ class Formula
def run_test
@prefix_returns_versioned_prefix = true
old_home = ENV["HOME"]
+ old_java_opts = ENV["_JAVA_OPTIONS"]
old_curl_home = ENV["CURL_HOME"]
old_tmpdir = ENV["TMPDIR"]
old_temp = ENV["TEMP"]
@@ -1626,6 +1629,7 @@ class Formula
ENV["TERM"] = "dumb"
ENV["PATH"] = PATH.new(old_path).append(HOMEBREW_PREFIX/"bin")
ENV["HOMEBREW_PATH"] = nil
+ ENV["_JAVA_OPTIONS"] = "#{old_java_opts} -Duser.home=#{HOMEBREW_CACHE}/java_cache"
ENV.clear_sensitive_environment!
@@ -1646,6 +1650,7 @@ class Formula
ensure
@testpath = nil
ENV["HOME"] = old_home
+ ENV["_JAVA_OPTIONS"] = old_java_opts
ENV["CURL_HOME"] = old_curl_home
ENV["TMPDIR"] = old_tmpdir
ENV["TEMP"] = old_temp
@@ -1888,11 +1893,13 @@ class Formula
mkdir_p env_home
old_home = ENV["HOME"]
+ old_java_opts = ENV["_JAVA_OPTIONS"]
old_curl_home = ENV["CURL_HOME"]
old_path = ENV["HOMEBREW_PATH"]
unless ARGV.interactive?
ENV["HOME"] = env_home
+ ENV["_JAVA_OPTIONS"] = "#{old_java_opts} -Duser.home=#{HOMEBREW_CACHE}/java_cache"
ENV["CURL_HOME"] = old_curl_home || old_home
end
ENV["HOMEBREW_PATH"] = nil
@@ -1907,6 +1914,7 @@ class Formula
@buildpath = nil
unless ARGV.interactive?
ENV["HOME"] = old_home
+ ENV["_JAVA_OPTIONS"] = old_java_opts
ENV["CURL_HOME"] = old_curl_home
end
ENV["HOMEBREW_PATH"] = old_path
diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb
index 6c5b8bdab..b4f9db845 100644
--- a/Library/Homebrew/formula_installer.rb
+++ b/Library/Homebrew/formula_installer.rb
@@ -85,13 +85,12 @@ class FormulaInstaller
return false if @pour_failed
bottle = formula.bottle
- return false unless bottle
+ return false if !bottle && !formula.local_bottle_path
return true if force_bottle?
return false if build_from_source? || build_bottle? || interactive?
return false if ARGV.cc
return false unless options.empty?
return false if formula.bottle_disabled?
- return true if formula.local_bottle_path
unless formula.pour_bottle?
if install_bottle_options[:warn] && formula.pour_bottle_check_unsatisfied_reason
opoo <<-EOS.undent
@@ -270,7 +269,7 @@ class FormulaInstaller
oh1 "Installing #{Formatter.identifier(formula.full_name)} #{options}".strip
end
- if formula.tap && !formula.tap.private?
+ unless formula.tap&.private?
action = "#{formula.full_name} #{options}".strip
Utils::Analytics.report_event("install", action)
@@ -561,7 +560,7 @@ class FormulaInstaller
end
raise
else
- ignore_interrupts { tmp_keg.rmtree if tmp_keg && tmp_keg.directory? }
+ ignore_interrupts { tmp_keg.rmtree if tmp_keg&.directory? }
end
def caveats
@@ -604,6 +603,12 @@ class FormulaInstaller
# let's reset Utils.git_available? if we just installed git
Utils.clear_git_available_cache if formula.name == "git"
+
+ # use installed curl when it's needed and available
+ if formula.name == "curl" &&
+ !DevelopmentTools.curl_handles_most_https_certificates?
+ ENV["HOMEBREW_CURL"] = formula.opt_bin/"curl"
+ end
ensure
unlock
end
diff --git a/Library/Homebrew/global.rb b/Library/Homebrew/global.rb
index 9f79781b4..32b5377a0 100644
--- a/Library/Homebrew/global.rb
+++ b/Library/Homebrew/global.rb
@@ -45,11 +45,15 @@ module Homebrew
@failed == true
end
- attr_writer :raise_deprecation_exceptions
+ attr_writer :raise_deprecation_exceptions, :auditing
def raise_deprecation_exceptions?
@raise_deprecation_exceptions == true
end
+
+ def auditing?
+ @auditing == true
+ end
end
end
diff --git a/Library/Homebrew/gpg.rb b/Library/Homebrew/gpg.rb
index f56473df3..de2089dda 100644
--- a/Library/Homebrew/gpg.rb
+++ b/Library/Homebrew/gpg.rb
@@ -7,8 +7,7 @@ class Gpg
next unless gpg_short_version
gpg_version = Version.create(gpg_short_version.to_s)
@version = gpg_version
- gpg_version == Version.create("2.1") ||
- gpg_version == Version.create("2.0")
+ gpg_version >= Version.create("2.0")
end
end
@@ -38,12 +37,30 @@ class Gpg
Key-Length: 2048
Subkey-Type: RSA
Subkey-Length: 2048
- Passphrase: ''
Name-Real: Testing
Name-Email: testing@foo.bar
Expire-Date: 1d
+ %no-protection
%commit
EOS
system GPG_EXECUTABLE, "--batch", "--gen-key", "batch.gpg"
end
+
+ def self.cleanup_test_processes!
+ odie "No GPG present to test against!" unless available?
+ gpgconf = Pathname.new(GPG_EXECUTABLE).parent/"gpgconf"
+
+ system gpgconf, "--kill", "gpg-agent"
+ system gpgconf, "--homedir", "keyrings/live", "--kill",
+ "gpg-agent"
+ end
+
+ def self.test(path)
+ create_test_key(path)
+ begin
+ yield
+ ensure
+ cleanup_test_processes!
+ end
+ end
end
diff --git a/Library/Homebrew/install_renamed.rb b/Library/Homebrew/install_renamed.rb
index 5e200244f..dc5d4cda8 100644
--- a/Library/Homebrew/install_renamed.rb
+++ b/Library/Homebrew/install_renamed.rb
@@ -16,12 +16,12 @@ module InstallRenamed
end
end
- def +(path)
- super(path).extend(InstallRenamed)
+ def +(other)
+ super(other).extend(InstallRenamed)
end
- def /(path)
- super(path).extend(InstallRenamed)
+ def /(other)
+ super(other).extend(InstallRenamed)
end
private
diff --git a/Library/Homebrew/keg.rb b/Library/Homebrew/keg.rb
index 92eab7ad3..677a97c85 100644
--- a/Library/Homebrew/keg.rb
+++ b/Library/Homebrew/keg.rb
@@ -338,7 +338,7 @@ class Keg
dir if dir.directory? && dir.children.any? { |f| f.basename.to_s.start_with?("_") }
when :fish then path/"share/fish/vendor_completions.d"
end
- dir && dir.directory? && !dir.children.empty?
+ dir&.directory? && !dir.children.empty?
end
def functions_installed?(shell)
diff --git a/Library/Homebrew/keg_relocate.rb b/Library/Homebrew/keg_relocate.rb
index ad4c01021..085748632 100644
--- a/Library/Homebrew/keg_relocate.rb
+++ b/Library/Homebrew/keg_relocate.rb
@@ -156,7 +156,7 @@ class Keg
libtool_files = []
path.find do |pn|
- next if pn.symlink? || pn.directory? || pn.extname != ".la"
+ next if pn.symlink? || pn.directory? || ![".la", ".lai"].include?(pn.extname)
libtool_files << pn
end
libtool_files
diff --git a/Library/Homebrew/language/python.rb b/Library/Homebrew/language/python.rb
index 0f8e3a4e6..bfec556d0 100644
--- a/Library/Homebrew/language/python.rb
+++ b/Library/Homebrew/language/python.rb
@@ -23,7 +23,7 @@ module Language
else
homebrew_site_packages(version)
end
- block.call python, version if block
+ block&.call python, version
end
ENV["PYTHONPATH"] = original_pythonpath
end
diff --git a/Library/Homebrew/locale.rb b/Library/Homebrew/locale.rb
index 5e778f3b4..d918e2a2a 100644
--- a/Library/Homebrew/locale.rb
+++ b/Library/Homebrew/locale.rb
@@ -44,8 +44,6 @@ class Locale
raise ParserError, "'#{value}' does not match #{regex}" unless value =~ regex
instance_variable_set(:"@#{key}", value)
end
-
- self
end
def include?(other)
diff --git a/Library/Homebrew/manpages/brew-cask.1.md b/Library/Homebrew/manpages/brew-cask.1.md
index bfb9cd7a5..715d8fd77 100644
--- a/Library/Homebrew/manpages/brew-cask.1.md
+++ b/Library/Homebrew/manpages/brew-cask.1.md
@@ -1,5 +1,5 @@
brew-cask(1) - a friendly binary installer for macOS
-========================================================
+====================================================
## SYNOPSIS
@@ -85,7 +85,7 @@ names, and other aspects of this manual are still subject to change.
If <token> is given, summarize the staged files associated with the
given Cask.
-
+
* `outdated` [--greedy] [--verbose|--quiet] [ <token> ...]:
Without token arguments, display all the installed Casks that have newer
versions available in the tap; otherwise check only the tokens given
@@ -101,9 +101,10 @@ names, and other aspects of this manual are still subject to change.
Reinstall the given Cask.
* `search` or `-S` [<text> | /<regexp>/]:
- Without an argument, display all Casks available for install; otherwise
- perform a substring search of known Cask tokens for <text> or, if the
- text is delimited by slashes (/<regexp>/), it is interpreted as a
+ Without an argument, display all locally available Casks for install; no
+ online search is performed.
+ 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> ... ]:
@@ -255,7 +256,7 @@ Environment variables specific to Homebrew-Cask:
export HOMEBREW_CASK_OPTS='--appdir=~/Applications --fontdir=/Library/Fonts'
Other environment variables:
-
+
* `SUDO_ASKPASS`:
When this variable is set, Homebrew-Cask will call `sudo`(8) with the `-A` option.
diff --git a/Library/Homebrew/missing_formula.rb b/Library/Homebrew/missing_formula.rb
index c3625c8bb..a3d182a2b 100644
--- a/Library/Homebrew/missing_formula.rb
+++ b/Library/Homebrew/missing_formula.rb
@@ -31,7 +31,7 @@ module Homebrew
#{Formatter.url("https://pip.readthedocs.io/en/stable/installing/")}
EOS
when "pil" then <<-EOS.undent
- Instead of PIL, consider `pip install pillow` or `brew install Homebrew/science/pillow`.
+ Instead of PIL, consider `pip2 install pillow`.
EOS
when "macruby" then <<-EOS.undent
MacRuby is not packaged and is on an indefinite development hiatus.
@@ -53,7 +53,7 @@ module Homebrew
ruin SSH's security.
EOS
when "gsutil" then <<-EOS.undent
- Install gsutil with `pip install gsutil`
+ Install gsutil with `pip2 install gsutil`
EOS
when "gfortran" then <<-EOS.undent
GNU Fortran is now provided as part of GCC, and can be installed with:
diff --git a/Library/Homebrew/options.rb b/Library/Homebrew/options.rb
index 9f1253531..05dd643ff 100644
--- a/Library/Homebrew/options.rb
+++ b/Library/Homebrew/options.rb
@@ -69,29 +69,29 @@ class Options
@options.each(*args, &block)
end
- def <<(o)
- @options << o
+ def <<(other)
+ @options << other
self
end
- def +(o)
- self.class.new(@options + o)
+ def +(other)
+ self.class.new(@options + other)
end
- def -(o)
- self.class.new(@options - o)
+ def -(other)
+ self.class.new(@options - other)
end
- def &(o)
- self.class.new(@options & o)
+ def &(other)
+ self.class.new(@options & other)
end
- def |(o)
- self.class.new(@options | o)
+ def |(other)
+ self.class.new(@options | other)
end
- def *(arg)
- @options.to_a * arg
+ def *(other)
+ @options.to_a * other
end
def empty?
diff --git a/Library/Homebrew/os/mac.rb b/Library/Homebrew/os/mac.rb
index 5074665fc..15c301f99 100644
--- a/Library/Homebrew/os/mac.rb
+++ b/Library/Homebrew/os/mac.rb
@@ -11,7 +11,7 @@ module OS
module Mac
module_function
- ::MacOS = self # rubocop:disable Style/ConstantName
+ ::MacOS = self # rubocop:disable Naming/ConstantName
raise "Loaded OS::Mac on generic OS!" if ENV["HOMEBREW_TEST_GENERIC_OS"]
@@ -34,12 +34,12 @@ module OS
def prerelease?
# TODO: bump version when new OS is released
- version >= "10.13"
+ version >= "10.14"
end
def outdated_release?
# TODO: bump version when new OS is released
- version < "10.10"
+ version < "10.11"
end
def cat
@@ -104,7 +104,7 @@ module OS
# Returns the path to an SDK or nil, following the rules set by #sdk.
def sdk_path(v = nil)
s = sdk(v)
- s.path unless s.nil?
+ s&.path
end
# See these issues for some history:
@@ -129,8 +129,8 @@ module OS
paths << path if path.exist?
end
- # Finally, some users make their MacPorts or Fink directorie
- # read-only in order to try out Homebrew, but this doens't work as
+ # Finally, some users make their MacPorts or Fink directories
+ # read-only in order to try out Homebrew, but this doesn't work as
# some build scripts error out when trying to read from these now
# unreadable paths.
%w[/sw /opt/local].map { |p| Pathname.new(p) }.each do |path|
diff --git a/Library/Homebrew/os/mac/linkage_checker.rb b/Library/Homebrew/os/mac/linkage_checker.rb
index 786827852..f6aa4c2f3 100644
--- a/Library/Homebrew/os/mac/linkage_checker.rb
+++ b/Library/Homebrew/os/mac/linkage_checker.rb
@@ -5,7 +5,7 @@ require "formula"
class LinkageChecker
attr_reader :keg, :formula
attr_reader :brewed_dylibs, :system_dylibs, :broken_dylibs, :variable_dylibs
- attr_reader :undeclared_deps, :reverse_links
+ attr_reader :undeclared_deps, :unnecessary_deps, :reverse_links
def initialize(keg, formula = nil)
@keg = keg
@@ -16,6 +16,7 @@ class LinkageChecker
@variable_dylibs = Set.new
@undeclared_deps = []
@reverse_links = Hash.new { |h, k| h[k] = Set.new }
+ @unnecessary_deps = []
check_dylibs
end
@@ -51,7 +52,7 @@ class LinkageChecker
end
end
- @undeclared_deps = check_undeclared_deps if formula
+ @undeclared_deps, @unnecessary_deps = check_undeclared_deps if formula
end
def check_undeclared_deps
@@ -77,6 +78,12 @@ class LinkageChecker
a <=> b
end
end
+ unnecessary_deps = declared_dep_names.reject do |full_name|
+ name = full_name.split("/").last
+ next true if Formula[name].bin.directory?
+ @brewed_dylibs.keys.map { |x| x.split("/").last }.include?(name)
+ end
+ [undeclared_deps, unnecessary_deps]
end
def display_normal_output
@@ -84,7 +91,8 @@ class LinkageChecker
display_items "Homebrew libraries", @brewed_dylibs
display_items "Variable-referenced libraries", @variable_dylibs
display_items "Missing libraries", @broken_dylibs
- display_items "Possible undeclared dependencies", @undeclared_deps
+ display_items "Undeclared dependencies with linkage", @undeclared_deps
+ display_items "Dependencies with no linkage", @unnecessary_deps
end
def display_reverse_output
@@ -102,6 +110,7 @@ class LinkageChecker
def display_test_output
display_items "Missing libraries", @broken_dylibs
+ display_items "Possible unnecessary dependencies", @unnecessary_deps
puts "No broken dylib links" if @broken_dylibs.empty?
end
@@ -113,6 +122,10 @@ class LinkageChecker
!@undeclared_deps.empty?
end
+ def unnecessary_deps?
+ !@unnecessary_deps.empty?
+ end
+
private
# Whether or not dylib is a harmless broken link, meaning that it's
diff --git a/Library/Homebrew/os/mac/version.rb b/Library/Homebrew/os/mac/version.rb
index 89016bb4d..db6dfcb1a 100644
--- a/Library/Homebrew/os/mac/version.rb
+++ b/Library/Homebrew/os/mac/version.rb
@@ -12,6 +12,7 @@ module OS
mountain_lion: "10.8",
lion: "10.7",
snow_leopard: "10.6",
+ leopard_64: "10.5",
leopard: "10.5",
tiger: "10.4",
}.freeze
diff --git a/Library/Homebrew/os/mac/xcode.rb b/Library/Homebrew/os/mac/xcode.rb
index 6f7deaa10..59e7026bd 100644
--- a/Library/Homebrew/os/mac/xcode.rb
+++ b/Library/Homebrew/os/mac/xcode.rb
@@ -216,7 +216,7 @@ module OS
# 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.13" then "900.0.34.1"
+ when "10.13" then "900.0.37"
when "10.12" then "802.0.42"
when "10.11" then "800.0.42.1"
when "10.10" then "700.1.81"
diff --git a/Library/Homebrew/pkg_version.rb b/Library/Homebrew/pkg_version.rb
index 761a349fd..b68d78cf8 100644
--- a/Library/Homebrew/pkg_version.rb
+++ b/Library/Homebrew/pkg_version.rb
@@ -23,7 +23,7 @@ class PkgVersion
end
def to_s
- if revision > 0
+ if revision.positive?
"#{version}_#{revision}"
else
version.to_s
diff --git a/Library/Homebrew/requirements/gpg2_requirement.rb b/Library/Homebrew/requirements/gpg2_requirement.rb
index d570983eb..ebdd71f6e 100644
--- a/Library/Homebrew/requirements/gpg2_requirement.rb
+++ b/Library/Homebrew/requirements/gpg2_requirement.rb
@@ -5,8 +5,8 @@ class GPG2Requirement < Requirement
fatal true
default_formula "gnupg"
- # GPGTools installs GnuPG 2.0.x as a vanilla `gpg` symlink
- # pointing to `gpg2`. Homebrew install 2.1.x as a non-symlink `gpg`.
- # We support both the 2.0.x "stable" and 2.1.x "modern" series here.
+ # GPGTools installs GnuPG 2.0.x as a `gpg` symlink pointing
+ # to `gpg2`. Our `gnupg` installs only a non-symlink `gpg`.
+ # The aim is to retain support for any version above 2.0.
satisfy(build_env: false) { Gpg.gpg || Gpg.gpg2 }
end
diff --git a/Library/Homebrew/requirements/java_requirement.rb b/Library/Homebrew/requirements/java_requirement.rb
index ab6dca51d..de3a33eb4 100644
--- a/Library/Homebrew/requirements/java_requirement.rb
+++ b/Library/Homebrew/requirements/java_requirement.rb
@@ -69,14 +69,14 @@ class JavaRequirement < Requirement
rescue FormulaUnavailableError
nil
end
- javas << jdk.bin/"java" if jdk && jdk.installed?
+ javas << jdk.bin/"java" if jdk&.installed?
javas << which("java")
javas
end
def preferred_java
possible_javas.detect do |java|
- next false unless java && java.executable?
+ next false unless java&.executable?
next true unless @version
next true if satisfies_version(java)
end
diff --git a/Library/Homebrew/requirements/ruby_requirement.rb b/Library/Homebrew/requirements/ruby_requirement.rb
index acc655924..a9ec8c42d 100644
--- a/Library/Homebrew/requirements/ruby_requirement.rb
+++ b/Library/Homebrew/requirements/ruby_requirement.rb
@@ -41,9 +41,7 @@ class RubyRequirement < Requirement
def rubies
rubies = which_all("ruby")
ruby_formula = Formula["ruby"]
- if ruby_formula && ruby_formula.installed?
- rubies.unshift ruby_formula.bin/"ruby"
- end
+ rubies.unshift ruby_formula.bin/"ruby" if ruby_formula&.installed?
rubies.uniq
end
diff --git a/Library/Homebrew/rubocops.rb b/Library/Homebrew/rubocops.rb
index b1144e075..8dc49bb45 100644
--- a/Library/Homebrew/rubocops.rb
+++ b/Library/Homebrew/rubocops.rb
@@ -11,3 +11,4 @@ require_relative "./rubocops/conflicts_cop"
require_relative "./rubocops/options_cop"
require_relative "./rubocops/urls_cop"
require_relative "./rubocops/lines_cop"
+require_relative "./rubocops/class_cop"
diff --git a/Library/Homebrew/rubocops/class_cop.rb b/Library/Homebrew/rubocops/class_cop.rb
new file mode 100644
index 000000000..dad81abfc
--- /dev/null
+++ b/Library/Homebrew/rubocops/class_cop.rb
@@ -0,0 +1,41 @@
+require_relative "./extend/formula_cop"
+
+module RuboCop
+ module Cop
+ module FormulaAudit
+ class ClassName < FormulaCop
+ DEPRECATED_CLASSES = %w[
+ GithubGistFormula
+ ScriptFileFormula
+ AmazonWebServicesFormula
+ ].freeze
+
+ def audit_formula(_node, _class_node, parent_class_node, _body_node)
+ parent_class = class_name(parent_class_node)
+ return unless DEPRECATED_CLASSES.include?(parent_class)
+ problem "#{parent_class} is deprecated, use Formula instead"
+ end
+
+ private
+
+ def autocorrect(node)
+ lambda do |corrector|
+ corrector.replace(node.source_range, "Formula")
+ end
+ end
+ end
+ end
+
+ module FormulaAuditStrict
+ # - `test do ..end` should be defined in the formula
+ class Test < FormulaCop
+ MSG = "A `test do` test block should be added".freeze
+
+ def audit_formula(_node, _class_node, _parent_class_node, body_node)
+ return if find_block(body_node, :test)
+ problem MSG
+ end
+ end
+ end
+ end
+end
diff --git a/Library/Homebrew/rubocops/components_order_cop.rb b/Library/Homebrew/rubocops/components_order_cop.rb
index f1179d9a4..3bf2ede16 100644
--- a/Library/Homebrew/rubocops/components_order_cop.rb
+++ b/Library/Homebrew/rubocops/components_order_cop.rb
@@ -87,8 +87,8 @@ module RuboCop
# preceding_comp_arr: array containing components of same type
order_idx, curr_p_idx, preceding_comp_arr = get_state(node1)
- # curr_p_idx > 0 means node1 needs to be grouped with its own kind
- if curr_p_idx > 0
+ # curr_p_idx.positive? means node1 needs to be grouped with its own kind
+ if curr_p_idx.positive?
node2 = preceding_comp_arr[curr_p_idx - 1]
indentation = " " * (start_column(node2) - line_start_column(node2))
line_breaks = node2.multiline? ? "\n\n" : "\n"
diff --git a/Library/Homebrew/rubocops/conflicts_cop.rb b/Library/Homebrew/rubocops/conflicts_cop.rb
index c1b801559..6f05d0567 100644
--- a/Library/Homebrew/rubocops/conflicts_cop.rb
+++ b/Library/Homebrew/rubocops/conflicts_cop.rb
@@ -18,7 +18,7 @@ module RuboCop
def audit_formula(_node, _class_node, _parent_class_node, body)
return unless versioned_formula?
- problem MSG if !formula_file_name.start_with?(*WHITELIST) &&
+ problem MSG if !@formula_name.start_with?(*WHITELIST) &&
method_called_ever?(body, :conflicts_with)
end
end
diff --git a/Library/Homebrew/rubocops/extend/formula_cop.rb b/Library/Homebrew/rubocops/extend/formula_cop.rb
index 7844f7bf2..47dd2d803 100644
--- a/Library/Homebrew/rubocops/extend/formula_cop.rb
+++ b/Library/Homebrew/rubocops/extend/formula_cop.rb
@@ -4,16 +4,17 @@ require_relative "../../extend/string"
module RuboCop
module Cop
class FormulaCop < Cop
+ attr_accessor :file_path
@registry = Cop.registry
# This method is called by RuboCop and is the main entry point
def on_class(node)
- file_path = processed_source.buffer.name
- return unless file_path_allowed?(file_path)
+ @file_path = processed_source.buffer.name
+ return unless file_path_allowed?
return unless formula_class?(node)
return unless respond_to?(:audit_formula)
class_node, parent_class_node, @body = *node
- @formula_name = class_name(class_node)
+ @formula_name = Pathname.new(@file_path).basename(".rb").to_s
audit_formula(node, class_node, parent_class_node, @body)
end
@@ -100,19 +101,22 @@ module RuboCop
def find_method_with_args(node, method_name, *args)
methods = find_every_method_call_by_name(node, method_name)
methods.each do |method|
- next unless parameters_passed?(method, *args)
- yield method
+ yield method if parameters_passed?(method, *args)
end
end
# Matches a method with a receiver,
# EX: to match `Formula.factory(name)`
# call `find_instance_method_call(node, "Formula", :factory)`
+ # EX: to match `build.head?`
+ # call `find_instance_method_call(node, :build, :head?)`
# yields to a block with matching method node
def find_instance_method_call(node, instance, method_name)
methods = find_every_method_call_by_name(node, method_name)
methods.each do |method|
- next unless method.receiver && method.receiver.const_name == instance
+ next if method.receiver.nil?
+ next if method.receiver.const_name != instance &&
+ method.receiver.method_name != instance
@offense_source_range = method.source_range
@offensive_node = method
yield method
@@ -400,12 +404,7 @@ module RuboCop
# Returns true if the formula is versioned
def versioned_formula?
- formula_file_name.include?("@") || @formula_name.match(/AT\d+/)
- end
-
- # Returns filename of the formula without the extension
- def formula_file_name
- File.basename(processed_source.buffer.name, ".rb")
+ @formula_name.include?("@")
end
# Returns printable component name
@@ -414,6 +413,12 @@ module RuboCop
method_name(component_node) if component_node.def_type?
end
+ # Returns the formula tap
+ def formula_tap
+ return unless match_obj = @file_path.match(%r{/(homebrew-\w+)/})
+ match_obj[1]
+ end
+
def problem(msg)
add_offense(@offensive_node, @offense_source_range, msg)
end
@@ -422,14 +427,21 @@ module RuboCop
def formula_class?(node)
_, class_node, = *node
- class_node && string_content(class_node) == "Formula"
+ class_names = %w[
+ Formula
+ GithubGistFormula
+ ScriptFileFormula
+ AmazonWebServicesFormula
+ ]
+
+ class_node && class_names.include?(string_content(class_node))
end
- def file_path_allowed?(file_path)
+ def file_path_allowed?
paths_to_exclude = [%r{/Library/Homebrew/compat/},
%r{/Library/Homebrew/test/}]
- return true if file_path.nil? # file_path is nil when source is directly passed to the cop eg., in specs
- file_path !~ Regexp.union(paths_to_exclude)
+ return true if @file_path.nil? # file_path is nil when source is directly passed to the cop eg., in specs
+ @file_path !~ Regexp.union(paths_to_exclude)
end
end
end
diff --git a/Library/Homebrew/rubocops/lines_cop.rb b/Library/Homebrew/rubocops/lines_cop.rb
index ed50ba49c..01b13585c 100644
--- a/Library/Homebrew/rubocops/lines_cop.rb
+++ b/Library/Homebrew/rubocops/lines_cop.rb
@@ -21,7 +21,7 @@ module RuboCop
begin_pos = start_column(parent_class_node)
end_pos = end_column(class_node)
return unless begin_pos-end_pos != 3
- problem "Use a space in class inheritance: class #{@formula_name} < #{class_name(parent_class_node)}"
+ problem "Use a space in class inheritance: class #{class_name(class_node)} < #{class_name(parent_class_node)}"
end
end
@@ -67,7 +67,72 @@ module RuboCop
next unless block_arg.source.size>1
problem "\"inreplace <filenames> do |s|\" is preferred over \"|#{block_arg.source}|\"."
end
+
+ [:rebuild, :version_scheme].each do |method_name|
+ find_method_with_args(body_node, method_name, 0) do
+ problem "'#{method_name} 0' should be removed"
+ end
+ end
+
+ [:mac?, :linux?].each do |method_name|
+ next unless formula_tap == "homebrew-core"
+ find_instance_method_call(body_node, "OS", method_name) do |check|
+ problem "Don't use #{check.source}; Homebrew/core only supports macOS"
+ end
+ end
+
+ find_method_with_args(body_node, :fails_with, :llvm) do
+ problem "'fails_with :llvm' is now a no-op so should be removed"
+ end
+
+ find_method_with_args(body_node, :system, /^(otool|install_name_tool|lipo)$/) do
+ next if @formula_name == "cctools"
+ problem "Use ruby-macho instead of calling #{@offensive_node.source}"
+ end
+
+ find_every_method_call_by_name(body_node, :system).each do |method_node|
+ # Skip Kibana: npm cache edge (see formula for more details)
+ next if @formula_name =~ /^kibana(\@\d+(\.\d+)?)?$/
+ first_param, second_param = parameters(method_node)
+ next if !node_equals?(first_param, "npm") ||
+ !node_equals?(second_param, "install")
+ offending_node(method_node)
+ problem "Use Language::Node for npm install args" unless languageNodeModule?(method_node)
+ end
+
+ if find_method_def(body_node, :test)
+ problem "Use new-style test definitions (test do)"
+ end
+
+ if find_method_def(body_node, :options)
+ problem "Use new-style option definitions"
+ end
+
+ find_method_with_args(body_node, :skip_clean, :all) do
+ problem <<-EOS.undent.chomp
+ `skip_clean :all` is deprecated; brew no longer strips symbols
+ Pass explicit paths to prevent Homebrew from removing empty folders.
+ EOS
+ end
+
+ find_instance_method_call(body_node, :build, :universal?) do
+ next if @formula_name == "wine"
+ problem "macOS has been 64-bit only since 10.6 so build.universal? is deprecated."
+ end
+
+ find_instance_method_call(body_node, "ENV", :universal_binary) do
+ problem "macOS has been 64-bit only since 10.6 so ENV.universal_binary is deprecated."
+ end
+
+ find_instance_method_call(body_node, "ENV", :x11) do
+ problem 'Use "depends_on :x11" instead of "ENV.x11"'
+ end
end
+
+ # Node Pattern search for Language::Node
+ def_node_search :languageNodeModule?, <<-EOS.undent
+ (const (const nil :Language) :Node)
+ EOS
end
end
end
diff --git a/Library/Homebrew/sandbox.rb b/Library/Homebrew/sandbox.rb
index 8c662857e..7d23e5966 100644
--- a/Library/Homebrew/sandbox.rb
+++ b/Library/Homebrew/sandbox.rb
@@ -167,7 +167,7 @@ class Sandbox
def add_rule(rule)
s = "("
- s << ((rule[:allow]) ? "allow" : "deny")
+ s << (rule[:allow] ? "allow" : "deny")
s << " #{rule[:operation]}"
s << " (#{rule[:filter]})" if rule[:filter]
s << " (with #{rule[:modifier]})" if rule[:modifier]
diff --git a/Library/Homebrew/software_spec.rb b/Library/Homebrew/software_spec.rb
index 49d818f0f..dd6026fcf 100644
--- a/Library/Homebrew/software_spec.rb
+++ b/Library/Homebrew/software_spec.rb
@@ -267,7 +267,7 @@ class Bottle
end
def suffix
- s = (rebuild > 0) ? ".#{rebuild}" : ""
+ s = rebuild.positive? ? ".#{rebuild}" : ""
".bottle#{s}.tar.gz"
end
end
diff --git a/Library/Homebrew/system_config.rb b/Library/Homebrew/system_config.rb
index 5663295c2..3e1acd4ff 100644
--- a/Library/Homebrew/system_config.rb
+++ b/Library/Homebrew/system_config.rb
@@ -134,7 +134,7 @@ class SystemConfig
# java_home doesn't exist on all macOSs; it might be missing on older versions.
return "N/A" unless File.executable? "/usr/libexec/java_home"
- java_xml = Utils.popen_read("/usr/libexec/java_home", "--xml", "--failfast")
+ java_xml = Utils.popen_read("/usr/libexec/java_home", "--xml", "--failfast", err: :close)
return "N/A" unless $CHILD_STATUS.success?
javas = []
REXML::XPath.each(REXML::Document.new(java_xml), "//key[text()='JVMVersion']/following-sibling::string") do |item|
diff --git a/Library/Homebrew/tab.rb b/Library/Homebrew/tab.rb
index e7df88356..af19cabe6 100644
--- a/Library/Homebrew/tab.rb
+++ b/Library/Homebrew/tab.rb
@@ -324,7 +324,7 @@ class Tab < OpenStruct
"poured_from_bottle" => poured_from_bottle,
"installed_as_dependency" => installed_as_dependency,
"installed_on_request" => installed_on_request,
- "changed_files" => changed_files && changed_files.map(&:to_s),
+ "changed_files" => changed_files&.map(&:to_s),
"time" => time,
"source_modified_time" => source_modified_time.to_i,
"HEAD" => self.HEAD,
diff --git a/Library/Homebrew/tap.rb b/Library/Homebrew/tap.rb
index acf2d196b..fff58b754 100644
--- a/Library/Homebrew/tap.rb
+++ b/Library/Homebrew/tap.rb
@@ -557,11 +557,9 @@ class CoreTap < Tap
@instance ||= new
end
- def self.ensure_installed!(options = {})
+ def self.ensure_installed!
return if instance.installed?
- args = ["tap", instance.name]
- args << "-q" if options.fetch(:quiet, true)
- safe_system HOMEBREW_BREW_FILE, *args
+ safe_system HOMEBREW_BREW_FILE, "tap", instance.name
end
# @private
@@ -656,6 +654,5 @@ class TapConfig
tap.path.cd do
safe_system "git", "config", "--local", "--replace-all", "homebrew.#{key}", value.to_s
end
- value
end
end
diff --git a/Library/Homebrew/test/cask/artifact/alt_target_spec.rb b/Library/Homebrew/test/cask/artifact/alt_target_spec.rb
index 9e8d83bb4..02be796ed 100644
--- a/Library/Homebrew/test/cask/artifact/alt_target_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/alt_target_spec.rb
@@ -3,7 +3,7 @@ describe Hbc::Artifact::App, :cask do
let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-alt-target.rb") }
let(:install_phase) {
- -> { Hbc::Artifact::App.new(cask).install_phase }
+ -> { described_class.for_cask(cask).each { |artifact| artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) } }
}
let(:source_path) { cask.staged_path.join("Caffeine.app") }
diff --git a/Library/Homebrew/test/cask/artifact/app_spec.rb b/Library/Homebrew/test/cask/artifact/app_spec.rb
index 0add472e2..f67ffd31b 100644
--- a/Library/Homebrew/test/cask/artifact/app_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/app_spec.rb
@@ -2,13 +2,13 @@ describe Hbc::Artifact::App, :cask do
let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb") }
let(:command) { Hbc::SystemCommand }
let(:force) { false }
- let(:app) { Hbc::Artifact::App.new(cask, command: command, force: force) }
+ let(:app) { described_class.for_cask(cask).first }
let(:source_path) { cask.staged_path.join("Caffeine.app") }
let(:target_path) { Hbc.appdir.join("Caffeine.app") }
- let(:install_phase) { app.install_phase }
- let(:uninstall_phase) { app.uninstall_phase }
+ let(:install_phase) { app.install_phase(command: command, force: force) }
+ let(:uninstall_phase) { app.uninstall_phase(command: command, force: force) }
before(:each) do
InstallHelper.install_without_artifacts(cask)
@@ -105,8 +105,8 @@ describe Hbc::Artifact::App, :cask do
describe "target is user-owned but contains read-only files" do
before(:each) do
- system "/usr/bin/touch", "--", "#{target_path}/foo"
- system "/bin/chmod", "--", "0555", target_path
+ FileUtils.touch "#{target_path}/foo"
+ FileUtils.chmod 0555, target_path
end
it "overwrites the existing app" do
@@ -138,7 +138,7 @@ describe Hbc::Artifact::App, :cask do
end
after(:each) do
- system "/bin/chmod", "--", "0755", target_path
+ FileUtils.chmod 0755, target_path
end
end
end
@@ -206,8 +206,8 @@ describe Hbc::Artifact::App, :cask do
end
describe "summary" do
- let(:description) { app.summary[:english_description] }
- let(:contents) { app.summary[:contents] }
+ let(:description) { app.class.english_description }
+ let(:contents) { app.summarize_installed }
it "returns the correct english_description" do
expect(description).to eq("Apps")
@@ -217,14 +217,13 @@ describe Hbc::Artifact::App, :cask do
it "returns the path to the app" do
install_phase
- expect(contents).to eq(["#{target_path} (#{target_path.abv})"])
+ expect(contents).to eq("#{target_path} (#{target_path.abv})")
end
end
describe "app is missing" do
it "returns a warning and the supposed path to the app" do
- expect(contents.size).to eq(1)
- expect(contents[0]).to match(/.*Missing App.*: #{target_path}/)
+ expect(contents).to match(/.*Missing App.*: #{target_path}/)
end
end
end
diff --git a/Library/Homebrew/test/cask/artifact/binary_spec.rb b/Library/Homebrew/test/cask/artifact/binary_spec.rb
index ce00e3935..5ffaca861 100644
--- a/Library/Homebrew/test/cask/artifact/binary_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/binary_spec.rb
@@ -26,7 +26,8 @@ describe Hbc::Artifact::Binary, :cask do
end
it "links the binary to the proper directory" do
- Hbc::Artifact::Binary.new(cask).install_phase
+ described_class.for_cask(cask)
+ .each { |artifact| artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) }
expect(expected_path).to be_a_symlink
expect(expected_path.readlink).to exist
@@ -45,7 +46,8 @@ describe Hbc::Artifact::Binary, :cask do
expect(FileUtils).to receive(:chmod)
.with("+x", cask.staged_path.join("naked_non_executable")).and_call_original
- Hbc::Artifact::Binary.new(cask).install_phase
+ described_class.for_cask(cask)
+ .each { |artifact| artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) }
expect(expected_path).to be_a_symlink
expect(expected_path.readlink).to be_executable
@@ -56,7 +58,8 @@ describe Hbc::Artifact::Binary, :cask do
FileUtils.touch expected_path
expect {
- Hbc::Artifact::Binary.new(cask).install_phase
+ described_class.for_cask(cask)
+ .each { |artifact| artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) }
}.to raise_error(Hbc::CaskError)
expect(expected_path).not_to be :symlink?
@@ -65,7 +68,8 @@ describe Hbc::Artifact::Binary, :cask do
it "clobbers an existing symlink" do
expected_path.make_symlink("/tmp")
- Hbc::Artifact::Binary.new(cask).install_phase
+ described_class.for_cask(cask)
+ .each { |artifact| artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) }
expect(File.readlink(expected_path)).not_to eq("/tmp")
end
@@ -73,7 +77,8 @@ describe Hbc::Artifact::Binary, :cask do
it "creates parent directory if it doesn't exist" do
FileUtils.rmdir Hbc.binarydir
- Hbc::Artifact::Binary.new(cask).install_phase
+ described_class.for_cask(cask)
+ .each { |artifact| artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) }
expect(expected_path.exist?).to be true
end
@@ -86,8 +91,10 @@ describe Hbc::Artifact::Binary, :cask do
}
it "links the binary to the proper directory" do
- Hbc::Artifact::App.new(cask).install_phase
- Hbc::Artifact::Binary.new(cask).install_phase
+ Hbc::Artifact::App.for_cask(cask)
+ .each { |artifact| artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) }
+ described_class.for_cask(cask)
+ .each { |artifact| artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) }
expect(expected_path).to be_a_symlink
expect(expected_path.readlink).to exist
diff --git a/Library/Homebrew/test/cask/artifact/generic_artifact_spec.rb b/Library/Homebrew/test/cask/artifact/generic_artifact_spec.rb
index cb2ef9850..bec8c2742 100644
--- a/Library/Homebrew/test/cask/artifact/generic_artifact_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/generic_artifact_spec.rb
@@ -2,7 +2,7 @@ describe Hbc::Artifact::Artifact, :cask do
let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-generic-artifact.rb") }
let(:install_phase) {
- -> { Hbc::Artifact::Artifact.new(cask).install_phase }
+ -> { described_class.for_cask(cask).each { |artifact| artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) } }
}
let(:source_path) { cask.staged_path.join("Caffeine.app") }
@@ -12,11 +12,11 @@ describe Hbc::Artifact::Artifact, :cask do
InstallHelper.install_without_artifacts(cask)
end
- describe "with no target" do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-generic-artifact-no-target.rb") }
-
- it "fails to install with no target" do
- expect(install_phase).to raise_error(Hbc::CaskInvalidError)
+ context "without target" do
+ it "fails to load" do
+ expect {
+ Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-generic-artifact-no-target.rb")
+ }.to raise_error(Hbc::CaskInvalidError, /target required for Generic Artifact/)
end
end
diff --git a/Library/Homebrew/test/cask/artifact/nested_container_spec.rb b/Library/Homebrew/test/cask/artifact/nested_container_spec.rb
index be7ba5ff8..41d143764 100644
--- a/Library/Homebrew/test/cask/artifact/nested_container_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/nested_container_spec.rb
@@ -5,7 +5,8 @@ describe Hbc::Artifact::NestedContainer, :cask do
InstallHelper.install_without_artifacts(c)
end
- Hbc::Artifact::NestedContainer.new(cask).install_phase
+ described_class.for_cask(cask)
+ .each { |artifact| artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) }
expect(cask.staged_path.join("MyNestedApp.app")).to be_a_directory
end
diff --git a/Library/Homebrew/test/cask/artifact/pkg_spec.rb b/Library/Homebrew/test/cask/artifact/pkg_spec.rb
index 3e62616ea..c6a45c49a 100644
--- a/Library/Homebrew/test/cask/artifact/pkg_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/pkg_spec.rb
@@ -8,7 +8,7 @@ describe Hbc::Artifact::Pkg, :cask do
describe "install_phase" do
it "runs the system installer on the specified pkgs" do
- pkg = Hbc::Artifact::Pkg.new(cask, command: fake_system_command)
+ pkg = described_class.for_cask(cask).first
expect(fake_system_command).to receive(:run!).with(
"/usr/sbin/installer",
@@ -17,7 +17,7 @@ describe Hbc::Artifact::Pkg, :cask do
print_stdout: true,
)
- pkg.install_phase
+ pkg.install_phase(command: fake_system_command)
end
end
@@ -25,7 +25,7 @@ describe Hbc::Artifact::Pkg, :cask do
let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-choices.rb") }
it "passes the choice changes xml to the system installer" do
- pkg = Hbc::Artifact::Pkg.new(cask, command: fake_system_command)
+ pkg = described_class.for_cask(cask).first
file = double(path: Pathname.new("/tmp/choices.xml"))
@@ -57,7 +57,7 @@ describe Hbc::Artifact::Pkg, :cask do
print_stdout: true,
)
- pkg.install_phase
+ pkg.install_phase(command: fake_system_command)
end
end
end
diff --git a/Library/Homebrew/test/cask/artifact/postflight_block_spec.rb b/Library/Homebrew/test/cask/artifact/postflight_block_spec.rb
index 51b1431f0..4a44bb59b 100644
--- a/Library/Homebrew/test/cask/artifact/postflight_block_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/postflight_block_spec.rb
@@ -11,7 +11,8 @@ describe Hbc::Artifact::PostflightBlock, :cask do
end
end
- described_class.new(cask).install_phase
+ described_class.for_cask(cask)
+ .each { |artifact| artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) }
expect(called).to be true
expect(yielded_arg).to be_kind_of(Hbc::DSL::Postflight)
@@ -30,7 +31,8 @@ describe Hbc::Artifact::PostflightBlock, :cask do
end
end
- described_class.new(cask).uninstall_phase
+ described_class.for_cask(cask)
+ .each { |artifact| artifact.uninstall_phase(command: Hbc::NeverSudoSystemCommand, force: false) }
expect(called).to be true
expect(yielded_arg).to be_kind_of(Hbc::DSL::UninstallPostflight)
diff --git a/Library/Homebrew/test/cask/artifact/preflight_block_spec.rb b/Library/Homebrew/test/cask/artifact/preflight_block_spec.rb
index b13c4ab9d..d7d4e72d9 100644
--- a/Library/Homebrew/test/cask/artifact/preflight_block_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/preflight_block_spec.rb
@@ -11,7 +11,8 @@ describe Hbc::Artifact::PreflightBlock, :cask do
end
end
- described_class.new(cask).install_phase
+ described_class.for_cask(cask)
+ .each { |artifact| artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) }
expect(called).to be true
expect(yielded_arg).to be_kind_of Hbc::DSL::Preflight
@@ -30,7 +31,8 @@ describe Hbc::Artifact::PreflightBlock, :cask do
end
end
- described_class.new(cask).uninstall_phase
+ described_class.for_cask(cask)
+ .each { |artifact| artifact.uninstall_phase(command: Hbc::NeverSudoSystemCommand, force: false) }
expect(called).to be true
expect(yielded_arg).to be_kind_of Hbc::DSL::UninstallPreflight
diff --git a/Library/Homebrew/test/cask/artifact/suite_spec.rb b/Library/Homebrew/test/cask/artifact/suite_spec.rb
index 8c217a9e0..2f913fecc 100644
--- a/Library/Homebrew/test/cask/artifact/suite_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/suite_spec.rb
@@ -1,7 +1,9 @@
describe Hbc::Artifact::Suite, :cask do
let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-suite.rb") }
- let(:install_phase) { -> { Hbc::Artifact::Suite.new(cask).install_phase } }
+ let(:install_phase) {
+ -> { described_class.for_cask(cask).each { |artifact| artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) } }
+ }
let(:target_path) { Hbc.appdir.join("Caffeine") }
let(:source_path) { cask.staged_path.join("Caffeine") }
diff --git a/Library/Homebrew/test/cask/artifact/two_apps_correct_spec.rb b/Library/Homebrew/test/cask/artifact/two_apps_correct_spec.rb
index a1fdd3b74..f6e0d3c97 100644
--- a/Library/Homebrew/test/cask/artifact/two_apps_correct_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/two_apps_correct_spec.rb
@@ -3,7 +3,7 @@ describe Hbc::Artifact::App, :cask do
let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-two-apps-correct.rb") }
let(:install_phase) {
- -> { Hbc::Artifact::App.new(cask).install_phase }
+ -> { described_class.for_cask(cask).each { |artifact| artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) } }
}
let(:source_path_mini) { cask.staged_path.join("Caffeine Mini.app") }
diff --git a/Library/Homebrew/test/cask/artifact/uninstall_no_zap_spec.rb b/Library/Homebrew/test/cask/artifact/uninstall_no_zap_spec.rb
index 8cd0b1e41..d6a8393da 100644
--- a/Library/Homebrew/test/cask/artifact/uninstall_no_zap_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/uninstall_no_zap_spec.rb
@@ -2,7 +2,7 @@ describe Hbc::Artifact::Zap, :cask do
let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-installable.rb") }
let(:zap_artifact) {
- Hbc::Artifact::Zap.new(cask)
+ described_class.for_cask(cask).first
}
before(:each) do
diff --git a/Library/Homebrew/test/cask/artifact/uninstall_zap_shared_examples.rb b/Library/Homebrew/test/cask/artifact/uninstall_zap_shared_examples.rb
index 0e522bc21..06eec4a01 100644
--- a/Library/Homebrew/test/cask/artifact/uninstall_zap_shared_examples.rb
+++ b/Library/Homebrew/test/cask/artifact/uninstall_zap_shared_examples.rb
@@ -1,12 +1,12 @@
shared_examples "#uninstall_phase or #zap_phase" do
- let(:artifact_name) { described_class.artifact_name }
- let(:artifact) { described_class.new(cask, command: fake_system_command) }
+ let(:artifact_dsl_key) { described_class.dsl_key }
+ let(:artifact) { described_class.for_cask(cask).first }
let(:fake_system_command) { Hbc::FakeSystemCommand }
- subject { artifact.public_send(:"#{artifact_name}_phase") }
+ subject { artifact.public_send(:"#{artifact_dsl_key}_phase", command: fake_system_command) }
context "using :launchctl" do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_name}-launchctl.rb") }
+ let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_dsl_key}-launchctl.rb") }
let(:launchctl_list_cmd) { %w[/bin/launchctl list my.fancy.package.service] }
let(:launchctl_remove_cmd) { %w[/bin/launchctl remove my.fancy.package.service] }
let(:unknown_response) { "launchctl list returned unknown response\n" }
@@ -61,7 +61,7 @@ shared_examples "#uninstall_phase or #zap_phase" do
context "using :pkgutil" do
let(:fake_system_command) { class_double(Hbc::SystemCommand) }
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_name}-pkgutil.rb") }
+ let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_dsl_key}-pkgutil.rb") }
let(:main_pkg_id) { "my.fancy.package.main" }
let(:agent_pkg_id) { "my.fancy.package.agent" }
@@ -85,7 +85,7 @@ shared_examples "#uninstall_phase or #zap_phase" do
end
context "using :kext" do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_name}-kext.rb") }
+ let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_dsl_key}-kext.rb") }
let(:kext_id) { "my.fancy.package.kernelextension" }
it "is supported" do
@@ -110,7 +110,7 @@ shared_examples "#uninstall_phase or #zap_phase" do
end
context "using :quit" do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_name}-quit.rb") }
+ let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_dsl_key}-quit.rb") }
let(:bundle_id) { "my.fancy.package.app" }
let(:quit_application_script) do
%Q(tell application id "#{bundle_id}" to quit)
@@ -130,7 +130,7 @@ shared_examples "#uninstall_phase or #zap_phase" do
end
context "using :signal" do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_name}-signal.rb") }
+ let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_dsl_key}-signal.rb") }
let(:bundle_id) { "my.fancy.package.app" }
let(:signals) { %w[TERM KILL] }
let(:unix_pids) { [12_345, 67_890] }
@@ -170,10 +170,10 @@ shared_examples "#uninstall_phase or #zap_phase" do
end
let(:fake_system_command) { Hbc::NeverSudoSystemCommand }
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_name}-#{directive}.rb") }
+ let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_dsl_key}-#{directive}.rb") }
before(:each) do
- allow_any_instance_of(Hbc::Artifact::UninstallBase).to receive(:trash_paths)
+ allow_any_instance_of(Hbc::Artifact::AbstractUninstall).to receive(:trash_paths)
.and_wrap_original do |method, *args|
result = method.call(*args)
FileUtils.rm_rf result.stdout.split("\0")
@@ -196,7 +196,7 @@ shared_examples "#uninstall_phase or #zap_phase" do
context "using :rmdir" do
let(:fake_system_command) { Hbc::NeverSudoSystemCommand }
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_name}-rmdir.rb") }
+ let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_dsl_key}-rmdir.rb") }
let(:empty_directory) { Pathname.new("#{TEST_TMPDIR}/empty_directory_path") }
let(:ds_store) { empty_directory.join(".DS_Store") }
@@ -223,7 +223,7 @@ shared_examples "#uninstall_phase or #zap_phase" do
[:script, :early_script].each do |script_type|
context "using #{script_type.inspect}" do
let(:fake_system_command) { Hbc::NeverSudoSystemCommand }
- let(:token) { "with-#{artifact_name}-#{script_type}".tr("_", "-") }
+ let(:token) { "with-#{artifact_dsl_key}-#{script_type}".tr("_", "-") }
let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/#{token}.rb") }
let(:script_pathname) { cask.staged_path.join("MyFancyPkg", "FancyUninstaller.tool") }
@@ -250,7 +250,7 @@ shared_examples "#uninstall_phase or #zap_phase" do
end
context "using :login_item" do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_name}-login-item.rb") }
+ let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-#{artifact_dsl_key}-login-item.rb") }
it "is supported" do
Hbc::FakeSystemCommand.expects_command(
diff --git a/Library/Homebrew/test/cask/audit_spec.rb b/Library/Homebrew/test/cask/audit_spec.rb
index ddc773e3e..7e140acb2 100644
--- a/Library/Homebrew/test/cask/audit_spec.rb
+++ b/Library/Homebrew/test/cask/audit_spec.rb
@@ -265,19 +265,14 @@ describe Hbc::Audit, :cask do
end
describe "generic artifact checks" do
- context "with no target" do
- let(:cask_token) { "generic-artifact-no-target" }
- it { is_expected.to fail_with(/target required for generic artifact/) }
- end
-
context "with relative target" do
let(:cask_token) { "generic-artifact-relative-target" }
- it { is_expected.to fail_with(/target must be absolute path for generic artifact/) }
+ it { is_expected.to fail_with(/target must be absolute path for Generic Artifact/) }
end
context "with absolute target" do
let(:cask_token) { "generic-artifact-absolute-target" }
- it { should_not fail_with(/target required for generic artifact/) }
+ it { should_not fail_with(/target required for Generic Artifact/) }
end
end
diff --git a/Library/Homebrew/test/cask/cask_spec.rb b/Library/Homebrew/test/cask/cask_spec.rb
index a6ecc207f..5858a7c6d 100644
--- a/Library/Homebrew/test/cask/cask_spec.rb
+++ b/Library/Homebrew/test/cask/cask_spec.rb
@@ -171,4 +171,38 @@ describe Hbc::Cask, :cask do
end
end
end
+
+ describe "full_name" do
+ context "when it is a core cask" do
+ it "is the cask token" do
+ c = Hbc::CaskLoader.load("local-caffeine")
+ expect(c.full_name).to eq("local-caffeine")
+ end
+ end
+
+ context "when it is from a non-core tap" do
+ it "returns the fully-qualified name of the cask" do
+ c = Hbc::CaskLoader.load("third-party/tap/third-party-cask")
+ expect(c.full_name).to eq("third-party/tap/third-party-cask")
+ end
+ end
+
+ context "when it is from no known tap" do
+ it "retuns the cask token" do
+ file = Tempfile.new(%w[tapless-cask .rb])
+
+ begin
+ cask_name = File.basename(file.path, ".rb")
+ file.write "cask '#{cask_name}'"
+ file.close
+
+ c = Hbc::CaskLoader.load(file.path)
+ expect(c.full_name).to eq(cask_name)
+ ensure
+ file.close
+ file.unlink
+ end
+ end
+ end
+ end
end
diff --git a/Library/Homebrew/test/cask/cli/audit_spec.rb b/Library/Homebrew/test/cask/cli/audit_spec.rb
index 01f506c8c..30ab437cb 100644
--- a/Library/Homebrew/test/cask/cli/audit_spec.rb
+++ b/Library/Homebrew/test/cask/cli/audit_spec.rb
@@ -1,8 +1,10 @@
describe Hbc::CLI::Audit, :cask do
- let(:cask) { double("cask", token: nil) }
+ let(:cask) { Hbc::Cask.new(nil) }
describe "selection of Casks to audit" do
it "audits all Casks if no tokens are given" do
+ expect(cask).to be_a Hbc::Cask
+
allow(Hbc).to receive(:all).and_return([cask, cask])
expect(Hbc::Auditor).to receive(:audit).twice.and_return(true)
diff --git a/Library/Homebrew/test/cask/cli/cat_spec.rb b/Library/Homebrew/test/cask/cli/cat_spec.rb
index b726a0b36..5a4b29c6f 100644
--- a/Library/Homebrew/test/cask/cli/cat_spec.rb
+++ b/Library/Homebrew/test/cask/cli/cat_spec.rb
@@ -35,8 +35,7 @@ describe Hbc::CLI::Cat, :cask do
it "raises an exception when the Cask does not exist" do
expect { Hbc::CLI::Cat.run("notacask") }
- .to output(/is unavailable/).to_stderr
- .and raise_error(Hbc::CaskError, "Cat incomplete.")
+ .to raise_error(Hbc::CaskUnavailableError, /is unavailable/)
end
describe "when no Cask is specified" do
diff --git a/Library/Homebrew/test/cask/cli/create_spec.rb b/Library/Homebrew/test/cask/cli/create_spec.rb
index d77b0a2aa..17d426f78 100644
--- a/Library/Homebrew/test/cask/cli/create_spec.rb
+++ b/Library/Homebrew/test/cask/cli/create_spec.rb
@@ -39,7 +39,7 @@ describe Hbc::CLI::Create, :cask do
it "raises an exception when more than one Cask is given" do
expect {
described_class.run("additional-cask", "another-cask")
- }.to raise_error(/Only one Cask can be created at a time./)
+ }.to raise_error(/Only one Cask can be created at a time\./)
end
it "raises an exception when the Cask already exists" do
diff --git a/Library/Homebrew/test/cask/cli/edit_spec.rb b/Library/Homebrew/test/cask/cli/edit_spec.rb
index 5d5cbf4b9..51542807f 100644
--- a/Library/Homebrew/test/cask/cli/edit_spec.rb
+++ b/Library/Homebrew/test/cask/cli/edit_spec.rb
@@ -12,7 +12,7 @@ describe Hbc::CLI::Edit, :cask do
it "raises an error when given more than one argument" do
expect {
described_class.new("local-caffeine", "local-transmission")
- }.to raise_error(/Only one Cask can be created at a time./)
+ }.to raise_error(/Only one Cask can be edited at a time\./)
end
it "raises an exception when the Cask doesnt exist" do
diff --git a/Library/Homebrew/test/cask/cli/fetch_spec.rb b/Library/Homebrew/test/cask/cli/fetch_spec.rb
index f71c23fb6..faaa69b35 100644
--- a/Library/Homebrew/test/cask/cli/fetch_spec.rb
+++ b/Library/Homebrew/test/cask/cli/fetch_spec.rb
@@ -42,7 +42,7 @@ describe Hbc::CLI::Fetch, :cask do
it "properly handles Casks that are not present" do
expect {
Hbc::CLI::Fetch.run("notacask")
- }.to raise_error(Hbc::CaskError, "Fetch incomplete.")
+ }.to raise_error(Hbc::CaskUnavailableError)
end
describe "when no Cask is specified" do
diff --git a/Library/Homebrew/test/cask/cli/info_spec.rb b/Library/Homebrew/test/cask/cli/info_spec.rb
index bffe900ec..aec7080de 100644
--- a/Library/Homebrew/test/cask/cli/info_spec.rb
+++ b/Library/Homebrew/test/cask/cli/info_spec.rb
@@ -10,7 +10,7 @@ describe Hbc::CLI::Info, :cask do
==> Name
None
==> Artifacts
- Caffeine.app (app)
+ Caffeine.app (App)
EOS
end
@@ -24,7 +24,7 @@ describe Hbc::CLI::Info, :cask do
==> Name
None
==> Artifacts
- Caffeine.app (app)
+ Caffeine.app (App)
local-transmission: 2.61
http://example.com/local-transmission
Not installed
@@ -32,7 +32,7 @@ describe Hbc::CLI::Info, :cask do
==> Name
None
==> Artifacts
- Transmission.app (app)
+ Transmission.app (App)
EOS
}
@@ -60,7 +60,7 @@ describe Hbc::CLI::Info, :cask do
==> Name
None
==> Artifacts
- Caffeine.app (app)
+ Caffeine.app (App)
==> Caveats
Here are some things you might want to know.
@@ -86,7 +86,7 @@ describe Hbc::CLI::Info, :cask do
==> Name
None
==> Artifacts
- Caffeine.app (app)
+ Caffeine.app (App)
EOS
end
diff --git a/Library/Homebrew/test/cask/cli/install_spec.rb b/Library/Homebrew/test/cask/cli/install_spec.rb
index 64feacce9..e30489789 100644
--- a/Library/Homebrew/test/cask/cli/install_spec.rb
+++ b/Library/Homebrew/test/cask/cli/install_spec.rb
@@ -56,27 +56,19 @@ describe Hbc::CLI::Install, :cask do
it "properly handles Casks that are not present" do
expect {
Hbc::CLI::Install.run("notacask")
- }.to raise_error(Hbc::CaskError, "Install incomplete.")
+ }.to raise_error(Hbc::CaskUnavailableError)
end
it "returns a suggestion for a misspelled Cask" do
expect {
- begin
- Hbc::CLI::Install.run("localcaffeine")
- rescue Hbc::CaskError
- nil
- end
- }.to output(/Cask 'localcaffeine' is unavailable: No Cask with this name exists\. Did you mean:\nlocal-caffeine/).to_stderr
+ Hbc::CLI::Install.run("localcaffeine")
+ }.to raise_error(Hbc::CaskUnavailableError, /Cask 'localcaffeine' is unavailable: No Cask with this name exists\. Did you mean “local-caffeine”?/)
end
it "returns multiple suggestions for a Cask fragment" do
expect {
- begin
- Hbc::CLI::Install.run("local-caf")
- rescue Hbc::CaskError
- nil
- end
- }.to output(/Cask 'local-caf' is unavailable: No Cask with this name exists\. Did you mean one of:\nlocal-caffeine/).to_stderr
+ Hbc::CLI::Install.run("local")
+ }.to raise_error(Hbc::CaskUnavailableError, /Cask 'local' is unavailable: No Cask with this name exists\. Did you mean one of these\?\nlocal-caffeine\nlocal-transmission/)
end
describe "when no Cask is specified" do
diff --git a/Library/Homebrew/test/cask/cli/list_spec.rb b/Library/Homebrew/test/cask/cli/list_spec.rb
index ecca3035f..d2d7efd3b 100644
--- a/Library/Homebrew/test/cask/cli/list_spec.rb
+++ b/Library/Homebrew/test/cask/cli/list_spec.rb
@@ -14,6 +14,26 @@ describe Hbc::CLI::List, :cask do
EOS
end
+ it "lists full names" do
+ casks = %w[
+ local-caffeine
+ third-party/tap/third-party-cask
+ local-transmission
+ ].map { |c| Hbc::CaskLoader.load(c) }
+
+ casks.each do |c|
+ InstallHelper.install_with_caskfile(c)
+ end
+
+ expect {
+ Hbc::CLI::List.run("--full-name")
+ }.to output(<<-EOS.undent).to_stdout
+ local-caffeine
+ local-transmission
+ third-party/tap/third-party-cask
+ EOS
+ end
+
describe "lists versions" do
let(:casks) { ["local-caffeine", "local-transmission"] }
let(:expected_output) {
@@ -48,7 +68,8 @@ describe Hbc::CLI::List, :cask do
it "lists the installed files for those Casks" do
casks.each(&InstallHelper.method(:install_without_artifacts_with_caskfile))
- Hbc::Artifact::App.new(transmission).install_phase
+ Hbc::Artifact::App.for_cask(transmission)
+ .each { |artifact| artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false) }
expect {
Hbc::CLI::List.run("local-transmission", "local-caffeine")
diff --git a/Library/Homebrew/test/cask/cli/search_spec.rb b/Library/Homebrew/test/cask/cli/search_spec.rb
index e237ad464..3d58e6a15 100644
--- a/Library/Homebrew/test/cask/cli/search_spec.rb
+++ b/Library/Homebrew/test/cask/cli/search_spec.rb
@@ -4,6 +4,8 @@ describe Hbc::CLI::Search, :cask do
end
it "lists the available Casks that match the search term" do
+ allow(GitHub).to receive(:search_code).and_return([])
+
expect {
Hbc::CLI::Search.run("local")
}.to output(<<-EOS.undent).to_stdout.as_tty
@@ -14,6 +16,8 @@ describe Hbc::CLI::Search, :cask do
end
it "outputs a plain list when stdout is not a TTY" do
+ allow(GitHub).to receive(:search_code).and_return([])
+
expect {
Hbc::CLI::Search.run("local")
}.to output(<<-EOS.undent).to_stdout
@@ -22,16 +26,37 @@ describe Hbc::CLI::Search, :cask do
EOS
end
+ it "returns matches even when online search failed" do
+ allow(GitHub).to receive(:search_code).and_raise(GitHub::Error.new("reason"))
+
+ expect {
+ Hbc::CLI::Search.run("local")
+ }.to output(<<-EOS.undent).to_stdout
+ local-caffeine
+ local-transmission
+ EOS
+ .and output(/^Warning: Error searching on GitHub: reason/).to_stderr
+ end
+
it "shows that there are no Casks matching a search term that did not result in anything" do
expect {
Hbc::CLI::Search.run("foo-bar-baz")
- }.to output("No Cask found for \"foo-bar-baz\".\n").to_stdout.as_tty
+ }.to output(<<-EOS.undent).to_stdout.as_tty
+ No Cask found for "foo-bar-baz".
+ EOS
end
- it "lists all available Casks with no search term" do
- expect {
- Hbc::CLI::Search.run
- }.to output(/local-caffeine/).to_stdout.as_tty
+ it "doesn't output anything to non-TTY stdout when there are no matches" do
+ expect { Hbc::CLI::Search.run("foo-bar-baz") }
+ .to not_to_output.to_stdout
+ .and not_to_output.to_stderr
+ end
+
+ it "lists all Casks available offline with no search term" do
+ allow(GitHub).to receive(:search_code).and_raise(GitHub::Error.new("reason"))
+ expect { Hbc::CLI::Search.run }
+ .to output(/local-caffeine/).to_stdout.as_tty
+ .and not_to_output.to_stderr
end
it "ignores hyphens in search terms" do
@@ -55,19 +80,29 @@ describe Hbc::CLI::Search, :cask do
it "accepts a regexp argument" do
expect {
Hbc::CLI::Search.run("/^local-c[a-z]ffeine$/")
- }.to output("==> Regexp Matches\nlocal-caffeine\n").to_stdout.as_tty
+ }.to output(<<-EOS.undent).to_stdout.as_tty
+ ==> Regexp Matches
+ local-caffeine
+ EOS
end
- it "Returns both exact and partial matches" do
+ it "returns both exact and partial matches" do
expect {
Hbc::CLI::Search.run("test-opera")
- }.to output(/^==> Exact Match\ntest-opera\n==> Partial Matches\ntest-opera-mail/).to_stdout.as_tty
+ }.to output(<<-EOS.undent).to_stdout.as_tty
+ ==> Exact Match
+ test-opera
+ ==> Partial Matches
+ test-opera-mail
+ EOS
end
it "does not search the Tap name" do
expect {
Hbc::CLI::Search.run("caskroom")
- }.to output(/^No Cask found for "caskroom"\.\n/).to_stdout.as_tty
+ }.to output(<<-EOS.undent).to_stdout.as_tty
+ No Cask found for "caskroom".
+ EOS
end
it "doesn't highlight packages that aren't installed" do
diff --git a/Library/Homebrew/test/cask/cli/uninstall_spec.rb b/Library/Homebrew/test/cask/cli/uninstall_spec.rb
index 1a1c57e88..2ec506839 100644
--- a/Library/Homebrew/test/cask/cli/uninstall_spec.rb
+++ b/Library/Homebrew/test/cask/cli/uninstall_spec.rb
@@ -16,14 +16,12 @@ describe Hbc::CLI::Uninstall, :cask do
it "shows an error when a bad Cask is provided" do
expect { Hbc::CLI::Uninstall.run("notacask") }
- .to output(/is unavailable/).to_stderr
- .and raise_error(Hbc::CaskError, "Uninstall incomplete.")
+ .to raise_error(Hbc::CaskUnavailableError, /is unavailable/)
end
it "shows an error when a Cask is provided that's not installed" do
expect { Hbc::CLI::Uninstall.run("local-caffeine") }
- .to output(/is not installed/).to_stderr
- .and raise_error(Hbc::CaskError, "Uninstall incomplete.")
+ .to raise_error(Hbc::CaskNotInstalledError, /is not installed/)
end
it "tries anyway on a non-present Cask when --force is given" do
@@ -76,8 +74,7 @@ describe Hbc::CLI::Uninstall, :cask do
Hbc.appdir.join("MyFancyApp.app").rmtree
expect { Hbc::CLI::Uninstall.run("with-uninstall-script-app") }
- .to output(/does not exist/).to_stderr
- .and raise_error(Hbc::CaskError, "Uninstall incomplete.")
+ .to raise_error(Hbc::CaskError, /uninstall script .* does not exist/)
expect(cask).to be_installed
diff --git a/Library/Homebrew/test/cask/cli/zap_spec.rb b/Library/Homebrew/test/cask/cli/zap_spec.rb
index fdc5b4125..502bf8e69 100644
--- a/Library/Homebrew/test/cask/cli/zap_spec.rb
+++ b/Library/Homebrew/test/cask/cli/zap_spec.rb
@@ -1,8 +1,7 @@
describe Hbc::CLI::Zap, :cask do
it "shows an error when a bad Cask is provided" do
expect { Hbc::CLI::Zap.run("notacask") }
- .to output(/is unavailable/).to_stderr
- .and raise_error(Hbc::CaskError, "Zap incomplete.")
+ .to raise_error(Hbc::CaskUnavailableError, /is unavailable/)
end
it "can zap and unlink multiple Casks at once" do
diff --git a/Library/Homebrew/test/cask/conflicts_with_spec.rb b/Library/Homebrew/test/cask/conflicts_with_spec.rb
index 0dc51cb2d..00dc252fe 100644
--- a/Library/Homebrew/test/cask/conflicts_with_spec.rb
+++ b/Library/Homebrew/test/cask/conflicts_with_spec.rb
@@ -8,7 +8,7 @@ describe "conflicts_with", :cask do
Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-conflicts-with.rb")
}
- it "installs the dependency of a Cask and the Cask itself", :focus do
+ it "installs the dependency of a Cask and the Cask itself" do
Hbc::Installer.new(local_caffeine).install
expect(local_caffeine).to be_installed
diff --git a/Library/Homebrew/test/cask/depends_on_spec.rb b/Library/Homebrew/test/cask/depends_on_spec.rb
index c603cf6e1..fb92a9a24 100644
--- a/Library/Homebrew/test/cask/depends_on_spec.rb
+++ b/Library/Homebrew/test/cask/depends_on_spec.rb
@@ -31,7 +31,7 @@ describe "Satisfy Dependencies and Requirements", :cask do
it { is_expected.not_to raise_error }
end
- context "given a comparisson" do
+ context "given a comparison" do
let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-depends-on-macos-comparison.rb") }
it { is_expected.not_to raise_error }
end
diff --git a/Library/Homebrew/test/cask/dsl_spec.rb b/Library/Homebrew/test/cask/dsl_spec.rb
index 7f2207a87..aec1e917f 100644
--- a/Library/Homebrew/test/cask/dsl_spec.rb
+++ b/Library/Homebrew/test/cask/dsl_spec.rb
@@ -186,12 +186,12 @@ describe Hbc::DSL, :cask do
app "Bar.app"
end
- expect(Array(cask.artifacts[:app])).to eq([["Foo.app"], ["Bar.app"]])
+ expect(cask.artifacts[:app].map(&:to_s)).to eq(["Foo.app (App)", "Bar.app (App)"])
end
it "allow app stanzas to be empty" do
cask = Hbc::Cask.new("cask-with-no-apps")
- expect(Array(cask.artifacts[:app])).to eq([])
+ expect(cask.artifacts[:app]).to be_empty
end
end
@@ -219,7 +219,7 @@ describe Hbc::DSL, :cask do
pkg "Bar.pkg"
end
- expect(Array(cask.artifacts[:pkg])).to eq([["Foo.pkg"], ["Bar.pkg"]])
+ expect(cask.artifacts[:pkg].map(&:to_s)).to eq(["Foo.pkg (Pkg)", "Bar.pkg (Pkg)"])
end
end
@@ -471,10 +471,10 @@ describe Hbc::DSL, :cask do
let(:token) { "with-installer-script" }
it "allows installer script to be specified" do
- expect(cask.artifacts[:installer].first.script[:executable]).to eq("/usr/bin/true")
- expect(cask.artifacts[:installer].first.script[:args]).to eq(["--flag"])
- expect(cask.artifacts[:installer].to_a[1].script[:executable]).to eq("/usr/bin/false")
- expect(cask.artifacts[:installer].to_a[1].script[:args]).to eq(["--flag"])
+ expect(cask.artifacts[:installer].first.path).to eq(Pathname("/usr/bin/true"))
+ expect(cask.artifacts[:installer].first.args[:args]).to eq(["--flag"])
+ expect(cask.artifacts[:installer].to_a[1].path).to eq(Pathname("/usr/bin/false"))
+ expect(cask.artifacts[:installer].to_a[1].args[:args]).to eq(["--flag"])
end
end
@@ -482,7 +482,9 @@ describe Hbc::DSL, :cask do
let(:token) { "with-installer-manual" }
it "allows installer manual to be specified" do
- expect(cask.artifacts[:installer].first.manual).to eq("Caffeine.app")
+ installer = cask.artifacts[:installer].first
+ expect(installer).to be_a(Hbc::Artifact::Installer::ManualInstaller)
+ expect(installer.path).to eq(cask.staged_path.join("Caffeine.app"))
end
end
end
@@ -492,7 +494,7 @@ describe Hbc::DSL, :cask do
let(:token) { "stage-only" }
it "allows stage_only stanza to be specified" do
- expect(cask.artifacts[:stage_only].first).to eq([true])
+ expect(cask.artifacts[:stage_only]).not_to be_empty
end
end
@@ -518,7 +520,7 @@ describe Hbc::DSL, :cask do
let(:token) { "appdir-interpolation" }
it "is allowed" do
- expect(cask.artifacts[:binary].first).to eq(["#{Hbc.appdir}/some/path"])
+ expect(cask.artifacts[:binary].first.source).to eq(Hbc.appdir/"some/path")
end
end
@@ -531,7 +533,7 @@ describe Hbc::DSL, :cask do
binary "#{appdir}/some/path"
end
- expect(cask.artifacts[:binary].first).to eq(["#{original_appdir}/some/path"])
+ expect(cask.artifacts[:binary].first.source).to eq(original_appdir/"some/path")
ensure
Hbc.appdir = original_appdir
end
diff --git a/Library/Homebrew/test/cleanup_spec.rb b/Library/Homebrew/test/cleanup_spec.rb
index 4e5e42efa..da262c5ca 100644
--- a/Library/Homebrew/test/cleanup_spec.rb
+++ b/Library/Homebrew/test/cleanup_spec.rb
@@ -5,6 +5,7 @@ require "pathname"
describe Homebrew::Cleanup do
let(:ds_store) { Pathname.new("#{HOMEBREW_PREFIX}/Library/.DS_Store") }
+ let(:sec_in_a_day) { 60 * 60 * 24 }
around(:each) do |example|
begin
@@ -104,14 +105,30 @@ describe Homebrew::Cleanup do
expect(f4).to be_installed
end
- specify "::cleanup_logs" do
- path = (HOMEBREW_LOGS/"delete_me")
- path.mkpath
- ARGV << "--prune=all"
+ describe "::cleanup_logs" do
+ let(:path) { (HOMEBREW_LOGS/"delete_me") }
- described_class.cleanup_logs
+ before do
+ path.mkpath
+ end
+
+ it "cleans all logs if prune all" do
+ ARGV << "--prune=all"
+ described_class.cleanup_logs
+ expect(path).not_to exist
+ end
- expect(path).not_to exist
+ it "cleans up logs if older than 14 days" do
+ allow_any_instance_of(Pathname).to receive(:mtime).and_return(Time.now - sec_in_a_day * 15)
+ described_class.cleanup_logs
+ expect(path).not_to exist
+ end
+
+ it "does not clean up logs less than 14 days old" do
+ allow_any_instance_of(Pathname).to receive(:mtime).and_return(Time.now - sec_in_a_day * 2)
+ described_class.cleanup_logs
+ expect(path).to exist
+ end
end
describe "::cleanup_cache" do
@@ -124,6 +141,15 @@ describe Homebrew::Cleanup do
expect(incomplete).not_to exist
end
+ it "cleans up 'glide_home'" do
+ glide_home = (HOMEBREW_CACHE/"glide_home")
+ glide_home.mkpath
+
+ described_class.cleanup_cache
+
+ expect(glide_home).not_to exist
+ end
+
it "cleans up 'java_cache'" do
java_cache = (HOMEBREW_CACHE/"java_cache")
java_cache.mkpath
@@ -141,5 +167,99 @@ describe Homebrew::Cleanup do
expect(npm_cache).not_to exist
end
+
+ it "cleans up all files and directories" do
+ git = (HOMEBREW_CACHE/"gist--git")
+ gist = (HOMEBREW_CACHE/"gist")
+ svn = (HOMEBREW_CACHE/"gist--svn")
+
+ git.mkpath
+ gist.mkpath
+ FileUtils.touch svn
+
+ allow(ARGV).to receive(:value).with("prune").and_return("all")
+
+ described_class.cleanup_cache
+
+ expect(git).not_to exist
+ expect(gist).to exist
+ expect(svn).not_to exist
+ end
+
+ it "does not clean up directories that are not VCS checkouts" do
+ git = (HOMEBREW_CACHE/"git")
+ git.mkpath
+ allow(ARGV).to receive(:value).with("prune").and_return("all")
+
+ described_class.cleanup_cache
+
+ expect(git).to exist
+ end
+
+ it "cleans up VCS checkout directories with modified time < prune time" do
+ foo = (HOMEBREW_CACHE/"--foo")
+ foo.mkpath
+ allow(ARGV).to receive(:value).with("prune").and_return("1")
+ allow_any_instance_of(Pathname).to receive(:mtime).and_return(Time.now - sec_in_a_day * 2)
+ described_class.cleanup_cache
+ expect(foo).not_to exist
+ end
+
+ it "does not clean up VCS checkout directories with modified time >= prune time" do
+ foo = (HOMEBREW_CACHE/"--foo")
+ foo.mkpath
+ allow(ARGV).to receive(:value).with("prune").and_return("1")
+ described_class.cleanup_cache
+ expect(foo).to exist
+ end
+
+ context "cleans old files in HOMEBREW_CACHE" do
+ let(:bottle) { (HOMEBREW_CACHE/"testball-0.0.1.bottle.tar.gz") }
+ let(:testball) { (HOMEBREW_CACHE/"testball-0.0.1") }
+
+ before(:each) do
+ FileUtils.touch(bottle)
+ FileUtils.touch(testball)
+ (HOMEBREW_CELLAR/"testball"/"0.0.1").mkpath
+ FileUtils.touch(CoreTap.instance.formula_dir/"testball.rb")
+ end
+
+ it "cleans up file if outdated" do
+ allow(Utils::Bottles).to receive(:file_outdated?).with(any_args).and_return(true)
+ described_class.cleanup_cache
+ expect(bottle).not_to exist
+ expect(testball).not_to exist
+ end
+
+ it "cleans up file if ARGV has -s and formula not installed" do
+ ARGV << "-s"
+ described_class.cleanup_cache
+ expect(bottle).not_to exist
+ expect(testball).not_to exist
+ end
+
+ it "cleans up file if stale" do
+ described_class.cleanup_cache
+ expect(bottle).not_to exist
+ expect(testball).not_to exist
+ end
+ end
+ end
+
+ describe "::prune?" do
+ before do
+ foo.mkpath
+ end
+
+ let(:foo) { HOMEBREW_CACHE/"foo" }
+
+ it "returns true when path_modified_time < days_default" do
+ allow_any_instance_of(Pathname).to receive(:mtime).and_return(Time.now - sec_in_a_day * 2)
+ expect(described_class.prune?(foo, days_default: "1")).to be_truthy
+ end
+
+ it "returns false when path_modified_time >= days_default" do
+ expect(described_class.prune?(foo, days_default: "2")).to be_falsey
+ end
end
end
diff --git a/Library/Homebrew/test/cmd/commands_spec.rb b/Library/Homebrew/test/cmd/commands_spec.rb
index cf6f56740..46ed3ddcf 100644
--- a/Library/Homebrew/test/cmd/commands_spec.rb
+++ b/Library/Homebrew/test/cmd/commands_spec.rb
@@ -68,7 +68,7 @@ describe Homebrew do
expect(cmds).to include("t1"), "Executable files should be included"
expect(cmds).to include("t2"), "Executable Ruby files should be included"
- expect(cmds).not_to include("t3"), "Executable files with a non Ruby extension shoudn't be included"
+ expect(cmds).not_to include("t3"), "Executable files with a non Ruby extension shouldn't be included"
expect(cmds).not_to include("t4"), "Non-executable files shouldn't be included"
end
end
diff --git a/Library/Homebrew/test/cmd/home_spec.rb b/Library/Homebrew/test/cmd/home_spec.rb
index 5a4070492..cf9453af2 100644
--- a/Library/Homebrew/test/cmd/home_spec.rb
+++ b/Library/Homebrew/test/cmd/home_spec.rb
@@ -7,10 +7,10 @@ describe "brew home", :integration_test do
end
it "opens the homepage for a given Formula" do
- setup_test_formula "testball"
+ setup_test_formula "testballhome"
- expect { brew "home", "testball", "HOMEBREW_BROWSER" => "echo" }
- .to output("#{Formula["testball"].homepage}\n").to_stdout
+ expect { brew "home", "testballhome", "HOMEBREW_BROWSER" => "echo" }
+ .to output("#{Formula["testballhome"].homepage}\n").to_stdout
.and not_to_output.to_stderr
.and be_a_success
end
diff --git a/Library/Homebrew/test/cmd/search_remote_tap_spec.rb b/Library/Homebrew/test/cmd/search_remote_tap_spec.rb
index b0beb122c..eb256b924 100644
--- a/Library/Homebrew/test/cmd/search_remote_tap_spec.rb
+++ b/Library/Homebrew/test/cmd/search_remote_tap_spec.rb
@@ -2,6 +2,9 @@ require "cmd/search"
describe Homebrew do
specify "#search_taps" do
+ # Otherwise the tested method returns [], regardless of our stub
+ ENV.delete("HOMEBREW_NO_GITHUB_API")
+
json_response = {
"items" => [
{
diff --git a/Library/Homebrew/test/dependency_expansion_spec.rb b/Library/Homebrew/test/dependency_expansion_spec.rb
index f955237a9..d6ecdf552 100644
--- a/Library/Homebrew/test/dependency_expansion_spec.rb
+++ b/Library/Homebrew/test/dependency_expansion_spec.rb
@@ -69,7 +69,7 @@ describe Dependency do
end
end
- it "merges dependencies and perserves env_proc" do
+ it "merges dependencies and preserves env_proc" do
env_proc = double
dep = described_class.new("foo", [], env_proc)
allow(dep).to receive(:to_formula).and_return(double(deps: [], name: "foo"))
diff --git a/Library/Homebrew/test/dev-cmd/audit_spec.rb b/Library/Homebrew/test/dev-cmd/audit_spec.rb
index 037865fdf..3e99bd06b 100644
--- a/Library/Homebrew/test/dev-cmd/audit_spec.rb
+++ b/Library/Homebrew/test/dev-cmd/audit_spec.rb
@@ -150,70 +150,6 @@ describe FormulaAuditor do
end
end
- describe "#audit_class" do
- specify "missing test" do
- fa = formula_auditor "foo", <<-EOS.undent
- class Foo < Formula
- url "http://example.com/foo-1.0.tgz"
- end
- EOS
-
- fa.audit_class
- expect(fa.problems).to eq([])
-
- fa = formula_auditor "foo", <<-EOS.undent, strict: true
- class Foo < Formula
- url "http://example.com/foo-1.0.tgz"
- end
- EOS
-
- fa.audit_class
- expect(fa.problems).to eq(["A `test do` test block should be added"])
- end
-
- specify "GithubGistFormula", :needs_compat do
- ENV.delete("HOMEBREW_DEVELOPER")
-
- fa = formula_auditor "foo", <<-EOS.undent
- class Foo < GithubGistFormula
- url "http://example.com/foo-1.0.tgz"
- end
- EOS
-
- fa.audit_class
- expect(fa.problems)
- .to eq(["GithubGistFormula is deprecated, use Formula instead"])
- end
-
- specify "ScriptFileFormula", :needs_compat do
- ENV.delete("HOMEBREW_DEVELOPER")
-
- fa = formula_auditor "foo", <<-EOS.undent
- class Foo < ScriptFileFormula
- url "http://example.com/foo-1.0.tgz"
- end
- EOS
-
- fa.audit_class
- expect(fa.problems)
- .to eq(["ScriptFileFormula is deprecated, use Formula instead"])
- end
-
- specify "AmazonWebServicesFormula", :needs_compat do
- ENV.delete("HOMEBREW_DEVELOPER")
-
- fa = formula_auditor "foo", <<-EOS.undent
- class Foo < AmazonWebServicesFormula
- url "http://example.com/foo-1.0.tgz"
- end
- EOS
-
- fa.audit_class
- expect(fa.problems)
- .to eq(["AmazonWebServicesFormula is deprecated, use Formula instead"])
- end
- end
-
describe "#line_problems" do
specify "pkgshare" do
fa = formula_auditor "foo", <<-EOS.undent, strict: true
diff --git a/Library/Homebrew/test/os/mac/diagnostic_spec.rb b/Library/Homebrew/test/os/mac/diagnostic_spec.rb
index d6186e46b..83d95c2ef 100644
--- a/Library/Homebrew/test/os/mac/diagnostic_spec.rb
+++ b/Library/Homebrew/test/os/mac/diagnostic_spec.rb
@@ -47,15 +47,10 @@ describe Homebrew::Diagnostic::Checks do
end
specify "#check_ruby_version" do
- allow(MacOS).to receive(:version).and_return(OS::Mac::Version.new("10.13"))
- stub_const("RUBY_VERSION", "2.3.3p222")
+ allow(MacOS).to receive(:version).and_return(OS::Mac::Version.new("10.12"))
+ stub_const("RUBY_VERSION", "1.8.6")
expect(subject.check_ruby_version)
- .to match <<-EOS.undent
- Ruby version 2.3.3p222 is unsupported on 10.13. Homebrew
- is developed and tested on Ruby 2.0, and may not work correctly
- on other Rubies. Patches are accepted as long as they don't cause breakage
- on supported Rubies.
- EOS
+ .to match "Ruby version 1.8.6 is unsupported on 10.12"
end
end
diff --git a/Library/Homebrew/test/pathname_spec.rb b/Library/Homebrew/test/pathname_spec.rb
index 0bc19c5ac..69314e5f4 100644
--- a/Library/Homebrew/test/pathname_spec.rb
+++ b/Library/Homebrew/test/pathname_spec.rb
@@ -295,7 +295,7 @@ describe FileUtils do
let(:dst) { mktmpdir }
describe "#mkdir" do
- it "creates indermediate directories" do
+ it "creates intermediate directories" do
described_class.mkdir dst/"foo/bar/baz" do
expect(dst/"foo/bar/baz").to exist, "foo/bar/baz was not created"
expect(dst/"foo/bar/baz").to be_a_directory, "foo/bar/baz was not a directory structure"
diff --git a/Library/Homebrew/test/requirement_spec.rb b/Library/Homebrew/test/requirement_spec.rb
index 71372aa69..11a3da8f4 100644
--- a/Library/Homebrew/test/requirement_spec.rb
+++ b/Library/Homebrew/test/requirement_spec.rb
@@ -48,7 +48,7 @@ describe Requirement do
it { is_expected.to be_fatal }
end
- context "#fatal is ommitted" do
+ context "#fatal is omitted" do
it { is_expected.not_to be_fatal }
end
end
@@ -184,7 +184,7 @@ describe Requirement do
it { is_expected.to have_a_default_formula }
end
- context "#default_formula ommitted" do
+ context "#default_formula omitted" do
it { is_expected.not_to have_a_default_formula }
end
end
diff --git a/Library/Homebrew/test/rubocops/class_cop_spec.rb b/Library/Homebrew/test/rubocops/class_cop_spec.rb
new file mode 100644
index 000000000..676dd4f6e
--- /dev/null
+++ b/Library/Homebrew/test/rubocops/class_cop_spec.rb
@@ -0,0 +1,81 @@
+require "rubocop"
+require "rubocop/rspec/support"
+require_relative "../../extend/string"
+require_relative "../../rubocops/class_cop"
+
+describe RuboCop::Cop::FormulaAudit::ClassName do
+ subject(:cop) { described_class.new }
+
+ context "When auditing formula" do
+ it "with deprecated inheritance" do
+ formulas = [{
+ "class" => "GithubGistFormula",
+ }, {
+ "class" => "ScriptFileFormula",
+ }, {
+ "class" => "AmazonWebServicesFormula",
+ }]
+
+ formulas.each do |formula|
+ source = <<-EOS.undent
+ class Foo < #{formula["class"]}
+ url 'http://example.com/foo-1.0.tgz'
+ end
+ EOS
+
+ expected_offenses = [{ message: "#{formula["class"]} is deprecated, use Formula instead",
+ severity: :convention,
+ line: 1,
+ column: 12,
+ source: source }]
+
+ inspect_source(cop, source)
+
+ expected_offenses.zip(cop.offenses.reverse).each do |expected, actual|
+ expect_offense(expected, actual)
+ end
+ end
+ end
+
+ it "with deprecated inheritance and autocorrect" do
+ source = <<-EOS.undent
+ class Foo < AmazonWebServicesFormula
+ url 'http://example.com/foo-1.0.tgz'
+ end
+ EOS
+ corrected_source = <<-EOS.undent
+ class Foo < Formula
+ url 'http://example.com/foo-1.0.tgz'
+ end
+ EOS
+
+ new_source = autocorrect_source(cop, source)
+ expect(new_source).to eq(corrected_source)
+ end
+ end
+end
+
+describe RuboCop::Cop::FormulaAuditStrict::Test do
+ subject(:cop) { described_class.new }
+
+ context "When auditing formula" do
+ it "without a test block" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ url 'http://example.com/foo-1.0.tgz'
+ end
+ EOS
+ expected_offenses = [{ message: described_class::MSG,
+ severity: :convention,
+ line: 1,
+ column: 0,
+ source: source }]
+
+ inspect_source(cop, source)
+
+ expected_offenses.zip(cop.offenses).each do |expected, actual|
+ expect_offense(expected, actual)
+ end
+ end
+ end
+end
diff --git a/Library/Homebrew/test/rubocops/conflicts_cop_spec.rb b/Library/Homebrew/test/rubocops/conflicts_cop_spec.rb
index 4fbab6c9e..3af0f9669 100644
--- a/Library/Homebrew/test/rubocops/conflicts_cop_spec.rb
+++ b/Library/Homebrew/test/rubocops/conflicts_cop_spec.rb
@@ -22,7 +22,7 @@ describe RuboCop::Cop::FormulaAudit::Conflicts do
column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(cop, source, "/homebrew-core/Formula/foo@2.0.rb")
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -36,7 +36,7 @@ describe RuboCop::Cop::FormulaAudit::Conflicts do
desc 'Bar'
end
EOS
- inspect_source(cop, source)
+ inspect_source(cop, source, "/homebrew-core/Formula/foo@2.0.rb")
expect(cop.offenses).to eq([])
end
end
diff --git a/Library/Homebrew/test/rubocops/formula_desc_cop_spec.rb b/Library/Homebrew/test/rubocops/formula_desc_cop_spec.rb
index 74ce478fb..48342e8bc 100644
--- a/Library/Homebrew/test/rubocops/formula_desc_cop_spec.rb
+++ b/Library/Homebrew/test/rubocops/formula_desc_cop_spec.rb
@@ -37,7 +37,7 @@ describe RuboCop::Cop::FormulaAuditStrict::DescLength do
msg = <<-EOS.undent
Description is too long. "name: desc" should be less than 80 characters.
- Length is calculated as Foo + desc. (currently 95)
+ Length is calculated as foo + desc. (currently 95)
EOS
expected_offenses = [{ message: msg,
severity: :convention,
@@ -45,7 +45,7 @@ describe RuboCop::Cop::FormulaAuditStrict::DescLength do
column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(cop, source, "/homebrew-core/Formula/foo.rb")
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
end
@@ -62,7 +62,7 @@ describe RuboCop::Cop::FormulaAuditStrict::DescLength do
msg = <<-EOS.undent
Description is too long. "name: desc" should be less than 80 characters.
- Length is calculated as Foo + desc. (currently 98)
+ Length is calculated as foo + desc. (currently 98)
EOS
expected_offenses = [{ message: msg,
severity: :convention,
@@ -70,7 +70,7 @@ describe RuboCop::Cop::FormulaAuditStrict::DescLength do
column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(cop, source, "/homebrew-core/Formula/foo.rb")
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
end
@@ -156,7 +156,7 @@ describe RuboCop::Cop::FormulaAuditStrict::Desc do
column: 8,
source: source }]
- inspect_source(cop, source)
+ inspect_source(cop, source, "/homebrew-core/Formula/foo.rb")
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
end
@@ -176,7 +176,7 @@ describe RuboCop::Cop::FormulaAuditStrict::Desc do
end
EOS
- corrected_source = autocorrect_source(cop, source)
+ corrected_source = autocorrect_source(cop, source, "/homebrew-core/Formula/foo.rb")
expect(corrected_source).to eq(correct_source)
end
end
diff --git a/Library/Homebrew/test/rubocops/lines_cop_spec.rb b/Library/Homebrew/test/rubocops/lines_cop_spec.rb
index b0ed8f4d1..d93962688 100644
--- a/Library/Homebrew/test/rubocops/lines_cop_spec.rb
+++ b/Library/Homebrew/test/rubocops/lines_cop_spec.rb
@@ -200,5 +200,317 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
expect_offense(expected, actual)
end
end
+
+ it "with invalid rebuild" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ desc "foo"
+ url 'http://example.com/foo-1.0.tgz'
+ bottle do
+ rebuild 0
+ sha256 "fe0679b932dd43a87fd415b609a7fbac7a069d117642ae8ebaac46ae1fb9f0b3" => :sierra
+ end
+ end
+ EOS
+
+ expected_offenses = [{ message: "'rebuild 0' should be removed",
+ severity: :convention,
+ line: 5,
+ column: 4,
+ source: source }]
+
+ inspect_source(cop, source)
+
+ expected_offenses.zip(cop.offenses).each do |expected, actual|
+ expect_offense(expected, actual)
+ end
+ end
+
+ it "with OS.linux? check" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ desc "foo"
+ url 'http://example.com/foo-1.0.tgz'
+ bottle do
+ if OS.linux?
+ nil
+ end
+ sha256 "fe0679b932dd43a87fd415b609a7fbac7a069d117642ae8ebaac46ae1fb9f0b3" => :sierra
+ end
+ end
+ EOS
+
+ expected_offenses = [{ message: "Don't use OS.linux?; Homebrew/core only supports macOS",
+ severity: :convention,
+ line: 5,
+ column: 7,
+ source: source }]
+
+ inspect_source(cop, source, "/homebrew-core/")
+
+ expected_offenses.zip(cop.offenses).each do |expected, actual|
+ expect_offense(expected, actual)
+ end
+ end
+
+ it "with fails_with :llvm" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ desc "foo"
+ url 'http://example.com/foo-1.0.tgz'
+ bottle do
+ sha256 "fe0679b932dd43a87fd415b609a7fbac7a069d117642ae8ebaac46ae1fb9f0b3" => :sierra
+ end
+ fails_with :llvm do
+ build 2335
+ cause "foo"
+ end
+ end
+ EOS
+
+ expected_offenses = [{ message: "'fails_with :llvm' is now a no-op so should be removed",
+ severity: :convention,
+ line: 7,
+ column: 2,
+ source: source }]
+
+ inspect_source(cop, source)
+
+ expected_offenses.zip(cop.offenses).each do |expected, actual|
+ expect_offense(expected, actual)
+ end
+ end
+
+ it "with def test" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ desc "foo"
+ url 'http://example.com/foo-1.0.tgz'
+
+ def test
+ assert_equals "1", "1"
+ end
+ end
+ EOS
+
+ expected_offenses = [{ message: "Use new-style test definitions (test do)",
+ severity: :convention,
+ line: 5,
+ column: 2,
+ source: source }]
+
+ inspect_source(cop, source)
+
+ expected_offenses.zip(cop.offenses).each do |expected, actual|
+ expect_offense(expected, actual)
+ end
+ end
+
+ it "with def options" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ desc "foo"
+ url 'http://example.com/foo-1.0.tgz'
+
+ def options
+ [["--bar", "desc"]]
+ end
+ end
+ EOS
+
+ expected_offenses = [{ message: "Use new-style option definitions",
+ severity: :convention,
+ line: 5,
+ column: 2,
+ source: source }]
+
+ inspect_source(cop, source)
+
+ expected_offenses.zip(cop.offenses).each do |expected, actual|
+ expect_offense(expected, actual)
+ end
+ end
+
+ it "with deprecated skip_clean call" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ desc "foo"
+ url 'http://example.com/foo-1.0.tgz'
+ skip_clean :all
+ end
+ EOS
+
+ expected_offenses = [{ message: <<-EOS.undent.chomp,
+ `skip_clean :all` is deprecated; brew no longer strips symbols
+ Pass explicit paths to prevent Homebrew from removing empty folders.
+ EOS
+ severity: :convention,
+ line: 4,
+ column: 2,
+ source: source }]
+
+ inspect_source(cop, source)
+
+ expected_offenses.zip(cop.offenses).each do |expected, actual|
+ expect_offense(expected, actual)
+ end
+ end
+
+ it "with build.universal?" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ desc "foo"
+ url 'http://example.com/foo-1.0.tgz'
+ if build.universal?
+ "foo"
+ end
+ end
+ EOS
+
+ expected_offenses = [{ message: "macOS has been 64-bit only since 10.6 so build.universal? is deprecated.",
+ severity: :convention,
+ line: 4,
+ column: 5,
+ source: source }]
+
+ inspect_source(cop, source)
+
+ expected_offenses.zip(cop.offenses).each do |expected, actual|
+ expect_offense(expected, actual)
+ end
+ end
+
+ it "with build.universal? exempted formula" do
+ source = <<-EOS.undent
+ class Wine < Formula
+ desc "foo"
+ url 'http://example.com/foo-1.0.tgz'
+ if build.universal?
+ "foo"
+ end
+ end
+ EOS
+
+ inspect_source(cop, source, "/homebrew-core/Formula/wine.rb")
+ expect(cop.offenses).to eq([])
+ end
+
+ it "with ENV.universal_binary" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ desc "foo"
+ url 'http://example.com/foo-1.0.tgz'
+ if build?
+ ENV.universal_binary
+ end
+ end
+ EOS
+
+ expected_offenses = [{ message: "macOS has been 64-bit only since 10.6 so ENV.universal_binary is deprecated.",
+ severity: :convention,
+ line: 5,
+ column: 5,
+ source: source }]
+
+ inspect_source(cop, source)
+
+ expected_offenses.zip(cop.offenses).each do |expected, actual|
+ expect_offense(expected, actual)
+ end
+ end
+
+ it "with ENV.universal_binary" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ desc "foo"
+ url 'http://example.com/foo-1.0.tgz'
+ if build?
+ ENV.x11
+ end
+ end
+ EOS
+
+ expected_offenses = [{ message: 'Use "depends_on :x11" instead of "ENV.x11"',
+ severity: :convention,
+ line: 5,
+ column: 5,
+ source: source }]
+
+ inspect_source(cop, source)
+
+ expected_offenses.zip(cop.offenses).each do |expected, actual|
+ expect_offense(expected, actual)
+ end
+ end
+
+ it "with ruby-macho alternatives" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ desc "foo"
+ url 'http://example.com/foo-1.0.tgz'
+ system "install_name_tool", "-id"
+ end
+ EOS
+
+ expected_offenses = [{ message: 'Use ruby-macho instead of calling "install_name_tool"',
+ severity: :convention,
+ line: 4,
+ column: 10,
+ source: source }]
+
+ inspect_source(cop, source)
+
+ expected_offenses.zip(cop.offenses).each do |expected, actual|
+ expect_offense(expected, actual)
+ end
+ end
+
+ it "with ruby-macho alternatives audit exempted formula" do
+ source = <<-EOS.undent
+ class Cctools < Formula
+ desc "foo"
+ url 'http://example.com/foo-1.0.tgz'
+ system "install_name_tool", "-id"
+ end
+ EOS
+
+ inspect_source(cop, source, "/homebrew-core/Formula/cctools.rb")
+ expect(cop.offenses).to eq([])
+ end
+
+ it "with npm install without language::Node args" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ desc "foo"
+ url 'http://example.com/foo-1.0.tgz'
+ system "npm", "install"
+ end
+ EOS
+
+ expected_offenses = [{ message: "Use Language::Node for npm install args",
+ severity: :convention,
+ line: 4,
+ column: 2,
+ source: source }]
+
+ inspect_source(cop, source)
+
+ expected_offenses.zip(cop.offenses).each do |expected, actual|
+ expect_offense(expected, actual)
+ end
+ end
+
+ it "with npm install without language::Node args in kibana" do
+ source = <<-EOS.undent
+ class KibanaAT44 < Formula
+ desc "foo"
+ url 'http://example.com/foo-1.0.tgz'
+ system "npm", "install"
+ end
+ EOS
+
+ inspect_source(cop, source, "/homebrew-core/Formula/kibana@4.4.rb")
+ expect(cop.offenses).to eq([])
+ end
end
end
diff --git a/Library/Homebrew/test/support/fixtures/third-party/Casks/third-party-cask.rb b/Library/Homebrew/test/support/fixtures/third-party/Casks/third-party-cask.rb
new file mode 100644
index 000000000..d7add0522
--- /dev/null
+++ b/Library/Homebrew/test/support/fixtures/third-party/Casks/third-party-cask.rb
@@ -0,0 +1,9 @@
+cask 'third-party-cask' do
+ version '1.2.3'
+ sha256 '8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b'
+
+ url 'http://example.com/ThirdParty.dmg'
+ homepage 'http://example.com/'
+
+ app 'ThirdParty.app'
+end
diff --git a/Library/Homebrew/test/support/helper/spec/shared_context/homebrew_cask.rb b/Library/Homebrew/test/support/helper/spec/shared_context/homebrew_cask.rb
index c51d339a7..fc83149d0 100644
--- a/Library/Homebrew/test/support/helper/spec/shared_context/homebrew_cask.rb
+++ b/Library/Homebrew/test/support/helper/spec/shared_context/homebrew_cask.rb
@@ -18,6 +18,7 @@ HOMEBREW_CASK_DIRS = [
RSpec.shared_context "Homebrew-Cask" do
around(:each) do |example|
+ third_party_tap = Tap.fetch("third-party", "tap")
begin
dirs = HOMEBREW_CASK_DIRS.map do |dir|
Pathname.new(TEST_TMPDIR).join("cask-#{dir}").tap do |path|
@@ -31,11 +32,18 @@ RSpec.shared_context "Homebrew-Cask" do
FileUtils.ln_sf TEST_FIXTURE_DIR.join("cask"), tap.path
end
+ third_party_tap.tap do |tap|
+ FileUtils.mkdir_p tap.path.dirname
+ FileUtils.ln_sf TEST_FIXTURE_DIR.join("third-party"), tap.path
+ end
+
example.run
ensure
FileUtils.rm_rf dirs
Hbc.default_tap.path.unlink
FileUtils.rm_rf Hbc.default_tap.path.parent
+ third_party_tap.path.unlink
+ FileUtils.rm_rf third_party_tap.path.parent
end
end
end
diff --git a/Library/Homebrew/test/utils/analytics_spec.rb b/Library/Homebrew/test/utils/analytics_spec.rb
new file mode 100644
index 000000000..bb6cda0b1
--- /dev/null
+++ b/Library/Homebrew/test/utils/analytics_spec.rb
@@ -0,0 +1,88 @@
+require "utils/analytics"
+require "formula_installer"
+
+describe Utils::Analytics do
+ describe "::os_prefix_ci" do
+ context "when anonymous_os_prefix_ci is not set" do
+ before(:each) do
+ described_class.clear_anonymous_os_prefix_ci_cache
+ end
+
+ it "returns OS_VERSION and prefix when HOMEBREW_PREFIX is not /usr/local" do
+ stub_const("HOMEBREW_PREFIX", "blah")
+ expect(described_class.os_prefix_ci).to include("#{OS_VERSION}, non-/usr/local")
+ end
+
+ it "includes CI when ENV['CI'] is set" do
+ ENV["CI"] = "true"
+ expect(described_class.os_prefix_ci).to include("CI")
+ end
+
+ it "does not include prefix when HOMEBREW_PREFIX is /usr/local" do
+ stub_const("HOMEBREW_PREFIX", "/usr/local")
+ expect(described_class.os_prefix_ci).not_to include("non-/usr/local")
+ end
+ end
+ end
+
+ describe "::report_event" do
+ let(:f) { formula { url "foo-1.0" } }
+ let(:options) { FormulaInstaller.new(f).display_options(f) }
+ let(:action) { "#{f.full_name} #{options}".strip }
+
+ context "when ENV vars is set" do
+ it "returns nil when HOMEBREW_NO_ANALYTICS is true" do
+ ENV["HOMEBREW_NO_ANALYTICS"] = "true"
+ expect(described_class.report_event("install", action)).to be_nil
+ end
+
+ it "returns nil when HOMEBREW_NO_ANALYTICS_THIS_RUN is true" do
+ ENV["HOMEBREW_NO_ANALYTICS_THIS_RUN"] = "true"
+ expect(described_class.report_event("install", action)).to be_nil
+ end
+
+ it "returns nil when HOMEBREW_ANALYTICS_DEBUG is true" do
+ ENV.delete("HOMEBREW_NO_ANALYTICS_THIS_RUN")
+ ENV.delete("HOMEBREW_NO_ANALYTICS")
+ ENV["HOMEBREW_ANALYTICS_DEBUG"] = "true"
+ expect(described_class.report_event("install", action)).to be_nil
+ end
+ end
+ end
+
+ describe "::report_build_error" do
+ context "when tap is installed" do
+ let(:err) { BuildError.new(f, "badprg", %w[arg1 arg2], {}) }
+ let(:f) { formula { url "foo-1.0" } }
+
+ it "reports event if BuildError raised for a formula with a public remote repository" do
+ allow_any_instance_of(Tap).to receive(:custom_remote?).and_return(false)
+ expect(described_class).to respond_to(:report_event)
+ described_class.report_build_error(err)
+ end
+
+ it "does not report event if BuildError raised for a formula with a private remote repository" do
+ expect(described_class.report_build_error(err)).to be_nil
+ end
+ end
+
+ context "when formula does not have a tap" do
+ let(:err) { BuildError.new(f, "badprg", %w[arg1 arg2], {}) }
+ let(:f) { double(Formula, name: "foo", path: "blah", tap: nil) }
+
+ it "does not report event if BuildError is raised" do
+ expect(described_class.report_build_error(err)).to be_nil
+ end
+ end
+
+ context "when tap for a formula is not installed" do
+ let(:err) { BuildError.new(f, "badprg", %w[arg1 arg2], {}) }
+ let(:f) { double(Formula, name: "foo", path: "blah", tap: CoreTap.instance) }
+
+ it "does not report event if BuildError is raised" do
+ allow_any_instance_of(Pathname).to receive(:directory?).and_return(false)
+ expect(described_class.report_build_error(err)).to be_nil
+ end
+ end
+ end
+end
diff --git a/Library/Homebrew/test/utils/git_spec.rb b/Library/Homebrew/test/utils/git_spec.rb
new file mode 100644
index 000000000..48fc1338e
--- /dev/null
+++ b/Library/Homebrew/test/utils/git_spec.rb
@@ -0,0 +1,150 @@
+require "utils/git"
+
+describe Git do
+ before(:each) do
+ git = HOMEBREW_SHIMS_PATH/"scm/git"
+
+ HOMEBREW_CACHE.cd do
+ system git, "init"
+
+ File.open(file, "w") { |f| f.write("blah") }
+ system git, "add", HOMEBREW_CACHE/file
+ system git, "commit", "-m", "'File added'"
+ @h1 = `git rev-parse HEAD`
+
+ File.open(file, "w") { |f| f.write("brew") }
+ system git, "add", HOMEBREW_CACHE/file
+ system git, "commit", "-m", "'written to File'"
+ @h2 = `git rev-parse HEAD`
+ end
+ end
+
+ let(:file) { "blah.rb" }
+ let(:hash1) { @h1[0..6] }
+ let(:hash2) { @h2[0..6] }
+
+ describe "#last_revision_commit_of_file" do
+ it "gives last revision commit when before_commit is nil" do
+ expect(
+ described_class.last_revision_commit_of_file(HOMEBREW_CACHE, file),
+ ).to eq(hash1)
+ end
+
+ it "gives revision commit based on before_commit when it is not nil" do
+ expect(
+ described_class.last_revision_commit_of_file(HOMEBREW_CACHE,
+ file,
+ before_commit: hash2),
+ ).to eq(hash2)
+ end
+ end
+
+ describe "#last_revision_of_file" do
+ it "returns last revision of file" do
+ expect(
+ described_class.last_revision_of_file(HOMEBREW_CACHE,
+ HOMEBREW_CACHE/file),
+ ).to eq("blah")
+ end
+
+ it "returns last revision of file based on before_commit" do
+ expect(
+ described_class.last_revision_of_file(HOMEBREW_CACHE, HOMEBREW_CACHE/file,
+ before_commit: "0..3"),
+ ).to eq("brew")
+ end
+ end
+end
+
+describe Utils do
+ before(:each) do
+ described_class.clear_git_available_cache
+ end
+
+ describe "::git_available?" do
+ it "returns true if git --version command succeeds" do
+ expect(described_class.git_available?).to be_truthy
+ end
+
+ it "returns false if git --version command does not succeed" do
+ stub_const("HOMEBREW_SHIMS_PATH", HOMEBREW_PREFIX/"bin/shim")
+ expect(described_class.git_available?).to be_falsey
+ end
+ end
+
+ describe "::git_path" do
+ it "returns nil when git is not available" do
+ stub_const("HOMEBREW_SHIMS_PATH", HOMEBREW_PREFIX/"bin/shim")
+ expect(described_class.git_path).to eq(nil)
+ end
+
+ it "returns path of git when git is available" do
+ expect(described_class.git_path).to end_with("git")
+ end
+ end
+
+ describe "::git_version" do
+ it "returns nil when git is not available" do
+ stub_const("HOMEBREW_SHIMS_PATH", HOMEBREW_PREFIX/"bin/shim")
+ expect(described_class.git_path).to eq(nil)
+ end
+
+ it "returns version of git when git is available" do
+ expect(described_class.git_version).not_to be_nil
+ end
+ end
+
+ describe "::ensure_git_installed!" do
+ it "returns nil if git already available" do
+ expect(described_class.ensure_git_installed!).to be_nil
+ end
+
+ context "when git is not already available" do
+ before do
+ stub_const("HOMEBREW_SHIMS_PATH", HOMEBREW_PREFIX/"bin/shim")
+ end
+
+ it "can't install brewed git if homebrew/core is unavailable" do
+ allow_any_instance_of(Pathname).to receive(:directory?).and_return(false)
+ expect { described_class.ensure_git_installed! }.to raise_error("Git is unavailable")
+ end
+
+ it "raises error if can't install git" do
+ stub_const("HOMEBREW_BREW_FILE", HOMEBREW_PREFIX/"bin/brew")
+ expect { described_class.ensure_git_installed! }.to raise_error("Git is unavailable")
+ end
+
+ it "installs git" do
+ allow(Homebrew).to receive(:_system).with(any_args).and_return(true)
+ described_class.ensure_git_installed!
+ end
+ end
+ end
+
+ describe "::git_remote_exists" do
+ it "returns true when git is not available" do
+ stub_const("HOMEBREW_SHIMS_PATH", HOMEBREW_PREFIX/"bin/shim")
+ expect(described_class.git_remote_exists("blah")).to be_truthy
+ end
+
+ context "when git is available" do
+ it "returns true when git remote exists", :needs_network do
+ git = HOMEBREW_SHIMS_PATH/"scm/git"
+ url = "https://github.com/Homebrew/homebrew.github.io"
+ repo = HOMEBREW_CACHE/"hey"
+ repo.mkpath
+
+ repo.cd do
+ system git, "init"
+ system git, "remote", "add", "origin", url
+ end
+
+ expect(described_class.git_remote_exists(url)).to be_truthy
+ end
+
+ it "returns false when git remote does not exist" do
+ expect(described_class.git_remote_exists("blah")).to be_falsey
+ end
+ end
+ end
+end
diff --git a/Library/Homebrew/test/utils/github_spec.rb b/Library/Homebrew/test/utils/github_spec.rb
index 9322898ee..a132894f9 100644
--- a/Library/Homebrew/test/utils/github_spec.rb
+++ b/Library/Homebrew/test/utils/github_spec.rb
@@ -2,7 +2,7 @@ require "utils/github"
describe GitHub do
describe "::search_code", :needs_network do
- it "queries GitHub code with the passed paramaters" do
+ it "queries GitHub code with the passed parameters" do
results = subject.search_code(repo: "Homebrew/brew", path: "/",
filename: "readme", language: "markdown")
diff --git a/Library/Homebrew/test/utils/svn_spec.rb b/Library/Homebrew/test/utils/svn_spec.rb
new file mode 100644
index 000000000..4edb365a0
--- /dev/null
+++ b/Library/Homebrew/test/utils/svn_spec.rb
@@ -0,0 +1,39 @@
+require "utils/svn"
+
+describe Utils do
+ describe "#self.svn_available?" do
+ before(:each) do
+ described_class.clear_svn_version_cache
+ end
+
+ it "returns svn version if svn available" do
+ expect(described_class.svn_available?).to be_truthy
+ end
+ end
+
+ describe "#self.svn_remote_exists" do
+ it "returns true when svn is not available" do
+ allow(Utils).to receive(:svn_available?).and_return(false)
+ expect(described_class.svn_remote_exists("blah")).to be_truthy
+ end
+
+ context "when svn is available" do
+ before do
+ allow(Utils).to receive(:svn_available?).and_return(true)
+ end
+
+ it "returns false when remote does not exist" do
+ expect(described_class.svn_remote_exists(HOMEBREW_CACHE/"install")).to be_falsey
+ end
+
+ it "returns true when remote exists", :needs_network do
+ remote = "http://github.com/Homebrew/install"
+ svn = HOMEBREW_SHIMS_PATH/"scm/svn"
+
+ HOMEBREW_CACHE.cd { system svn, "checkout", remote }
+
+ expect(described_class.svn_remote_exists(HOMEBREW_CACHE/"install")).to be_truthy
+ end
+ end
+ end
+end
diff --git a/Library/Homebrew/test/utils_spec.rb b/Library/Homebrew/test/utils_spec.rb
index 37bd83c4f..3b5355b15 100644
--- a/Library/Homebrew/test/utils_spec.rb
+++ b/Library/Homebrew/test/utils_spec.rb
@@ -296,4 +296,33 @@ describe "globally-scoped helper methods" do
expect(ENV["PATH"]).not_to eq("/bin")
end
end
+
+ describe "#tap_and_name_comparison" do
+ describe "both strings are only names" do
+ it "alphabetizes the strings" do
+ expect(%w[a b].sort(&tap_and_name_comparison)).to eq(%w[a b])
+ expect(%w[b a].sort(&tap_and_name_comparison)).to eq(%w[a b])
+ end
+ end
+
+ describe "both strings include tap" do
+ it "alphabetizes the strings" do
+ expect(%w[a/z/z b/z/z].sort(&tap_and_name_comparison)).to eq(%w[a/z/z b/z/z])
+ expect(%w[b/z/z a/z/z].sort(&tap_and_name_comparison)).to eq(%w[a/z/z b/z/z])
+
+ expect(%w[z/a/z z/b/z].sort(&tap_and_name_comparison)).to eq(%w[z/a/z z/b/z])
+ expect(%w[z/b/z z/a/z].sort(&tap_and_name_comparison)).to eq(%w[z/a/z z/b/z])
+
+ expect(%w[z/z/a z/z/b].sort(&tap_and_name_comparison)).to eq(%w[z/z/a z/z/b])
+ expect(%w[z/z/b z/z/a].sort(&tap_and_name_comparison)).to eq(%w[z/z/a z/z/b])
+ end
+ end
+
+ describe "only one string includes tap" do
+ it "prefers the string without tap" do
+ expect(%w[a/z/z z].sort(&tap_and_name_comparison)).to eq(%w[z a/z/z])
+ expect(%w[z a/z/z].sort(&tap_and_name_comparison)).to eq(%w[z a/z/z])
+ end
+ end
+ end
end
diff --git a/Library/Homebrew/test/version_spec.rb b/Library/Homebrew/test/version_spec.rb
index cee57e935..d670d79c8 100644
--- a/Library/Homebrew/test/version_spec.rb
+++ b/Library/Homebrew/test/version_spec.rb
@@ -241,8 +241,18 @@ describe Version do
describe "::detect" do
matcher :be_detected_from do |url, specs = {}|
- match do |version|
- Version.detect(url, specs) == version
+ detected = Version.detect(url, specs)
+
+ match do |expected|
+ detected == expected
+ end
+
+ failure_message do |expected|
+ message = <<-EOS
+ expected: %s
+ detected: %s
+ EOS
+ format(message, expected, detected)
end
end
diff --git a/Library/Homebrew/utils.rb b/Library/Homebrew/utils.rb
index e3137ac49..3033eb4dd 100644
--- a/Library/Homebrew/utils.rb
+++ b/Library/Homebrew/utils.rb
@@ -102,7 +102,7 @@ def odeprecated(method, replacement = nil, disable: false, disable_on: nil, call
if ARGV.homebrew_developer? || disable ||
Homebrew.raise_deprecation_exceptions?
raise MethodDeprecatedError, message
- else
+ elsif !Homebrew.auditing?
opoo "#{message}\n"
end
end
@@ -560,3 +560,15 @@ end
def shell_profile
Utils::Shell.profile
end
+
+def tap_and_name_comparison
+ proc do |a, b|
+ if a.include?("/") && !b.include?("/")
+ 1
+ elsif !a.include?("/") && b.include?("/")
+ -1
+ else
+ a <=> b
+ end
+ end
+end
diff --git a/Library/Homebrew/utils/analytics.rb b/Library/Homebrew/utils/analytics.rb
index a89995ba9..9766c14db 100644
--- a/Library/Homebrew/utils/analytics.rb
+++ b/Library/Homebrew/utils/analytics.rb
@@ -3,6 +3,11 @@ require "erb"
module Utils
module Analytics
class << self
+ def clear_anonymous_os_prefix_ci_cache
+ return unless instance_variable_defined?(:@anonymous_os_prefix_ci)
+ remove_instance_variable(:@anonymous_os_prefix_ci)
+ end
+
def os_prefix_ci
@anonymous_os_prefix_ci ||= begin
os = OS_VERSION
diff --git a/Library/Homebrew/utils/curl.rb b/Library/Homebrew/utils/curl.rb
index bc7055c0c..7807d2034 100644
--- a/Library/Homebrew/utils/curl.rb
+++ b/Library/Homebrew/utils/curl.rb
@@ -38,11 +38,14 @@ def curl(*args)
end
def curl_download(*args, to: nil, continue_at: "-", **options)
+ had_incomplete_download ||= File.exist?(to)
curl("--location", "--remote-time", "--continue-at", continue_at.to_s, "--output", to, *args, **options)
rescue ErrorDuringExecution
# `curl` error 33: HTTP server doesn't seem to support byte ranges. Cannot resume.
- if $CHILD_STATUS.exitstatus == 33 && continue_at == "-"
+ # HTTP status 416: Requested range not satisfiable
+ if ($CHILD_STATUS.exitstatus == 33 || had_incomplete_download) && continue_at == "-"
continue_at = 0
+ had_incomplete_download = false
retry
end
diff --git a/Library/Homebrew/utils/git.rb b/Library/Homebrew/utils/git.rb
index 43d93b64e..f1113af66 100644
--- a/Library/Homebrew/utils/git.rb
+++ b/Library/Homebrew/utils/git.rb
@@ -16,8 +16,7 @@ module Git
def last_revision_of_file(repo, file, before_commit: nil)
relative_file = Pathname(file).relative_path_from(repo)
- commit_hash = last_revision_commit_of_file(repo, file, before_commit: before_commit)
-
+ commit_hash = last_revision_commit_of_file(repo, relative_file, before_commit: before_commit)
out, = Open3.capture3(
HOMEBREW_SHIMS_PATH/"scm/git", "-C", repo,
"show", "#{commit_hash}:#{relative_file}"
@@ -28,8 +27,7 @@ end
module Utils
def self.git_available?
- return @git if instance_variable_defined?(:@git)
- @git = quiet_system HOMEBREW_SHIMS_PATH/"scm/git", "--version"
+ @git ||= quiet_system HOMEBREW_SHIMS_PATH/"scm/git", "--version"
end
def self.git_path
@@ -50,21 +48,20 @@ module Utils
return if git_available?
# we cannot install brewed git if homebrew/core is unavailable.
- raise "Git is unavailable" unless CoreTap.instance.installed?
-
- begin
- oh1 "Installing git"
- safe_system HOMEBREW_BREW_FILE, "install", "git"
- rescue
- raise "Git is unavailable"
+ if CoreTap.instance.installed?
+ begin
+ oh1 "Installing git"
+ safe_system HOMEBREW_BREW_FILE, "install", "git"
+ rescue
+ raise "Git is unavailable"
+ end
end
- clear_git_available_cache
raise "Git is unavailable" unless git_available?
end
def self.clear_git_available_cache
- remove_instance_variable(:@git) if instance_variable_defined?(:@git)
+ @git = nil
@git_path = nil
@git_version = nil
end
diff --git a/Library/Homebrew/utils/github.rb b/Library/Homebrew/utils/github.rb
index a1cf5fbba..df0811e95 100644
--- a/Library/Homebrew/utils/github.rb
+++ b/Library/Homebrew/utils/github.rb
@@ -86,15 +86,9 @@ module GitHub
def api_credentials_type
token, username = api_credentials
- if token && !token.empty?
- if username && !username.empty?
- :keychain
- else
- :environment
- end
- else
- :none
- end
+ return :none if !token || token.empty?
+ return :keychain if !username || username.empty?
+ :environment
end
def api_credentials_error_message(response_headers, needed_scopes)
@@ -245,7 +239,7 @@ module GitHub
end
def print_pull_requests_matching(query)
- open_or_closed_prs = search_issues(query, type: "pr")
+ open_or_closed_prs = search_issues(query, type: "pr", user: "Homebrew")
open_prs = open_or_closed_prs.select { |i| i["state"] == "open" }
prs = if !open_prs.empty?
diff --git a/Library/Homebrew/utils/popen.rb b/Library/Homebrew/utils/popen.rb
index 4e03711a1..2fa3ade46 100644
--- a/Library/Homebrew/utils/popen.rb
+++ b/Library/Homebrew/utils/popen.rb
@@ -1,20 +1,20 @@
module Utils
- def self.popen_read(*args, &block)
- popen(args, "rb", &block)
+ def self.popen_read(*args, **options, &block)
+ popen(args, "rb", options, &block)
end
- def self.popen_write(*args, &block)
- popen(args, "wb", &block)
+ def self.popen_write(*args, **options, &block)
+ popen(args, "wb", options, &block)
end
- def self.popen(args, mode)
+ def self.popen(args, mode, options = {})
IO.popen("-", mode) do |pipe|
if pipe
return pipe.read unless block_given?
yield pipe
else
- $stderr.reopen("/dev/null", "w")
- exec(*args)
+ options[:err] ||= :close unless ENV["HOMEBREW_STDERR"]
+ exec(*args, options)
end
end
end
diff --git a/Library/Homebrew/utils/ruby.sh b/Library/Homebrew/utils/ruby.sh
index 6945c068b..9a3ab2e81 100644
--- a/Library/Homebrew/utils/ruby.sh
+++ b/Library/Homebrew/utils/ruby.sh
@@ -2,7 +2,8 @@ setup-ruby-path() {
local vendor_dir
local vendor_ruby_current_version
local vendor_ruby_path
- local ruby_version_major
+ local ruby_old_version
+ local minimum_ruby_version="2.3.3"
vendor_dir="$HOMEBREW_LIBRARY/Homebrew/vendor"
vendor_ruby_current_version="$vendor_dir/portable-ruby/current"
@@ -21,7 +22,7 @@ setup-ruby-path() {
if [[ $(readlink "$vendor_ruby_current_version") != "$(<"$vendor_dir/portable-ruby-version")" ]]
then
- if ! brew vendor-install ruby --quiet
+ if ! brew vendor-install ruby
then
onoe "Failed to upgrade vendor Ruby."
fi
@@ -36,14 +37,12 @@ setup-ruby-path() {
if [[ -n "$HOMEBREW_RUBY_PATH" ]]
then
- ruby_version_major="$("$HOMEBREW_RUBY_PATH" --version)"
- ruby_version_major="${ruby_version_major#ruby }"
- ruby_version_major="${ruby_version_major%%.*}"
+ ruby_old_version="$("$HOMEBREW_RUBY_PATH" -rrubygems -e "puts Gem::Version.new('$minimum_ruby_version') > Gem::Version.new(RUBY_VERSION)")"
fi
- if [[ "$ruby_version_major" != "2" || -n "$HOMEBREW_FORCE_VENDOR_RUBY" ]]
+ if [[ "$ruby_old_version" == "true" || -n "$HOMEBREW_FORCE_VENDOR_RUBY" ]]
then
- brew vendor-install ruby --quiet
+ brew vendor-install ruby
if [[ ! -x "$vendor_ruby_path" ]]
then
odie "Failed to install vendor Ruby."
diff --git a/Library/Homebrew/utils/shell.rb b/Library/Homebrew/utils/shell.rb
index 5327f6ecf..8c1c5f984 100644
--- a/Library/Homebrew/utils/shell.rb
+++ b/Library/Homebrew/utils/shell.rb
@@ -51,8 +51,6 @@ module Utils
end
end
- private
-
SHELL_PROFILE_MAP = {
bash: "~/.bash_profile",
csh: "~/.cshrc",
@@ -65,8 +63,6 @@ module Utils
UNSAFE_SHELL_CHAR = %r{([^A-Za-z0-9_\-.,:/@\n])}
- module_function
-
def csh_quote(str)
# ruby's implementation of shell_escape
str = str.to_s
diff --git a/Library/Homebrew/utils/svn.rb b/Library/Homebrew/utils/svn.rb
index fb49ac2e9..150b7eee7 100644
--- a/Library/Homebrew/utils/svn.rb
+++ b/Library/Homebrew/utils/svn.rb
@@ -1,4 +1,8 @@
module Utils
+ def self.clear_svn_version_cache
+ remove_instance_variable(:@svn) if instance_variable_defined?(:@svn)
+ end
+
def self.svn_available?
return @svn if instance_variable_defined?(:@svn)
@svn = quiet_system HOMEBREW_SHIMS_PATH/"scm/svn", "--version"
diff --git a/Library/Homebrew/vendor/portable-ruby-version b/Library/Homebrew/vendor/portable-ruby-version
index 633c00da3..0bee604df 100644
--- a/Library/Homebrew/vendor/portable-ruby-version
+++ b/Library/Homebrew/vendor/portable-ruby-version
@@ -1 +1 @@
-2.0.0-p648
+2.3.3
diff --git a/README.md b/README.md
index 4d63942ae..a9684b5bb 100644
--- a/README.md
+++ b/README.md
@@ -65,6 +65,10 @@ Our Jenkins CI installation is hosted by [DigitalOcean](https://m.do.co/c/7e39c3
![DigitalOcean](https://cloud.githubusercontent.com/assets/125011/26827038/4b7b5ade-4ab3-11e7-811b-fed3ab0e934d.png)
+Our physical hardware is hosted by [Commsworld](https://www.commsworld.com).
+
+![Commsworld powered by Fluency](https://user-images.githubusercontent.com/125011/30822845-1716bc2c-a222-11e7-843e-ea7c7b6a1503.png)
+
Our bottles (binary packages) are hosted by [Bintray](https://bintray.com/homebrew).
[![Downloads by Bintray](https://bintray.com/docs/images/downloads_by_bintray_96.png)](https://bintray.com/homebrew)
diff --git a/completions/zsh/_brew b/completions/zsh/_brew
index bc88f402b..22792860d 100644
--- a/completions/zsh/_brew
+++ b/completions/zsh/_brew
@@ -592,8 +592,14 @@ _brew_style() {
# brew switch name version:
_brew_switch() {
- _message "name version"
- return 1
+ local -a versions
+ if [[ -n ${words[2]} ]]; then
+ versions=(${$(brew ls "${words[2]}" --versions)#${words[2]}})
+ fi
+ _arguments -S \
+ '1::formula:__brew_formulae' \
+ "2:: :(${versions[*]})" \
+ && ret=0
}
# brew tap:
diff --git a/docs/Analytics.md b/docs/Analytics.md
index 15fa6fc93..18dc7bfa6 100644
--- a/docs/Analytics.md
+++ b/docs/Analytics.md
@@ -37,7 +37,9 @@ As far as we can tell it would be impossible for Google to match the randomly ge
Homebrew's analytics are sent throughout Homebrew's execution to Google Analytics over HTTPS.
## Who?
-Homebrew's analytics are accessible to Homebrew's current maintainers. Contact @MikeMcQuaid if you are a maintainer and need access.
+Homebrew's detailed analytics are accessible to Homebrew's current maintainers. Contact @MikeMcQuaid if you are a maintainer and need access.
+
+Summaries of installation and error analytics are publicly available [here](https://brew.sh/analytics/).
## How?
The code is viewable in [analytics.rb](https://github.com/Homebrew/brew/blob/master/Library/Homebrew/utils/analytics.rb) and [analytics.sh](https://github.com/Homebrew/brew/blob/master/Library/Homebrew/utils/analytics.sh). They are done in a separate background process and fail fast to avoid delaying any execution. They will fail immediately and silently if you have no network connection.
diff --git a/docs/Installation.md b/docs/Installation.md
index e36ed3efa..9f091d2e5 100644
--- a/docs/Installation.md
+++ b/docs/Installation.md
@@ -47,7 +47,7 @@ PowerPC and Tiger branches from other users in the fork network. See
[Interesting Taps and Forks](Interesting-Taps-and-Forks.md).
<a name="2"><sup>2</sup></a> 10.10 or higher is recommended. 10.5–10.9 are
-supported on a best-effort basis. For 10.4 and 10.5, see
+supported on a best-effort basis. For 10.4 see
[Tigerbrew](https://github.com/mistydemeo/tigerbrew).
<a name="3"><sup>3</sup></a> Most formulae require a compiler. A handful
diff --git a/manpages/brew-cask.1 b/manpages/brew-cask.1
index 763d78ebe..f8f58a123 100644
--- a/manpages/brew-cask.1
+++ b/manpages/brew-cask.1
@@ -103,7 +103,7 @@ Reinstall the given Cask\.
.
.TP
\fBsearch\fR or \fB\-S\fR [\fItext\fR | /\fIregexp\fR/]
-Without an argument, display all Casks available for install; otherwise perform a substring search of known Cask tokens for \fItext\fR or, if the text is delimited by slashes (/\fIregexp\fR/), it is interpreted as a Ruby regular expression\.
+Without an argument, display all locally available Casks for install; no online search is performed\. Otherwise perform a substring search of known Cask tokens for \fItext\fR or, if the text is delimited by slashes (/\fIregexp\fR/), it is interpreted as a Ruby regular expression\.
.
.TP
\fBstyle\fR [\-\-fix] [ \fItoken\fR \.\.\. ]