aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGautham Goli2017-10-12 00:29:19 +0530
committerGautham Goli2017-10-13 19:50:46 +0530
commit7fa51f71f1a8a21b905bafc1fb4106f0222d654f (patch)
tree098d2477a8262a5770310fed4693da31c4392e1c
parentafdd0e2437426ec85ff86e5b7562d3a6a69ba3e5 (diff)
parent56458f03fcc68ef6d8ee3ee4a7c1d16021aa5800 (diff)
downloadbrew-7fa51f71f1a8a21b905bafc1fb4106f0222d654f.tar.bz2
Merge branch 'master' into audit_line_rubocop_part_4_rebase_attempt_1
-rw-r--r--.github/ISSUE_TEMPLATE.md17
-rw-r--r--.travis.yml9
-rw-r--r--CODE_OF_CONDUCT.md (renamed from CODEOFCONDUCT.md)0
-rw-r--r--CONTRIBUTING.md2
-rw-r--r--Library/.rubocop.yml23
-rw-r--r--Library/Homebrew/.rubocop.yml30
-rw-r--r--Library/Homebrew/.rubocop_todo.yml145
-rwxr-xr-xLibrary/Homebrew/.simplecov37
-rw-r--r--Library/Homebrew/brew.rb30
-rw-r--r--Library/Homebrew/brew.sh11
-rw-r--r--Library/Homebrew/build.rb6
-rw-r--r--Library/Homebrew/cask/lib/hbc.rb1
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact.rb42
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/abstract_artifact.rb109
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/abstract_flight_block.rb42
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/abstract_uninstall.rb (renamed from Library/Homebrew/cask/lib/hbc/artifact/uninstall_base.rb)146
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/artifact.rb31
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/base.rb80
-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.rb32
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/pkg.rb65
-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.rb30
-rw-r--r--Library/Homebrew/cask/lib/hbc/auditor.rb2
-rw-r--r--Library/Homebrew/cask/lib/hbc/cask.rb10
-rw-r--r--Library/Homebrew/cask/lib/hbc/cask_loader.rb43
-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.rb18
-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_audit_modified_casks.rb2
-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.rb16
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/reinstall.rb2
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/search.rb22
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/uninstall.rb6
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/zap.rb4
-rw-r--r--Library/Homebrew/cask/lib/hbc/container.rb3
-rw-r--r--Library/Homebrew/cask/lib/hbc/container/base.rb2
-rw-r--r--Library/Homebrew/cask/lib/hbc/container/criteria.rb6
-rw-r--r--Library/Homebrew/cask/lib/hbc/container/directory.rb24
-rw-r--r--Library/Homebrew/cask/lib/hbc/container/executable.rb2
-rw-r--r--Library/Homebrew/cask/lib/hbc/container/naked.rb2
-rw-r--r--Library/Homebrew/cask/lib/hbc/container/svn_repository.rb15
-rw-r--r--Library/Homebrew/cask/lib/hbc/download_strategy.rb85
-rw-r--r--Library/Homebrew/cask/lib/hbc/dsl.rb153
-rw-r--r--Library/Homebrew/cask/lib/hbc/dsl/appcast.rb20
-rw-r--r--Library/Homebrew/cask/lib/hbc/dsl/base.rb6
-rw-r--r--Library/Homebrew/cask/lib/hbc/dsl/caveats.rb2
-rw-r--r--Library/Homebrew/cask/lib/hbc/dsl/conflicts_with.rb19
-rw-r--r--Library/Homebrew/cask/lib/hbc/dsl/gpg.rb6
-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/exceptions.rb13
-rw-r--r--Library/Homebrew/cask/lib/hbc/installer.rb43
-rw-r--r--Library/Homebrew/cask/lib/hbc/staged.rb2
-rw-r--r--Library/Homebrew/cask/lib/hbc/system_command.rb6
-rw-r--r--Library/Homebrew/cask/lib/hbc/underscore_supporting_uri.rb28
-rw-r--r--Library/Homebrew/cask/lib/hbc/url.rb13
-rw-r--r--Library/Homebrew/cask/lib/hbc/verify/gpg.rb2
-rw-r--r--Library/Homebrew/caveats.rb2
-rw-r--r--Library/Homebrew/cleanup.rb8
-rw-r--r--Library/Homebrew/cmd/deps.rb134
-rw-r--r--Library/Homebrew/cmd/fetch.rb6
-rw-r--r--Library/Homebrew/cmd/install.rb2
-rw-r--r--Library/Homebrew/cmd/irb.rb8
-rw-r--r--Library/Homebrew/cmd/list.rb10
-rw-r--r--Library/Homebrew/cmd/pin.rb3
-rw-r--r--Library/Homebrew/cmd/postinstall.rb2
-rw-r--r--Library/Homebrew/cmd/prune.rb2
-rw-r--r--Library/Homebrew/cmd/reinstall.rb4
-rw-r--r--Library/Homebrew/cmd/search.rb31
-rw-r--r--Library/Homebrew/cmd/style.rb5
-rw-r--r--Library/Homebrew/cmd/tap-info.rb4
-rw-r--r--Library/Homebrew/cmd/tap.rb3
-rw-r--r--Library/Homebrew/cmd/unlinkapps.rb2
-rw-r--r--Library/Homebrew/cmd/unpin.rb4
-rw-r--r--Library/Homebrew/cmd/update-report.rb9
-rw-r--r--Library/Homebrew/cmd/update.sh7
-rw-r--r--Library/Homebrew/cmd/upgrade.rb1
-rw-r--r--Library/Homebrew/cmd/uses.rb6
-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.rb8
-rw-r--r--Library/Homebrew/debrew/irb.rb5
-rw-r--r--Library/Homebrew/dependency.rb4
-rw-r--r--Library/Homebrew/dependency_collector.rb11
-rw-r--r--Library/Homebrew/descriptions.rb4
-rw-r--r--Library/Homebrew/dev-cmd/aspell-dictionaries.rb5
-rw-r--r--Library/Homebrew/dev-cmd/audit.rb173
-rw-r--r--Library/Homebrew/dev-cmd/bottle.rb15
-rw-r--r--Library/Homebrew/dev-cmd/bump-formula-pr.rb20
-rw-r--r--Library/Homebrew/dev-cmd/man.rb9
-rw-r--r--Library/Homebrew/dev-cmd/mirror.rb10
-rw-r--r--Library/Homebrew/dev-cmd/pull.rb26
-rw-r--r--Library/Homebrew/dev-cmd/release-notes.rb4
-rw-r--r--Library/Homebrew/dev-cmd/test.rb4
-rw-r--r--Library/Homebrew/dev-cmd/update-test.rb2
-rw-r--r--Library/Homebrew/development_tools.rb2
-rw-r--r--Library/Homebrew/diagnostic.rb26
-rw-r--r--Library/Homebrew/download_strategy.rb135
-rw-r--r--Library/Homebrew/exceptions.rb12
-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/ENV/super.rb10
-rw-r--r--Library/Homebrew/extend/cachable.rb9
-rw-r--r--Library/Homebrew/extend/fileutils.rb2
-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.rb12
-rw-r--r--Library/Homebrew/extend/os/mac/formula_cellar_checks.rb16
-rw-r--r--Library/Homebrew/extend/os/mac/hardware/cpu.rb2
-rw-r--r--Library/Homebrew/extend/pathname.rb4
-rw-r--r--Library/Homebrew/extend/string.rb2
-rw-r--r--Library/Homebrew/formula.rb81
-rw-r--r--Library/Homebrew/formula_installer.rb78
-rw-r--r--Library/Homebrew/formula_versions.rb2
-rw-r--r--Library/Homebrew/formulary.rb29
-rw-r--r--Library/Homebrew/global.rb6
-rw-r--r--Library/Homebrew/gpg.rb24
-rw-r--r--Library/Homebrew/install_renamed.rb8
-rw-r--r--Library/Homebrew/keg.rb7
-rw-r--r--Library/Homebrew/keg_relocate.rb3
-rw-r--r--Library/Homebrew/language/python.rb2
-rw-r--r--Library/Homebrew/locale.rb8
-rw-r--r--Library/Homebrew/manpages/brew-cask.1.md20
-rw-r--r--Library/Homebrew/migrator.rb6
-rw-r--r--Library/Homebrew/missing_formula.rb13
-rw-r--r--Library/Homebrew/official_taps.rb2
-rw-r--r--Library/Homebrew/options.rb24
-rw-r--r--Library/Homebrew/os/mac.rb16
-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.rb4
-rw-r--r--Library/Homebrew/patch.rb12
-rw-r--r--Library/Homebrew/pkg_version.rb2
-rw-r--r--Library/Homebrew/postinstall.rb2
-rw-r--r--Library/Homebrew/readall.rb2
-rw-r--r--Library/Homebrew/requirements/gpg2_requirement.rb8
-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.rb54
-rw-r--r--Library/Homebrew/rubocops/lines_cop.rb168
-rw-r--r--Library/Homebrew/rubocops/patches_cop.rb32
-rw-r--r--Library/Homebrew/rubocops/urls_cop.rb6
-rw-r--r--Library/Homebrew/sandbox.rb8
-rwxr-xr-xLibrary/Homebrew/shims/super/cc2
-rwxr-xr-xLibrary/Homebrew/shims/super/make9
-rw-r--r--Library/Homebrew/software_spec.rb16
-rw-r--r--Library/Homebrew/system_config.rb2
-rw-r--r--Library/Homebrew/tab.rb14
-rw-r--r--Library/Homebrew/tap.rb18
-rw-r--r--Library/Homebrew/test.rb2
-rw-r--r--Library/Homebrew/test/Gemfile4
-rw-r--r--Library/Homebrew/test/Gemfile.lock22
-rw-r--r--Library/Homebrew/test/bottle_hooks_spec.rb2
-rw-r--r--Library/Homebrew/test/cask/accessibility_spec.rb2
-rw-r--r--Library/Homebrew/test/cask/artifact/alt_target_spec.rb8
-rw-r--r--Library/Homebrew/test/cask/artifact/app_spec.rb23
-rw-r--r--Library/Homebrew/test/cask/artifact/binary_spec.rb37
-rw-r--r--Library/Homebrew/test/cask/artifact/generic_artifact_spec.rb18
-rw-r--r--Library/Homebrew/test/cask/artifact/nested_container_spec.rb6
-rw-r--r--Library/Homebrew/test/cask/artifact/pkg_spec.rb12
-rw-r--r--Library/Homebrew/test/cask/artifact/postflight_block_spec.rb8
-rw-r--r--Library/Homebrew/test/cask/artifact/preflight_block_spec.rb8
-rw-r--r--Library/Homebrew/test/cask/artifact/suite_spec.rb12
-rw-r--r--Library/Homebrew/test/cask/artifact/two_apps_correct_spec.rb10
-rw-r--r--Library/Homebrew/test/cask/artifact/two_apps_incorrect_spec.rb2
-rw-r--r--Library/Homebrew/test/cask/artifact/uninstall_no_zap_spec.rb4
-rw-r--r--Library/Homebrew/test/cask/artifact/uninstall_zap_shared_examples.rb30
-rw-r--r--Library/Homebrew/test/cask/audit_spec.rb9
-rw-r--r--Library/Homebrew/test/cask/cask_loader/from_content_loader_spec.rb57
-rw-r--r--Library/Homebrew/test/cask/cask_loader/from_uri_loader_spec.rb21
-rw-r--r--Library/Homebrew/test/cask/cask_spec.rb34
-rw-r--r--Library/Homebrew/test/cask/cli/audit_spec.rb20
-rw-r--r--Library/Homebrew/test/cask/cli/cat_spec.rb37
-rw-r--r--Library/Homebrew/test/cask/cli/cleanup_spec.rb4
-rw-r--r--Library/Homebrew/test/cask/cli/create_spec.rb30
-rw-r--r--Library/Homebrew/test/cask/cli/doctor_spec.rb4
-rw-r--r--Library/Homebrew/test/cask/cli/edit_spec.rb24
-rw-r--r--Library/Homebrew/test/cask/cli/fetch_spec.rb36
-rw-r--r--Library/Homebrew/test/cask/cli/home_spec.rb4
-rw-r--r--Library/Homebrew/test/cask/cli/info_spec.rb70
-rw-r--r--Library/Homebrew/test/cask/cli/install_spec.rb86
-rw-r--r--Library/Homebrew/test/cask/cli/list_spec.rb40
-rw-r--r--Library/Homebrew/test/cask/cli/options_spec.rb32
-rw-r--r--Library/Homebrew/test/cask/cli/outdated_spec.rb16
-rw-r--r--Library/Homebrew/test/cask/cli/reinstall_spec.rb14
-rw-r--r--Library/Homebrew/test/cask/cli/search_spec.rb57
-rw-r--r--Library/Homebrew/test/cask/cli/shared_examples/invalid_option.rb15
-rw-r--r--Library/Homebrew/test/cask/cli/shared_examples/requires_cask_token.rb9
-rw-r--r--Library/Homebrew/test/cask/cli/style_spec.rb4
-rw-r--r--Library/Homebrew/test/cask/cli/uninstall_spec.rb65
-rw-r--r--Library/Homebrew/test/cask/cli/zap_spec.rb33
-rw-r--r--Library/Homebrew/test/cask/conflicts_with_spec.rb23
-rw-r--r--Library/Homebrew/test/cask/container/dmg_spec.rb2
-rw-r--r--Library/Homebrew/test/cask/depends_on_spec.rb29
-rw-r--r--Library/Homebrew/test/cask/download_strategy_spec.rb66
-rw-r--r--Library/Homebrew/test/cask/dsl/appcast_spec.rb13
-rw-r--r--Library/Homebrew/test/cask/dsl/caveats_spec.rb2
-rw-r--r--Library/Homebrew/test/cask/dsl/postflight_spec.rb2
-rw-r--r--Library/Homebrew/test/cask/dsl/preflight_spec.rb2
-rw-r--r--Library/Homebrew/test/cask/dsl/uninstall_postflight_spec.rb2
-rw-r--r--Library/Homebrew/test/cask/dsl/uninstall_preflight_spec.rb2
-rw-r--r--Library/Homebrew/test/cask/dsl_spec.rb83
-rw-r--r--Library/Homebrew/test/cask/installer_spec.rb48
-rw-r--r--Library/Homebrew/test/cask/staged_spec.rb2
-rw-r--r--Library/Homebrew/test/cask/underscore_supporting_uri_spec.rb14
-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/cmd/search_spec.rb14
-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/download_strategies_spec.rb11
-rw-r--r--Library/Homebrew/test/exceptions_spec.rb6
-rw-r--r--Library/Homebrew/test/formula_installer_spec.rb2
-rw-r--r--Library/Homebrew/test/formulary_spec.rb2
-rw-r--r--Library/Homebrew/test/locale_spec.rb4
-rw-r--r--Library/Homebrew/test/missing_formula_spec.rb6
-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/bottle_block_cop_spec.rb4
-rw-r--r--Library/Homebrew/test/rubocops/caveats_cop_spec.rb2
-rw-r--r--Library/Homebrew/test/rubocops/checksum_cop_spec.rb12
-rw-r--r--Library/Homebrew/test/rubocops/class_cop_spec.rb81
-rw-r--r--Library/Homebrew/test/rubocops/components_order_cop_spec.rb12
-rw-r--r--Library/Homebrew/test/rubocops/components_redundancy_cop_spec.rb6
-rw-r--r--Library/Homebrew/test/rubocops/conflicts_cop_spec.rb4
-rw-r--r--Library/Homebrew/test/rubocops/formula_desc_cop_spec.rb20
-rw-r--r--Library/Homebrew/test/rubocops/homepage_cop_spec.rb6
-rw-r--r--Library/Homebrew/test/rubocops/lines_cop_spec.rb190
-rw-r--r--Library/Homebrew/test/rubocops/options_cop_spec.rb10
-rw-r--r--Library/Homebrew/test/rubocops/patches_cop_spec.rb202
-rw-r--r--Library/Homebrew/test/rubocops/text_cop_spec.rb66
-rw-r--r--Library/Homebrew/test/rubocops/urls_cop_spec.rb31
-rw-r--r--Library/Homebrew/test/support/fixtures/bottles/testball_bottle-0.1.yosemite.bottle.tar.gzbin1379 -> 1731 bytes
-rw-r--r--Library/Homebrew/test/support/fixtures/cask/Casks/with-conflicts-with.rb2
-rw-r--r--Library/Homebrew/test/support/fixtures/cask/Casks/with-languages.rb18
-rw-r--r--Library/Homebrew/test/support/fixtures/cask/Casks/without-languages.rb9
-rw-r--r--Library/Homebrew/test/support/fixtures/testball_bottle.rb2
-rw-r--r--Library/Homebrew/test/support/fixtures/third-party/Casks/third-party-cask.rb9
-rw-r--r--Library/Homebrew/test/support/helper/fixtures.rb4
-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.rb30
-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.rb19
-rw-r--r--Library/Homebrew/utils.rb22
-rw-r--r--Library/Homebrew/utils/analytics.rb5
-rw-r--r--Library/Homebrew/utils/bottles.rb13
-rw-r--r--Library/Homebrew/utils/curl.rb51
-rw-r--r--Library/Homebrew/utils/fork.rb9
-rw-r--r--Library/Homebrew/utils/git.rb23
-rw-r--r--Library/Homebrew/utils/github.rb92
-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--Library/Homebrew/version.rb214
-rw-r--r--README.md6
-rw-r--r--completions/bash/brew6
-rw-r--r--completions/zsh/_brew20
-rw-r--r--docs/Analytics.md4
-rw-r--r--docs/FAQ.md15
-rw-r--r--docs/Formula-Cookbook.md2
-rw-r--r--docs/Homebrew-and-Python.md8
-rw-r--r--docs/Installation.md2
-rw-r--r--docs/Interesting-Taps-and-Forks.md12
-rw-r--r--docs/Kickstarter-Supporters.md2
-rw-r--r--docs/Manpage.md20
-rw-r--r--docs/Prose-Style-Guidelines.md2
-rw-r--r--docs/Python-for-Formula-Authors.md48
-rw-r--r--manpages/brew-cask.112
-rw-r--r--manpages/brew.120
301 files changed, 3992 insertions, 2856 deletions
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index f4e56604e..287e95b03 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -1,17 +1,22 @@
+**Please note we will close your issue without comment if you delete, do not read or do not fill out the issue checklist below and provide ALL the requested information. If you repeatedly fail to use the issue template, we will block you from ever submitting issues to Homebrew again.**
+
# Please always follow these steps:
-- [ ] Confirmed this is a problem with running a `brew` command and not `brew install`ing or the post-install behaviour of one or more formulae? If it's a formulae-specific problem please file this issue at https://github.com/Homebrew/homebrew-core/issues/new
+- [ ] Confirmed this is a problem with running a `brew` command and not `brew install`ing or the post-install behaviour of one or more formulae? If it's a formulae-specific problem please file this issue at the relevant tap e.g. for Homebrew/homebrew-core https://github.com/Homebrew/homebrew-core/issues/new
- [ ] Ran `brew update` and retried your prior step?
- [ ] Ran `brew doctor`, fixed all issues and retried your prior step?
- [ ] Ran `brew config` and `brew doctor` and included their output with your issue?
-**Please note we will close your issue without comment if you delete or do not fill out the issue checklist and provide ALL the requested information.**
-
To help us debug your issue please explain:
- What you were trying to do (and why)
- What happened (include command output)
- What you expected to happen
- Step-by-step reproduction instructions (by running `brew` commands)
-# Or propose a feature:
-Please replace this section with a detailed description of your proposed feature, the motivation for it, how it would be relevant to at least 90% of Homebrew users and alternatives considered.
-Please note we will close this issue or ask you to create a pull-request if it's something we're not actively planning to work on.
+# Features
+Please replace this section with:
+- a detailed description of your proposed feature
+- the motivation for the feature
+- how the feature would be relevant to at least 90% of Homebrew users
+- what alternatives to the feature you have considered
+
+We will close this issue or ask you to create a pull-request if it's something we're not actively planning to work on.
diff --git a/.travis.yml b/.travis.yml
index 9cdebda83..670e69ad0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,30 +11,31 @@ matrix:
fast_finish: true
include:
- os: osx
- osx_image: xcode8.3
+ osx_image: xcode9
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
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";
+ git clone --depth=1 https://github.com/Homebrew/homebrew-test-bot Library/Taps/homebrew/homebrew-test-bot;
else
+ umask 022;
git fetch --unshallow;
export PATH="$PWD/bin:$PATH";
HOMEBREW_CORE_TAP_DIR="$(brew --repo "homebrew/core")";
mkdir -p "$HOMEBREW_CORE_TAP_DIR";
+ git clone --depth=1 https://github.com/Homebrew/homebrew-test-bot Library/Taps/homebrew/homebrew-test-bot;
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/CODEOFCONDUCT.md b/CODE_OF_CONDUCT.md
index 9706e18f9..9706e18f9 100644
--- a/CODEOFCONDUCT.md
+++ b/CODE_OF_CONDUCT.md
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index e5272c682..4729d6ca3 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,5 +1,5 @@
# Contributing to Homebrew
-First time contributing to Homebrew? Read our [Code of Conduct](https://github.com/Homebrew/brew/blob/master/CODEOFCONDUCT.md#code-of-conduct).
+First time contributing to Homebrew? Read our [Code of Conduct](https://github.com/Homebrew/brew/blob/master/CODE_OF_CONDUCT.md#code-of-conduct).
### Report a bug
diff --git a/Library/.rubocop.yml b/Library/.rubocop.yml
index a2e3cc9c9..ed31de595 100644
--- a/Library/.rubocop.yml
+++ b/Library/.rubocop.yml
@@ -1,5 +1,5 @@
AllCops:
- TargetRubyVersion: 2.0
+ TargetRubyVersion: 2.3
Exclude:
- '**/Casks/**/*'
- '**/vendor/**/*'
@@ -123,7 +123,7 @@ Style/Tab:
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
@@ -193,8 +193,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..143468643 100644
--- a/Library/Homebrew/.rubocop.yml
+++ b/Library/Homebrew/.rubocop.yml
@@ -1,6 +1,5 @@
inherit_from:
- ../.rubocop.yml
- - .rubocop_todo.yml
AllCops:
Include:
@@ -26,12 +25,30 @@ Lint/NestedMethodDefinition:
Lint/ParenthesesAsGroupedExpression:
Enabled: true
+Metrics/BlockNesting:
+ Max: 5
+
+Metrics/ModuleLength:
+ Max: 360
+
Metrics/ParameterLists:
CountKeywordArgs: false
+# we won't change backward compatible method names
+Naming/MethodName:
+ Exclude:
+ - 'compat/**/*'
+
+# we won't change backward compatible predicate names
+Naming/PredicateName:
+ Exclude:
+ - 'compat/**/*'
+ NameWhitelist: is_32_bit?, is_64_bit?
+
Style/BlockDelimiters:
Exclude:
- '**/*_spec.rb'
+ - '**/shared_examples/**/*.rb'
# so many of these in formulae but none in here
Style/GuardClause:
@@ -40,14 +57,3 @@ Style/GuardClause:
# hash-rockets preferred for formulae, a: 1 preferred elsewhere
Style/HashSyntax:
EnforcedStyle: ruby19_no_mixed_keys
-
-# we won't change backward compatible method names
-Style/MethodName:
- Exclude:
- - 'compat/**/*'
-
-# we won't change backward compatible predicate names
-Style/PredicateName:
- Exclude:
- - 'compat/**/*'
- NameWhitelist: is_32_bit?, is_64_bit?
diff --git a/Library/Homebrew/.rubocop_todo.yml b/Library/Homebrew/.rubocop_todo.yml
deleted file mode 100644
index 37518a5f0..000000000
--- a/Library/Homebrew/.rubocop_todo.yml
+++ /dev/null
@@ -1,145 +0,0 @@
-# This configuration was generated by
-# `rubocop --auto-gen-config --exclude-limit 100`
-# on 2017-01-27 21:44:55 +0000 using RuboCop version 0.47.1.
-# The point is for the user to remove these configuration records
-# one by one as the offenses are removed from the code base.
-# Note that changes in the inspected code, or installation of new
-# versions of RuboCop, may require this file to be generated again.
-
-# Offense count: 17
-Lint/HandleExceptions:
- Exclude:
- - 'cmd/install.rb'
- - 'cmd/reinstall.rb'
- - 'cmd/tap.rb'
- - 'cmd/update-report.rb'
- - 'cmd/upgrade.rb'
- - 'cmd/uses.rb'
- - 'descriptions.rb'
- - 'diagnostic.rb'
- - 'extend/ENV/super.rb'
- - 'extend/pathname.rb'
- - 'formula.rb'
- - 'formula_versions.rb'
- - 'test/ENV_test.rb'
-
-# Offense count: 3
-Lint/IneffectiveAccessModifier:
- Exclude:
- - 'formula.rb'
- - 'version.rb'
-
-# Offense count: 1
-Lint/Loop:
- Exclude:
- - 'patch.rb'
-
-# Offense count: 28
-Lint/RescueException:
- Exclude:
- - 'brew.rb'
- - 'build.rb'
- - 'cmd/fetch.rb'
- - 'cmd/reinstall.rb'
- - 'cmd/update-report.rb'
- - 'debrew.rb'
- - 'dev-cmd/pull.rb'
- - 'dev-cmd/test.rb'
- - 'formula.rb'
- - 'formula_installer.rb'
- - 'migrator.rb'
- - 'postinstall.rb'
- - 'readall.rb'
- - 'test.rb'
- - 'test/ENV_test.rb'
- - 'utils/fork.rb'
-
-# Offense count: 1
-Lint/ShadowedException:
- Exclude:
- - 'utils/fork.rb'
-
-# Offense count: 13
-# Configuration parameters: CountBlocks.
-Metrics/BlockNesting:
- Max: 5
-
-# Offense count: 19
-# Configuration parameters: CountComments.
-Metrics/ModuleLength:
- Max: 400
-
-# Offense count: 1
-# Configuration parameters: CountKeywordArgs.
-Metrics/ParameterLists:
- Max: 6
-
-# Offense count: 2
-Security/MarshalLoad:
- Exclude:
- - 'dependency.rb'
- - 'utils/fork.rb'
-
-# Offense count: 1
-Style/AccessorMethodName:
- Exclude:
- - 'extend/ENV/super.rb'
-
-# Offense count: 6
-Style/ClassVars:
- Exclude:
- - 'dev-cmd/audit.rb'
- - 'formula_installer.rb'
- - 'test/support/helper/fs_leak_logger.rb'
-
-# Offense count: 13
-# Cop supports --auto-correct.
-# Configuration parameters: EnforcedStyle, SupportedStyles.
-# SupportedStyles: compact, expanded
-Style/EmptyMethod:
- Exclude:
- - 'debrew/irb.rb'
- - 'download_strategy.rb'
- - 'extend/ENV/super.rb'
- - 'formula.rb'
- - 'patch.rb'
-
-# Offense count: 13
-# Configuration parameters: AllowedVariables.
-Style/GlobalVars:
- Exclude:
- - 'diagnostic.rb'
- - 'utils.rb'
-
-# Offense count: 1
-# Configuration parameters: EnforcedStyle, SupportedStyles.
-# SupportedStyles: module_function, extend_self
-Style/ModuleFunction:
- Exclude:
- - 'os/mac/xcode.rb'
-
-# Offense count: 8
-Style/MultilineBlockChain:
- Exclude:
- - 'cmd/search.rb'
- - 'dev-cmd/aspell-dictionaries.rb'
- - 'dev-cmd/audit.rb'
- - 'dev-cmd/man.rb'
- - 'diagnostic.rb'
- - 'test/patching_test.rb'
-
-# Offense count: 4
-# Cop supports --auto-correct.
-Style/MutableConstant:
- Exclude:
- - 'dependency_collector.rb'
- - 'formulary.rb'
- - 'tab.rb'
- - 'tap.rb'
-
-# Offense count: 8
-Style/OpMethod:
- Exclude:
- - 'dependencies.rb'
- - 'install_renamed.rb'
- - 'options.rb'
diff --git a/Library/Homebrew/.simplecov b/Library/Homebrew/.simplecov
index 23e60faeb..e0d6d7601 100755
--- a/Library/Homebrew/.simplecov
+++ b/Library/Homebrew/.simplecov
@@ -11,11 +11,6 @@ SimpleCov.start do
# tests to be dropped. This causes random fluctuations in test coverage.
merge_timeout 86400
- add_filter "/Homebrew/compat/"
- add_filter "/Homebrew/dev-cmd/tests.rb"
- add_filter "/Homebrew/test/"
- add_filter "/Homebrew/vendor/"
-
if ENV["HOMEBREW_INTEGRATION_TEST"]
command_name "#{ENV["HOMEBREW_INTEGRATION_TEST"]} (#{$PROCESS_ID})"
@@ -33,22 +28,32 @@ SimpleCov.start do
end
else
command_name "#{command_name} (#{$PROCESS_ID})"
+
+ subdirs = Dir.chdir(SimpleCov.root) { Dir.glob("*") }
+ .reject { |d| d.end_with?(".rb") || ["test", "vendor"].include?(d) }
+ .map { |d| "#{d}/**/*.rb" }.join(",")
+
# Not using this during integration tests makes the tests 4x times faster
# without changing the coverage.
- track_files "#{SimpleCov.root}/**/*.rb"
+ track_files "#{SimpleCov.root}/{#{subdirs},*.rb}"
end
+ add_filter %r{^/compat/}
+ add_filter %r{^/dev-cmd/tests.rb$}
+ add_filter %r{^/test/}
+ add_filter %r{^/vendor/}
+
# Add groups and the proper project name to the output.
project_name "Homebrew"
- add_group "Cask", "/Homebrew/cask/"
- add_group "Commands", %w[/Homebrew/cmd/ /Homebrew/dev-cmd/]
- add_group "Extensions", "/Homebrew/extend/"
- add_group "OS", %w[/Homebrew/extend/os/ /Homebrew/os/]
- add_group "Requirements", "/Homebrew/requirements/"
- add_group "Scripts", %w[
- /Homebrew/brew.rb
- /Homebrew/build.rb
- /Homebrew/postinstall.rb
- /Homebrew/test.rb
+ add_group "Cask", %r{^/cask/}
+ add_group "Commands", [%r{/cmd/}, %r{^/dev-cmd/}]
+ add_group "Extensions", %r{^/extend/}
+ add_group "OS", [%r{^/extend/os/}, %r{^/os/}]
+ add_group "Requirements", %r{^/requirements/}
+ add_group "Scripts", [
+ %r{^/brew.rb$},
+ %r{^/build.rb$},
+ %r{^/postinstall.rb$},
+ %r{^/test.rb$},
]
end
diff --git a/Library/Homebrew/brew.rb b/Library/Homebrew/brew.rb
index ec86bd794..86b40a79d 100644
--- a/Library/Homebrew/brew.rb
+++ b/Library/Homebrew/brew.rb
@@ -5,8 +5,12 @@ end
std_trap = trap("INT") { exit! 130 } # no backtrace thanks
# check ruby version before requiring any modules.
-RUBY_TWO = RUBY_VERSION.split(".").first.to_i >= 2
-raise "Homebrew must be run under Ruby 2!" unless RUBY_TWO
+RUBY_VERSION_SPLIT = RUBY_VERSION.split "."
+RUBY_X = RUBY_VERSION_SPLIT[0].to_i
+RUBY_Y = RUBY_VERSION_SPLIT[1].to_i
+if RUBY_X < 2 || (RUBY_X == 2 && RUBY_Y < 3)
+ raise "Homebrew must be run under Ruby 2.3!"
+end
require "pathname"
HOMEBREW_LIBRARY_PATH = Pathname.new(__FILE__).realpath.parent
@@ -105,18 +109,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"
@@ -144,7 +146,7 @@ rescue MethodDeprecatedError => e
$stderr.puts " #{Formatter.url(e.issues_url)}"
end
exit 1
-rescue Exception => e
+rescue Exception => e # rubocop:disable Lint/RescueException
onoe e
if internal_cmd && defined?(OS::ISSUES_URL) &&
!ENV["HOMEBREW_NO_AUTO_UPDATE"]
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..836b360da 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
@@ -186,7 +190,7 @@ begin
options = Options.create(ARGV.flags_only)
build = Build.new(formula, options)
build.install
-rescue Exception => e
+rescue Exception => e # rubocop:disable Lint/RescueException
Marshal.dump(e, error_pipe)
error_pipe.close
exit! 1
diff --git a/Library/Homebrew/cask/lib/hbc.rb b/Library/Homebrew/cask/lib/hbc.rb
index 780acedf5..01a085019 100644
--- a/Library/Homebrew/cask/lib/hbc.rb
+++ b/Library/Homebrew/cask/lib/hbc.rb
@@ -25,7 +25,6 @@ require "hbc/scopes"
require "hbc/staged"
require "hbc/system_command"
require "hbc/topological_hash"
-require "hbc/underscore_supporting_uri"
require "hbc/url"
require "hbc/utils"
require "hbc/verify"
diff --git a/Library/Homebrew/cask/lib/hbc/artifact.rb b/Library/Homebrew/cask/lib/hbc/artifact.rb
index 074d15017..1cbe49cf2 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact.rb
@@ -25,47 +25,5 @@ require "hbc/artifact/zap"
module Hbc
module Artifact
- # NOTE: Order is important here!
- #
- # The `uninstall` stanza should be run first, as it may
- # depend on other artifacts still being installed.
- #
- # We want to extract nested containers before we
- # handle any other artifacts.
- #
- TYPES = [
- PreflightBlock,
- Uninstall,
- NestedContainer,
- Installer,
- App,
- Suite,
- Artifact, # generic 'artifact' stanza
- Colorpicker,
- Pkg,
- Prefpane,
- Qlplugin,
- Dictionary,
- Font,
- Service,
- StageOnly,
- Binary,
- InputMethod,
- InternetPlugin,
- AudioUnitPlugin,
- VstPlugin,
- Vst3Plugin,
- ScreenSaver,
- PostflightBlock,
- Zap,
- ].freeze
-
- def self.for_cask(cask, options = {})
- odebug "Determining which artifacts are present in Cask #{cask}"
-
- TYPES
- .select { |klass| klass.me?(cask) }
- .map { |klass| klass.new(cask, options) }
- end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/abstract_artifact.rb b/Library/Homebrew/cask/lib/hbc/artifact/abstract_artifact.rb
new file mode 100644
index 000000000..f9f736662
--- /dev/null
+++ b/Library/Homebrew/cask/lib/hbc/artifact/abstract_artifact.rb
@@ -0,0 +1,109 @@
+module Hbc
+ module Artifact
+ class AbstractArtifact
+ include Comparable
+ extend Predicable
+
+ def self.english_name
+ @english_name ||= name.sub(/^.*:/, "").gsub(/(.)([A-Z])/, '\1 \2')
+ end
+
+ def self.english_article
+ @english_article ||= (english_name =~ /^[aeiou]/i) ? "an" : "a"
+ end
+
+ def self.dsl_key
+ @dsl_key ||= name.sub(/^.*:/, "").gsub(/(.)([A-Z])/, '\1_\2').downcase.to_sym
+ end
+
+ def self.dirmethod
+ @dirmethod ||= "#{dsl_key}dir".to_sym
+ end
+
+ def <=>(other)
+ return unless other.class < AbstractArtifact
+ return 0 if self.class == other.class
+
+ @@sort_order ||= [ # rubocop:disable Style/ClassVars
+ PreflightBlock,
+ # The `uninstall` stanza should be run first, as it may
+ # depend on other artifacts still being installed.
+ Uninstall,
+ # We want to extract nested containers before we
+ # handle any other artifacts.
+ NestedContainer,
+ Installer,
+ [
+ App,
+ Suite,
+ Artifact,
+ Colorpicker,
+ Prefpane,
+ Qlplugin,
+ Dictionary,
+ Font,
+ Service,
+ InputMethod,
+ InternetPlugin,
+ AudioUnitPlugin,
+ VstPlugin,
+ Vst3Plugin,
+ ScreenSaver,
+ ],
+ # `pkg` should be run before `binary`, so
+ # targets are created prior to linking.
+ Pkg,
+ Binary,
+ PostflightBlock,
+ Zap,
+ ].each_with_index.flat_map { |classes, i| [*classes].map { |c| [c, i] } }.to_h
+
+ (@@sort_order[self.class] <=> @@sort_order[other.class]).to_i
+ end
+
+ # TODO: this sort of logic would make more sense in dsl.rb, or a
+ # constructor called from dsl.rb, so long as that isn't slow.
+ def self.read_script_arguments(arguments, stanza, default_arguments = {}, override_arguments = {}, key = nil)
+ # TODO: when stanza names are harmonized with class names,
+ # stanza may not be needed as an explicit argument
+ description = key ? "#{stanza} #{key.inspect}" : stanza.to_s
+
+ # backward-compatible string value
+ arguments = { executable: arguments } if arguments.is_a?(String)
+
+ # key sanity
+ permitted_keys = [:args, :input, :executable, :must_succeed, :sudo, :print_stdout, :print_stderr]
+ unknown_keys = arguments.keys - permitted_keys
+ unless unknown_keys.empty?
+ opoo %Q{Unknown arguments to #{description} -- #{unknown_keys.inspect} (ignored). Running "brew update; brew cleanup; brew cask cleanup" will likely fix it.}
+ end
+ arguments.select! { |k| permitted_keys.include?(k) }
+
+ # key warnings
+ override_keys = override_arguments.keys
+ ignored_keys = arguments.keys & override_keys
+ unless ignored_keys.empty?
+ onoe "Some arguments to #{description} will be ignored -- :#{unknown_keys.inspect} (overridden)."
+ end
+
+ # extract executable
+ executable = arguments.key?(:executable) ? arguments.delete(:executable) : nil
+
+ arguments = default_arguments.merge arguments
+ arguments.merge! override_arguments
+
+ [executable, arguments]
+ end
+
+ attr_reader :cask
+
+ def initialize(cask)
+ @cask = cask
+ end
+
+ def to_s
+ "#{summarize} (#{self.class.english_name})"
+ end
+ end
+ end
+end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/abstract_flight_block.rb b/Library/Homebrew/cask/lib/hbc/artifact/abstract_flight_block.rb
index be3050acb..a3075ff40 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,45 @@
-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}")
- end
+ attr_reader :directives
- def self.me?(cask)
- cask.artifacts[artifact_dsl_key].any? ||
- cask.artifacts[uninstall_artifact_dsl_key].any?
+ 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..3f63dae8f 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.flat_map { |key, val| [*val].map { |v| "#{key.inspect} => #{v.inspect}" } }.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, **_)
+ result = 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)
@@ -250,7 +267,7 @@ module Hbc
set trashedItem to POSIX path of (item i of trashedItems as string)
set output to output & trashedItem
if i < count trashedItems then
- set output to output & (do shell script "printf \"\\0\"")
+ set output to output & character id 0
end if
end repeat
@@ -258,9 +275,12 @@ module Hbc
end tell
end run
EOS
+
+ # Remove AppleScript's automatic newline.
+ result.tap { |r| r.stdout.sub!(/\n$/, "") }
end
- def uninstall_rmdir(*directories)
+ def uninstall_rmdir(*directories, command: nil, **_)
return if directories.empty?
ohai "Removing directories if empty:"
@@ -268,10 +288,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/base.rb b/Library/Homebrew/cask/lib/hbc/artifact/base.rb
deleted file mode 100644
index ae15552a4..000000000
--- a/Library/Homebrew/cask/lib/hbc/artifact/base.rb
+++ /dev/null
@@ -1,80 +0,0 @@
-module Hbc
- module Artifact
- class Base
- extend Predicable
-
- def self.artifact_name
- @artifact_name ||= name.sub(/^.*:/, "").gsub(/(.)([A-Z])/, '\1_\2').downcase
- end
-
- def self.artifact_english_name
- @artifact_english_name ||= name.sub(/^.*:/, "").gsub(/(.)([A-Z])/, '\1 \2')
- end
-
- def self.artifact_english_article
- @artifact_english_article ||= (artifact_english_name =~ /^[aeiou]/i) ? "an" : "a"
- end
-
- def self.artifact_dsl_key
- @artifact_dsl_key ||= artifact_name.to_sym
- end
-
- def self.artifact_dirmethod
- @artifact_dirmethod ||= "#{artifact_name}dir".to_sym
- end
-
- def self.me?(cask)
- cask.artifacts[artifact_dsl_key].any?
- end
-
- attr_reader :force
-
- # TODO: this sort of logic would make more sense in dsl.rb, or a
- # constructor called from dsl.rb, so long as that isn't slow.
- def self.read_script_arguments(arguments, stanza, default_arguments = {}, override_arguments = {}, key = nil)
- # TODO: when stanza names are harmonized with class names,
- # stanza may not be needed as an explicit argument
- description = key ? "#{stanza} #{key.inspect}" : stanza.to_s
-
- # backward-compatible string value
- arguments = { executable: arguments } if arguments.is_a?(String)
-
- # key sanity
- permitted_keys = [:args, :input, :executable, :must_succeed, :sudo, :print_stdout, :print_stderr]
- unknown_keys = arguments.keys - permitted_keys
- unless unknown_keys.empty?
- opoo %Q{Unknown arguments to #{description} -- #{unknown_keys.inspect} (ignored). Running "brew update; brew cleanup; brew cask cleanup" will likely fix it.}
- end
- arguments.select! { |k| permitted_keys.include?(k) }
-
- # key warnings
- override_keys = override_arguments.keys
- ignored_keys = arguments.keys & override_keys
- unless ignored_keys.empty?
- onoe "Some arguments to #{description} will be ignored -- :#{unknown_keys.inspect} (overridden)."
- end
-
- # extract executable
- executable = arguments.key?(:executable) ? arguments.delete(:executable) : nil
-
- arguments = default_arguments.merge arguments
- arguments.merge! override_arguments
-
- [executable, arguments]
- end
-
- def summary
- {}
- end
-
- attr_predicate :force?, :verbose?
-
- def initialize(cask, command: SystemCommand, force: false, verbose: false)
- @cask = cask
- @command = command
- @force = force
- @verbose = verbose
- end
- 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..c9fd3dc27 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/nested_container.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/nested_container.rb
@@ -1,23 +1,35 @@
-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
+
+ private
+
+ def summarize
+ path.relative_path_from(cask.staged_path).to_s
end
- def extract(container_relative_path)
- source = @cask.staged_path.join(container_relative_path)
- container = Container.for_path(source, @command)
+ 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..b4bdf3de6 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,61 @@ 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, **stanza_options)
+ stanza_options.extend(HashValidator).assert_valid_keys(
+ :allow_untrusted, :choices
+ )
+ new(cask, path, **stanza_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, :stanza_options
+
+ def initialize(cask, path, **stanza_options)
+ super(cask)
+ @path = cask.staged_path.join(path)
+ @stanza_options = stanza_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
+ if stanza_options.fetch(:allow_untrusted, false)
+ args << "-allowUntrusted"
+ end
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 = stanza_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 cee1fe807..bd25477ac 100644
--- a/Library/Homebrew/cask/lib/hbc/audit.rb
+++ b/Library/Homebrew/cask/lib/hbc/audit.rb
@@ -70,12 +70,16 @@ module Hbc
previous_cask_contents = Git.last_revision_of_file(tap.path, @cask.sourcefile_path, before_commit: commit_range)
return if previous_cask_contents.empty?
- previous_cask = CaskLoader.load_from_string(previous_cask_contents)
+ begin
+ previous_cask = CaskLoader.load(previous_cask_contents)
- return unless previous_cask.version == cask.version
- return if previous_cask.sha256 == cask.sha256
+ return unless previous_cask.version == cask.version
+ return if previous_cask.sha256 == cask.sha256
- add_error "only sha256 changed (see: https://github.com/caskroom/homebrew-cask/blob/master/doc/cask_language_reference/stanzas/sha256.md)"
+ add_error "only sha256 changed (see: https://github.com/caskroom/homebrew-cask/blob/master/doc/cask_language_reference/stanzas/sha256.md)"
+ rescue CaskError => e
+ add_warning "Skipped version and checksum comparison. Reading previous version failed: #{e}"
+ end
end
def check_version
@@ -143,7 +147,15 @@ module Hbc
def check_appcast_http_code
odebug "Verifying appcast returns 200 HTTP response code"
- result = @command.run("/usr/bin/curl", args: ["--compressed", "--location", "--user-agent", URL::FAKE_USER_AGENT, "--output", "/dev/null", "--write-out", "%{http_code}", cask.appcast], print_stderr: false)
+
+ curl_executable, *args = curl_args(
+ "--compressed", "--location", "--fail",
+ "--write-out", "%{http_code}",
+ "--output", "/dev/null",
+ cask.appcast,
+ user_agent: :fake
+ )
+ result = @command.run(curl_executable, args: args, print_stderr: false)
if result.success?
http_code = result.stdout.chomp
add_warning "unexpected HTTP response code retrieving appcast: #{http_code}" unless http_code == "200"
@@ -206,12 +218,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.select { |a| a.is_a?(Hbc::Artifact::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/auditor.rb b/Library/Homebrew/cask/lib/hbc/auditor.rb
index 48f36a54d..231c005f9 100644
--- a/Library/Homebrew/cask/lib/hbc/auditor.rb
+++ b/Library/Homebrew/cask/lib/hbc/auditor.rb
@@ -43,7 +43,7 @@ module Hbc
def audit_languages(languages)
ohai "Auditing language: #{languages.map { |lang| "'#{lang}'" }.join(", ")}"
MacOS.instance_variable_set(:@languages, languages)
- audit_cask_instance(CaskLoader.load_from_file(cask.sourcefile_path))
+ audit_cask_instance(CaskLoader.load(cask.sourcefile_path))
ensure
CLI::Cleanup.run(cask.token) if audit_download?
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 500314671..08d457643 100644
--- a/Library/Homebrew/cask/lib/hbc/cask_loader.rb
+++ b/Library/Homebrew/cask/lib/hbc/cask_loader.rb
@@ -3,6 +3,18 @@ module Hbc
class FromContentLoader
attr_reader :content
+ def self.can_load?(ref)
+ return false unless ref.respond_to?(:to_str)
+ content = ref.to_str
+
+ token = /(?:"[^"]*"|'[^']*')/
+ curly = /\(\s*#{token}\s*\)\s*\{.*\}/
+ do_end = /\s+#{token}\s+do(?:\s*;\s*|\s+).*end/
+ regex = /\A\s*cask(?:#{curly.source}|#{do_end.source})\s*\Z/m
+
+ content.match?(regex)
+ end
+
def initialize(content)
@content = content
end
@@ -56,7 +68,8 @@ module Hbc
class FromURILoader < FromPathLoader
def self.can_load?(ref)
- ref.to_s.match?(::URI.regexp)
+ uri_regex = ::URI::DEFAULT_PARSER.make_regexp
+ ref.to_s.match?(Regexp.new('\A' + uri_regex.source + '\Z', uri_regex.options))
end
attr_reader :url
@@ -71,7 +84,7 @@ module Hbc
begin
ohai "Downloading #{url}."
- curl url, "-o", path
+ curl_download url, to: path
rescue ErrorDuringExecution
raise CaskUnavailableError.new(token, "Failed to download #{Formatter.url(url)}.")
end
@@ -116,6 +129,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
@@ -131,14 +160,6 @@ module Hbc
end
end
- def self.load_from_file(path)
- FromPathLoader.new(path).load
- end
-
- def self.load_from_string(content)
- FromContentLoader.new(content).load
- end
-
def self.path(ref)
self.for(ref).path
end
@@ -149,6 +170,8 @@ module Hbc
def self.for(ref)
[
+ FromInstanceLoader,
+ FromContentLoader,
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..f12fe5564 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/info.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/info.rb
@@ -23,6 +23,7 @@ module Hbc
installation_info(cask)
repo_info(cask)
name_info(cask)
+ language_info(cask)
artifact_info(cask)
Installer.print_caveats(cask)
end
@@ -51,6 +52,13 @@ module Hbc
puts cask.name.empty? ? Formatter.error("None") : cask.name
end
+ def self.language_info(cask)
+ return if cask.languages.empty?
+
+ ohai "Languages"
+ puts cask.languages.join(", ")
+ end
+
def self.repo_info(cask)
user, repo, token = QualifiedToken.parse(Hbc.all_tokens.detect { |t| t.split("/").last == cask.token })
@@ -69,12 +77,10 @@ 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
+ cask.artifacts.each do |artifact|
+ next unless artifact.respond_to?(:install_phase)
+ next unless DSL::ORDINARY_ARTIFACT_CLASSES.include?(artifact.class)
+ puts artifact.to_s
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_audit_modified_casks.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_audit_modified_casks.rb
index 3673a5391..b83224fb1 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/internal_audit_modified_casks.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/internal_audit_modified_casks.rb
@@ -59,7 +59,7 @@ module Hbc
end
def modified_cask_files
- @modified_cask_files ||= git_filter_cask_files("AM")
+ @modified_cask_files ||= git_filter_cask_files("AMR")
end
def added_cask_files
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..4a50ae74a 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
@@ -23,16 +23,16 @@ module Hbc
elsif versions?
puts self.class.format_versioned(cask)
else
- cask = CaskLoader.load_from_file(cask.installed_caskfile)
+ cask = CaskLoader.load(cask.installed_caskfile)
self.class.list_artifacts(cask)
end
end
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?
+ cask.artifacts.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 643d18d55..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,18 @@ module Hbc
end
def self.search_remote(query)
- matches = GitHub.search_code("user:caskroom", "path:Casks", "filename:#{query}", "extension:rb")
- [*matches].map do |match|
+ 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?
"#{tap.name}/#{File.basename(match["path"], ".rb")}"
diff --git a/Library/Homebrew/cask/lib/hbc/cli/uninstall.rb b/Library/Homebrew/cask/lib/hbc/cli/uninstall.rb
index c0697c808..f2059605c 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}"
@@ -20,7 +16,7 @@ module Hbc
if cask.installed? && !cask.installed_caskfile.nil?
# use the same cask file that was used for installation, if possible
- cask = CaskLoader.load_from_file(cask.installed_caskfile) if cask.installed_caskfile.exist?
+ cask = CaskLoader.load(cask.installed_caskfile) if cask.installed_caskfile.exist?
end
Installer.new(cask, binaries: binaries?, verbose: verbose?, force: force?).uninstall
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.rb b/Library/Homebrew/cask/lib/hbc/container.rb
index 93e825e03..fab3a3c1c 100644
--- a/Library/Homebrew/cask/lib/hbc/container.rb
+++ b/Library/Homebrew/cask/lib/hbc/container.rb
@@ -4,6 +4,7 @@ require "hbc/container/bzip2"
require "hbc/container/cab"
require "hbc/container/criteria"
require "hbc/container/dmg"
+require "hbc/container/directory"
require "hbc/container/executable"
require "hbc/container/generic_unar"
require "hbc/container/gpg"
@@ -14,6 +15,7 @@ require "hbc/container/otf"
require "hbc/container/pkg"
require "hbc/container/seven_zip"
require "hbc/container/sit"
+require "hbc/container/svn_repository"
require "hbc/container/tar"
require "hbc/container/ttf"
require "hbc/container/rar"
@@ -43,6 +45,7 @@ module Hbc
Xz, # pure xz
Gpg, # GnuPG signed data
Executable,
+ SvnRepository,
]
# for explicit use only (never autodetected):
# Hbc::Container::Naked
diff --git a/Library/Homebrew/cask/lib/hbc/container/base.rb b/Library/Homebrew/cask/lib/hbc/container/base.rb
index 52eb5aab1..78610a1ab 100644
--- a/Library/Homebrew/cask/lib/hbc/container/base.rb
+++ b/Library/Homebrew/cask/lib/hbc/container/base.rb
@@ -20,7 +20,7 @@ module Hbc
unless children.count == 1 &&
!nested_container.directory? &&
- @cask.artifacts[:nested_container].empty? &&
+ @cask.artifacts.none? { |a| a.is_a?(Artifact::NestedContainer) } &&
extract_nested_container(nested_container)
children.each do |src|
diff --git a/Library/Homebrew/cask/lib/hbc/container/criteria.rb b/Library/Homebrew/cask/lib/hbc/container/criteria.rb
index 66ecb8c87..52f171d6a 100644
--- a/Library/Homebrew/cask/lib/hbc/container/criteria.rb
+++ b/Library/Homebrew/cask/lib/hbc/container/criteria.rb
@@ -13,9 +13,11 @@ module Hbc
end
def magic_number(regex)
+ return false if path.directory?
+
# 262: length of the longest regex (currently: Hbc::Container::Tar)
- @magic_number ||= File.open(@path, "rb") { |f| f.read(262) }
- @magic_number =~ regex
+ @magic_number ||= File.open(path, "rb") { |f| f.read(262) }
+ @magic_number.match?(regex)
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/container/directory.rb b/Library/Homebrew/cask/lib/hbc/container/directory.rb
new file mode 100644
index 000000000..e4bb1095b
--- /dev/null
+++ b/Library/Homebrew/cask/lib/hbc/container/directory.rb
@@ -0,0 +1,24 @@
+require "hbc/container/base"
+
+module Hbc
+ class Container
+ class Directory < Base
+ def self.me?(*)
+ false
+ end
+
+ def extract
+ @path.children.each do |child|
+ next if skip_path?(child)
+ FileUtils.cp child, @cask.staged_path
+ end
+ end
+
+ private
+
+ def skip_path?(*)
+ false
+ end
+ end
+ end
+end
diff --git a/Library/Homebrew/cask/lib/hbc/container/executable.rb b/Library/Homebrew/cask/lib/hbc/container/executable.rb
index 848f6d4be..af3b36fd1 100644
--- a/Library/Homebrew/cask/lib/hbc/container/executable.rb
+++ b/Library/Homebrew/cask/lib/hbc/container/executable.rb
@@ -8,7 +8,7 @@ module Hbc
return true if criteria.magic_number(/^#!\s*\S+/)
begin
- MachO.open(criteria.path).header.executable?
+ criteria.path.file? && MachO.open(criteria.path).header.executable?
rescue MachO::MagicError
false
end
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/container/svn_repository.rb b/Library/Homebrew/cask/lib/hbc/container/svn_repository.rb
new file mode 100644
index 000000000..cae613b2d
--- /dev/null
+++ b/Library/Homebrew/cask/lib/hbc/container/svn_repository.rb
@@ -0,0 +1,15 @@
+require "hbc/container/directory"
+
+module Hbc
+ class Container
+ class SvnRepository < Directory
+ def self.me?(criteria)
+ criteria.path.join(".svn").directory?
+ end
+
+ def skip_path?(path)
+ path.basename.to_s == ".svn"
+ end
+ end
+ end
+end
diff --git a/Library/Homebrew/cask/lib/hbc/download_strategy.rb b/Library/Homebrew/cask/lib/hbc/download_strategy.rb
index 016bb66e6..245ad4ade 100644
--- a/Library/Homebrew/cask/lib/hbc/download_strategy.rb
+++ b/Library/Homebrew/cask/lib/hbc/download_strategy.rb
@@ -10,7 +10,7 @@ module Hbc
class AbstractDownloadStrategy
attr_reader :cask, :name, :url, :uri_object, :version
- def initialize(cask, command = SystemCommand)
+ def initialize(cask, command: SystemCommand)
@cask = cask
@command = command
# TODO: this excess of attributes is a function of integrating
@@ -33,8 +33,8 @@ module Hbc
class HbVCSDownloadStrategy < AbstractDownloadStrategy
REF_TYPES = [:branch, :revision, :revisions, :tag].freeze
- def initialize(cask, command = SystemCommand)
- super
+ def initialize(*args, **options)
+ super(*args, **options)
@ref_type, @ref = extract_ref
@clone = Hbc.cache.join(cache_filename)
end
@@ -64,11 +64,6 @@ module Hbc
end
class CurlDownloadStrategy < AbstractDownloadStrategy
- # TODO: should be part of url object
- def mirrors
- @mirrors ||= []
- end
-
def tarball_path
@tarball_path ||= Hbc.cache.join("#{name}--#{version}#{ext}")
end
@@ -95,13 +90,8 @@ module Hbc
end
end
- def downloaded_size
- temporary_path.size? || 0
- end
-
def _fetch
- odebug "Calling curl with args #{cask_curl_args}"
- curl(*cask_curl_args)
+ curl_download url, *cask_curl_args, to: temporary_path, user_agent: uri_object.user_agent
end
def fetch
@@ -131,33 +121,12 @@ module Hbc
ignore_interrupts { temporary_path.rename(tarball_path) }
end
tarball_path
- rescue CurlDownloadStrategyError
- raise if mirrors.empty?
- puts "Trying a mirror..."
- @url = mirrors.shift
- retry
end
private
def cask_curl_args
- default_curl_args.tap do |args|
- args.concat(user_agent_args)
- args.concat(cookies_args)
- args.concat(referer_args)
- end
- end
-
- def default_curl_args
- [url, "-C", downloaded_size, "-o", temporary_path]
- end
-
- def user_agent_args
- if uri_object.user_agent
- ["-A", uri_object.user_agent]
- else
- []
- end
+ cookies_args + referer_args
end
def cookies_args
@@ -191,8 +160,7 @@ module Hbc
class CurlPostDownloadStrategy < CurlDownloadStrategy
def cask_curl_args
- super
- default_curl_args.concat(post_args)
+ super.concat(post_args)
end
def post_args
@@ -225,8 +193,8 @@ module Hbc
# super does not provide checks for already-existing downloads
def fetch
- if tarball_path.exist?
- puts "Already downloaded: #{tarball_path}"
+ if cached_location.directory?
+ puts "Already downloaded: #{cached_location}"
else
@url = @url.sub(/^svn\+/, "") if @url =~ %r{^svn\+http://}
ohai "Checking out #{@url}"
@@ -252,9 +220,8 @@ module Hbc
else
fetch_repo @clone, @url
end
- compress
end
- tarball_path
+ cached_location
end
# This primary reason for redefining this method is the trust_cert
@@ -288,10 +255,6 @@ module Hbc
print_stderr: false)
end
- def tarball_path
- @tarball_path ||= cached_location.dirname.join(cached_location.basename.to_s + "-#{@cask.version}.tar")
- end
-
def shell_quote(str)
# Oh god escaping shell args.
# See http://notetoself.vrensk.com/2008/08/escaping-single-quotes-in-ruby-harder-than-expected/
@@ -304,35 +267,5 @@ module Hbc
yield name, url
end
end
-
- private
-
- # TODO/UPDATE: the tar approach explained below is fragile
- # against challenges such as case-sensitive filesystems,
- # and must be re-implemented.
- #
- # Seems nutty: we "download" the contents into a tape archive.
- # Why?
- # * A single file is tractable to the rest of the Cask toolchain,
- # * An alternative would be to create a Directory container type.
- # However, some type of file-serialization trick would still be
- # needed in order to enable calculating a single checksum over
- # a directory. So, in that alternative implementation, the
- # special cases would propagate outside this class, including
- # the use of tar or equivalent.
- # * SubversionDownloadStrategy.cached_location is not versioned
- # * tarball_path provides a needed return value for our overridden
- # fetch method.
- # * We can also take this private opportunity to strip files from
- # the download which are protocol-specific.
-
- def compress
- Dir.chdir(cached_location) do
- @command.run!("/usr/bin/tar",
- args: ['-s/^\.//', "--exclude", ".svn", "-cf", Pathname.new(tarball_path), "--", "."],
- print_stderr: false)
- end
- clear_cache
- end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/dsl.rb b/Library/Homebrew/cask/lib/hbc/dsl.rb
index 8ad206c2f..2db2c66a9 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_CLASSES = ORDINARY_ARTIFACT_CLASSES - [Artifact::StageOnly]
- ARTIFACT_BLOCK_TYPES = [
- :preflight,
- :postflight,
- :uninstall_preflight,
- :uninstall_postflight,
+ ARTIFACT_BLOCK_CLASSES = [
+ Artifact::PreflightBlock,
+ Artifact::PostflightBlock,
].freeze
DSL_METHODS = Set.new [
@@ -66,21 +63,23 @@ module Hbc
:gpg,
:homepage,
:language,
+ :languages,
:name,
:sha256,
:staged_path,
:url,
:version,
:appdir,
- *ORDINARY_ARTIFACT_TYPES,
- *ACTIVATABLE_ARTIFACT_TYPES,
- *SPECIAL_ARTIFACT_TYPES,
- *ARTIFACT_BLOCK_TYPES,
+ *ORDINARY_ARTIFACT_CLASSES.map(&:dsl_key),
+ *ACTIVATABLE_ARTIFACT_CLASSES.map(&:dsl_key),
+ *ARTIFACT_BLOCK_CLASSES.flat_map { |klass| [klass.dsl_key, klass.uninstall_dsl_key] },
].freeze
- attr_reader :token
- def initialize(token)
- @token = token
+ attr_reader :cask, :token
+
+ def initialize(cask)
+ @cask = cask
+ @token = cask.token
end
def name(*args)
@@ -93,12 +92,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)
@@ -106,19 +107,21 @@ module Hbc
end
def language(*args, default: false, &block)
- if !args.empty? && block_given?
+ if args.empty?
+ language_eval
+ elsif block_given?
@language_blocks ||= {}
@language_blocks[args] = block
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
else
- language_eval
+ raise CaskInvalidError.new(cask, "No block given to language stanza.")
end
end
@@ -127,6 +130,10 @@ module Hbc
return @language = nil if @language_blocks.nil? || @language_blocks.empty?
+ if @language_blocks.default.nil?
+ raise CaskInvalidError.new(cask, "No default language specified.")
+ end
+
MacOS.languages.map(&Locale.method(:parse)).each do |locale|
key = @language_blocks.keys.detect do |strings|
strings.any? { |string| locale.include?(string) }
@@ -140,6 +147,12 @@ module Hbc
@language = @language_blocks.default.call
end
+ def languages
+ return [] if @language_blocks.nil?
+
+ @language_blocks.keys.flatten
+ end
+
def url(*args, &block)
set_unique_stanza(:url, args.empty? && !block_given?) do
begin
@@ -162,8 +175,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.add(Artifact::NestedContainer.new(cask, container.nested))
end
end
end
@@ -173,7 +186,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 +195,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 +208,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
@@ -206,7 +219,7 @@ module Hbc
end
def artifacts
- @artifacts ||= Hash.new { |hash, key| hash[key] = Set.new }
+ @artifacts ||= SortedSet.new
end
def caskroom_path
@@ -237,39 +250,27 @@ module Hbc
set_unique_stanza(:auto_updates, auto_updates.nil?) { auto_updates }
end
- ORDINARY_ARTIFACT_TYPES.each do |type|
- define_method(type) do |*args|
- if type == :stage_only
- if args != [true]
- raise CaskInvalidError.new(token, "'stage_only' takes a single argument: true")
+ ORDINARY_ARTIFACT_CLASSES.each do |klass|
+ define_method(klass.dsl_key) do |*args|
+ begin
+ if [*artifacts.map(&:class), klass].include?(Artifact::StageOnly) && (artifacts.map(&:class) & ACTIVATABLE_ARTIFACT_CLASSES).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.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.add(klass.new(cask, dsl_key => block))
+ end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb b/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb
index d302d0946..f3994b81f 100644
--- a/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb
+++ b/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb
@@ -3,16 +3,20 @@ require "hbc/system_command"
module Hbc
class DSL
class Appcast
- attr_reader :parameters, :checkpoint
+ attr_reader :uri, :checkpoint, :parameters
- def initialize(uri, parameters = {})
- @parameters = parameters
- @uri = UnderscoreSupportingURI.parse(uri)
- @checkpoint = @parameters[:checkpoint]
+ def initialize(uri, **parameters)
+ @uri = URI(uri)
+ @parameters = parameters
+ @checkpoint = parameters[:checkpoint]
end
def calculate_checkpoint
- result = SystemCommand.run("/usr/bin/curl", args: ["--compressed", "--location", "--user-agent", URL::FAKE_USER_AGENT, "--fail", @uri], print_stderr: false)
+ curl_executable, *args = curl_args(
+ "--compressed", "--location", "--fail", uri,
+ user_agent: :fake
+ )
+ result = SystemCommand.run(curl_executable, args: args, print_stderr: false)
checkpoint = if result.success?
processed_appcast_text = result.stdout.gsub(%r{<pubDate>[^<]*</pubDate>}m, "")
@@ -26,11 +30,11 @@ module Hbc
end
def to_yaml
- [@uri, @parameters].to_yaml
+ [uri, parameters].to_yaml
end
def to_s
- @uri.to_s
+ uri.to_s
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/dsl/base.rb b/Library/Homebrew/cask/lib/hbc/dsl/base.rb
index 63df847e9..b97c4e104 100644
--- a/Library/Homebrew/cask/lib/hbc/dsl/base.rb
+++ b/Library/Homebrew/cask/lib/hbc/dsl/base.rb
@@ -10,14 +10,14 @@ module Hbc
def_delegators :@cask, :token, :version, :caskroom_path, :staged_path, :appdir, :language
- def system_command(executable, options = {})
- @command.run!(executable, options)
+ def system_command(executable, **options)
+ @command.run!(executable, **options)
end
def method_missing(method, *)
if method
underscored_class = self.class.name.gsub(/([[:lower:]])([[:upper:]][[:lower:]])/, '\1_\2').downcase
- section = underscored_class.downcase.split("::").last
+ section = underscored_class.split("::").last
Utils.method_missing_message(method, @cask.to_s, section)
nil
else
diff --git a/Library/Homebrew/cask/lib/hbc/dsl/caveats.rb b/Library/Homebrew/cask/lib/hbc/dsl/caveats.rb
index 402574456..7d373b5f3 100644
--- a/Library/Homebrew/cask/lib/hbc/dsl/caveats.rb
+++ b/Library/Homebrew/cask/lib/hbc/dsl/caveats.rb
@@ -48,7 +48,7 @@ module Hbc
brew cask install java
EOS
- elsif java_version.include?("8") || java_version.include?("+")
+ elsif java_version.include?("9") || java_version.include?("+")
puts <<-EOS.undent
#{@cask} requires Java #{java_version}. You can install the latest version with
diff --git a/Library/Homebrew/cask/lib/hbc/dsl/conflicts_with.rb b/Library/Homebrew/cask/lib/hbc/dsl/conflicts_with.rb
index 948348239..dfaa55a5c 100644
--- a/Library/Homebrew/cask/lib/hbc/dsl/conflicts_with.rb
+++ b/Library/Homebrew/cask/lib/hbc/dsl/conflicts_with.rb
@@ -10,25 +10,20 @@ module Hbc
:java,
]
- attr_accessor(*VALID_KEYS)
- attr_accessor :pairs
+ attr_reader *VALID_KEYS
def initialize(pairs = {})
@pairs = pairs
+
+ VALID_KEYS.each do |key|
+ instance_variable_set("@#{key}", Set.new)
+ end
+
pairs.each do |key, value|
raise "invalid conflicts_with key: '#{key.inspect}'" unless VALID_KEYS.include?(key)
- writer_method = "#{key}=".to_sym
- send(writer_method, value)
+ instance_variable_set("@#{key}", instance_variable_get("@#{key}").merge([*value]))
end
end
-
- def to_yaml
- @pairs.to_yaml
- end
-
- def to_s
- @pairs.inspect
- end
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/dsl/gpg.rb b/Library/Homebrew/cask/lib/hbc/dsl/gpg.rb
index b49ebb97c..99b39d43f 100644
--- a/Library/Homebrew/cask/lib/hbc/dsl/gpg.rb
+++ b/Library/Homebrew/cask/lib/hbc/dsl/gpg.rb
@@ -14,11 +14,11 @@ module Hbc
def initialize(signature, parameters = {})
@parameters = parameters
- @signature = UnderscoreSupportingURI.parse(signature)
+ @signature = URI(signature)
parameters.each do |hkey, hvalue|
raise "invalid 'gpg' parameter: '#{hkey.inspect}'" unless VALID_PARAMETERS.include?(hkey)
writer_method = "#{hkey}=".to_sym
- hvalue = UnderscoreSupportingURI.parse(hvalue) if hkey == :key_url
+ hvalue = URI(hvalue) if hkey == :key_url
valid_id?(hvalue) if hkey == :key_id
send(writer_method, hvalue)
end
@@ -35,7 +35,7 @@ module Hbc
end
def to_yaml
- # bug, :key_url value is not represented as an instance of Hbc::UnderscoreSupportingURI
+ # bug, :key_url value is not represented as an instance of URI
[@signature, @parameters].to_yaml
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/exceptions.rb b/Library/Homebrew/cask/lib/hbc/exceptions.rb
index 1a246be65..f7f9e43b6 100644
--- a/Library/Homebrew/cask/lib/hbc/exceptions.rb
+++ b/Library/Homebrew/cask/lib/hbc/exceptions.rb
@@ -17,6 +17,19 @@ module Hbc
end
end
+ class CaskConflictError < AbstractCaskErrorWithToken
+ attr_reader :conflicting_cask
+
+ def initialize(token, conflicting_cask)
+ super(token)
+ @conflicting_cask = conflicting_cask
+ end
+
+ def to_s
+ "Cask '#{token}' conflicts with '#{conflicting_cask}'."
+ end
+ end
+
class CaskUnavailableError < AbstractCaskErrorWithToken
def to_s
"Cask '#{token}' is unavailable" << (reason.empty? ? "." : ": #{reason}")
diff --git a/Library/Homebrew/cask/lib/hbc/installer.rb b/Library/Homebrew/cask/lib/hbc/installer.rb
index 53210ed4b..68b9595e1 100644
--- a/Library/Homebrew/cask/lib/hbc/installer.rb
+++ b/Library/Homebrew/cask/lib/hbc/installer.rb
@@ -86,6 +86,8 @@ module Hbc
raise CaskAlreadyInstalledError, @cask
end
+ check_conflicts
+
print_caveats
fetch
uninstall_existing_cask if @reinstall
@@ -98,6 +100,21 @@ module Hbc
puts summary
end
+ def check_conflicts
+ return unless @cask.conflicts_with
+
+ @cask.conflicts_with.cask.each do |conflicting_cask|
+ begin
+ conflicting_cask = CaskLoader.load(conflicting_cask)
+ if conflicting_cask.installed?
+ raise CaskConflictError.new(@cask, conflicting_cask)
+ end
+ rescue CaskUnavailableError
+ next # Ignore conflicting Casks that do not exist.
+ end
+ end
+ end
+
def reinstall
odebug "Hbc::Installer#reinstall"
@reinstall = true
@@ -109,7 +126,7 @@ module Hbc
# use the same cask file that was used for installation, if possible
installed_caskfile = @cask.installed_caskfile
- installed_cask = installed_caskfile.exist? ? CaskLoader.load_from_file(installed_caskfile) : @cask
+ installed_cask = installed_caskfile.exist? ? CaskLoader.load(installed_caskfile) : @cask
# Always force uninstallation, ignore method parameter
Installer.new(installed_cask, binaries: binaries?, verbose: verbose?, force: true).uninstall
@@ -142,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)
@@ -160,7 +177,7 @@ module Hbc
already_installed_artifacts = []
odebug "Installing artifacts"
- artifacts = Artifact.for_cask(@cask, command: @command, verbose: verbose?, force: force?)
+ artifacts = @cask.artifacts
odebug "#{artifacts.length} artifact/s defined", artifacts
artifacts.each do |artifact|
@@ -171,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
@@ -179,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
@@ -344,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
@@ -357,25 +374,27 @@ module Hbc
def uninstall_artifacts
odebug "Un-installing artifacts"
- artifacts = Artifact.for_cask(@cask, command: @command, verbose: verbose?, force: force?)
+ artifacts = @cask.artifacts
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 = @cask.artifacts.select { |a| a.is_a?(Artifact::Zap) }).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..da097e0cf 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.select { |a| a.is_a?(Artifact::App) }.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 901617b71..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
@@ -112,11 +112,7 @@ module Hbc
processed_output[:stderr],
processed_status.exitstatus)
end
- end
-end
-module Hbc
- class SystemCommand
class Result
attr_accessor :command, :stdout, :stderr, :exit_status
diff --git a/Library/Homebrew/cask/lib/hbc/underscore_supporting_uri.rb b/Library/Homebrew/cask/lib/hbc/underscore_supporting_uri.rb
deleted file mode 100644
index 8f8f66f43..000000000
--- a/Library/Homebrew/cask/lib/hbc/underscore_supporting_uri.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-require "uri"
-
-module Hbc
- module UnderscoreSupportingURI
- def self.parse(maybe_uri)
- return nil if maybe_uri.nil?
- URI.parse(maybe_uri)
- rescue URI::InvalidURIError => e
- scheme, host, path = simple_parse(maybe_uri)
- raise e unless path && host.include?("_")
- URI.parse(without_host_underscores(scheme, host, path)).tap do |uri|
- uri.instance_variable_set("@host", host)
- end
- end
-
- def self.simple_parse(maybe_uri)
- scheme, host_and_path = maybe_uri.split("://")
- host, path = host_and_path.split("/", 2)
- [scheme, host, path]
- rescue StandardError
- nil
- end
-
- def self.without_host_underscores(scheme, host, path)
- ["#{scheme}:/", host.tr("_", "-"), path].join("/")
- end
- end
-end
diff --git a/Library/Homebrew/cask/lib/hbc/url.rb b/Library/Homebrew/cask/lib/hbc/url.rb
index 15da2ced2..35020c5db 100644
--- a/Library/Homebrew/cask/lib/hbc/url.rb
+++ b/Library/Homebrew/cask/lib/hbc/url.rb
@@ -1,8 +1,6 @@
module Hbc
class URL
- FAKE_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10) https://caskroom.github.io".freeze
-
- attr_reader :using, :revision, :trust_cert, :uri, :cookies, :referer, :data
+ attr_reader :using, :revision, :trust_cert, :uri, :cookies, :referer, :data, :user_agent
extend Forwardable
def_delegators :uri, :path, :scheme, :to_s
@@ -16,8 +14,8 @@ module Hbc
end
def initialize(uri, options = {})
- @uri = Hbc::UnderscoreSupportingURI.parse(uri)
- @user_agent = options[:user_agent]
+ @uri = URI(uri)
+ @user_agent = options.fetch(:user_agent, :default)
@cookies = options[:cookies]
@referer = options[:referer]
@using = options[:using]
@@ -25,10 +23,5 @@ module Hbc
@trust_cert = options[:trust_cert]
@data = options[:data]
end
-
- def user_agent
- return FAKE_USER_AGENT if @user_agent == :fake
- @user_agent
- end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/verify/gpg.rb b/Library/Homebrew/cask/lib/hbc/verify/gpg.rb
index dbb537756..f4996a5b5 100644
--- a/Library/Homebrew/cask/lib/hbc/verify/gpg.rb
+++ b/Library/Homebrew/cask/lib/hbc/verify/gpg.rb
@@ -33,7 +33,7 @@ module Hbc
meta_dir = cached || cask.metadata_subdir("gpg", :now, true)
sig_path = meta_dir.join("signature.asc")
- curl(cask.gpg.signature, "-o", sig_path.to_s) unless cached || force
+ curl_download cask.gpg.signature, to: sig_path unless cached || force
sig_path
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/deps.rb b/Library/Homebrew/cmd/deps.rb
index bbf0c1b0b..de7aa4a51 100644
--- a/Library/Homebrew/cmd/deps.rb
+++ b/Library/Homebrew/cmd/deps.rb
@@ -1,4 +1,4 @@
-#: * `deps` [`--1`] [`-n`] [`--union`] [`--full-name`] [`--installed`] [`--include-build`] [`--include-optional`] [`--skip-recommended`] <formulae>:
+#: * `deps` [`--1`] [`-n`] [`--union`] [`--full-name`] [`--installed`] [`--include-build`] [`--include-optional`] [`--skip-recommended`] [`--include-requirements`] <formulae>:
#: Show dependencies for <formulae>. When given multiple formula arguments,
#: show the intersection of dependencies for <formulae>.
#:
@@ -19,15 +19,22 @@
#: <formulae>. To include the `:build` type dependencies, pass `--include-build`.
#: Similarly, pass `--include-optional` to include `:optional` dependencies.
#: To skip `:recommended` type dependencies, pass `--skip-recommended`.
+#: To include requirements in addition to dependencies, pass `--include-requirements`.
#:
-#: * `deps` `--tree` [<filters>] (<formulae>|`--installed`):
+#: * `deps` `--tree` [`--1`] [<filters>] [`--annotate`] (<formulae>|`--installed`):
#: Show dependencies as a tree. When given multiple formula arguments, output
#: individual trees for every formula.
#:
+#: If `--1` is passed, only one level of children is displayed.
+#:
#: If `--installed` is passed, output a tree for every installed formula.
#:
#: The <filters> placeholder is any combination of options `--include-build`,
-#: `--include-optional`, and `--skip-recommended` as documented above.
+#: `--include-optional`, `--skip-recommended`, and `--include-requirements` as
+#: documented above.
+#:
+#: If `--annotate` is passed, the build, optional, and recommended dependencies
+#: are marked as such in the output.
#:
#: * `deps` [<filters>] (`--installed`|`--all`):
#: Show dependencies for installed or all available formulae. Every line of
@@ -37,6 +44,10 @@
#: The <filters> placeholder is any combination of options `--include-build`,
#: `--include-optional`, and `--skip-recommended` as documented above.
+# The undocumented `--for-each` option will switch into the mode used by `deps --all`,
+# but only list dependencies for specified formula, one specified formula per line.
+# This is used for debugging the `--installed`/`--all` display mode.
+
# encoding: UTF-8
require "formula"
@@ -52,20 +63,26 @@ module Homebrew
all?: ARGV.include?("--all"),
topo_order?: ARGV.include?("-n"),
union?: ARGV.include?("--union"),
+ for_each?: ARGV.include?("--for-each"),
)
- if mode.installed? && mode.tree?
- puts_deps_tree Formula.installed
+ if mode.tree?
+ if mode.installed?
+ puts_deps_tree Formula.installed, !ARGV.one?
+ else
+ raise FormulaUnspecifiedError if ARGV.named.empty?
+ puts_deps_tree ARGV.formulae, !ARGV.one?
+ end
elsif mode.all?
puts_deps Formula
- elsif mode.tree?
- raise FormulaUnspecifiedError if ARGV.named.empty?
- puts_deps_tree ARGV.formulae
elsif ARGV.named.empty?
raise FormulaUnspecifiedError unless mode.installed?
puts_deps Formula.installed
+ elsif mode.for_each?
+ puts_deps ARGV.formulae
else
all_deps = deps_for_formulae(ARGV.formulae, !ARGV.one?, &(mode.union? ? :| : :&))
+ all_deps = condense_requirements(all_deps)
all_deps = all_deps.select(&:installed?) if mode.installed?
all_deps = all_deps.map(&method(:dep_display_name)).uniq
all_deps.sort! unless mode.topo_order?
@@ -73,24 +90,59 @@ module Homebrew
end
end
- def dep_display_name(d)
- ARGV.include?("--full-name") ? d.to_formula.full_name : d.name
+ def condense_requirements(deps)
+ if ARGV.include?("--include-requirements")
+ deps
+ else
+ deps.map do |dep|
+ if dep.is_a? Dependency
+ dep
+ elsif dep.default_formula?
+ dep.to_dependency
+ end
+ end.compact
+ end
+ end
+
+ def dep_display_name(dep)
+ str = if dep.is_a? Requirement
+ if ARGV.include?("--include-requirements")
+ if dep.default_formula?
+ ":#{dep.display_s} (#{dep_display_name(dep.to_dependency)})"
+ else
+ ":#{dep.display_s}"
+ end
+ elsif dep.default_formula?
+ dep_display_name(dep.to_dependency)
+ else
+ # This shouldn't happen, but we'll put something here to help debugging
+ "::#{dep.name}"
+ end
+ else
+ ARGV.include?("--full-name") ? dep.to_formula.full_name : dep.name
+ end
+ if ARGV.include?("--annotate")
+ str = "#{str} [build]" if dep.build?
+ str = "#{str} [optional" if dep.optional?
+ str = "#{str} [recommended]" if dep.recommended?
+ end
+ str
end
def deps_for_formula(f, recursive = false)
includes = []
ignores = []
- if ARGV.include? "--include-build"
+ if ARGV.include?("--include-build")
includes << "build?"
else
ignores << "build?"
end
- if ARGV.include? "--include-optional"
+ if ARGV.include?("--include-optional")
includes << "optional?"
else
ignores << "optional?"
end
- ignores << "recommended?" if ARGV.include? "--skip-recommended"
+ ignores << "recommended?" if ARGV.include?("--skip-recommended")
if recursive
deps = f.recursive_dependencies do |dependent, dep|
@@ -120,7 +172,7 @@ module Homebrew
end
end
- deps + reqs.select(&:default_formula?).map(&:to_dependency)
+ deps + reqs.to_a
end
def deps_for_formulae(formulae, recursive = false, &block)
@@ -129,41 +181,55 @@ module Homebrew
def puts_deps(formulae)
formulae.each do |f|
- deps = deps_for_formula(f).sort_by(&:name).map(&method(:dep_display_name))
+ deps = deps_for_formula(f)
+ deps = condense_requirements(deps)
+ deps = deps.sort_by(&:name).map(&method(:dep_display_name))
puts "#{f.full_name}: #{deps.join(" ")}"
end
end
- def puts_deps_tree(formulae)
+ def puts_deps_tree(formulae, recursive = false)
formulae.each do |f|
- puts "#{f.full_name} (required dependencies)"
- recursive_deps_tree(f, "")
+ puts f.full_name
+ @dep_stack = []
+ recursive_deps_tree(f, "", recursive)
puts
end
end
- def recursive_deps_tree(f, prefix)
- reqs = f.requirements.select(&:default_formula?)
- deps = f.deps.default
- max = reqs.length - 1
- reqs.each_with_index do |req, i|
- chr = if i == max && deps.empty?
+ def recursive_deps_tree(f, prefix, recursive)
+ reqs = f.requirements
+ deps = f.deps
+ dependables = reqs + deps
+ dependables = dependables.reject(&:optional?) unless ARGV.include?("--include-optional")
+ dependables = dependables.reject(&:build?) unless ARGV.include?("--include-build")
+ dependables = dependables.reject(&:recommended?) if ARGV.include?("--skip-recommended")
+ max = dependables.length - 1
+ @dep_stack.push f.name
+ dependables.each_with_index do |dep, i|
+ next if !ARGV.include?("--include-requirements") && dep.is_a?(Requirement) && !dep.default_formula?
+ tree_lines = if i == max
"└──"
else
"├──"
end
- puts prefix + "#{chr} :#{dep_display_name(req.to_dependency)}"
- end
- max = deps.length - 1
- deps.each_with_index do |dep, i|
- chr = if i == max
- "└──"
+ display_s = "#{tree_lines} #{dep_display_name(dep)}"
+ is_circular = @dep_stack.include?(dep.name)
+ display_s = "#{display_s} (CIRCULAR DEPENDENCY)" if is_circular
+ puts "#{prefix}#{display_s}"
+ next if !recursive || is_circular
+ prefix_addition = if i == max
+ " "
else
- "├──"
+ "│ "
+ end
+ if dep.is_a?(Requirement) && dep.default_formula?
+ recursive_deps_tree(Formulary.factory(dep.to_dependency.name), prefix + prefix_addition, true)
+ end
+ if dep.is_a? Dependency
+ recursive_deps_tree(Formulary.factory(dep.name), prefix + prefix_addition, true)
end
- prefix_ext = (i == max) ? " " : "│ "
- puts prefix + "#{chr} #{dep_display_name(dep)}"
- recursive_deps_tree(Formulary.factory(dep.name), prefix + prefix_ext)
end
+ @dep_stack.pop
end
end
diff --git a/Library/Homebrew/cmd/fetch.rb b/Library/Homebrew/cmd/fetch.rb
index 006c63746..411753992 100644
--- a/Library/Homebrew/cmd/fetch.rb
+++ b/Library/Homebrew/cmd/fetch.rb
@@ -49,8 +49,10 @@ module Homebrew
if fetch_bottle?(f)
begin
fetch_formula(f.bottle)
- rescue Exception => e
- raise if ARGV.homebrew_developer? || e.is_a?(Interrupt)
+ rescue Interrupt
+ raise
+ rescue => e
+ raise if ARGV.homebrew_developer?
fetched_bottle = false
onoe e.message
opoo "Bottle fetch failed: fetching the source."
diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb
index c00087705..ca8f29477 100644
--- a/Library/Homebrew/cmd/install.rb
+++ b/Library/Homebrew/cmd/install.rb
@@ -219,6 +219,7 @@ module Homebrew
end
end
+ return if formulae.empty?
perform_preinstall_checks
formulae.each do |f|
@@ -338,6 +339,7 @@ module Homebrew
rescue FormulaInstallationAlreadyAttemptedError
# We already attempted to install f as part of the dependency tree of
# another formula. In that case, don't generate an error, just move on.
+ return
rescue CannotInstallFormulaError => e
ofail e.message
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/pin.rb b/Library/Homebrew/cmd/pin.rb
index c5087f6d4..5a14f853c 100644
--- a/Library/Homebrew/cmd/pin.rb
+++ b/Library/Homebrew/cmd/pin.rb
@@ -1,6 +1,7 @@
#: * `pin` <formulae>:
#: Pin the specified <formulae>, preventing them from being upgraded when
-#: issuing the `brew upgrade` command. See also `unpin`.
+#: issuing the `brew upgrade <formulae>` command (but can still be upgraded
+#: as dependencies for other formulae). See also `unpin`.
require "formula"
diff --git a/Library/Homebrew/cmd/postinstall.rb b/Library/Homebrew/cmd/postinstall.rb
index f5d091227..02fd8a5f6 100644
--- a/Library/Homebrew/cmd/postinstall.rb
+++ b/Library/Homebrew/cmd/postinstall.rb
@@ -29,8 +29,6 @@ module Homebrew
args << "--devel"
end
- Sandbox.print_sandbox_message if Sandbox.formula?(formula)
-
Utils.safe_fork do
if Sandbox.formula?(formula)
sandbox = Sandbox.new
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/reinstall.rb b/Library/Homebrew/cmd/reinstall.rb
index 94096d2dd..6727c0b6b 100644
--- a/Library/Homebrew/cmd/reinstall.rb
+++ b/Library/Homebrew/cmd/reinstall.rb
@@ -47,8 +47,8 @@ module Homebrew
fi.install
fi.finish
rescue FormulaInstallationAlreadyAttemptedError
- # next
- rescue Exception
+ return
+ rescue Exception # rubocop:disable Lint/RescueException
ignore_interrupts { restore_backup(keg, keg_was_linked) }
raise
else
diff --git a/Library/Homebrew/cmd/search.rb b/Library/Homebrew/cmd/search.rb
index b2d069744..c01a11c10 100644
--- a/Library/Homebrew/cmd/search.rb
+++ b/Library/Homebrew/cmd/search.rb
@@ -34,38 +34,40 @@ module Homebrew
elsif ARGV.include? "--opensuse"
exec_browser "https://software.opensuse.org/search?q=#{ARGV.next}"
elsif ARGV.include? "--fedora"
- exec_browser "https://admin.fedoraproject.org/pkgdb/packages/%2A#{ARGV.next}%2A/"
+ exec_browser "https://apps.fedoraproject.org/packages/s/#{ARGV.next}"
elsif ARGV.include? "--ubuntu"
- exec_browser "http://packages.ubuntu.com/search?keywords=#{ARGV.next}&searchon=names&suite=all&section=all"
+ exec_browser "https://packages.ubuntu.com/search?keywords=#{ARGV.next}&searchon=names&suite=all&section=all"
elsif ARGV.include? "--desc"
query = ARGV.next
regex = query_regexp(query)
Descriptions.search(regex, :desc).print
elsif ARGV.first =~ HOMEBREW_TAP_FORMULA_REGEX
query = ARGV.first
- user, repo, name = query.split("/", 3)
begin
result = Formulary.factory(query).name
+ results = Array(result)
rescue FormulaUnavailableError
- result = search_tap(user, repo, name)
+ _, _, name = query.split("/", 3)
+ results = search_taps(name)
end
- results = Array(result)
puts Formatter.columns(results) unless results.empty?
else
query = ARGV.first
regex = query_regexp(query)
local_results = search_formulae(regex)
puts Formatter.columns(local_results) unless local_results.empty?
+
tap_results = search_taps(query)
puts Formatter.columns(tap_results) unless tap_results.empty?
if $stdout.tty?
count = local_results.length + tap_results.length
+ 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
@@ -100,10 +102,18 @@ module Homebrew
odie "#{query} is not a valid regex"
end
- def search_taps(query)
+ def search_taps(query, silent: false)
+ return [] if ENV["HOMEBREW_NO_GITHUB_API"]
+
+ # Use stderr to avoid breaking parsed output
+ unless silent
+ $stderr.puts Formatter.headline("Searching taps on GitHub...", color: :blue)
+ end
+
valid_dirnames = ["Formula", "HomebrewFormula", "Casks", "."].freeze
- matches = GitHub.search_code("user:Homebrew", "user:caskroom", "filename:#{query}", "extension:rb")
- [*matches].map do |match|
+ matches = GitHub.search_code(user: ["Homebrew", "caskroom"], filename: query, extension: "rb")
+
+ matches.map do |match|
dirname, filename = File.split(match["path"])
next unless valid_dirnames.include?(dirname)
tap = Tap.fetch(match["repository"]["full_name"])
@@ -113,6 +123,9 @@ module Homebrew
end
def search_formulae(regex)
+ # Use stderr to avoid breaking parsed output
+ $stderr.puts Formatter.headline("Searching local taps...", color: :blue)
+
aliases = Formula.alias_full_names
results = (Formula.full_names + aliases).grep(regex).sort
diff --git a/Library/Homebrew/cmd/style.rb b/Library/Homebrew/cmd/style.rb
index b0f46fadc..58f430a27 100644
--- a/Library/Homebrew/cmd/style.rb
+++ b/Library/Homebrew/cmd/style.rb
@@ -117,12 +117,13 @@ module Homebrew
case output_type
when :print
+ args << "--debug" if ARGV.debug?
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/tap.rb b/Library/Homebrew/cmd/tap.rb
index 2a07c1b2f..fa520e2c5 100644
--- a/Library/Homebrew/cmd/tap.rb
+++ b/Library/Homebrew/cmd/tap.rb
@@ -54,8 +54,7 @@ module Homebrew
quiet: ARGV.quieter?
rescue TapRemoteMismatchError => e
odie e
- rescue TapAlreadyTappedError, TapAlreadyUnshallowError
- # Do nothing.
+ rescue TapAlreadyTappedError, TapAlreadyUnshallowError # rubocop:disable Lint/HandleExceptions
end
end
end
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/unpin.rb b/Library/Homebrew/cmd/unpin.rb
index a669df1ec..e15a156ea 100644
--- a/Library/Homebrew/cmd/unpin.rb
+++ b/Library/Homebrew/cmd/unpin.rb
@@ -1,6 +1,6 @@
#: * `unpin` <formulae>:
-#: Unpin <formulae>, allowing them to be upgraded by `brew upgrade`. See also
-#: `pin`.
+#: Unpin <formulae>, allowing them to be upgraded by `brew upgrade <formulae>`.
+#: See also `pin`.
require "formula"
diff --git a/Library/Homebrew/cmd/update-report.rb b/Library/Homebrew/cmd/update-report.rb
index ea915f99c..0974df0b4 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.
@@ -371,7 +372,7 @@ class Reporter
new_version = formula.pkg_version
old_version = FormulaVersions.new(formula).formula_at_revision(@initial_revision, &:pkg_version)
next if new_version == old_version
- rescue Exception => e
+ rescue Exception => e # rubocop:disable Lint/RescueException
onoe "#{e.message}\n#{e.backtrace.join "\n"}" if ARGV.homebrew_developer?
end
@report[:M] << tap.formula_file_to_name(src)
@@ -459,7 +460,7 @@ class Reporter
unless Formulary.factory(new_full_name).keg_only?
system HOMEBREW_BREW_FILE, "link", new_full_name, "--overwrite"
end
- rescue Exception => e
+ rescue Exception => e # rubocop:disable Lint/RescueException
onoe "#{e.message}\n#{e.backtrace.join "\n"}" if ARGV.homebrew_developer?
end
next
@@ -520,7 +521,7 @@ class Reporter
begin
f = Formulary.factory(new_full_name)
- rescue Exception => e
+ rescue Exception => e # rubocop:disable Lint/RescueException
onoe "#{e.message}\n#{e.backtrace.join "\n"}" if ARGV.homebrew_developer?
next
end
diff --git a/Library/Homebrew/cmd/update.sh b/Library/Homebrew/cmd/update.sh
index fb6a3459c..3507fa92b 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
@@ -564,6 +570,7 @@ EOS
-d "$HOMEBREW_LIBRARY/LinkedKegs" ||
(-n "$HOMEBREW_DEVELOPER" && -z "$HOMEBREW_UPDATE_PREINSTALL") ]]
then
+ unset HOMEBREW_RUBY_PATH
brew update-report "$@"
return $?
elif [[ -z "$HOMEBREW_UPDATE_PREINSTALL" ]]
diff --git a/Library/Homebrew/cmd/upgrade.rb b/Library/Homebrew/cmd/upgrade.rb
index 1cdb497cf..f1ce3c7da 100644
--- a/Library/Homebrew/cmd/upgrade.rb
+++ b/Library/Homebrew/cmd/upgrade.rb
@@ -150,6 +150,7 @@ module Homebrew
rescue FormulaInstallationAlreadyAttemptedError
# We already attempted to upgrade f as part of the dependency tree of
# another formula. In that case, don't generate an error, just move on.
+ return
rescue CannotInstallFormulaError => e
ofail e
rescue BuildError => e
diff --git a/Library/Homebrew/cmd/uses.rb b/Library/Homebrew/cmd/uses.rb
index 24684c3b6..0b09e1bf1 100644
--- a/Library/Homebrew/cmd/uses.rb
+++ b/Library/Homebrew/cmd/uses.rb
@@ -74,12 +74,13 @@ module Homebrew
end
end
- dep_formulae = deps.map do |dep|
+ dep_formulae = deps.flat_map do |dep|
begin
dep.to_formula
rescue
+ []
end
- end.compact
+ end
reqs_by_formula = ([f] + dep_formulae).flat_map do |formula|
formula.requirements.map { |req| [formula, req] }
@@ -118,6 +119,7 @@ module Homebrew
rescue FormulaUnavailableError
# Silently ignore this case as we don't care about things used in
# taps that aren't currently tapped.
+ next
end
end
end
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..6206eb8a2 100644
--- a/Library/Homebrew/debrew.rb
+++ b/Library/Homebrew/debrew.rb
@@ -9,7 +9,7 @@ module Debrew
module Raise
def raise(*)
super
- rescue Exception => e
+ rescue Exception => e # rubocop:disable Lint/RescueException
e.extend(Ignorable)
super(e) unless Debrew.debug(e) == :ignore
end
@@ -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) }
@@ -92,7 +92,7 @@ module Debrew
yield
rescue SystemExit
original_raise
- rescue Exception => e
+ rescue Exception => e # rubocop:disable Lint/RescueException
debug(e)
ensure
@active = false
@@ -119,7 +119,7 @@ module Debrew
if e.is_a?(Ignorable)
menu.choice(:irb) do
puts "When you exit this IRB session, execution will continue."
- set_trace_func proc { |event, _, _, id, binding, klass|
+ set_trace_func proc { |event, _, _, id, binding, klass| # rubocop:disable Metrics/ParameterLists
if klass == Raise && id == :raise && event == "return"
set_trace_func(nil)
synchronize { IRB.start_within(binding) }
diff --git a/Library/Homebrew/debrew/irb.rb b/Library/Homebrew/debrew/irb.rb
index f97403782..eeb3758a9 100644
--- a/Library/Homebrew/debrew/irb.rb
+++ b/Library/Homebrew/debrew/irb.rb
@@ -4,8 +4,7 @@ module IRB
@setup_done = false
extend Module.new {
- def parse_opts
- end
+ def parse_opts; end
def start_within(binding)
unless @setup_done
@@ -16,7 +15,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..7f0e7fbff 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
@@ -64,7 +64,7 @@ class Dependency
end
def self._load(marshaled)
- new(*Marshal.load(marshaled))
+ new(*Marshal.load(marshaled)) # rubocop:disable Security/MarshalLoad
end
class << self
diff --git a/Library/Homebrew/dependency_collector.rb b/Library/Homebrew/dependency_collector.rb
index fff80a28c..f855669e0 100644
--- a/Library/Homebrew/dependency_collector.rb
+++ b/Library/Homebrew/dependency_collector.rb
@@ -4,6 +4,7 @@ require "ld64_dependency"
require "requirement"
require "requirements"
require "set"
+require "extend/cachable"
## A dependency is a formula that another formula needs to install.
## A requirement is something other than a formula that another formula
@@ -16,17 +17,13 @@ require "set"
# This class is used by `depends_on` in the formula DSL to turn dependency
# specifications into the proper kinds of dependencies and requirements.
class DependencyCollector
+ extend Cachable
+
# Define the languages that we can handle as external dependencies.
LANGUAGE_MODULES = Set[
:lua, :lua51, :perl, :python, :python3, :ruby
].freeze
- CACHE = {}
-
- def self.clear_cache
- CACHE.clear
- end
-
attr_reader :deps, :requirements
def initialize
@@ -45,7 +42,7 @@ class DependencyCollector
end
def fetch(spec)
- CACHE.fetch(cache_key(spec)) { |key| CACHE[key] = build(spec) }
+ self.class.cache.fetch(cache_key(spec)) { |key| self.class.cache[key] = build(spec) }
end
def cache_key(spec)
diff --git a/Library/Homebrew/descriptions.rb b/Library/Homebrew/descriptions.rb
index ac1d68216..bc1982673 100644
--- a/Library/Homebrew/descriptions.rb
+++ b/Library/Homebrew/descriptions.rb
@@ -78,10 +78,10 @@ class Descriptions
formula_names.each do |name|
begin
- desc = Formulary.factory(name).desc
+ @cache[name] = Formulary.factory(name).desc
rescue FormulaUnavailableError, *FormulaVersions::IGNORED_EXCEPTIONS
+ @cache.delete(name)
end
- @cache[name] = desc
end
save_cache if options[:save]
end
diff --git a/Library/Homebrew/dev-cmd/aspell-dictionaries.rb b/Library/Homebrew/dev-cmd/aspell-dictionaries.rb
index 955e41b01..ab0e66d2b 100644
--- a/Library/Homebrew/dev-cmd/aspell-dictionaries.rb
+++ b/Library/Homebrew/dev-cmd/aspell-dictionaries.rb
@@ -27,13 +27,12 @@ module Homebrew
end
end
- languages.inject([]) do |resources, (lang, path)|
+ languages.each do |lang, path|
r = Resource.new(lang)
r.owner = Formulary.factory("aspell")
r.url "#{dict_url}/#{path}"
r.mirror "#{dict_mirror}/#{path}"
- resources << r
- end.each(&:fetch).each do |r|
+ r.fetch
puts <<-EOS
option "with-lang-#{r.name}", "Install #{r.name} dictionary"
resource "#{r.name}" do
diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb
index f8236e6a6..b58672043 100644
--- a/Library/Homebrew/dev-cmd/audit.rb
+++ b/Library/Homebrew/dev-cmd/audit.rb
@@ -53,7 +53,8 @@ module Homebrew
module_function
def audit
- Homebrew.inject_dump_stats!(FormulaAuditor, /^audit_/) if ARGV.switch? "D"
+ 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,18 +242,40 @@ 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)
max_time = hash_needed ? "600" : "25"
- args = curl_args(
- extra_args: ["--connect-timeout", "15", "--include", "--max-time", max_time, url],
- show_output: true,
- user_agent: user_agent,
+ output, = curl_output(
+ "--connect-timeout", "15", "--include", "--max-time", max_time, "--location", url,
+ user_agent: user_agent
)
- output = Open3.popen3(*args) { |_, stdout, _, _| stdout.read }
status_code = :unknown
while status_code == :unknown || status_code.to_s.start_with?("3")
@@ -262,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
@@ -329,7 +358,8 @@ 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
@@ -357,31 +387,17 @@ 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
+ def self.aliases
+ # core aliases + tap alias names + tap alias full name
+ @aliases ||= Formula.aliases + Formula.tap_aliases
end
- # core aliases + tap alias names + tap alias full name
- @@aliases ||= Formula.aliases + Formula.tap_aliases
-
def audit_formula_name
return unless @strict
# skip for non-official taps
return if formula.tap.nil? || !formula.tap.official?
name = formula.name
- full_name = formula.full_name
if Homebrew::MissingFormula.blacklisted_reason(name)
problem "'#{name}' is blacklisted."
@@ -397,33 +413,10 @@ class FormulaAuditor
return
end
- if !formula.core_formula? && Formula.core_names.include?(name)
- problem "Formula name conflicts with existing core formula."
- return
- end
-
- @@local_official_taps_name_map ||= Tap.select(&:official?).flat_map(&:formula_names)
- .each_with_object({}) do |tap_formula_full_name, name_map|
- tap_formula_name = tap_formula_full_name.split("/").last
- name_map[tap_formula_name] ||= []
- name_map[tap_formula_name] << tap_formula_full_name
- name_map
- end
+ return if formula.core_formula?
+ return unless Formula.core_names.include?(name)
- same_name_tap_formulae = @@local_official_taps_name_map[name] || []
-
- if @online
- Homebrew.search_taps(name).each do |tap_formula_full_name|
- tap_formula_name = tap_formula_full_name.split("/").last
- next if tap_formula_name != name
- same_name_tap_formulae << tap_formula_full_name
- end
- end
-
- same_name_tap_formulae.delete(full_name)
-
- return if same_name_tap_formulae.empty?
- problem "Formula name conflicts with #{same_name_tap_formulae.join ", "}"
+ problem "Formula name conflicts with existing core formula."
end
def audit_deps
@@ -451,7 +444,7 @@ class FormulaAuditor
problem "Dependency '#{dep.name}' was renamed; use new name '#{dep_f.name}'."
end
- if @@aliases.include?(dep.name) &&
+ if self.class.aliases.include?(dep.name) &&
(dep_f.core_formula? || !dep_f.versioned_formula?)
problem "Dependency '#{dep.name}' is an alias; use the canonical name '#{dep.to_formula.full_name}'."
end
@@ -462,16 +455,16 @@ class FormulaAuditor
problem "Dependency '#{dep.name}' may be unnecessary as it is provided by macOS; try to build this formula without it."
end
- dep.options.reject do |opt|
- next true if dep_f.option_defined?(opt)
- dep_f.requirements.detect do |r|
+ dep.options.each do |opt|
+ next if dep_f.option_defined?(opt)
+ next if dep_f.requirements.detect do |r|
if r.recommended?
opt.name == "with-#{r.name}"
elsif r.optional?
opt.name == "without-#{r.name}"
end
end
- end.each do |opt|
+
problem "Dependency #{dep} does not define option #{opt.name.inspect}"
end
@@ -564,10 +557,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
@@ -598,7 +592,8 @@ class FormulaAuditor
return if metadata.nil?
problem "GitHub fork (not canonical repository)" if metadata["fork"]
- if (metadata["forks_count"] < 20) && (metadata["subscribers_count"] < 20) &&
+ if formula&.tap&.core_tap? &&
+ (metadata["forks_count"] < 20) && (metadata["subscribers_count"] < 20) &&
(metadata["stargazers_count"] < 50)
problem "GitHub repository not notable enough (<20 forks, <20 watchers and <50 stars)"
end
@@ -617,13 +612,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}"
}
@@ -688,7 +684,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+$/, "")
@@ -855,7 +851,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
@@ -918,10 +914,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
@@ -929,9 +925,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
@@ -1005,11 +1003,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
@@ -1021,7 +1037,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
@@ -1030,6 +1046,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..fb862c773 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| %>
@@ -75,7 +75,7 @@ module Homebrew
@put_filenames ||= []
- return if @put_filenames.include? filename
+ return if @put_filenames.include?(filename)
puts Formatter.error(filename.to_s)
@put_filenames << filename
@@ -84,8 +84,7 @@ module Homebrew
result = false
keg.each_unique_file_matching(string) do |file|
- # skip document file.
- next if Metafiles::EXTENSIONS.include? file.extname
+ next if Metafiles::EXTENSIONS.include?(file.extname) # Skip document files.
linked_libraries = Keg.file_linked_libraries(file, string)
result ||= !linked_libraries.empty?
@@ -156,9 +155,7 @@ module Homebrew
return ofail "Formula not installed or up-to-date: #{f.full_name}"
end
- tap = f.tap
-
- unless tap
+ unless tap = f.tap
unless ARGV.include?("--force-core-tap")
return ofail "Formula not from core or any taps: #{f.full_name}"
end
@@ -186,7 +183,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 +280,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 1c56749a3..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
@@ -176,7 +177,10 @@ module Homebrew
rsrc.version = forced_version if forced_version
odie "No version specified!" unless rsrc.version
rsrc_path = rsrc.fetch
- if Utils.popen_read("/usr/bin/tar", "-tf", rsrc_path) =~ %r{/.*\.}
+ gnu_tar_gtar_path = HOMEBREW_PREFIX/"opt/gnu-tar/bin/gtar"
+ gnu_tar_gtar = gnu_tar_gtar_path if gnu_tar_gtar_path.executable?
+ tar = which("gtar") || gnu_tar_gtar || which("tar")
+ if Utils.popen_read(tar, "-tf", rsrc_path) =~ %r{/.*\.}
new_hash = rsrc_path.sha256
elsif new_url.include? ".tar"
odie "#{formula}: no url/#{hash_type} specified!"
@@ -293,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 -"
@@ -305,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/man.rb b/Library/Homebrew/dev-cmd/man.rb
index 472bb7c2b..b2bb3c8c3 100644
--- a/Library/Homebrew/dev-cmd/man.rb
+++ b/Library/Homebrew/dev-cmd/man.rb
@@ -48,12 +48,9 @@ module Homebrew
def path_glob_commands(glob)
Pathname.glob(glob)
.sort_by { |source_file| sort_key_for_path(source_file) }
- .map do |source_file|
- source_file.read.lines
- .grep(/^#:/)
- .map { |line| line.slice(2..-1) }
- .join
- end.reject { |s| s.strip.empty? || s.include?("@hide_from_man_page") }
+ .map(&:read).map(&:lines)
+ .map { |lines| lines.grep(/^#:/).map { |line| line.slice(2..-1) }.join }
+ .reject { |s| s.strip.empty? || s.include?("@hide_from_man_page") }
end
def build_man_page
diff --git a/Library/Homebrew/dev-cmd/mirror.rb b/Library/Homebrew/dev-cmd/mirror.rb
index e2492203d..6445bc34c 100644
--- a/Library/Homebrew/dev-cmd/mirror.rb
+++ b/Library/Homebrew/dev-cmd/mirror.rb
@@ -25,9 +25,9 @@ module Homebrew
"public_download_numbers": true,
"public_stats": true}
EOS
- curl "--silent", "--fail", "-u#{bintray_user}:#{bintray_key}",
- "-H", "Content-Type: application/json",
- "-d", package_blob, bintray_repo_url
+ curl "--silent", "--fail", "--user", "#{bintray_user}:#{bintray_key}",
+ "--header", "Content-Type: application/json",
+ "--data", package_blob, bintray_repo_url
puts
end
@@ -40,8 +40,8 @@ module Homebrew
content_url = "https://api.bintray.com/content/homebrew/mirror"
content_url += "/#{bintray_package}/#{f.pkg_version}/#{filename}"
content_url += "?publish=1"
- curl "--silent", "--fail", "-u#{bintray_user}:#{bintray_key}",
- "-T", download, content_url
+ curl "--silent", "--fail", "--user", "#{bintray_user}:#{bintray_key}",
+ "--upload-file", download, content_url
puts
ohai "Mirrored #{filename}!"
end
diff --git a/Library/Homebrew/dev-cmd/pull.rb b/Library/Homebrew/dev-cmd/pull.rb
index 9681bb2bc..8cb270303 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}"
@@ -154,8 +154,8 @@ module Homebrew
begin
f = Formula[name]
- # Make sure we catch syntax errors.
- rescue Exception
+ rescue Exception # rubocop:disable Lint/RescueException
+ # Make sure we catch syntax errors.
next
end
@@ -228,7 +228,7 @@ module Homebrew
"https://github.com/BrewTestBot/homebrew-#{tap.repo}/compare/homebrew:master...pr-#{issue}"
end
- curl "--silent", "--fail", "-o", "/dev/null", "-I", bottle_commit_url
+ curl "--silent", "--fail", "--output", "/dev/null", "--head", bottle_commit_url
safe_system "git", "checkout", "--quiet", "-B", bottle_branch, orig_revision
pull_patch bottle_commit_url, "bottle commit"
@@ -303,7 +303,7 @@ module Homebrew
extra_msg = @description ? "(#{@description})" : nil
ohai "Fetching patch #{extra_msg}"
puts "Patch: #{patch_url}"
- curl patch_url, "-s", "-o", patchpath
+ curl_download patch_url, to: patchpath
end
def apply_patch
@@ -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
@@ -433,10 +433,10 @@ module Homebrew
end
version = info.pkg_version
ohai "Publishing on Bintray: #{package} #{version}"
- curl "-w", '\n', "--silent", "--fail",
- "-u#{creds[:user]}:#{creds[:key]}", "-X", "POST",
- "-H", "Content-Type: application/json",
- "-d", '{"publish_wait_for_secs": 0}',
+ curl "--write-out", '\n', "--silent", "--fail",
+ "--user", "#{creds[:user]}:#{creds[:key]}", "--request", "POST",
+ "--header", "Content-Type: application/json",
+ "--data", '{"publish_wait_for_secs": 0}',
"https://api.bintray.com/content/homebrew/#{repo}/#{package}/#{version}/publish"
true
rescue => e
@@ -587,7 +587,7 @@ module Homebrew
# We're in the cache; make sure to force re-download
loop do
begin
- curl url, "-o", filename
+ curl_download url, continue_at: 0, to: filename
break
rescue
if retry_count >= max_curl_retries
@@ -606,7 +606,7 @@ module Homebrew
end
def check_bintray_mirror(name, url)
- headers = curl_output("--connect-timeout", "15", "--head", url)[0]
+ headers, = curl_output("--connect-timeout", "15", "--location", "--head", url)
status_code = headers.scan(%r{^HTTP\/.* (\d+)}).last.first
return if status_code.start_with?("2")
opoo "The Bintray mirror #{url} is not reachable (HTTP status code #{status_code})."
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/dev-cmd/test.rb b/Library/Homebrew/dev-cmd/test.rb
index c678171ac..6622a8c25 100644
--- a/Library/Homebrew/dev-cmd/test.rb
+++ b/Library/Homebrew/dev-cmd/test.rb
@@ -65,8 +65,6 @@ module Homebrew
args << "--devel"
end
- Sandbox.print_sandbox_message if Sandbox.test?
-
Utils.safe_fork do
if Sandbox.test?
sandbox = Sandbox.new
@@ -86,7 +84,7 @@ module Homebrew
rescue ::Test::Unit::AssertionFailedError => e
ofail "#{f.full_name}: failed"
puts e.message
- rescue Exception => e
+ rescue Exception => e # rubocop:disable Lint/RescueException
ofail "#{f.full_name}: failed"
puts e, e.backtrace
ensure
diff --git a/Library/Homebrew/dev-cmd/update-test.rb b/Library/Homebrew/dev-cmd/update-test.rb
index aa7fe6a92..1f1cdbeed 100644
--- a/Library/Homebrew/dev-cmd/update-test.rb
+++ b/Library/Homebrew/dev-cmd/update-test.rb
@@ -81,7 +81,7 @@ module Homebrew
safe_system "git", "reset", "--hard", start_commit
# update ENV["PATH"]
- ENV["PATH"] = "#{curdir}/bin:/usr/local/bin:/usr/bin:/bin"
+ ENV["PATH"] = PATH.new(ENV["PATH"]).prepend(curdir/"bin")
# run brew update
oh1 "Running brew update..."
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 ceb6ad4d1..3edf31012 100644
--- a/Library/Homebrew/diagnostic.rb
+++ b/Library/Homebrew/diagnostic.rb
@@ -151,8 +151,10 @@ module Homebrew
return unless File.directory?(dir)
files = Dir.chdir(dir) do
- Dir[pattern].select { |f| File.file?(f) && !File.symlink?(f) } - Dir.glob(white_list)
- end.map { |file| File.join(dir, file) }
+ (Dir.glob(pattern) - Dir.glob(white_list))
+ .select { |f| File.file?(f) && !File.symlink?(f) }
+ .map { |f| File.join(dir, f) }
+ end
return if files.empty?
inject_file_list(files, message)
@@ -427,15 +429,15 @@ module Homebrew
end
def check_user_path_1
- $seen_prefix_bin = false
- $seen_prefix_sbin = false
+ @seen_prefix_bin = false
+ @seen_prefix_sbin = false
message = ""
paths(ENV["HOMEBREW_PATH"]).each do |p|
case p
when "/usr/bin"
- unless $seen_prefix_bin
+ unless @seen_prefix_bin
# only show the doctor message if there are any conflicts
# rationale: a default install should not trigger any brew doctor messages
conflicts = Dir["#{HOMEBREW_PREFIX}/bin/*"]
@@ -458,9 +460,9 @@ module Homebrew
end
end
when "#{HOMEBREW_PREFIX}/bin"
- $seen_prefix_bin = true
+ @seen_prefix_bin = true
when "#{HOMEBREW_PREFIX}/sbin"
- $seen_prefix_sbin = true
+ @seen_prefix_sbin = true
end
end
@@ -468,7 +470,7 @@ module Homebrew
end
def check_user_path_2
- return if $seen_prefix_bin
+ return if @seen_prefix_bin
<<-EOS.undent
Homebrew's bin was not found in your PATH.
@@ -478,7 +480,7 @@ module Homebrew
end
def check_user_path_3
- return if $seen_prefix_sbin
+ return if @seen_prefix_sbin
# Don't complain about sbin not being in the path if it doesn't exist
sbin = HOMEBREW_PREFIX/"sbin"
@@ -522,7 +524,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 +542,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.
@@ -952,6 +954,7 @@ module Homebrew
Putting non-prefixed coreutils in your path can cause gmp builds to fail.
EOS
rescue FormulaUnavailableError
+ return
end
def check_for_non_prefixed_findutils
@@ -966,6 +969,7 @@ module Homebrew
Putting non-prefixed findutils in your path can cause python builds to fail.
EOS
rescue FormulaUnavailableError
+ return
end
def check_for_pydistutils_cfg_in_home
diff --git a/Library/Homebrew/download_strategy.rb b/Library/Homebrew/download_strategy.rb
index 717334714..e69a56ddf 100644
--- a/Library/Homebrew/download_strategy.rb
+++ b/Library/Homebrew/download_strategy.rb
@@ -18,8 +18,7 @@ class AbstractDownloadStrategy
end
# Download and cache the resource as {#cached_location}.
- def fetch
- end
+ def fetch; end
# Suppress output
def shutup!
@@ -37,13 +36,11 @@ class AbstractDownloadStrategy
# Unpack {#cached_location} into the current working directory, and possibly
# chdir into the newly-unpacked directory.
# Unlike {Resource#stage}, this does not take a block.
- def stage
- end
+ def stage; end
# @!attribute [r] cached_location
# The path to the cached file or directory associated with the resource.
- def cached_location
- end
+ def cached_location; end
# @!attribute [r]
# return most recent modified time for all files in the current working directory after stage.
@@ -204,14 +201,11 @@ class VCSDownloadStrategy < AbstractDownloadStrategy
true
end
- def clone_repo
- end
+ def clone_repo; end
- def update
- end
+ def update; end
- def current_revision
- end
+ def current_revision; end
def extract_ref(specs)
key = REF_TYPES.find { |type| specs.key?(type) }
@@ -331,20 +325,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
@@ -375,75 +359,59 @@ class CurlDownloadStrategy < AbstractFileDownloadStrategy
ohai "Downloading from #{url}"
end
- urls = actual_urls(url)
- unless urls.empty?
- ohai "Downloading from #{urls.last}"
- if !ENV["HOMEBREW_NO_INSECURE_REDIRECT"].nil? && url.start_with?("https://") &&
- urls.any? { |u| !u.start_with? "https://" }
- puts "HTTPS to HTTP redirect detected & HOMEBREW_NO_INSECURE_REDIRECT is set."
- raise CurlDownloadStrategyError, url
- end
- url = urls.last
- end
-
- curl url, "-C", downloaded_size, "-o", temporary_path
+ curl_download resolved_url(url), to: temporary_path
end
# Curl options to be always passed to curl,
- # with raw head calls (`curl -I`) or with actual `fetch`.
+ # with raw head calls (`curl --head`) or with actual `fetch`.
def _curl_opts
- copts = []
- copts << "--user" << meta.fetch(:user) if meta.key?(:user)
- copts
+ return ["--user", meta.fetch(:user)] if meta.key?(:user)
+ []
end
- def actual_urls(url)
- urls = []
- curl_args = _curl_opts << "-I" << "-L" << url
- Utils.popen_read("curl", *curl_args).scan(/^Location: (.+)$/).map do |m|
- urls << URI.join(urls.last || url, m.first.chomp).to_s
+ def resolved_url(url)
+ redirect_url, _, status = curl_output(
+ *_curl_opts, "--silent", "--head",
+ "--write-out", "%{redirect_url}",
+ "--output", "/dev/null",
+ url.to_s
+ )
+
+ return url unless status.success?
+ return url if redirect_url.empty?
+
+ ohai "Downloading from #{redirect_url}"
+ if ENV["HOMEBREW_NO_INSECURE_REDIRECT"] &&
+ url.start_with?("https://") && !redirect_url.start_with?("https://")
+ puts "HTTPS to HTTP redirect detected & HOMEBREW_NO_INSECURE_REDIRECT is set."
+ raise CurlDownloadStrategyError, url
end
- urls
- end
- def downloaded_size
- temporary_path.size? || 0
+ redirect_url
end
- def curl(*args)
+ def curl(*args, **options)
args.concat _curl_opts
args << "--connect-timeout" << "5" unless mirrors.empty?
- super
+ super(*args, **options)
end
end
# Detect and download from Apache Mirror
class CurlApacheMirrorDownloadStrategy < CurlDownloadStrategy
def apache_mirrors
- rd, wr = IO.pipe
- buf = ""
-
- pid = fork do
- ENV.delete "HOMEBREW_CURL_VERBOSE"
- rd.close
- $stdout.reopen(wr)
- $stderr.reopen(wr)
- curl "#{@url}&asjson=1"
- end
- wr.close
+ mirrors, = Open3.capture3(
+ *curl_args(*_curl_opts, "--silent", "--location", "#{@url}&asjson=1"),
+ )
- rd.readline if ARGV.verbose? # Remove Homebrew output
- buf << rd.read until rd.eof?
- rd.close
- Process.wait(pid)
- buf
+ JSON.parse(mirrors)
end
def _fetch
return super if @tried_apache_mirror
@tried_apache_mirror = true
- mirrors = JSON.parse(apache_mirrors)
+ mirrors = apache_mirrors
path_info = mirrors.fetch("path_info")
@url = mirrors.fetch("preferred") + path_info
@mirrors |= %W[https://archive.apache.org/dist/#{path_info}]
@@ -460,7 +428,7 @@ end
class CurlPostDownloadStrategy < CurlDownloadStrategy
def _fetch
base_url, data = @url.split("?")
- curl base_url, "-d", data, "-C", downloaded_size, "-o", temporary_path
+ curl_download base_url, "--data", data, to: temporary_path
end
end
@@ -530,7 +498,7 @@ class S3DownloadStrategy < CurlDownloadStrategy
s3url = obj.public_url
end
- curl s3url, "-C", downloaded_size, "-o", temporary_path
+ curl_download s3url, to: temporary_path
end
end
@@ -566,7 +534,7 @@ class GitHubPrivateRepositoryDownloadStrategy < CurlDownloadStrategy
end
def _fetch
- curl download_url, "-C", downloaded_size, "-o", temporary_path
+ curl_download download_url, to: temporary_path
end
private
@@ -615,7 +583,7 @@ class GitHubPrivateRepositoryReleaseDownloadStrategy < GitHubPrivateRepositoryDo
def _fetch
# HTTP request header `Accept: application/octet-stream` is required.
# Without this, the GitHub API will respond with metadata, not binary.
- curl download_url, "-C", downloaded_size, "-o", temporary_path, "-H", "Accept: application/octet-stream"
+ curl_download download_url, "--header", "Accept: application/octet-stream", to: temporary_path
end
private
@@ -915,18 +883,27 @@ class GitHubGitDownloadStrategy < GitDownloadStrategy
def github_last_commit
return if ENV["HOMEBREW_NO_GITHUB_API"]
- output, _, status = curl_output "-H", "Accept: application/vnd.github.v3.sha", \
- "-I", "https://api.github.com/repos/#{@user}/#{@repo}/commits/#{@ref}"
+ output, _, status = curl_output(
+ "--silent", "--head", "--location",
+ "-H", "Accept: application/vnd.github.v3.sha",
+ "https://api.github.com/repos/#{@user}/#{@repo}/commits/#{@ref}"
+ )
+
+ return unless status.success?
- commit = output[/^ETag: \"(\h+)\"/, 1] if status.success?
+ commit = output[/^ETag: \"(\h+)\"/, 1]
version.update_commit(commit) if commit
commit
end
def multiple_short_commits_exist?(commit)
return if ENV["HOMEBREW_NO_GITHUB_API"]
- output, _, status = curl_output "-H", "Accept: application/vnd.github.v3.sha", \
- "-I", "https://api.github.com/repos/#{@user}/#{@repo}/commits/#{commit}"
+
+ output, _, status = curl_output(
+ "--silent", "--head", "--location",
+ "-H", "Accept: application/vnd.github.v3.sha",
+ "https://api.github.com/repos/#{@user}/#{@repo}/commits/#{commit}"
+ )
!(status.success? && output && output[/^Status: (200)/, 1] == "200")
end
@@ -1159,15 +1136,13 @@ class DownloadStrategyDetector
SubversionDownloadStrategy
when %r{^cvs://}
CVSDownloadStrategy
- when %r{^https?://(.+?\.)?googlecode\.com/hg}
- MercurialDownloadStrategy
- when %r{^hg://}
+ when %r{^hg://}, %r{^https?://(.+?\.)?googlecode\.com/hg}
MercurialDownloadStrategy
when %r{^bzr://}
BazaarDownloadStrategy
when %r{^fossil://}
FossilDownloadStrategy
- when %r{^http://svn\.apache\.org/repos/}, %r{^svn\+http://}
+ when %r{^svn\+http://}, %r{^http://svn\.apache\.org/repos/}
SubversionDownloadStrategy
when %r{^https?://(.+?\.)?sourceforge\.net/hgweb/}
MercurialDownloadStrategy
diff --git a/Library/Homebrew/exceptions.rb b/Library/Homebrew/exceptions.rb
index 8b4cddc59..22a7fe023 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
@@ -555,12 +555,12 @@ end
# raised when a single patch file is not found and apply hasn't been specified
class MissingApplyError < RuntimeError; end
-class BottleVersionMismatchError < RuntimeError
- def initialize(bottle_file, bottle_version, formula, formula_version)
+class BottleFormulaUnavailableError < RuntimeError
+ def initialize(bottle_path, formula_path)
super <<-EOS.undent
- Bottle version mismatch
- Bottle: #{bottle_file} (#{bottle_version})
- Formula: #{formula.full_name} (#{formula_version})
+ This bottle does not contain the formula file:
+ #{bottle_path}
+ #{formula_path}
EOS
end
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/ENV/super.rb b/Library/Homebrew/extend/ENV/super.rb
index 692fd3623..b4f0dfcac 100644
--- a/Library/Homebrew/extend/ENV/super.rb
+++ b/Library/Homebrew/extend/ENV/super.rb
@@ -24,8 +24,7 @@ module Superenv
end
# @private
- def self.bin
- end
+ def self.bin; end
def reset
super
@@ -138,7 +137,6 @@ module Superenv
def determine_pkg_config_libdir
PATH.new(
- "/usr/lib/pkgconfig",
homebrew_extra_pkg_config_paths,
).existing
end
@@ -325,11 +323,9 @@ module Superenv
end
end
- def set_x11_env_if_installed
- end
+ def set_x11_env_if_installed; end
- def set_cpu_flags(*)
- end
+ def set_cpu_flags(_, _ = "", _ = {}); end
end
require "extend/os/extend/ENV/super"
diff --git a/Library/Homebrew/extend/cachable.rb b/Library/Homebrew/extend/cachable.rb
new file mode 100644
index 000000000..69d86ccb7
--- /dev/null
+++ b/Library/Homebrew/extend/cachable.rb
@@ -0,0 +1,9 @@
+module Cachable
+ def cache
+ @cache ||= {}
+ end
+
+ def clear_cache
+ cache.clear
+ end
+end
diff --git a/Library/Homebrew/extend/fileutils.rb b/Library/Homebrew/extend/fileutils.rb
index 52d4cbf51..ed5bfe6c3 100644
--- a/Library/Homebrew/extend/fileutils.rb
+++ b/Library/Homebrew/extend/fileutils.rb
@@ -3,7 +3,7 @@ require "tmpdir"
require "etc"
# Homebrew extends Ruby's `FileUtils` to make our code more readable.
-# @see http://ruby-doc.org/stdlib-2.0.0/libdoc/fileutils/rdoc/FileUtils.html Ruby's FileUtils API
+# @see https://ruby-doc.org/stdlib-2.0.0/libdoc/fileutils/rdoc/FileUtils.html Ruby's FileUtils API
module FileUtils
# Create a temporary directory then yield. When the block returns,
# recursively delete the temporary directory. Passing opts[:retain]
diff --git a/Library/Homebrew/extend/os/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 f97a2dbbb..5872c2264 100644
--- a/Library/Homebrew/extend/os/mac/extend/ENV/super.rb
+++ b/Library/Homebrew/extend/os/mac/extend/ENV/super.rb
@@ -28,7 +28,7 @@ module Superenv
# @private
def homebrew_extra_pkg_config_paths
paths = \
- ["#{HOMEBREW_LIBRARY}/Homebrew/os/mac/pkgconfig/#{MacOS.version}"]
+ ["/usr/lib/pkgconfig", "#{HOMEBREW_LIBRARY}/Homebrew/os/mac/pkgconfig/#{MacOS.version}"]
paths << "#{MacOS::X11.lib}/pkgconfig" << "#{MacOS::X11.share}/pkgconfig" if x11?
paths
end
@@ -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/formula_cellar_checks.rb b/Library/Homebrew/extend/os/mac/formula_cellar_checks.rb
index 66e038774..32e5774f6 100644
--- a/Library/Homebrew/extend/os/mac/formula_cellar_checks.rb
+++ b/Library/Homebrew/extend/os/mac/formula_cellar_checks.rb
@@ -67,11 +67,19 @@ module FormulaCellarChecks
checker = LinkageChecker.new(keg, formula)
return unless checker.broken_dylibs?
- problem_if_output <<-EOS.undent
- The installation was broken.
- Broken dylib links found:
- #{checker.broken_dylibs.to_a * "\n "}
+ output = <<-EOS.undent
+ #{formula} has broken dynamic library links:
+ #{checker.broken_dylibs.to_a * "\n "}
EOS
+ tab = Tab.for_keg(keg)
+ if tab.poured_from_bottle
+ output += <<-EOS.undent
+ Rebuild this from source with:
+ brew reinstall --build-from-source #{formula}
+ If that's successful, file an issue#{formula.tap ? " here:\n #{formula.tap.issues_url}" : "."}
+ EOS
+ end
+ problem_if_output output
end
def audit_installed
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/pathname.rb b/Library/Homebrew/extend/pathname.rb
index 767d83ff9..e3d6880ba 100644
--- a/Library/Homebrew/extend/pathname.rb
+++ b/Library/Homebrew/extend/pathname.rb
@@ -59,7 +59,7 @@ module DiskUsageExtension
end
# Homebrew extends Ruby's `Pathname` to make our code more readable.
-# @see http://ruby-doc.org/stdlib-1.8.7/libdoc/pathname/rdoc/Pathname.html Ruby's Pathname API
+# @see https://ruby-doc.org/stdlib-1.8.7/libdoc/pathname/rdoc/Pathname.html Ruby's Pathname API
class Pathname
include DiskUsageExtension
@@ -186,7 +186,7 @@ class Pathname
begin
tf.chown(uid, gid)
tf.chmod(old_stat.mode)
- rescue Errno::EPERM
+ rescue Errno::EPERM # rubocop:disable Lint/HandleExceptions
end
File.rename(tf.path, self)
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..61042aae7 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)
@@ -1041,14 +1041,14 @@ class Formula
# keg's formula is deleted.
begin
keg = Keg.for(path)
- rescue NotAKegError, Errno::ENOENT
+ rescue NotAKegError, Errno::ENOENT # rubocop:disable Lint/HandleExceptions
# file doesn't belong to any keg.
else
tab_tap = Tab.for_keg(keg).tap
return false if tab_tap.nil? # this keg doesn't below to any core/tap formula, most likely coming from a DIY install.
begin
Formulary.factory(keg.name)
- rescue FormulaUnavailableError
+ rescue FormulaUnavailableError # rubocop:disable Lint/HandleExceptions
# formula for this keg is deleted, so defer to whitelist
rescue TapFormulaAmbiguityError, TapFormulaWithOldnameAmbiguityError
return false # this keg belongs to another formula
@@ -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?
@@ -1378,12 +1379,13 @@ class Formula
# An array of all installed {Formula}
# @private
def self.installed
- @installed ||= racks.map do |rack|
+ @installed ||= racks.flat_map do |rack|
begin
Formulary.from_rack(rack)
rescue FormulaUnavailableError, TapFormulaAmbiguityError, TapFormulaWithOldnameAmbiguityError
+ []
end
- end.compact.uniq(&:name)
+ end.uniq(&:name)
end
def self.installed_with_alias_path(alias_path)
@@ -1440,13 +1442,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 +1528,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 +1573,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 +1616,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 +1630,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!
@@ -1638,7 +1643,7 @@ class Formula
with_logging("test") do
test
end
- rescue Exception
+ rescue Exception # rubocop:disable Lint/RescueException
staging.retain! if ARGV.debug?
raise
end
@@ -1646,6 +1651,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
@@ -1662,8 +1668,7 @@ class Formula
end
# @private
- def test
- end
+ def test; end
# @private
def test_fixtures(file)
@@ -1678,8 +1683,7 @@ class Formula
# system "./configure", "--prefix=#{prefix}"
# system "make", "install"
# end</pre>
- def install
- end
+ def install; end
protected
@@ -1888,11 +1892,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 +1913,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
@@ -1924,28 +1931,28 @@ class Formula
end
end
- def self.method_added(method)
- case method
- when :brew
- raise "You cannot override Formula#brew in class #{name}"
- when :test
- define_method(:test_defined?) { true }
- when :options
- instance = allocate
+ # The methods below define the formula DSL.
+ class << self
+ include BuildEnvironment::DSL
- specs.each do |spec|
- instance.options.each do |opt, desc|
- spec.option(opt[/^--(.+)$/, 1], desc)
+ def method_added(method)
+ case method
+ when :brew
+ raise "You cannot override Formula#brew in class #{name}"
+ when :test
+ define_method(:test_defined?) { true }
+ when :options
+ instance = allocate
+
+ specs.each do |spec|
+ instance.options.each do |opt, desc|
+ spec.option(opt[/^--(.+)$/, 1], desc)
+ end
end
- end
- remove_method(:options)
+ remove_method(:options)
+ end
end
- end
-
- # The methods below define the formula DSL.
- class << self
- include BuildEnvironment::DSL
# The reason for why this software is not linked (by default) to
# {::HOMEBREW_PREFIX}.
diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb
index b2a528381..7cd87e751 100644
--- a/Library/Homebrew/formula_installer.rb
+++ b/Library/Homebrew/formula_installer.rb
@@ -58,13 +58,14 @@ class FormulaInstaller
@options = Options.new
@invalid_option_names = []
@requirement_messages = []
-
- @@attempted ||= Set.new
-
@poured_bottle = false
@pour_failed = false
end
+ def self.attempted
+ @attempted ||= Set.new
+ end
+
# When no build tools are available and build flags are passed through ARGV,
# it's necessary to interrupt the user before any sort of installation
# can proceed. Only invoked when the user has no developer tools.
@@ -84,14 +85,12 @@ class FormulaInstaller
return false if @pour_failed
- bottle = formula.bottle
- return false unless bottle
+ return false if !formula.bottled? && !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
@@ -102,6 +101,7 @@ class FormulaInstaller
return false
end
+ bottle = formula.bottle_specification
unless bottle.compatible_cellar?
if install_bottle_options[:warn]
opoo <<-EOS.undent
@@ -146,7 +146,7 @@ class FormulaInstaller
end
def check_install_sanity
- raise FormulaInstallationAlreadyAttemptedError, formula if @@attempted.include?(formula)
+ raise FormulaInstallationAlreadyAttemptedError, formula if self.class.attempted.include?(formula)
return if ignore_deps?
@@ -237,6 +237,15 @@ class FormulaInstaller
raise CannotInstallFormulaError, message
end
+ # Warn if a more recent version of this formula is available in the tap.
+ begin
+ if formula.pkg_version < (v = Formulary.factory(formula.full_name).pkg_version)
+ opoo "#{formula.full_name} #{v} is available and more recent than version #{formula.pkg_version}."
+ end
+ rescue FormulaUnavailableError
+ nil
+ end
+
check_conflicts
if !pour_bottle? && !formula.bottle_unneeded? && !DevelopmentTools.installed?
@@ -270,7 +279,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)
@@ -279,12 +288,12 @@ class FormulaInstaller
end
end
- @@attempted << formula
+ self.class.attempted << formula
if pour_bottle?(warn: true)
begin
pour
- rescue Exception => e
+ rescue Exception => e # rubocop:disable Lint/RescueException
# any exceptions must leave us with nothing installed
ignore_interrupts do
formula.prefix.rmtree if formula.prefix.directory?
@@ -310,7 +319,12 @@ class FormulaInstaller
clean
# Store the formula used to build the keg in the keg.
- s = formula.path.read.gsub(/ bottle do.+?end\n\n?/m, "")
+ formula_contents = if formula.local_bottle_path
+ Utils::Bottles.formula_contents formula.local_bottle_path, name: formula.name
+ else
+ formula.path.read
+ end
+ s = formula_contents.gsub(/ bottle do.+?end\n\n?/m, "")
brew_prefix = formula.prefix/".brew"
brew_prefix.mkdir
Pathname(brew_prefix/"#{formula.name}.rb").atomic_write(s)
@@ -554,14 +568,14 @@ class FormulaInstaller
oh1 "Installing #{formula.full_name} dependency: #{Formatter.identifier(dep.name)}"
fi.install
fi.finish
- rescue Exception
+ rescue Exception # rubocop:disable Lint/RescueException
ignore_interrupts do
tmp_keg.rename(installed_keg) if tmp_keg && !installed_keg.directory?
linked_keg.link if keg_was_linked
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 +618,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
@@ -679,8 +699,6 @@ class FormulaInstaller
#{formula.specified_path}
].concat(build_argv)
- Sandbox.print_sandbox_message if Sandbox.formula?(formula)
-
Utils.safe_fork do
# Invalidate the current sudo timestamp in case a build script calls sudo.
# Travis CI's Linux sudoless workers have a weird sudo that fails here.
@@ -706,7 +724,7 @@ class FormulaInstaller
if !formula.prefix.directory? || Keg.new(formula.prefix).empty_installation?
raise "Empty installation"
end
- rescue Exception => e
+ rescue Exception => e # rubocop:disable Lint/RescueException
e.options = display_options(formula) if e.is_a?(BuildError)
ignore_interrupts do
# any exceptions must leave us with nothing installed
@@ -767,7 +785,7 @@ class FormulaInstaller
puts " brew link #{formula.name}"
@show_summary_heading = true
Homebrew.failed = true
- rescue Exception => e
+ rescue Exception => e # rubocop:disable Lint/RescueException
onoe "An unexpected error occurred during the `brew link` step"
puts "The formula built, but is not symlinked into #{HOMEBREW_PREFIX}"
puts e
@@ -798,7 +816,7 @@ class FormulaInstaller
formula.plist_path.chmod 0644
log = formula.var/"log"
log.mkpath if formula.plist.include? log.to_s
- rescue Exception => e
+ rescue Exception => e # rubocop:disable Lint/RescueException
onoe "Failed to install plist file"
ohai e, e.backtrace if debug?
Homebrew.failed = true
@@ -806,7 +824,7 @@ class FormulaInstaller
def fix_dynamic_linkage(keg)
keg.fix_dynamic_linkage
- rescue Exception => e
+ rescue Exception => e # rubocop:disable Lint/RescueException
onoe "Failed to fix install linkage"
puts "The formula built, but you may encounter issues using it or linking other"
puts "formula against it."
@@ -818,7 +836,7 @@ class FormulaInstaller
def clean
ohai "Cleaning" if verbose?
Cleaner.new(formula).clean
- rescue Exception => e
+ rescue Exception => e # rubocop:disable Lint/RescueException
opoo "The cleaning step did not complete successfully"
puts "Still, the installation was successful, so we will link it into your prefix"
ohai e, e.backtrace if debug?
@@ -828,7 +846,7 @@ class FormulaInstaller
def post_install
Homebrew.run_post_install(formula)
- rescue Exception => e
+ rescue Exception => e # rubocop:disable Lint/RescueException
opoo "The post-install step did not complete successfully"
puts "You can try again using `brew postinstall #{formula.full_name}`"
ohai e, e.backtrace if debug?
@@ -888,27 +906,31 @@ class FormulaInstaller
super
end
+ def self.locked
+ @locked ||= []
+ end
+
private
attr_predicate :hold_locks?
def lock
- return unless (@@locked ||= []).empty?
+ return unless self.class.locked.empty?
unless ignore_deps?
formula.recursive_dependencies.each do |dep|
- @@locked << dep.to_formula
+ self.class.locked << dep.to_formula
end
end
- @@locked.unshift(formula)
- @@locked.uniq!
- @@locked.each(&:lock)
+ self.class.locked.unshift(formula)
+ self.class.locked.uniq!
+ self.class.locked.each(&:lock)
@hold_locks = true
end
def unlock
return unless hold_locks?
- @@locked.each(&:unlock)
- @@locked.clear
+ self.class.locked.each(&:unlock)
+ self.class.locked.clear
@hold_locks = false
end
diff --git a/Library/Homebrew/formula_versions.rb b/Library/Homebrew/formula_versions.rb
index bb6803567..c10c69e67 100644
--- a/Library/Homebrew/formula_versions.rb
+++ b/Library/Homebrew/formula_versions.rb
@@ -44,7 +44,7 @@ class FormulaVersions
# continue walking the history
ohai "#{e} in #{name} at revision #{rev}", e.backtrace if ARGV.debug?
rescue FormulaUnavailableError
- # Suppress this error
+ return
ensure
Homebrew.raise_deprecation_exceptions = false
end
diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb
index 195d15cec..fddeac631 100644
--- a/Library/Homebrew/formulary.rb
+++ b/Library/Homebrew/formulary.rb
@@ -1,18 +1,19 @@
require "digest/md5"
require "tap"
+require "extend/cachable"
# The Formulary is responsible for creating instances of Formula.
# It is not meant to be used directly from formulae.
module Formulary
- FORMULAE = {}
+ extend Cachable
def self.formula_class_defined?(path)
- FORMULAE.key?(path)
+ cache.key?(path)
end
def self.formula_class_get(path)
- FORMULAE.fetch(path)
+ cache.fetch(path)
end
def self.load_formula(name, path, contents, namespace)
@@ -44,7 +45,7 @@ module Formulary
contents = path.open("r") { |f| ensure_utf8_encoding(f).read }
namespace = "FormulaNamespace#{Digest::MD5.hexdigest(path.to_s)}"
klass = load_formula(name, path, contents, namespace)
- FORMULAE[path] = klass
+ cache[path] = klass
end
if IO.method_defined?(:set_encoding)
@@ -122,14 +123,18 @@ module Formulary
super name, Formulary.path(full_name)
end
- def get_formula(spec, alias_path: nil)
- formula = super
- formula.local_bottle_path = @bottle_filename
- formula_version = formula.pkg_version
- bottle_version = Utils::Bottles.resolve_version(@bottle_filename)
- unless formula_version == bottle_version
- raise BottleVersionMismatchError.new(@bottle_filename, bottle_version, formula, formula_version)
+ def get_formula(spec, **)
+ contents = Utils::Bottles.formula_contents @bottle_filename, name: name
+ formula = begin
+ Formulary.from_contents name, @bottle_filename, contents, spec
+ rescue FormulaUnreadableError => e
+ opoo <<-EOS.undent
+ Unreadable formula in #{@bottle_filename}:
+ #{e}
+ EOS
+ super
end
+ formula.local_bottle_path = @bottle_filename
formula
end
end
@@ -165,7 +170,7 @@ module Formulary
def load_file
HOMEBREW_CACHE_FORMULA.mkpath
FileUtils.rm_f(path)
- curl url, "-o", path
+ curl_download url, to: path
super
rescue MethodDeprecatedError => e
if url =~ %r{github.com/([\w-]+)/homebrew-([\w-]+)/}
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 cb9e367df..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.0") ||
- gpg_version == Version.create("2.1")
+ gpg_version >= Version.create("2.0")
end
end
@@ -20,7 +19,7 @@ class Gpg
find_gpg("gpg2")
end
- GPG_EXECUTABLE = gpg2 || gpg
+ GPG_EXECUTABLE = gpg || gpg2
def self.available?
File.executable?(GPG_EXECUTABLE.to_s)
@@ -41,8 +40,27 @@ class Gpg
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 8fcbecfbd..677a97c85 100644
--- a/Library/Homebrew/keg.rb
+++ b/Library/Homebrew/keg.rb
@@ -253,6 +253,11 @@ class Keg
FileUtils.rm_rf bad_tap_opt if bad_tap_opt.directory?
end
+ aliases.each do |a|
+ alias_symlink = opt/a
+ alias_symlink.delete if alias_symlink.symlink? || alias_symlink.exist?
+ end
+
Pathname.glob("#{opt_record}@*").each do |a|
a = a.basename
next if aliases.include?(a)
@@ -333,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..71773db81 100644
--- a/Library/Homebrew/keg_relocate.rb
+++ b/Library/Homebrew/keg_relocate.rb
@@ -124,6 +124,7 @@ class Keg
next true if pn.symlink?
next true if pn.directory?
next false if pn.basename.to_s == "orig-prefix.txt" # for python virtualenvs
+ next true if pn == self/".brew/#{name}.rb"
next true if Metafiles::EXTENSIONS.include?(pn.extname)
if pn.text_executable?
text_files << pn
@@ -156,7 +157,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..c430d11b6 100644
--- a/Library/Homebrew/locale.rb
+++ b/Library/Homebrew/locale.rb
@@ -2,9 +2,9 @@ class Locale
class ParserError < StandardError
end
- LANGUAGE_REGEX = /(?:[a-z]{2,3})/ # ISO 639-1 or ISO 639-2
- REGION_REGEX = /(?:[A-Z]{2})/ # ISO 3166-1
- SCRIPT_REGEX = /(?:[A-Z][a-z]{3})/ # ISO 15924
+ LANGUAGE_REGEX = /(?:[a-z]{2,3})/ # ISO 639-1 or ISO 639-2
+ REGION_REGEX = /(?:[A-Z]{2}|\d{3})/ # ISO 3166-1 or UN M.49
+ SCRIPT_REGEX = /(?:[A-Z][a-z]{3})/ # ISO 15924
LOCALE_REGEX = /\A((?:#{LANGUAGE_REGEX}|#{REGION_REGEX}|#{SCRIPT_REGEX})(?:\-|$)){1,3}\Z/
@@ -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..1c7c198b0 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
@@ -19,7 +19,7 @@ names, and other aspects of this manual are still subject to change.
## FREQUENTLY USED COMMANDS
- * `install` [--force] [--skip-cask-deps] [--require-sha] <token> [ <token> ... ]:
+ * `install` [--force] [--skip-cask-deps] [--require-sha] [--language=<iso-language>[,<iso-language> ... ]] <token> [ <token> ... ]:
Install Cask identified by <token>.
* `uninstall` [--force] <token> [ <token> ... ]:
@@ -34,7 +34,7 @@ names, and other aspects of this manual are still subject to change.
## COMMANDS
- * `audit` [ <token> ... ]:
+ * `audit` [--language=<iso-language>[,<iso-language> ... ]] [ <token> ... ]:
Check the given Casks for installability.
If no tokens are given on the command line, all Casks are audited.
@@ -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> ... ]:
@@ -166,6 +167,9 @@ in a future version.
* `--appdir=<path>`:
Target location for Applications. The default value is `/Applications`.
+ * `--language=<iso-language>[,<iso-language> ... ]]`:
+ Set language of the Cask to install. The first matching language is used, otherwise the default language on the Cask. The default value is the `language of your system`.
+
* `--colorpickerdir=<path>`:
Target location for Color Pickers. The default value is `~/Library/ColorPickers`.
@@ -255,7 +259,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/migrator.rb b/Library/Homebrew/migrator.rb
index 7ecdafe2f..0eb7492df 100644
--- a/Library/Homebrew/migrator.rb
+++ b/Library/Homebrew/migrator.rb
@@ -100,7 +100,7 @@ class Migrator
begin
migrator = Migrator.new(formula)
migrator.migrate
- rescue Exception => e
+ rescue => e
onoe e
end
end
@@ -196,7 +196,7 @@ class Migrator
update_tabs
rescue Interrupt
ignore_interrupts { backup_oldname }
- rescue Exception => e
+ rescue Exception => e # rubocop:disable Lint/RescueException
onoe "Error occurred while migrating."
puts e
puts e.backtrace if ARGV.debug?
@@ -304,7 +304,7 @@ class Migrator
puts
puts "You can try again using:"
puts " brew link #{formula.name}"
- rescue Exception => e
+ rescue Exception => e # rubocop:disable Lint/RescueException
onoe "An unexpected error occurred during linking"
puts e
puts e.backtrace if ARGV.debug?
diff --git a/Library/Homebrew/missing_formula.rb b/Library/Homebrew/missing_formula.rb
index 4d90ddb61..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,16 +53,7 @@ module Homebrew
ruin SSH's security.
EOS
when "gsutil" then <<-EOS.undent
- Install gsutil with `pip install gsutil`
- EOS
- when "clojure" then <<-EOS.undent
- Clojure isn't really a program but a library managed as part of a
- project and Leiningen is the user interface to that library.
-
- To install Clojure you should install Leiningen:
- brew install leiningen
- and then follow the tutorial:
- #{Formatter.url("https://github.com/technomancy/leiningen/blob/stable/doc/TUTORIAL.md")}
+ 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/official_taps.rb b/Library/Homebrew/official_taps.rb
index dcb65d9f8..ed966c804 100644
--- a/Library/Homebrew/official_taps.rb
+++ b/Library/Homebrew/official_taps.rb
@@ -1,5 +1,4 @@
OFFICIAL_TAPS = %w[
- apache
nginx
php
science
@@ -17,6 +16,7 @@ OFFICIAL_CMD_TAPS = {
}.freeze
DEPRECATED_OFFICIAL_TAPS = %w[
+ apache
binary
completions
devel-only
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..853f75140 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|
@@ -229,7 +229,9 @@ module OS
end
def app_with_bundle_id(*ids)
- path = mdfind(*ids).first
+ path = mdfind(*ids)
+ .reject { |p| p.include?("/Backups.backupdb/") }
+ .first
Pathname.new(path) unless path.nil? || path.empty?
end
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 e23a7cf3d..5071aafcf 100644
--- a/Library/Homebrew/os/mac/xcode.rb
+++ b/Library/Homebrew/os/mac/xcode.rb
@@ -183,7 +183,7 @@ module OS
end
module CLT
- extend self
+ module_function
STANDALONE_PKG_ID = "com.apple.pkg.DeveloperToolsCLILeo".freeze
FROM_XCODE_PKG_ID = "com.apple.pkg.DeveloperToolsCLI".freeze
@@ -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.31"
+ 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/patch.rb b/Library/Homebrew/patch.rb
index 7045adf5e..8a1b00930 100644
--- a/Library/Homebrew/patch.rb
+++ b/Library/Homebrew/patch.rb
@@ -60,8 +60,7 @@ class EmbeddedPatch
false
end
- def contents
- end
+ def contents; end
def apply
data = contents.gsub("HOMEBREW_PREFIX", HOMEBREW_PREFIX)
@@ -87,10 +86,13 @@ class DATAPatch < EmbeddedPatch
def contents
data = ""
path.open("rb") do |f|
- begin
+ loop do
line = f.gets
- end until line.nil? || line =~ /^__END__$/
- data << line while line = f.gets
+ break if line.nil? || line =~ /^__END__$/
+ end
+ while line = f.gets
+ data << line
+ end
end
data
end
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/postinstall.rb b/Library/Homebrew/postinstall.rb
index 0b6d8f6b0..53a5b7e75 100644
--- a/Library/Homebrew/postinstall.rb
+++ b/Library/Homebrew/postinstall.rb
@@ -14,7 +14,7 @@ begin
formula = ARGV.resolved_formulae.first
formula.extend(Debrew::Formula) if ARGV.debug?
formula.run_post_install
-rescue Exception => e
+rescue Exception => e # rubocop:disable Lint/RescueException
Marshal.dump(e, error_pipe)
error_pipe.close
exit! 1
diff --git a/Library/Homebrew/readall.rb b/Library/Homebrew/readall.rb
index 3595c16be..5f4fd947c 100644
--- a/Library/Homebrew/readall.rb
+++ b/Library/Homebrew/readall.rb
@@ -52,7 +52,7 @@ module Readall
Formulary.factory(file)
rescue Interrupt
raise
- rescue Exception => e
+ rescue Exception => e # rubocop:disable Lint/RescueException
onoe "Invalid formula: #{file}"
puts e
failed = true
diff --git a/Library/Homebrew/requirements/gpg2_requirement.rb b/Library/Homebrew/requirements/gpg2_requirement.rb
index 97fabcca0..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"
- # MacGPG2/GPGTools installs GnuPG 2.0.x as a vanilla `gpg` symlink
- # pointing to `gpg2`, as do we. Ensure we're actually using a 2.0 `gpg`.
- # Support both the 2.0.x "stable" and 2.1.x "modern" series.
- satisfy(build_env: false) { Gpg.gpg2 || Gpg.gpg }
+ # 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 76c7e43e9..63c75194c 100644
--- a/Library/Homebrew/rubocops/extend/formula_cop.rb
+++ b/Library/Homebrew/rubocops/extend/formula_cop.rb
@@ -1,4 +1,5 @@
require "parser/current"
+require_relative "../../extend/string"
module RuboCop
module Cop
@@ -13,7 +14,7 @@ module RuboCop
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
@@ -110,11 +111,15 @@ module RuboCop
# 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 || method.receiver.method_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
return true unless block_given?
@@ -146,17 +151,14 @@ module RuboCop
case type
when :required
- type_match = !node.method_args.nil? &&
- (node.method_args.first.str_type? || node.method_args.first.sym_type?)
+ type_match = required_dependency?(node)
if type_match && !name_match
- name_match = node_equals?(node.method_args.first, name)
+ name_match = required_dependency_name?(node, name)
end
when :build, :optional, :recommended, :run
- type_match = !node.method_args.nil? &&
- node.method_args.first.hash_type? &&
- node.method_args.first.values.first.children.first == type
+ type_match = dependency_type_hash_match?(node, type)
if type_match && !name_match
- name_match = node_equals?(node.method_args.first.keys.first.children.first, name)
+ name_match = dependency_name_hash_match?(node, name)
end
else
type_match = false
@@ -183,6 +185,22 @@ module RuboCop
nil
end
+ def_node_search :required_dependency?, <<-EOS.undent
+ (send nil :depends_on ({str sym} _))
+ EOS
+
+ def_node_search :required_dependency_name?, <<-EOS.undent
+ (send nil :depends_on ({str sym} %1))
+ EOS
+
+ def_node_search :dependency_type_hash_match?, <<-EOS.undent
+ (hash (pair ({str sym} _) ({str sym} %1)))
+ EOS
+
+ def_node_search :dependency_name_hash_match?, <<-EOS.undent
+ (hash (pair ({str sym} %1) ({str sym} _)))
+ EOS
+
# To compare node with appropriate Ruby variable
def node_equals?(node, var)
node == Parser::CurrentRuby.parse(var.inspect)
@@ -309,7 +327,7 @@ module RuboCop
# Returns the array of arguments of the method_node
def parameters(method_node)
- method_node.method_args if method_node.send_type? || method_node.block_type?
+ method_node.arguments if method_node.send_type? || method_node.block_type?
end
# Returns true if the given parameters are present in method call
@@ -415,12 +433,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
@@ -443,7 +456,14 @@ 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?
diff --git a/Library/Homebrew/rubocops/lines_cop.rb b/Library/Homebrew/rubocops/lines_cop.rb
index ef199fb6e..97bc45bc0 100644
--- a/Library/Homebrew/rubocops/lines_cop.rb
+++ b/Library/Homebrew/rubocops/lines_cop.rb
@@ -22,19 +22,12 @@ 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 #{@formula_name.capitalize} < #{class_name(parent_class_node)}"
end
end
class Comments < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, _body_node)
- # Commented-out cmake support from default template
- audit_comments do |comment|
- next unless comment.include?('# system "cmake')
- problem "Commented cmake call found"
- end
-
- # Comments from default template
audit_comments do |comment|
[
"# PLEASE REMOVE",
@@ -45,6 +38,7 @@ module RuboCop
"# if your formula requires any X11/XQuartz components",
"# if your formula fails when building in parallel",
"# Remove unrecognized options if warned by configure",
+ '# system "cmake',
].each do |template_comment|
next unless comment.include?(template_comment)
problem "Please remove default template comments"
@@ -55,7 +49,7 @@ module RuboCop
audit_comments do |comment|
# Commented-out depends_on
next unless comment =~ /#\s*depends_on\s+(.+)\s*$/
- problem "Commented-out dep #{Regexp.last_match(1)}"
+ problem "Commented-out dependency #{Regexp.last_match(1)}"
end
end
end
@@ -75,33 +69,33 @@ module RuboCop
problem "\"inreplace <filenames> do |s|\" is preferred over \"|#{block_arg.source}|\"."
end
- [:rebuild, :version_scheme].each do |m|
- find_method_with_args(body_node, m, 0) do
- problem "'#{m} 0' should be removed"
+ [: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 |m|
+ [:mac?, :linux?].each do |method_name|
next unless formula_tap == "homebrew-core"
- find_instance_method_call(body_node, "OS", m) do |check|
+ find_instance_method_call(body_node, "OS", method_name) do |check|
problem "Don't use #{check.source}; Homebrew/core only supports macOS"
end
end
- [:debug?, :verbose?, :value].each do |m|
- find_instance_method_call(body_node, "ARGV", m) do
+ [:debug?, :verbose?, :value].each do |method_name|
+ find_instance_method_call(body_node, "ARGV", method_name) do
problem "Use build instead of ARGV to check options"
end
end
- find_instance_method_call(body_node, :man, :+) do |m|
- next unless match = regex_match_group(parameters(m).first, %r{man[1-8]})
- problem "\"#{m.source}\" should be \"#{match[0]}\""
+ find_instance_method_call(body_node, :man, :+) do |method|
+ next unless match = regex_match_group(parameters(method).first, %r{man[1-8]})
+ problem "\"#{method.source}\" should be \"#{match[0]}\""
end
# Avoid hard-coding compilers
- find_every_method_call_by_name(body_node, :system).each do |m|
- param = parameters(m).first
+ find_every_method_call_by_name(body_node, :system).each do |method|
+ param = parameters(method).first
if match = regex_match_group(param, %r{(/usr/bin/)?(gcc|llvm-gcc|clang)\s?})
problem "Use \"\#{ENV.cc}\" instead of hard-coding \"#{match[2]}\""
elsif match = regex_match_group(param, %r{(/usr/bin/)?((g|llvm-g|clang)\+\+)\s?})
@@ -109,8 +103,8 @@ module RuboCop
end
end
- find_instance_method_call(body_node, "ENV", :[]=) do |m|
- param = parameters(m)[1]
+ find_instance_method_call(body_node, "ENV", :[]=) do |method|
+ param = parameters(method)[1]
if match = regex_match_group(param, %r{(/usr/bin/)?(gcc|llvm-gcc|clang)\s?})
problem "Use \"\#{ENV.cc}\" instead of hard-coding \"#{match[2]}\""
elsif match = regex_match_group(param, %r{(/usr/bin/)?((g|llvm-g|clang)\+\+)\s?})
@@ -136,29 +130,29 @@ module RuboCop
end
end
- find_every_method_call_by_name(body_node, :depends_on).each do |m|
- key, value = destructure_hash(parameters(m).first)
+ find_every_method_call_by_name(body_node, :depends_on).each do |method|
+ key, value = destructure_hash(parameters(method).first)
next if (key.nil? || value.nil?)
next unless match = regex_match_group(value, %r{(lua|perl|python|ruby)(\d*)})
- problem "#{match[1]} modules should be vendored rather than use deprecated #{m.source}`"
+ problem "#{match[1]} modules should be vendored rather than use deprecated #{method.source}`"
end
- find_every_method_call_by_name(body_node, :system).each do |m|
- next unless match = regex_match_group(parameters(m).first, %r{(env|export)(\s+)?})
+ find_every_method_call_by_name(body_node, :system).each do |method|
+ next unless match = regex_match_group(parameters(method).first, %r{(env|export)(\s+)?})
problem "Use ENV instead of invoking '#{match[1]}' to modify the environment"
end
- find_every_method_call_by_name(body_node, :depends_on).each do |m|
- next if modifier?(m.parent)
- param = parameters(m).first
+ find_every_method_call_by_name(body_node, :depends_on).each do |method|
+ next if modifier?(method.parent)
+ param = parameters(method).first
dep, option = hash_dep(param)
next if dep.nil? || option.nil?
offending_node(param)
problem "Dependency #{string_content(dep)} should not use option #{string_content(option)}"
end
- find_instance_method_call(body_node, :version, :==) do |m|
- next unless parameters_passed?(m, "HEAD")
+ find_instance_method_call(body_node, :version, :==) do |method|
+ next unless parameters_passed?(method, "HEAD")
problem "Use 'build.head?' instead of inspecting 'version'"
end
@@ -167,8 +161,8 @@ module RuboCop
problem "Use `depends_on :fortran` instead of `ENV.fortran`"
end
- find_instance_method_call(body_node, "ARGV", :include?) do |m|
- param = parameters(m).first
+ find_instance_method_call(body_node, "ARGV", :include?) do |method|
+ param = parameters(method).first
next unless match = regex_match_group(param, %r{--(HEAD|devel)})
problem "Use \"if build.#{match[1].downcase}?\" instead"
end
@@ -202,14 +196,21 @@ module RuboCop
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
+ 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_method_with_args(body_node, :system, /npm/, /install/) do |m|
- next if @formula_name =~ /^kibana(\@\d+(\.\d+)?)?$/
- problem "Use Language::Node for npm install args" unless languageNode?(m)
+
+ 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+)?)?$/i
+ 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
@@ -219,12 +220,15 @@ module RuboCop
end
find_method_with_args(body_node, :skip_clean, :all) do
- problem "`skip_clean :all` is deprecated; brew no longer strips symbols\n" \
- "\tPass explicit paths to prevent Homebrew from removing empty folders."
+ 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
- problem "macOS has been 64-bit only so build.universal? is deprecated."
+ 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
@@ -235,85 +239,85 @@ module RuboCop
problem 'Use "depends_on :x11" instead of "ENV.x11"'
end
- find_every_method_call_by_name(body_node, :assert).each do |m|
- if method_called?(m, :include?) && !method_called?(m, :!)
+ find_every_method_call_by_name(body_node, :assert).each do |method|
+ if method_called?(method, :include?) && !method_called?(method, :!)
problem "Use `assert_match` instead of `assert ...include?`"
end
end
- find_every_method_call_by_name(body_node, :depends_on).each do |m|
- next unless method_called?(m, :new)
+ find_every_method_call_by_name(body_node, :depends_on).each do |method|
+ next unless method_called?(method, :new)
problem "`depends_on` can take requirement classes instead of instances"
end
os = [:leopard?, :snow_leopard?, :lion?, :mountain_lion?]
os.each do |version|
- find_instance_method_call(body_node, "MacOS", version) do |m|
- problem "\"#{m.source}\" is deprecated, use a comparison to MacOS.version instead"
+ find_instance_method_call(body_node, "MacOS", version) do |method|
+ problem "\"#{method.source}\" is deprecated, use a comparison to MacOS.version instead"
end
end
- find_instance_method_call(body_node, "Dir", :[]) do |m|
- path = parameters(m).first
+ find_instance_method_call(body_node, "Dir", :[]) do |method|
+ path = parameters(method).first
next if !path.str_type?
next unless match = regex_match_group(path, /^[^\*{},]+$/)
problem "Dir([\"#{string_content(path)}\"]) is unnecessary; just use \"#{match[0]}\""
end
- fileUtils_methods= Regexp.new(FileUtils.singleton_methods(false).map { |m| Regexp.escape(m) }.join "|")
- find_every_method_call_by_name(body_node, :system).each do |m|
- param = parameters(m).first
+ fileUtils_methods= Regexp.new(FileUtils.singleton_methods(false).map { |m| '(?-mix:^'+Regexp.escape(m)+'$)' }.join '|')
+ find_every_method_call_by_name(body_node, :system).each do |method|
+ param = parameters(method).first
next unless match = regex_match_group(param, fileUtils_methods)
- problem "Use the `#{match}` Ruby method instead of `#{m.source}`"
+ problem "Use the `#{match}` Ruby method instead of `#{method.source}`"
end
if find_method_def(@processed_source.ast)
problem "Define method #{method_name(@offensive_node)} in the class body, not at the top-level"
end
- find_instance_method_call(body_node, :build, :without?) do |m|
- next unless unless_modifier?(m.parent)
- correct = m.source.gsub("out?", "?")
- problem "Use if #{correct} instead of unless #{m.source}"
+ find_instance_method_call(body_node, :build, :without?) do |method|
+ next unless unless_modifier?(method.parent)
+ correct = method.source.gsub("out?", "?")
+ problem "Use if #{correct} instead of unless #{method.source}"
end
- find_instance_method_call(body_node, :build, :with?) do |m|
- next unless unless_modifier?(m.parent)
- correct = m.source.gsub("?", "out?")
- problem "Use if #{correct} instead of unless #{m.source}"
+ find_instance_method_call(body_node, :build, :with?) do |method|
+ next unless unless_modifier?(method.parent)
+ correct = method.source.gsub("?", "out?")
+ problem "Use if #{correct} instead of unless #{method.source}"
end
- find_instance_method_call(body_node, :build, :with?) do |m|
- next unless negated?(m.parent)
+ find_instance_method_call(body_node, :build, :with?) do |method|
+ next unless negated?(method.parent)
problem "Don't negate 'build.with?': use 'build.without?'"
end
- find_instance_method_call(body_node, :build, :without?) do |m|
- next unless negated?(m.parent)
+ find_instance_method_call(body_node, :build, :without?) do |method|
+ next unless negated?(method.parent)
problem "Don't negate 'build.without?': use 'build.with?'"
end
- find_instance_method_call(body_node, :build, :without?) do |m|
- arg = parameters(m).first
+ find_instance_method_call(body_node, :build, :without?) do |method|
+ arg = parameters(method).first
next unless match = regex_match_group(arg, %r{-?-?without-(.*)})
problem "Don't duplicate 'without': Use `build.without? \"#{match[1]}\"` to check for \"--without-#{match[1]}\""
end
- find_instance_method_call(body_node, :build, :with?) do |m|
- arg = parameters(m).first
+ find_instance_method_call(body_node, :build, :with?) do |method|
+ arg = parameters(method).first
next unless match = regex_match_group(arg, %r{-?-?with-(.*)})
problem "Don't duplicate 'with': Use `build.with? \"#{match[1]}\"` to check for \"--with-#{match[1]}\""
end
- find_instance_method_call(body_node, :build, :include?) do |m|
- arg = parameters(m).first
+ find_instance_method_call(body_node, :build, :include?) do |method|
+ arg = parameters(method).first
next unless match = regex_match_group(arg, %r{with(out)?-(.*)})
problem "Use build.with#{match[1]}? \"#{match[2]}\" instead of build.include? 'with#{match[1]}-#{match[2]}'"
end
- find_instance_method_call(body_node, :build, :include?) do |m|
- arg = parameters(m).first
+ find_instance_method_call(body_node, :build, :include?) do |method|
+ arg = parameters(method).first
next unless match = regex_match_group(arg, %r{\-\-(.*)})
problem "Reference '#{match[1]}' without dashes"
end
@@ -352,19 +356,11 @@ module RuboCop
(dstr _ (begin (send nil %1)) $(str _ ))}
EOS
- # This is Pattern Matching method for AST
- # Takes the AST node as argument and yields matching node if block given
- # Else returns boolean for the match
- def_node_search :languageNode?, <<-PATTERN
+ # Node Pattern search for Language::Node
+ def_node_search :languageNodeModule?, <<-EOS.undent
(const (const nil :Language) :Node)
- PATTERN
-
+ EOS
end
end
end
end
-
-# Strict rules ported early
-# find_method_with_args(@processed_source.ast, :require, "formula") do |m|
-# problem "#{m.source} is now unnecessary"
-# end
diff --git a/Library/Homebrew/rubocops/patches_cop.rb b/Library/Homebrew/rubocops/patches_cop.rb
index fb14d8acc..7ee1a127a 100644
--- a/Library/Homebrew/rubocops/patches_cop.rb
+++ b/Library/Homebrew/rubocops/patches_cop.rb
@@ -25,13 +25,26 @@ module RuboCop
def patch_problems(patch)
patch_url = string_content(patch)
+ gh_patch_param_pattern = %r{https?://github\.com/.+/.+/(?:commit|pull)/[a-fA-F0-9]*.(?:patch|diff)}
+ if regex_match_group(patch, gh_patch_param_pattern)
+ if patch_url !~ /\?full_index=\w+$/
+ problem <<-EOS.undent
+ GitHub patches should use the full_index parameter:
+ #{patch_url}?full_index=1
+ EOS
+ end
+ end
+
gh_patch_patterns = Regexp.union([%r{/raw\.github\.com/},
%r{gist\.github\.com/raw},
%r{gist\.github\.com/.+/raw},
%r{gist\.githubusercontent\.com/.+/raw}])
if regex_match_group(patch, gh_patch_patterns)
- unless patch_url =~ /[a-fA-F0-9]{40}/
- problem "GitHub/Gist patches should specify a revision:\n#{patch_url}"
+ if patch_url !~ /[a-fA-F0-9]{40}/
+ problem <<-EOS.undent.chomp
+ GitHub/Gist patches should specify a revision:
+ #{patch_url}
+ EOS
end
end
@@ -46,15 +59,24 @@ module RuboCop
end
if regex_match_group(patch, %r{macports/trunk})
- problem "MacPorts patches should specify a revision instead of trunk:\n#{patch_url}"
+ problem <<-EOS.undent.chomp
+ MacPorts patches should specify a revision instead of trunk:
+ #{patch_url}
+ EOS
end
if regex_match_group(patch, %r{^http://trac\.macports\.org})
- problem "Patches from MacPorts Trac should be https://, not http:\n#{patch_url}"
+ problem <<-EOS.undent.chomp
+ Patches from MacPorts Trac should be https://, not http:
+ #{patch_url}
+ EOS
end
return unless regex_match_group(patch, %r{^http://bugs\.debian\.org})
- problem "Patches from Debian should be https://, not http:\n#{patch_url}"
+ problem <<-EOS.undent.chomp
+ Patches from Debian should be https://, not http:
+ #{patch_url}
+ EOS
end
end
end
diff --git a/Library/Homebrew/rubocops/urls_cop.rb b/Library/Homebrew/rubocops/urls_cop.rb
index 676e73523..071a4c42d 100644
--- a/Library/Homebrew/rubocops/urls_cop.rb
+++ b/Library/Homebrew/rubocops/urls_cop.rb
@@ -104,8 +104,10 @@ module RuboCop
end
if url =~ %r{^https?://prdownloads\.}
- problem "Don't use prdownloads in SourceForge urls (url is #{url}).\n" \
- "\tSee: http://librelist.com/browser/homebrew/2011/1/12/prdownloads-is-bad/"
+ problem <<-EOS.undent.chomp
+ Don't use prdownloads in SourceForge urls (url is #{url}).
+ See: http://librelist.com/browser/homebrew/2011/1/12/prdownloads-is-bad/
+ EOS
end
if url =~ %r{^http://\w+\.dl\.}
diff --git a/Library/Homebrew/sandbox.rb b/Library/Homebrew/sandbox.rb
index 0de970773..7d23e5966 100644
--- a/Library/Homebrew/sandbox.rb
+++ b/Library/Homebrew/sandbox.rb
@@ -18,12 +18,6 @@ class Sandbox
!ARGV.no_sandbox?
end
- def self.print_sandbox_message
- return if @printed_sandbox_message
- ohai "Using the sandbox"
- @printed_sandbox_message = true
- end
-
def initialize
@profile = SandboxProfile.new
end
@@ -173,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/shims/super/cc b/Library/Homebrew/shims/super/cc
index d894d3d69..afe72156f 100755
--- a/Library/Homebrew/shims/super/cc
+++ b/Library/Homebrew/shims/super/cc
@@ -43,6 +43,8 @@ class Cmd
else
:cc
end
+ elsif @args.include?("-xc++-header") || @args.each_cons(2).include?(["-x", "c++-header"])
+ :cxx
elsif @args.include? "-E"
:ccE
else
diff --git a/Library/Homebrew/shims/super/make b/Library/Homebrew/shims/super/make
index 7b49e56c0..46de53131 100755
--- a/Library/Homebrew/shims/super/make
+++ b/Library/Homebrew/shims/super/make
@@ -1,5 +1,10 @@
#!/bin/bash
-export MAKE=${HOMEBREW_MAKE:-make}
+if [[ -n "$HOMEBREW_MAKE" && "$HOMEBREW_MAKE" != "make" ]]
+then
+ export MAKE="$HOMEBREW_MAKE"
+else
+ MAKE="make"
+fi
export HOMEBREW_CCCFG="O$HOMEBREW_CCCFG"
-exec xcrun $MAKE "$@"
+exec xcrun "$MAKE" "$@"
diff --git a/Library/Homebrew/software_spec.rb b/Library/Homebrew/software_spec.rb
index c6e704350..dd6026fcf 100644
--- a/Library/Homebrew/software_spec.rb
+++ b/Library/Homebrew/software_spec.rb
@@ -51,8 +51,18 @@ class SoftwareSpec
@owner = owner
@resource.owner = self
resources.each_value do |r|
- r.owner = self
- r.version ||= (version.head? ? Version.create("HEAD") : version.dup)
+ r.owner = self
+ r.version ||= begin
+ if version.nil?
+ raise "#{full_name}: version missing for \"#{r.name}\" resource!"
+ end
+
+ if version.head?
+ Version.create("HEAD")
+ else
+ version.dup
+ end
+ end
end
patches.each { |p| p.owner = self }
end
@@ -257,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..aa0208d51 100644
--- a/Library/Homebrew/tab.rb
+++ b/Library/Homebrew/tab.rb
@@ -3,18 +3,16 @@ require "ostruct"
require "options"
require "json"
require "development_tools"
+require "extend/cachable"
# Inherit from OpenStruct to gain a generic initialization method that takes a
# hash and creates an attribute for each key and value. `Tab.new` probably
# should not be called directly, instead use one of the class methods like
# `Tab.create`.
class Tab < OpenStruct
- FILENAME = "INSTALL_RECEIPT.json".freeze
- CACHE = {}
+ extend Cachable
- def self.clear_cache
- CACHE.clear
- end
+ FILENAME = "INSTALL_RECEIPT.json".freeze
# Instantiates a Tab for a new installation of a formula.
def self.create(formula, compiler, stdlib)
@@ -57,7 +55,7 @@ class Tab < OpenStruct
# Returns the Tab for an install receipt at `path`.
# Results are cached.
def self.from_file(path)
- CACHE.fetch(path) { |p| CACHE[p] = from_file_content(File.read(p), p) }
+ cache.fetch(path) { |p| cache[p] = from_file_content(File.read(p), p) }
end
# Like Tab.from_file, but bypass the cache.
@@ -324,7 +322,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,
@@ -343,7 +341,7 @@ class Tab < OpenStruct
# will no longer be valid.
Formula.clear_installed_formulae_cache unless tabfile.exist?
- CACHE[tabfile] = self
+ self.class.cache[tabfile] = self
tabfile.atomic_write(to_json)
end
diff --git a/Library/Homebrew/tap.rb b/Library/Homebrew/tap.rb
index f232be428..78dc4cf4e 100644
--- a/Library/Homebrew/tap.rb
+++ b/Library/Homebrew/tap.rb
@@ -1,4 +1,5 @@
require "extend/string"
+require "extend/cachable"
require "readall"
# a {Tap} is used to extend the formulae provided by Homebrew core.
@@ -8,13 +9,9 @@ require "readall"
# {#user} represents Github username and {#repo} represents repository
# name without leading `homebrew-`.
class Tap
- TAP_DIRECTORY = HOMEBREW_LIBRARY/"Taps"
-
- CACHE = {}
+ extend Cachable
- def self.clear_cache
- CACHE.clear
- end
+ TAP_DIRECTORY = HOMEBREW_LIBRARY/"Taps"
def self.fetch(*args)
case args.length
@@ -38,7 +35,7 @@ class Tap
end
cache_key = "#{user}/#{repo}".downcase
- CACHE.fetch(cache_key) { |key| CACHE[key] = Tap.new(user, repo) }
+ cache.fetch(cache_key) { |key| cache[key] = Tap.new(user, repo) }
end
def self.from_path(path)
@@ -551,11 +548,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
@@ -650,6 +645,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.rb b/Library/Homebrew/test.rb
index d9ec8250e..3d5e62a88 100644
--- a/Library/Homebrew/test.rb
+++ b/Library/Homebrew/test.rb
@@ -27,7 +27,7 @@ begin
Timeout.timeout TEST_TIMEOUT_SECONDS do
raise "test returned false" if formula.run_test == false
end
-rescue Exception => e
+rescue Exception => e # rubocop:disable Lint/RescueException
Marshal.dump(e, error_pipe)
error_pipe.close
exit! 1
diff --git a/Library/Homebrew/test/Gemfile b/Library/Homebrew/test/Gemfile
index dbe76b51c..b6d1405ff 100644
--- a/Library/Homebrew/test/Gemfile
+++ b/Library/Homebrew/test/Gemfile
@@ -1,10 +1,12 @@
source "https://rubygems.org"
+require_relative "../constants"
+
gem "parallel_tests"
gem "rspec"
gem "rspec-its", require: false
gem "rspec-wait", require: false
-gem "rubocop"
+gem "rubocop", HOMEBREW_RUBOCOP_VERSION
group :coverage do
gem "codecov", require: false
diff --git a/Library/Homebrew/test/Gemfile.lock b/Library/Homebrew/test/Gemfile.lock
index ccfd91542..ba12d091d 100644
--- a/Library/Homebrew/test/Gemfile.lock
+++ b/Library/Homebrew/test/Gemfile.lock
@@ -9,15 +9,15 @@ GEM
diff-lcs (1.3)
docile (1.1.5)
json (2.1.0)
- parallel (1.11.2)
- parallel_tests (2.14.1)
+ parallel (1.12.0)
+ parallel_tests (2.17.0)
parallel
parser (2.4.0.0)
ast (~> 2.2)
powerpack (0.1.1)
rainbow (2.2.2)
rake
- rake (12.0.0)
+ rake (12.1.0)
rspec (3.6.0)
rspec-core (~> 3.6.0)
rspec-expectations (~> 3.6.0)
@@ -36,20 +36,20 @@ GEM
rspec-support (3.6.0)
rspec-wait (0.0.9)
rspec (>= 3, < 4)
- rubocop (0.49.1)
+ rubocop (0.50.0)
parallel (~> 1.10)
parser (>= 2.3.3.1, < 3.0)
powerpack (~> 0.1)
- rainbow (>= 1.99.1, < 3.0)
+ rainbow (>= 2.2.2, < 3.0)
ruby-progressbar (~> 1.7)
unicode-display_width (~> 1.0, >= 1.0.1)
- ruby-progressbar (1.8.1)
- simplecov (0.14.1)
+ ruby-progressbar (1.9.0)
+ simplecov (0.15.1)
docile (~> 1.1.0)
json (>= 1.8, < 3)
simplecov-html (~> 0.10.0)
- simplecov-html (0.10.0)
- unicode-display_width (1.2.1)
+ simplecov-html (0.10.2)
+ unicode-display_width (1.3.0)
url (0.3.2)
PLATFORMS
@@ -61,8 +61,8 @@ DEPENDENCIES
rspec
rspec-its
rspec-wait
- rubocop
+ rubocop (= 0.50.0)
simplecov
BUNDLED WITH
- 1.14.6
+ 1.15.4
diff --git a/Library/Homebrew/test/bottle_hooks_spec.rb b/Library/Homebrew/test/bottle_hooks_spec.rb
index e70b558a1..eb6617380 100644
--- a/Library/Homebrew/test/bottle_hooks_spec.rb
+++ b/Library/Homebrew/test/bottle_hooks_spec.rb
@@ -8,7 +8,7 @@ describe Homebrew::Hooks::Bottles do
let(:formula) do
double(
- bottle: nil,
+ bottled?: false,
local_bottle_path: nil,
bottle_disabled?: false,
some_random_method: true,
diff --git a/Library/Homebrew/test/cask/accessibility_spec.rb b/Library/Homebrew/test/cask/accessibility_spec.rb
index 9e56f6bd3..b77bcb002 100644
--- a/Library/Homebrew/test/cask/accessibility_spec.rb
+++ b/Library/Homebrew/test/cask/accessibility_spec.rb
@@ -1,7 +1,7 @@
# TODO: this test should be named after the corresponding class, once
# that class is abstracted from installer.rb.
describe "Accessibility Access", :cask do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-accessibility-access.rb") }
+ let(:cask) { Hbc::CaskLoader.load(cask_path("with-accessibility-access")) }
let(:fake_system_command) { class_double(Hbc::SystemCommand) }
let(:installer) { Hbc::Installer.new(cask, command: fake_system_command) }
diff --git a/Library/Homebrew/test/cask/artifact/alt_target_spec.rb b/Library/Homebrew/test/cask/artifact/alt_target_spec.rb
index 9e8d83bb4..847bf25fa 100644
--- a/Library/Homebrew/test/cask/artifact/alt_target_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/alt_target_spec.rb
@@ -1,9 +1,13 @@
describe Hbc::Artifact::App, :cask do
describe "activate to alternate target" do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-alt-target.rb") }
+ let(:cask) { Hbc::CaskLoader.load(cask_path("with-alt-target")) }
let(:install_phase) {
- -> { Hbc::Artifact::App.new(cask).install_phase }
+ lambda do
+ cask.artifacts.select { |a| a.is_a?(described_class) }.each do |artifact|
+ artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false)
+ end
+ end
}
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..4ead8b7f9 100644
--- a/Library/Homebrew/test/cask/artifact/app_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/app_spec.rb
@@ -1,14 +1,14 @@
describe Hbc::Artifact::App, :cask do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb") }
+ let(:cask) { Hbc::CaskLoader.load(cask_path("local-caffeine")) }
let(:command) { Hbc::SystemCommand }
let(:force) { false }
- let(:app) { Hbc::Artifact::App.new(cask, command: command, force: force) }
+ let(:app) { cask.artifacts.find { |a| a.is_a?(described_class) } }
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..6a3f1da34 100644
--- a/Library/Homebrew/test/cask/artifact/binary_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/binary_spec.rb
@@ -1,9 +1,10 @@
describe Hbc::Artifact::Binary, :cask do
let(:cask) {
- Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-binary.rb").tap do |cask|
+ Hbc::CaskLoader.load(cask_path("with-binary")).tap do |cask|
InstallHelper.install_without_artifacts(cask)
end
}
+ let(:artifacts) { cask.artifacts.select { |a| a.is_a?(described_class) } }
let(:expected_path) { Hbc.binarydir.join("binary") }
before(:each) do
@@ -16,7 +17,7 @@ describe Hbc::Artifact::Binary, :cask do
context "when --no-binaries is specified" do
let(:cask) {
- Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-binary.rb")
+ Hbc::CaskLoader.load(cask_path("with-binary"))
}
it "doesn't link the binary when --no-binaries is specified" do
@@ -26,7 +27,9 @@ describe Hbc::Artifact::Binary, :cask do
end
it "links the binary to the proper directory" do
- Hbc::Artifact::Binary.new(cask).install_phase
+ artifacts.each do |artifact|
+ artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false)
+ end
expect(expected_path).to be_a_symlink
expect(expected_path.readlink).to exist
@@ -34,7 +37,7 @@ describe Hbc::Artifact::Binary, :cask do
context "when the binary is not executable" do
let(:cask) {
- Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-non-executable-binary.rb").tap do |cask|
+ Hbc::CaskLoader.load(cask_path("with-non-executable-binary")).tap do |cask|
InstallHelper.install_without_artifacts(cask)
end
}
@@ -45,7 +48,9 @@ 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
+ artifacts.each do |artifact|
+ artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false)
+ end
expect(expected_path).to be_a_symlink
expect(expected_path.readlink).to be_executable
@@ -56,7 +61,9 @@ describe Hbc::Artifact::Binary, :cask do
FileUtils.touch expected_path
expect {
- Hbc::Artifact::Binary.new(cask).install_phase
+ artifacts.each do |artifact|
+ artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false)
+ end
}.to raise_error(Hbc::CaskError)
expect(expected_path).not_to be :symlink?
@@ -65,7 +72,9 @@ describe Hbc::Artifact::Binary, :cask do
it "clobbers an existing symlink" do
expected_path.make_symlink("/tmp")
- Hbc::Artifact::Binary.new(cask).install_phase
+ artifacts.each do |artifact|
+ artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false)
+ end
expect(File.readlink(expected_path)).not_to eq("/tmp")
end
@@ -73,21 +82,27 @@ 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
+ artifacts.each do |artifact|
+ artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false)
+ end
expect(expected_path.exist?).to be true
end
context "binary is inside an app package" do
let(:cask) {
- Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-embedded-binary.rb").tap do |cask|
+ Hbc::CaskLoader.load(cask_path("with-embedded-binary")).tap do |cask|
InstallHelper.install_without_artifacts(cask)
end
}
it "links the binary to the proper directory" do
- Hbc::Artifact::App.new(cask).install_phase
- Hbc::Artifact::Binary.new(cask).install_phase
+ cask.artifacts.select { |a| a.is_a?(Hbc::Artifact::App) }.each do |artifact|
+ artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false)
+ end
+ artifacts.each do |artifact|
+ artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false)
+ end
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..ea567abee 100644
--- a/Library/Homebrew/test/cask/artifact/generic_artifact_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/generic_artifact_spec.rb
@@ -1,8 +1,12 @@
describe Hbc::Artifact::Artifact, :cask do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-generic-artifact.rb") }
+ let(:cask) { Hbc::CaskLoader.load(cask_path("with-generic-artifact")) }
let(:install_phase) {
- -> { Hbc::Artifact::Artifact.new(cask).install_phase }
+ lambda do
+ cask.artifacts.select { |a| a.is_a?(described_class) }.each do |artifact|
+ artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false)
+ end
+ end
}
let(:source_path) { cask.staged_path.join("Caffeine.app") }
@@ -12,11 +16,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(cask_path("with-generic-artifact-no-target"))
+ }.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..f9cd056f8 100644
--- a/Library/Homebrew/test/cask/artifact/nested_container_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/nested_container_spec.rb
@@ -1,11 +1,13 @@
describe Hbc::Artifact::NestedContainer, :cask do
describe "install" do
it "extracts the specified paths as containers" do
- cask = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/nested-app.rb").tap do |c|
+ cask = Hbc::CaskLoader.load(cask_path("nested-app")).tap do |c|
InstallHelper.install_without_artifacts(c)
end
- Hbc::Artifact::NestedContainer.new(cask).install_phase
+ cask.artifacts.select { |a| a.is_a?(described_class) }.each do |artifact|
+ artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false)
+ end
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..7f1b64d1a 100644
--- a/Library/Homebrew/test/cask/artifact/pkg_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/pkg_spec.rb
@@ -1,5 +1,5 @@
describe Hbc::Artifact::Pkg, :cask do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-installable.rb") }
+ let(:cask) { Hbc::CaskLoader.load(cask_path("with-installable")) }
let(:fake_system_command) { class_double(Hbc::SystemCommand) }
before(:each) do
@@ -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 = cask.artifacts.find { |a| a.is_a?(described_class) }
expect(fake_system_command).to receive(:run!).with(
"/usr/sbin/installer",
@@ -17,15 +17,15 @@ describe Hbc::Artifact::Pkg, :cask do
print_stdout: true,
)
- pkg.install_phase
+ pkg.install_phase(command: fake_system_command)
end
end
describe "choices" do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-choices.rb") }
+ let(:cask) { Hbc::CaskLoader.load(cask_path("with-choices")) }
it "passes the choice changes xml to the system installer" do
- pkg = Hbc::Artifact::Pkg.new(cask, command: fake_system_command)
+ pkg = cask.artifacts.find { |a| a.is_a?(described_class) }
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..18cc4ca91 100644
--- a/Library/Homebrew/test/cask/artifact/postflight_block_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/postflight_block_spec.rb
@@ -11,7 +11,9 @@ describe Hbc::Artifact::PostflightBlock, :cask do
end
end
- described_class.new(cask).install_phase
+ cask.artifacts.select { |a| a.is_a?(described_class) }.each do |artifact|
+ artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false)
+ end
expect(called).to be true
expect(yielded_arg).to be_kind_of(Hbc::DSL::Postflight)
@@ -30,7 +32,9 @@ describe Hbc::Artifact::PostflightBlock, :cask do
end
end
- described_class.new(cask).uninstall_phase
+ cask.artifacts.select { |a| a.is_a?(described_class) }.each do |artifact|
+ artifact.uninstall_phase(command: Hbc::NeverSudoSystemCommand, force: false)
+ end
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..405cdbd6f 100644
--- a/Library/Homebrew/test/cask/artifact/preflight_block_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/preflight_block_spec.rb
@@ -11,7 +11,9 @@ describe Hbc::Artifact::PreflightBlock, :cask do
end
end
- described_class.new(cask).install_phase
+ cask.artifacts.select { |a| a.is_a?(described_class) }.each do |artifact|
+ artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false)
+ end
expect(called).to be true
expect(yielded_arg).to be_kind_of Hbc::DSL::Preflight
@@ -30,7 +32,9 @@ describe Hbc::Artifact::PreflightBlock, :cask do
end
end
- described_class.new(cask).uninstall_phase
+ cask.artifacts.select { |a| a.is_a?(described_class) }.each do |artifact|
+ artifact.uninstall_phase(command: Hbc::NeverSudoSystemCommand, force: false)
+ end
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..80d3e917f 100644
--- a/Library/Homebrew/test/cask/artifact/suite_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/suite_spec.rb
@@ -1,7 +1,13 @@
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(:cask) { Hbc::CaskLoader.load(cask_path("with-suite")) }
+
+ let(:install_phase) {
+ lambda do
+ cask.artifacts.select { |a| a.is_a?(described_class) }.each do |artifact|
+ artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false)
+ end
+ end
+ }
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..7f2ef75b3 100644
--- a/Library/Homebrew/test/cask/artifact/two_apps_correct_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/two_apps_correct_spec.rb
@@ -1,9 +1,13 @@
describe Hbc::Artifact::App, :cask do
describe "multiple apps" do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-two-apps-correct.rb") }
+ let(:cask) { Hbc::CaskLoader.load(cask_path("with-two-apps-correct")) }
let(:install_phase) {
- -> { Hbc::Artifact::App.new(cask).install_phase }
+ lambda do
+ cask.artifacts.select { |a| a.is_a?(described_class) }.each do |artifact|
+ artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false)
+ end
+ end
}
let(:source_path_mini) { cask.staged_path.join("Caffeine Mini.app") }
@@ -27,7 +31,7 @@ describe Hbc::Artifact::App, :cask do
end
describe "when apps are in a subdirectory" do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-two-apps-subdir.rb") }
+ let(:cask) { Hbc::CaskLoader.load(cask_path("with-two-apps-subdir")) }
it "installs both apps using the proper target directory" do
install_phase.call
diff --git a/Library/Homebrew/test/cask/artifact/two_apps_incorrect_spec.rb b/Library/Homebrew/test/cask/artifact/two_apps_incorrect_spec.rb
index 6427ec32c..cda5b4488 100644
--- a/Library/Homebrew/test/cask/artifact/two_apps_incorrect_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/two_apps_incorrect_spec.rb
@@ -2,7 +2,7 @@ describe Hbc::Artifact::App, :cask do
# FIXME: Doesn't actually raise because the `app` stanza is not evaluated on load.
# it "must raise" do
# lambda {
- # Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-two-apps-incorrect.rb")
+ # Hbc::CaskLoader.load(cask_path("with-two-apps-incorrect"))
# }.must_raise
# # TODO: later give the user a nice exception for this case and check for it here
# end
diff --git a/Library/Homebrew/test/cask/artifact/uninstall_no_zap_spec.rb b/Library/Homebrew/test/cask/artifact/uninstall_no_zap_spec.rb
index 8cd0b1e41..c6ff7d30e 100644
--- a/Library/Homebrew/test/cask/artifact/uninstall_no_zap_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/uninstall_no_zap_spec.rb
@@ -1,8 +1,8 @@
describe Hbc::Artifact::Zap, :cask do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-installable.rb") }
+ let(:cask) { Hbc::CaskLoader.load(cask_path("with-installable")) }
let(:zap_artifact) {
- Hbc::Artifact::Zap.new(cask)
+ cask.artifacts.find { |a| a.is_a?(described_class) }
}
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..b9872ab9e 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) { cask.artifacts.find { |a| a.is_a?(described_class) } }
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(cask_path("with-#{artifact_dsl_key}-launchctl")) }
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(cask_path("with-#{artifact_dsl_key}-pkgutil")) }
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(cask_path("with-#{artifact_dsl_key}-kext")) }
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(cask_path("with-#{artifact_dsl_key}-quit")) }
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(cask_path("with-#{artifact_dsl_key}-signal")) }
let(:bundle_id) { "my.fancy.package.app" }
let(:signals) { %w[TERM KILL] }
let(:unix_pids) { [12_345, 67_890] }
@@ -149,6 +149,8 @@ shared_examples "#uninstall_phase or #zap_phase" do
end
[:delete, :trash].each do |directive|
+ next if directive == :trash && ENV["HOMEBREW_TESTS_COVERAGE"].nil?
+
context "using :#{directive}" do
let(:dir) { TEST_TMPDIR }
let(:absolute_path) { Pathname.new("#{dir}/absolute_path") }
@@ -170,10 +172,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(cask_path("with-#{artifact_dsl_key}-#{directive}")) }
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 +198,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(cask_path("with-#{artifact_dsl_key}-rmdir")) }
let(:empty_directory) { Pathname.new("#{TEST_TMPDIR}/empty_directory_path") }
let(:ds_store) { empty_directory.join(".DS_Store") }
@@ -223,8 +225,8 @@ 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(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/#{token}.rb") }
+ let(:token) { "with-#{artifact_dsl_key}-#{script_type}".tr("_", "-") }
+ let(:cask) { Hbc::CaskLoader.load(cask_path(token.to_s)) }
let(:script_pathname) { cask.staged_path.join("MyFancyPkg", "FancyUninstaller.tool") }
it "is supported" do
@@ -250,7 +252,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(cask_path("with-#{artifact_dsl_key}-login-item")) }
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_loader/from_content_loader_spec.rb b/Library/Homebrew/test/cask/cask_loader/from_content_loader_spec.rb
new file mode 100644
index 000000000..e735d5eca
--- /dev/null
+++ b/Library/Homebrew/test/cask/cask_loader/from_content_loader_spec.rb
@@ -0,0 +1,57 @@
+describe Hbc::CaskLoader::FromContentLoader do
+ alias_matcher :be_able_to_load, :be_can_load
+
+ describe "::can_load?" do
+ it "returns true for Casks specified with `cask \"token\" do … end`" do
+ expect(described_class).to be_able_to_load <<~EOS
+ cask "token" do
+ end
+ EOS
+ end
+
+ it "returns true for Casks specified with `cask \"token\" do; end`" do
+ expect(described_class).to be_able_to_load <<~EOS
+ cask "token" do; end
+ EOS
+ end
+
+ it "returns true for Casks specified with `cask 'token' do … end`" do
+ expect(described_class).to be_able_to_load <<~EOS
+ cask 'token' do
+ end
+ EOS
+ end
+
+ it "returns true for Casks specified with `cask 'token' do; end`" do
+ expect(described_class).to be_able_to_load <<~EOS
+ cask 'token' do; end
+ EOS
+ end
+
+ it "returns true for Casks specified with `cask(\"token\") { … }`" do
+ expect(described_class).to be_able_to_load <<~EOS
+ cask("token") {
+ }
+ EOS
+ end
+
+ it "returns true for Casks specified with `cask(\"token\") {}`" do
+ expect(described_class).to be_able_to_load <<~EOS
+ cask("token") {}
+ EOS
+ end
+
+ it "returns true for Casks specified with `cask('token') { … }`" do
+ expect(described_class).to be_able_to_load <<~EOS
+ cask('token') {
+ }
+ EOS
+ end
+
+ it "returns true for Casks specified with `cask('token') {}`" do
+ expect(described_class).to be_able_to_load <<~EOS
+ cask('token') {}
+ EOS
+ end
+ end
+end
diff --git a/Library/Homebrew/test/cask/cask_loader/from_uri_loader_spec.rb b/Library/Homebrew/test/cask/cask_loader/from_uri_loader_spec.rb
new file mode 100644
index 000000000..df2de1f82
--- /dev/null
+++ b/Library/Homebrew/test/cask/cask_loader/from_uri_loader_spec.rb
@@ -0,0 +1,21 @@
+describe Hbc::CaskLoader::FromURILoader do
+ alias_matcher :be_able_to_load, :be_can_load
+
+ describe "::can_load?" do
+ it "returns true when given an URI" do
+ expect(described_class).to be_able_to_load(URI("http://example.com/"))
+ end
+
+ it "returns true when given a String which can be parsed to a URI" do
+ expect(described_class).to be_able_to_load("http://example.com/")
+ end
+
+ it "returns false when given a String with Cask contents containing a URL" do
+ expect(described_class).not_to be_able_to_load <<~EOS
+ cask 'token' do
+ url 'http://example.com/'
+ end
+ EOS
+ end
+ 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..da8bf1273 100644
--- a/Library/Homebrew/test/cask/cli/audit_spec.rb
+++ b/Library/Homebrew/test/cask/cli/audit_spec.rb
@@ -1,13 +1,19 @@
+require_relative "shared_examples/invalid_option"
+
describe Hbc::CLI::Audit, :cask do
- let(:cask) { double("cask", token: nil) }
+ let(:cask) { Hbc::Cask.new(nil) }
+
+ it_behaves_like "a command that handles invalid options"
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)
- Hbc::CLI::Audit.run
+ described_class.run
end
it "audits specified Casks if tokens are given" do
@@ -18,7 +24,7 @@ describe Hbc::CLI::Audit, :cask do
.with(cask, audit_download: false, check_token_conflicts: false)
.and_return(true)
- Hbc::CLI::Audit.run(cask_token)
+ described_class.run(cask_token)
end
end
@@ -29,7 +35,7 @@ describe Hbc::CLI::Audit, :cask do
.with(cask, audit_download: false, check_token_conflicts: false)
.and_return(true)
- Hbc::CLI::Audit.run("casktoken")
+ described_class.run("casktoken")
end
it "download a Cask if --download flag is set" do
@@ -38,7 +44,7 @@ describe Hbc::CLI::Audit, :cask do
.with(cask, audit_download: true, check_token_conflicts: false)
.and_return(true)
- Hbc::CLI::Audit.run("casktoken", "--download")
+ described_class.run("casktoken", "--download")
end
end
@@ -49,7 +55,7 @@ describe Hbc::CLI::Audit, :cask do
.with(cask, audit_download: false, check_token_conflicts: false)
.and_return(true)
- Hbc::CLI::Audit.run("casktoken")
+ described_class.run("casktoken")
end
it "checks for token conflicts if --token-conflicts flag is set" do
@@ -58,7 +64,7 @@ describe Hbc::CLI::Audit, :cask do
.with(cask, audit_download: false, check_token_conflicts: true)
.and_return(true)
- Hbc::CLI::Audit.run("casktoken", "--token-conflicts")
+ described_class.run("casktoken", "--token-conflicts")
end
end
end
diff --git a/Library/Homebrew/test/cask/cli/cat_spec.rb b/Library/Homebrew/test/cask/cli/cat_spec.rb
index b726a0b36..6b54a2e4b 100644
--- a/Library/Homebrew/test/cask/cli/cat_spec.rb
+++ b/Library/Homebrew/test/cask/cli/cat_spec.rb
@@ -1,4 +1,10 @@
+require_relative "shared_examples/requires_cask_token"
+require_relative "shared_examples/invalid_option"
+
describe Hbc::CLI::Cat, :cask do
+ it_behaves_like "a command that requires a Cask token"
+ it_behaves_like "a command that handles invalid options"
+
describe "given a basic Cask" do
let(:basic_cask_content) {
<<-EOS.undent
@@ -16,42 +22,19 @@ describe Hbc::CLI::Cat, :cask do
it "displays the Cask file content about the specified Cask" do
expect {
- Hbc::CLI::Cat.run("basic-cask")
+ described_class.run("basic-cask")
}.to output(basic_cask_content).to_stdout
end
it "can display multiple Casks" do
expect {
- Hbc::CLI::Cat.run("basic-cask", "basic-cask")
+ described_class.run("basic-cask", "basic-cask")
}.to output(basic_cask_content * 2).to_stdout
end
-
- it "fails when option is unknown" do
- expect {
- Hbc::CLI::Cat.run("--notavalidoption", "basic-cask")
- }.to raise_error(/invalid option/)
- end
end
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.")
- end
-
- describe "when no Cask is specified" do
- it "raises an exception" do
- expect {
- Hbc::CLI::Cat.run
- }.to raise_error(Hbc::CaskUnspecifiedError)
- end
- end
-
- describe "when no Cask is specified, but an invalid option" do
- it "raises an exception" do
- expect {
- Hbc::CLI::Cat.run("--notavalidoption")
- }.to raise_error(/invalid option/)
- end
+ expect { described_class.run("notacask") }
+ .to raise_error(Hbc::CaskUnavailableError, /is unavailable/)
end
end
diff --git a/Library/Homebrew/test/cask/cli/cleanup_spec.rb b/Library/Homebrew/test/cask/cli/cleanup_spec.rb
index 64e3ef49f..7cf00352d 100644
--- a/Library/Homebrew/test/cask/cli/cleanup_spec.rb
+++ b/Library/Homebrew/test/cask/cli/cleanup_spec.rb
@@ -1,3 +1,5 @@
+require_relative "shared_examples/invalid_option"
+
describe Hbc::CLI::Cleanup, :cask do
let(:cache_location) { Pathname.new(Dir.mktmpdir).realpath }
let(:outdated_only) { false }
@@ -12,6 +14,8 @@ describe Hbc::CLI::Cleanup, :cask do
cache_location.rmtree
end
+ it_behaves_like "a command that handles invalid options"
+
describe "cleanup" do
let(:cask_token) { "caffeine" }
let(:cask_tokens) { [cask_token] }
diff --git a/Library/Homebrew/test/cask/cli/create_spec.rb b/Library/Homebrew/test/cask/cli/create_spec.rb
index d77b0a2aa..60c03db75 100644
--- a/Library/Homebrew/test/cask/cli/create_spec.rb
+++ b/Library/Homebrew/test/cask/cli/create_spec.rb
@@ -1,3 +1,6 @@
+require_relative "shared_examples/requires_cask_token"
+require_relative "shared_examples/invalid_option"
+
describe Hbc::CLI::Create, :cask do
around(:each) do |example|
begin
@@ -13,6 +16,9 @@ describe Hbc::CLI::Create, :cask do
allow_any_instance_of(described_class).to receive(:exec_editor)
end
+ it_behaves_like "a command that requires a Cask token"
+ it_behaves_like "a command that handles invalid options"
+
it "opens the editor for the specified Cask" do
command = described_class.new("new-cask")
expect(command).to receive(:exec_editor).with(Hbc::CaskLoader.path("new-cask"))
@@ -39,7 +45,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
@@ -53,26 +59,4 @@ describe Hbc::CLI::Create, :cask do
expect(command).to receive(:exec_editor).with(Hbc::CaskLoader.path("local-caff"))
command.run
end
-
- describe "when no Cask is specified" do
- it "raises an exception" do
- expect {
- described_class.run
- }.to raise_error(Hbc::CaskUnspecifiedError)
- end
- end
-
- context "when an invalid option is specified" do
- it "raises an exception when no Cask is specified" do
- expect {
- described_class.run("--notavalidoption")
- }.to raise_error(/invalid option/)
- end
-
- it "raises an exception" do
- expect {
- described_class.run("--notavalidoption", "yet-another-cask")
- }.to raise_error(/invalid option/)
- end
- end
end
diff --git a/Library/Homebrew/test/cask/cli/doctor_spec.rb b/Library/Homebrew/test/cask/cli/doctor_spec.rb
index b24c777eb..e3967060e 100644
--- a/Library/Homebrew/test/cask/cli/doctor_spec.rb
+++ b/Library/Homebrew/test/cask/cli/doctor_spec.rb
@@ -1,4 +1,8 @@
+require_relative "shared_examples/invalid_option"
+
describe Hbc::CLI::Doctor, :cask do
+ it_behaves_like "a command that handles invalid options"
+
it "displays some nice info about the environment" do
expect {
Hbc::CLI::Doctor.run
diff --git a/Library/Homebrew/test/cask/cli/edit_spec.rb b/Library/Homebrew/test/cask/cli/edit_spec.rb
index 5d5cbf4b9..347522020 100644
--- a/Library/Homebrew/test/cask/cli/edit_spec.rb
+++ b/Library/Homebrew/test/cask/cli/edit_spec.rb
@@ -1,8 +1,14 @@
+require_relative "shared_examples/requires_cask_token"
+require_relative "shared_examples/invalid_option"
+
describe Hbc::CLI::Edit, :cask do
before(:each) do
allow_any_instance_of(described_class).to receive(:exec_editor)
end
+ it_behaves_like "a command that requires a Cask token"
+ it_behaves_like "a command that handles invalid options"
+
it "opens the editor for the specified Cask" do
command = described_class.new("local-caffeine")
expect(command).to receive(:exec_editor).with(Hbc::CaskLoader.path("local-caffeine"))
@@ -12,7 +18,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
@@ -20,20 +26,4 @@ describe Hbc::CLI::Edit, :cask do
described_class.run("notacask")
}.to raise_error(Hbc::CaskUnavailableError)
end
-
- describe "when no Cask is specified" do
- it "raises an exception" do
- expect {
- described_class.run
- }.to raise_error(Hbc::CaskUnspecifiedError)
- end
- end
-
- describe "when no Cask is specified, but an invalid option" do
- it "raises an exception" do
- expect {
- described_class.run("--notavalidoption")
- }.to raise_error(/invalid option/)
- end
- end
end
diff --git a/Library/Homebrew/test/cask/cli/fetch_spec.rb b/Library/Homebrew/test/cask/cli/fetch_spec.rb
index f71c23fb6..67cf6e61d 100644
--- a/Library/Homebrew/test/cask/cli/fetch_spec.rb
+++ b/Library/Homebrew/test/cask/cli/fetch_spec.rb
@@ -1,14 +1,20 @@
+require_relative "shared_examples/requires_cask_token"
+require_relative "shared_examples/invalid_option"
+
describe Hbc::CLI::Fetch, :cask do
let(:local_transmission) {
- Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb")
+ Hbc::CaskLoader.load(cask_path("local-transmission"))
}
let(:local_caffeine) {
- Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb")
+ Hbc::CaskLoader.load(cask_path("local-caffeine"))
}
+ it_behaves_like "a command that requires a Cask token"
+ it_behaves_like "a command that handles invalid options"
+
it "allows download the installer of a Cask" do
- Hbc::CLI::Fetch.run("local-transmission", "local-caffeine")
+ described_class.run("local-transmission", "local-caffeine")
expect(Hbc::CurlDownloadStrategy.new(local_transmission).cached_location).to exist
expect(Hbc::CurlDownloadStrategy.new(local_caffeine).cached_location).to exist
end
@@ -19,7 +25,7 @@ describe Hbc::CLI::Fetch, :cask do
Hbc::Download.new(local_transmission).perform
old_ctime = File.stat(download_stategy.cached_location).ctime
- Hbc::CLI::Fetch.run("local-transmission")
+ described_class.run("local-transmission")
new_ctime = File.stat(download_stategy.cached_location).ctime
expect(old_ctime.to_i).to eq(new_ctime.to_i)
@@ -32,7 +38,7 @@ describe Hbc::CLI::Fetch, :cask do
old_ctime = File.stat(download_stategy.cached_location).ctime
sleep(1)
- Hbc::CLI::Fetch.run("local-transmission", "--force")
+ described_class.run("local-transmission", "--force")
download_stategy = Hbc::CurlDownloadStrategy.new(local_transmission)
new_ctime = File.stat(download_stategy.cached_location).ctime
@@ -41,23 +47,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.")
- end
-
- describe "when no Cask is specified" do
- it "raises an exception" do
- expect {
- Hbc::CLI::Fetch.run
- }.to raise_error(Hbc::CaskUnspecifiedError)
- end
- end
-
- describe "when no Cask is specified, but an invalid option" do
- it "raises an exception" do
- expect {
- Hbc::CLI::Fetch.run("--notavalidoption")
- }.to raise_error(/invalid option/)
- end
+ described_class.run("notacask")
+ }.to raise_error(Hbc::CaskUnavailableError)
end
end
diff --git a/Library/Homebrew/test/cask/cli/home_spec.rb b/Library/Homebrew/test/cask/cli/home_spec.rb
index e985fb6cd..8960d2acc 100644
--- a/Library/Homebrew/test/cask/cli/home_spec.rb
+++ b/Library/Homebrew/test/cask/cli/home_spec.rb
@@ -1,8 +1,12 @@
+require_relative "shared_examples/invalid_option"
+
describe Hbc::CLI::Home, :cask do
before do
allow(described_class).to receive(:open_url)
end
+ it_behaves_like "a command that handles invalid options"
+
it "opens the homepage for the specified Cask" do
expect(described_class).to receive(:open_url).with("http://example.com/local-caffeine")
described_class.run("local-caffeine")
diff --git a/Library/Homebrew/test/cask/cli/info_spec.rb b/Library/Homebrew/test/cask/cli/info_spec.rb
index bffe900ec..e24eead11 100644
--- a/Library/Homebrew/test/cask/cli/info_spec.rb
+++ b/Library/Homebrew/test/cask/cli/info_spec.rb
@@ -1,7 +1,13 @@
+require_relative "shared_examples/requires_cask_token"
+require_relative "shared_examples/invalid_option"
+
describe Hbc::CLI::Info, :cask do
+ it_behaves_like "a command that requires a Cask token"
+ it_behaves_like "a command that handles invalid options"
+
it "displays some nice info about the specified Cask" do
expect {
- Hbc::CLI::Info.run("local-caffeine")
+ described_class.run("local-caffeine")
}.to output(<<-EOS.undent).to_stdout
local-caffeine: 1.2.3
http://example.com/local-caffeine
@@ -10,7 +16,7 @@ describe Hbc::CLI::Info, :cask do
==> Name
None
==> Artifacts
- Caffeine.app (app)
+ Caffeine.app (App)
EOS
end
@@ -24,7 +30,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,26 +38,20 @@ describe Hbc::CLI::Info, :cask do
==> Name
None
==> Artifacts
- Transmission.app (app)
+ Transmission.app (App)
EOS
}
it "displays the info" do
expect {
- Hbc::CLI::Info.run("local-caffeine", "local-transmission")
+ described_class.run("local-caffeine", "local-transmission")
}.to output(expected_output).to_stdout
end
-
- it "throws away stray options" do
- expect {
- Hbc::CLI::Info.run("--notavalidoption", "local-caffeine", "local-transmission")
- }.to raise_error(/invalid option/)
- end
end
it "should print caveats if the Cask provided one" do
expect {
- Hbc::CLI::Info.run("with-caveats")
+ described_class.run("with-caveats")
}.to output(<<-EOS.undent).to_stdout
with-caveats: 1.2.3
http://example.com/local-caffeine
@@ -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.
@@ -77,7 +77,7 @@ describe Hbc::CLI::Info, :cask do
it 'should not print "Caveats" section divider if the caveats block has no output' do
expect {
- Hbc::CLI::Info.run("with-conditional-caveats")
+ described_class.run("with-conditional-caveats")
}.to output(<<-EOS.undent).to_stdout
with-conditional-caveats: 1.2.3
http://example.com/local-caffeine
@@ -86,23 +86,39 @@ describe Hbc::CLI::Info, :cask do
==> Name
None
==> Artifacts
- Caffeine.app (app)
+ Caffeine.app (App)
EOS
end
- describe "when no Cask is specified" do
- it "raises an exception" do
- expect {
- Hbc::CLI::Info.run
- }.to raise_error(Hbc::CaskUnspecifiedError)
- end
+ it "prints languages specified in the Cask" do
+ expect {
+ described_class.run("with-languages")
+ }.to output(<<-EOS.undent).to_stdout
+ with-languages: 1.2.3
+ http://example.com/local-caffeine
+ Not installed
+ From: https://github.com/caskroom/homebrew-spec/blob/master/Casks/with-languages.rb
+ ==> Name
+ None
+ ==> Languages
+ zh, en-US
+ ==> Artifacts
+ Caffeine.app (App)
+ EOS
end
- describe "when no Cask is specified, but an invalid option" do
- it "raises an exception" do
- expect {
- Hbc::CLI::Info.run("--notavalidoption")
- }.to raise_error(/invalid option/)
- end
+ it 'does not print "Languages" section divider if the languages block has no output' do
+ expect {
+ described_class.run("without-languages")
+ }.to output(<<-EOS.undent).to_stdout
+ without-languages: 1.2.3
+ http://example.com/local-caffeine
+ Not installed
+ From: https://github.com/caskroom/homebrew-spec/blob/master/Casks/without-languages.rb
+ ==> Name
+ None
+ ==> Artifacts
+ Caffeine.app (App)
+ EOS
end
end
diff --git a/Library/Homebrew/test/cask/cli/install_spec.rb b/Library/Homebrew/test/cask/cli/install_spec.rb
index 64feacce9..c918a3529 100644
--- a/Library/Homebrew/test/cask/cli/install_spec.rb
+++ b/Library/Homebrew/test/cask/cli/install_spec.rb
@@ -1,4 +1,10 @@
+require_relative "shared_examples/requires_cask_token"
+require_relative "shared_examples/invalid_option"
+
describe Hbc::CLI::Install, :cask do
+ it_behaves_like "a command that requires a Cask token"
+ it_behaves_like "a command that handles invalid options"
+
it "displays the installation progress" do
output = Regexp.new <<-EOS.undent
==> Downloading file:.*caffeine.zip
@@ -9,103 +15,65 @@ describe Hbc::CLI::Install, :cask do
EOS
expect {
- Hbc::CLI::Install.run("local-caffeine")
+ described_class.run("local-caffeine")
}.to output(output).to_stdout
end
it "allows staging and activation of multiple Casks at once" do
- Hbc::CLI::Install.run("local-transmission", "local-caffeine")
+ described_class.run("local-transmission", "local-caffeine")
- expect(Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb")).to be_installed
+ expect(Hbc::CaskLoader.load(cask_path("local-transmission"))).to be_installed
expect(Hbc.appdir.join("Transmission.app")).to be_a_directory
- expect(Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb")).to be_installed
+ expect(Hbc::CaskLoader.load(cask_path("local-caffeine"))).to be_installed
expect(Hbc.appdir.join("Caffeine.app")).to be_a_directory
end
it "skips double install (without nuking existing installation)" do
- Hbc::CLI::Install.run("local-transmission")
- Hbc::CLI::Install.run("local-transmission")
- expect(Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb")).to be_installed
+ described_class.run("local-transmission")
+ described_class.run("local-transmission")
+ expect(Hbc::CaskLoader.load(cask_path("local-transmission"))).to be_installed
end
it "prints a warning message on double install" do
- Hbc::CLI::Install.run("local-transmission")
+ described_class.run("local-transmission")
expect {
- Hbc::CLI::Install.run("local-transmission")
+ described_class.run("local-transmission")
}.to output(/Warning: Cask 'local-transmission' is already installed./).to_stderr
end
it "allows double install with --force" do
- Hbc::CLI::Install.run("local-transmission")
+ described_class.run("local-transmission")
expect {
expect {
- Hbc::CLI::Install.run("local-transmission", "--force")
+ described_class.run("local-transmission", "--force")
}.to output(/It seems there is already an App at.*overwriting\./).to_stderr
}.to output(/local-transmission was successfully installed!/).to_stdout
end
it "skips dependencies with --skip-cask-deps" do
- Hbc::CLI::Install.run("with-depends-on-cask-multiple", "--skip-cask-deps")
- expect(Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-depends-on-cask-multiple.rb")).to be_installed
- expect(Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb")).not_to be_installed
- expect(Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb")).not_to be_installed
+ described_class.run("with-depends-on-cask-multiple", "--skip-cask-deps")
+ expect(Hbc::CaskLoader.load(cask_path("with-depends-on-cask-multiple"))).to be_installed
+ expect(Hbc::CaskLoader.load(cask_path("local-caffeine"))).not_to be_installed
+ expect(Hbc::CaskLoader.load(cask_path("local-transmission"))).not_to be_installed
end
it "properly handles Casks that are not present" do
expect {
- Hbc::CLI::Install.run("notacask")
- }.to raise_error(Hbc::CaskError, "Install incomplete.")
+ described_class.run("notacask")
+ }.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
+ described_class.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
- end
-
- describe "when no Cask is specified" do
- with_options = lambda do |options|
- it "raises an exception" do
- expect {
- Hbc::CLI::Install.run(*options)
- }.to raise_error(Hbc::CaskUnspecifiedError)
- end
- end
-
- describe "without options" do
- with_options.call([])
- end
-
- describe "with --force" do
- with_options.call(["--force"])
- end
-
- describe "with --skip-cask-deps" do
- with_options.call(["--skip-cask-deps"])
- end
-
- describe "with an invalid option" do
- it "raises an error" do
- expect {
- Hbc::CLI::Install.run("--notavalidoption")
- }.to raise_error(/invalid option/)
- end
- end
+ described_class.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
end
diff --git a/Library/Homebrew/test/cask/cli/list_spec.rb b/Library/Homebrew/test/cask/cli/list_spec.rb
index ecca3035f..301ca9b89 100644
--- a/Library/Homebrew/test/cask/cli/list_spec.rb
+++ b/Library/Homebrew/test/cask/cli/list_spec.rb
@@ -1,4 +1,8 @@
+require_relative "shared_examples/invalid_option"
+
describe Hbc::CLI::List, :cask do
+ it_behaves_like "a command that handles invalid options"
+
it "lists the installed Casks in a pretty fashion" do
casks = %w[local-caffeine local-transmission].map { |c| Hbc::CaskLoader.load(c) }
@@ -7,10 +11,30 @@ describe Hbc::CLI::List, :cask do
end
expect {
- Hbc::CLI::List.run
+ described_class.run
+ }.to output(<<-EOS.undent).to_stdout
+ local-caffeine
+ local-transmission
+ 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 {
+ described_class.run("--full-name")
}.to output(<<-EOS.undent).to_stdout
local-caffeine
local-transmission
+ third-party/tap/third-party-cask
EOS
end
@@ -29,29 +53,31 @@ describe Hbc::CLI::List, :cask do
it "of all installed Casks" do
expect {
- Hbc::CLI::List.run("--versions")
+ described_class.run("--versions")
}.to output(expected_output).to_stdout
end
it "of given Casks" do
expect {
- Hbc::CLI::List.run("--versions", "local-caffeine", "local-transmission")
+ described_class.run("--versions", "local-caffeine", "local-transmission")
}.to output(expected_output).to_stdout
end
end
describe "given a set of installed Casks" do
- let(:caffeine) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb") }
- let(:transmission) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb") }
+ let(:caffeine) { Hbc::CaskLoader.load(cask_path("local-caffeine")) }
+ let(:transmission) { Hbc::CaskLoader.load(cask_path("local-transmission")) }
let(:casks) { [caffeine, transmission] }
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
+ transmission.artifacts.select { |a| a.is_a?(Hbc::Artifact::App) }.each do |artifact|
+ artifact.install_phase(command: Hbc::NeverSudoSystemCommand, force: false)
+ end
expect {
- Hbc::CLI::List.run("local-transmission", "local-caffeine")
+ described_class.run("local-transmission", "local-caffeine")
}.to output(<<-EOS.undent).to_stdout
==> Apps
#{Hbc.appdir.join("Transmission.app")} (#{Hbc.appdir.join("Transmission.app").abv})
diff --git a/Library/Homebrew/test/cask/cli/options_spec.rb b/Library/Homebrew/test/cask/cli/options_spec.rb
index 98eb05f7e..82d830795 100644
--- a/Library/Homebrew/test/cask/cli/options_spec.rb
+++ b/Library/Homebrew/test/cask/cli/options_spec.rb
@@ -1,6 +1,6 @@
describe Hbc::CLI, :cask do
it "supports setting the appdir" do
- Hbc::CLI.new.process_options("help", "--appdir=/some/path/foo")
+ described_class.new.process_options("help", "--appdir=/some/path/foo")
expect(Hbc.appdir).to eq(Pathname.new("/some/path/foo"))
end
@@ -8,13 +8,13 @@ describe Hbc::CLI, :cask do
it "supports setting the appdir from ENV" do
ENV["HOMEBREW_CASK_OPTS"] = "--appdir=/some/path/bar"
- Hbc::CLI.new.process_options("help")
+ described_class.new.process_options("help")
expect(Hbc.appdir).to eq(Pathname.new("/some/path/bar"))
end
it "supports setting the prefpanedir" do
- Hbc::CLI.new.process_options("help", "--prefpanedir=/some/path/foo")
+ described_class.new.process_options("help", "--prefpanedir=/some/path/foo")
expect(Hbc.prefpanedir).to eq(Pathname.new("/some/path/foo"))
end
@@ -22,13 +22,13 @@ describe Hbc::CLI, :cask do
it "supports setting the prefpanedir from ENV" do
ENV["HOMEBREW_CASK_OPTS"] = "--prefpanedir=/some/path/bar"
- Hbc::CLI.new.process_options("help")
+ described_class.new.process_options("help")
expect(Hbc.prefpanedir).to eq(Pathname.new("/some/path/bar"))
end
it "supports setting the qlplugindir" do
- Hbc::CLI.new.process_options("help", "--qlplugindir=/some/path/foo")
+ described_class.new.process_options("help", "--qlplugindir=/some/path/foo")
expect(Hbc.qlplugindir).to eq(Pathname.new("/some/path/foo"))
end
@@ -36,13 +36,13 @@ describe Hbc::CLI, :cask do
it "supports setting the qlplugindir from ENV" do
ENV["HOMEBREW_CASK_OPTS"] = "--qlplugindir=/some/path/bar"
- Hbc::CLI.new.process_options("help")
+ described_class.new.process_options("help")
expect(Hbc.qlplugindir).to eq(Pathname.new("/some/path/bar"))
end
it "supports setting the colorpickerdir" do
- Hbc::CLI.new.process_options("help", "--colorpickerdir=/some/path/foo")
+ described_class.new.process_options("help", "--colorpickerdir=/some/path/foo")
expect(Hbc.colorpickerdir).to eq(Pathname.new("/some/path/foo"))
end
@@ -50,13 +50,13 @@ describe Hbc::CLI, :cask do
it "supports setting the colorpickerdir from ENV" do
ENV["HOMEBREW_CASK_OPTS"] = "--colorpickerdir=/some/path/bar"
- Hbc::CLI.new.process_options("help")
+ described_class.new.process_options("help")
expect(Hbc.colorpickerdir).to eq(Pathname.new("/some/path/bar"))
end
it "supports setting the dictionarydir" do
- Hbc::CLI.new.process_options("help", "--dictionarydir=/some/path/foo")
+ described_class.new.process_options("help", "--dictionarydir=/some/path/foo")
expect(Hbc.dictionarydir).to eq(Pathname.new("/some/path/foo"))
end
@@ -64,13 +64,13 @@ describe Hbc::CLI, :cask do
it "supports setting the dictionarydir from ENV" do
ENV["HOMEBREW_CASK_OPTS"] = "--dictionarydir=/some/path/bar"
- Hbc::CLI.new.process_options("help")
+ described_class.new.process_options("help")
expect(Hbc.dictionarydir).to eq(Pathname.new("/some/path/bar"))
end
it "supports setting the fontdir" do
- Hbc::CLI.new.process_options("help", "--fontdir=/some/path/foo")
+ described_class.new.process_options("help", "--fontdir=/some/path/foo")
expect(Hbc.fontdir).to eq(Pathname.new("/some/path/foo"))
end
@@ -78,13 +78,13 @@ describe Hbc::CLI, :cask do
it "supports setting the fontdir from ENV" do
ENV["HOMEBREW_CASK_OPTS"] = "--fontdir=/some/path/bar"
- Hbc::CLI.new.process_options("help")
+ described_class.new.process_options("help")
expect(Hbc.fontdir).to eq(Pathname.new("/some/path/bar"))
end
it "supports setting the servicedir" do
- Hbc::CLI.new.process_options("help", "--servicedir=/some/path/foo")
+ described_class.new.process_options("help", "--servicedir=/some/path/foo")
expect(Hbc.servicedir).to eq(Pathname.new("/some/path/foo"))
end
@@ -92,13 +92,13 @@ describe Hbc::CLI, :cask do
it "supports setting the servicedir from ENV" do
ENV["HOMEBREW_CASK_OPTS"] = "--servicedir=/some/path/bar"
- Hbc::CLI.new.process_options("help")
+ described_class.new.process_options("help")
expect(Hbc.servicedir).to eq(Pathname.new("/some/path/bar"))
end
it "allows additional options to be passed through" do
- rest = Hbc::CLI.new.process_options("edit", "foo", "--create", "--appdir=/some/path/qux")
+ rest = described_class.new.process_options("edit", "foo", "--create", "--appdir=/some/path/qux")
expect(Hbc.appdir).to eq(Pathname.new("/some/path/qux"))
expect(rest).to eq(%w[edit foo --create])
@@ -106,7 +106,7 @@ describe Hbc::CLI, :cask do
describe "--help" do
it "sets the Cask help method to true" do
- command = Hbc::CLI.new("foo", "--help")
+ command = described_class.new("foo", "--help")
expect(command.help?).to be true
end
end
diff --git a/Library/Homebrew/test/cask/cli/outdated_spec.rb b/Library/Homebrew/test/cask/cli/outdated_spec.rb
index 946092f89..5bbf18d21 100644
--- a/Library/Homebrew/test/cask/cli/outdated_spec.rb
+++ b/Library/Homebrew/test/cask/cli/outdated_spec.rb
@@ -1,11 +1,13 @@
+require_relative "shared_examples/invalid_option"
+
describe Hbc::CLI::Outdated, :cask do
let(:installed) do
[
- Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/basic-cask.rb"),
- Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/outdated/local-caffeine.rb"),
- Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/outdated/local-transmission.rb"),
- Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/version-latest-string.rb"),
- Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/outdated/auto-updates.rb"),
+ Hbc::CaskLoader.load(cask_path("basic-cask")),
+ Hbc::CaskLoader.load(cask_path("outdated/local-caffeine")),
+ Hbc::CaskLoader.load(cask_path("outdated/local-transmission")),
+ Hbc::CaskLoader.load(cask_path("version-latest-string")),
+ Hbc::CaskLoader.load(cask_path("outdated/auto-updates")),
]
end
@@ -15,6 +17,8 @@ describe Hbc::CLI::Outdated, :cask do
allow_any_instance_of(described_class).to receive(:verbose?).and_return(true)
end
+ it_behaves_like "a command that handles invalid options"
+
describe 'without --greedy it ignores the Casks with "vesion latest" or "auto_updates true"' do
it "checks all the installed Casks when no token is provided" do
expect {
@@ -70,7 +74,7 @@ describe Hbc::CLI::Outdated, :cask do
end
it 'does not include the Casks with "auto_updates true" when the version did not change' do
- cask = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/auto-updates.rb")
+ cask = Hbc::CaskLoader.load(cask_path("auto-updates"))
InstallHelper.install_with_caskfile(cask)
expect {
diff --git a/Library/Homebrew/test/cask/cli/reinstall_spec.rb b/Library/Homebrew/test/cask/cli/reinstall_spec.rb
index 3a9c3e2f5..95294b695 100644
--- a/Library/Homebrew/test/cask/cli/reinstall_spec.rb
+++ b/Library/Homebrew/test/cask/cli/reinstall_spec.rb
@@ -1,6 +1,10 @@
+require_relative "shared_examples/invalid_option"
+
describe Hbc::CLI::Reinstall, :cask do
+ it_behaves_like "a command that handles invalid options"
+
it "displays the reinstallation progress" do
- caffeine = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb")
+ caffeine = Hbc::CaskLoader.load(cask_path("local-caffeine"))
Hbc::Installer.new(caffeine).install
@@ -23,16 +27,16 @@ describe Hbc::CLI::Reinstall, :cask do
it "allows reinstalling a Cask" do
Hbc::CLI::Install.run("local-transmission")
- expect(Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb")).to be_installed
+ expect(Hbc::CaskLoader.load(cask_path("local-transmission"))).to be_installed
Hbc::CLI::Reinstall.run("local-transmission")
- expect(Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb")).to be_installed
+ expect(Hbc::CaskLoader.load(cask_path("local-transmission"))).to be_installed
end
it "allows reinstalling a non installed Cask" do
- expect(Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb")).not_to be_installed
+ expect(Hbc::CaskLoader.load(cask_path("local-transmission"))).not_to be_installed
Hbc::CLI::Reinstall.run("local-transmission")
- expect(Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb")).to be_installed
+ expect(Hbc::CaskLoader.load(cask_path("local-transmission"))).to be_installed
end
end
diff --git a/Library/Homebrew/test/cask/cli/search_spec.rb b/Library/Homebrew/test/cask/cli/search_spec.rb
index e237ad464..a4f796f3c 100644
--- a/Library/Homebrew/test/cask/cli/search_spec.rb
+++ b/Library/Homebrew/test/cask/cli/search_spec.rb
@@ -1,9 +1,15 @@
+require_relative "shared_examples/invalid_option"
+
describe Hbc::CLI::Search, :cask do
before(:each) do
allow(Tty).to receive(:width).and_return(0)
end
+ it_behaves_like "a command that handles invalid options"
+
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,24 +20,47 @@ 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
+ local-caffeine
+ local-transmission
+ 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 +84,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/shared_examples/invalid_option.rb b/Library/Homebrew/test/cask/cli/shared_examples/invalid_option.rb
new file mode 100644
index 000000000..12a05be92
--- /dev/null
+++ b/Library/Homebrew/test/cask/cli/shared_examples/invalid_option.rb
@@ -0,0 +1,15 @@
+shared_examples "a command that handles invalid options" do
+ context "when an invalid option is specified" do
+ it "raises an exception when no Cask is specified" do
+ expect {
+ described_class.run("--not-a-valid-option")
+ }.to raise_error("invalid option: --not-a-valid-option")
+ end
+
+ it "raises an exception when a Cask is specified" do
+ expect {
+ described_class.run("--not-a-valid-option", "basic-cask")
+ }.to raise_error("invalid option: --not-a-valid-option")
+ end
+ end
+end
diff --git a/Library/Homebrew/test/cask/cli/shared_examples/requires_cask_token.rb b/Library/Homebrew/test/cask/cli/shared_examples/requires_cask_token.rb
new file mode 100644
index 000000000..dc1e471e5
--- /dev/null
+++ b/Library/Homebrew/test/cask/cli/shared_examples/requires_cask_token.rb
@@ -0,0 +1,9 @@
+shared_examples "a command that requires a Cask token" do
+ context "when no Cask is specified" do
+ it "raises an exception " do
+ expect {
+ described_class.run
+ }.to raise_error(Hbc::CaskUnspecifiedError, "This command requires a Cask token.")
+ end
+ end
+end
diff --git a/Library/Homebrew/test/cask/cli/style_spec.rb b/Library/Homebrew/test/cask/cli/style_spec.rb
index 2007b87d7..12cd348a0 100644
--- a/Library/Homebrew/test/cask/cli/style_spec.rb
+++ b/Library/Homebrew/test/cask/cli/style_spec.rb
@@ -1,11 +1,13 @@
require "open3"
require "rubygems"
+require_relative "shared_examples/invalid_option"
+
describe Hbc::CLI::Style, :cask do
let(:args) { [] }
let(:cli) { described_class.new(*args) }
- around(&:run)
+ it_behaves_like "a command that handles invalid options"
describe "#run" do
subject { cli.run }
diff --git a/Library/Homebrew/test/cask/cli/uninstall_spec.rb b/Library/Homebrew/test/cask/cli/uninstall_spec.rb
index 1a1c57e88..80b7edbd3 100644
--- a/Library/Homebrew/test/cask/cli/uninstall_spec.rb
+++ b/Library/Homebrew/test/cask/cli/uninstall_spec.rb
@@ -1,6 +1,12 @@
+require_relative "shared_examples/requires_cask_token"
+require_relative "shared_examples/invalid_option"
+
describe Hbc::CLI::Uninstall, :cask do
+ it_behaves_like "a command that requires a Cask token"
+ it_behaves_like "a command that handles invalid options"
+
it "displays the uninstallation progress" do
- caffeine = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb")
+ caffeine = Hbc::CaskLoader.load(cask_path("local-caffeine"))
Hbc::Installer.new(caffeine).install
@@ -10,31 +16,29 @@ describe Hbc::CLI::Uninstall, :cask do
EOS
expect {
- Hbc::CLI::Uninstall.run("local-caffeine")
+ described_class.run("local-caffeine")
}.to output(output).to_stdout
end
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.")
+ expect { described_class.run("notacask") }
+ .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.")
+ expect { described_class.run("local-caffeine") }
+ .to raise_error(Hbc::CaskNotInstalledError, /is not installed/)
end
it "tries anyway on a non-present Cask when --force is given" do
expect {
- Hbc::CLI::Uninstall.run("local-caffeine", "--force")
+ described_class.run("local-caffeine", "--force")
}.not_to raise_error
end
it "can uninstall and unlink multiple Casks at once" do
- caffeine = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb")
- transmission = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb")
+ caffeine = Hbc::CaskLoader.load(cask_path("local-caffeine"))
+ transmission = Hbc::CaskLoader.load(cask_path("local-transmission"))
Hbc::Installer.new(caffeine).install
Hbc::Installer.new(transmission).install
@@ -42,7 +46,7 @@ describe Hbc::CLI::Uninstall, :cask do
expect(caffeine).to be_installed
expect(transmission).to be_installed
- Hbc::CLI::Uninstall.run("local-caffeine", "local-transmission")
+ described_class.run("local-caffeine", "local-transmission")
expect(caffeine).not_to be_installed
expect(Hbc.appdir.join("Transmission.app")).not_to exist
@@ -51,7 +55,7 @@ describe Hbc::CLI::Uninstall, :cask do
end
it "calls `uninstall` before removing artifacts" do
- cask = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-uninstall-script-app.rb")
+ cask = Hbc::CaskLoader.load(cask_path("with-uninstall-script-app"))
Hbc::Installer.new(cask).install
@@ -59,7 +63,7 @@ describe Hbc::CLI::Uninstall, :cask do
expect(Hbc.appdir.join("MyFancyApp.app")).to exist
expect {
- Hbc::CLI::Uninstall.run("with-uninstall-script-app")
+ described_class.run("with-uninstall-script-app")
}.not_to raise_error
expect(cask).not_to be_installed
@@ -67,7 +71,7 @@ describe Hbc::CLI::Uninstall, :cask do
end
it "can uninstall Casks when the uninstall script is missing, but only when using `--force`" do
- cask = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-uninstall-script-app.rb")
+ cask = Hbc::CaskLoader.load(cask_path("with-uninstall-script-app"))
Hbc::Installer.new(cask).install
@@ -75,14 +79,13 @@ 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.")
+ expect { described_class.run("with-uninstall-script-app") }
+ .to raise_error(Hbc::CaskError, /uninstall script .* does not exist/)
expect(cask).to be_installed
expect {
- Hbc::CLI::Uninstall.run("with-uninstall-script-app", "--force")
+ described_class.run("with-uninstall-script-app", "--force")
}.not_to raise_error
expect(cask).not_to be_installed
@@ -115,13 +118,13 @@ describe Hbc::CLI::Uninstall, :cask do
end
it "uninstalls one version at a time" do
- Hbc::CLI::Uninstall.run("versioned-cask")
+ described_class.run("versioned-cask")
expect(caskroom_path.join(first_installed_version)).to exist
expect(caskroom_path.join(last_installed_version)).not_to exist
expect(caskroom_path).to exist
- Hbc::CLI::Uninstall.run("versioned-cask")
+ described_class.run("versioned-cask")
expect(caskroom_path.join(first_installed_version)).not_to exist
expect(caskroom_path).not_to exist
@@ -130,7 +133,7 @@ describe Hbc::CLI::Uninstall, :cask do
it "displays a message when versions remain installed" do
expect {
expect {
- Hbc::CLI::Uninstall.run("versioned-cask")
+ described_class.run("versioned-cask")
}.not_to output.to_stderr
}.to output(/#{token} #{first_installed_version} is still installed./).to_stdout
end
@@ -160,26 +163,10 @@ describe Hbc::CLI::Uninstall, :cask do
end
it "can still uninstall those Casks" do
- Hbc::CLI::Uninstall.run("ive-been-renamed")
+ described_class.run("ive-been-renamed")
expect(app).not_to exist
expect(caskroom_path).not_to exist
end
end
-
- describe "when no Cask is specified" do
- it "raises an exception" do
- expect {
- Hbc::CLI::Uninstall.run
- }.to raise_error(Hbc::CaskUnspecifiedError)
- end
- end
-
- describe "when no Cask is specified, but an invalid option" do
- it "raises an exception" do
- expect {
- Hbc::CLI::Uninstall.run("--notavalidoption")
- }.to raise_error(/invalid option/)
- end
- end
end
diff --git a/Library/Homebrew/test/cask/cli/zap_spec.rb b/Library/Homebrew/test/cask/cli/zap_spec.rb
index fdc5b4125..05c882854 100644
--- a/Library/Homebrew/test/cask/cli/zap_spec.rb
+++ b/Library/Homebrew/test/cask/cli/zap_spec.rb
@@ -1,13 +1,18 @@
+require_relative "shared_examples/requires_cask_token"
+require_relative "shared_examples/invalid_option"
+
describe Hbc::CLI::Zap, :cask do
+ it_behaves_like "a command that requires a Cask token"
+ it_behaves_like "a command that handles invalid options"
+
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.")
+ expect { described_class.run("notacask") }
+ .to raise_error(Hbc::CaskUnavailableError, /is unavailable/)
end
it "can zap and unlink multiple Casks at once" do
- caffeine = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb")
- transmission = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb")
+ caffeine = Hbc::CaskLoader.load(cask_path("local-caffeine"))
+ transmission = Hbc::CaskLoader.load(cask_path("local-transmission"))
Hbc::Installer.new(caffeine).install
Hbc::Installer.new(transmission).install
@@ -15,7 +20,7 @@ describe Hbc::CLI::Zap, :cask do
expect(caffeine).to be_installed
expect(transmission).to be_installed
- Hbc::CLI::Zap.run("local-caffeine", "local-transmission")
+ described_class.run("local-caffeine", "local-transmission")
expect(caffeine).not_to be_installed
expect(Hbc.appdir.join("Caffeine.app")).not_to be_a_symlink
@@ -46,20 +51,4 @@ describe Hbc::CLI::Zap, :cask do
#
# with_zap.wont_be :installed?
# end
-
- describe "when no Cask is specified" do
- it "raises an exception" do
- expect {
- Hbc::CLI::Zap.run
- }.to raise_error(Hbc::CaskUnspecifiedError)
- end
- end
-
- describe "when no Cask is specified, but an invalid option" do
- it "raises an exception" do
- expect {
- Hbc::CLI::Zap.run("--notavalidoption")
- }.to raise_error(/invalid option/)
- end
- end
end
diff --git a/Library/Homebrew/test/cask/conflicts_with_spec.rb b/Library/Homebrew/test/cask/conflicts_with_spec.rb
new file mode 100644
index 000000000..81c22ded6
--- /dev/null
+++ b/Library/Homebrew/test/cask/conflicts_with_spec.rb
@@ -0,0 +1,23 @@
+describe "conflicts_with", :cask do
+ describe "conflicts_with cask" do
+ let(:local_caffeine) {
+ Hbc::CaskLoader.load(cask_path("local-caffeine"))
+ }
+
+ let(:with_conflicts_with) {
+ Hbc::CaskLoader.load(cask_path("with-conflicts-with"))
+ }
+
+ it "installs the dependency of a Cask and the Cask itself" do
+ Hbc::Installer.new(local_caffeine).install
+
+ expect(local_caffeine).to be_installed
+
+ expect {
+ Hbc::Installer.new(with_conflicts_with).install
+ }.to raise_error(Hbc::CaskConflictError, "Cask 'with-conflicts-with' conflicts with 'local-caffeine'.")
+
+ expect(with_conflicts_with).not_to be_installed
+ end
+ end
+end
diff --git a/Library/Homebrew/test/cask/container/dmg_spec.rb b/Library/Homebrew/test/cask/container/dmg_spec.rb
index 4f3f57071..df99a6264 100644
--- a/Library/Homebrew/test/cask/container/dmg_spec.rb
+++ b/Library/Homebrew/test/cask/container/dmg_spec.rb
@@ -1,7 +1,7 @@
describe Hbc::Container::Dmg, :cask do
describe "#mount!" do
it "does not store nil mounts for dmgs with extra data" do
- transmission = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb")
+ transmission = Hbc::CaskLoader.load(cask_path("local-transmission"))
dmg = Hbc::Container::Dmg.new(
transmission,
diff --git a/Library/Homebrew/test/cask/depends_on_spec.rb b/Library/Homebrew/test/cask/depends_on_spec.rb
index c603cf6e1..453a761f7 100644
--- a/Library/Homebrew/test/cask/depends_on_spec.rb
+++ b/Library/Homebrew/test/cask/depends_on_spec.rb
@@ -9,12 +9,15 @@ describe "Satisfy Dependencies and Requirements", :cask do
describe "depends_on cask" do
context "when depends_on cask is cyclic" do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-depends-on-cask-cyclic.rb") }
- it { is_expected.to raise_error(Hbc::CaskCyclicDependencyError) }
+ let(:cask) { Hbc::CaskLoader.load(cask_path("with-depends-on-cask-cyclic")) }
+ it {
+ is_expected.to raise_error(Hbc::CaskCyclicDependencyError,
+ "Cask 'with-depends-on-cask-cyclic' includes cyclic dependencies on other Casks: with-depends-on-cask-cyclic-helper")
+ }
end
context do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-depends-on-cask.rb") }
+ let(:cask) { Hbc::CaskLoader.load(cask_path("with-depends-on-cask")) }
let(:dependency) { Hbc::CaskLoader.load(cask.depends_on.cask.first) }
it "installs the dependency of a Cask and the Cask itself" do
@@ -27,34 +30,34 @@ describe "Satisfy Dependencies and Requirements", :cask do
describe "depends_on macos" do
context "given an array" do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-depends-on-macos-array.rb") }
+ let(:cask) { Hbc::CaskLoader.load(cask_path("with-depends-on-macos-array")) }
it { is_expected.not_to raise_error }
end
- context "given a comparisson" do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-depends-on-macos-comparison.rb") }
+ context "given a comparison" do
+ let(:cask) { Hbc::CaskLoader.load(cask_path("with-depends-on-macos-comparison")) }
it { is_expected.not_to raise_error }
end
context "given a string" do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-depends-on-macos-string.rb") }
+ let(:cask) { Hbc::CaskLoader.load(cask_path("with-depends-on-macos-string")) }
it { is_expected.not_to raise_error }
end
context "given a symbol" do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-depends-on-macos-symbol.rb") }
+ let(:cask) { Hbc::CaskLoader.load(cask_path("with-depends-on-macos-symbol")) }
it { is_expected.not_to raise_error }
end
context "when not satisfied" do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-depends-on-macos-failure.rb") }
+ let(:cask) { Hbc::CaskLoader.load(cask_path("with-depends-on-macos-failure")) }
it { is_expected.to raise_error(Hbc::CaskError) }
end
end
describe "depends_on arch" do
context "when satisfied" do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-depends-on-arch.rb") }
+ let(:cask) { Hbc::CaskLoader.load(cask_path("with-depends-on-arch")) }
it { is_expected.not_to raise_error }
end
end
@@ -65,21 +68,21 @@ describe "Satisfy Dependencies and Requirements", :cask do
end
context "when satisfied" do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-depends-on-x11.rb") }
+ let(:cask) { Hbc::CaskLoader.load(cask_path("with-depends-on-x11")) }
let(:x11_installed) { true }
it { is_expected.not_to raise_error }
end
context "when not satisfied" do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-depends-on-x11.rb") }
+ let(:cask) { Hbc::CaskLoader.load(cask_path("with-depends-on-x11")) }
let(:x11_installed) { false }
it { is_expected.to raise_error(Hbc::CaskX11DependencyError) }
end
context "when depends_on x11: false" do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-depends-on-x11-false.rb") }
+ let(:cask) { Hbc::CaskLoader.load(cask_path("with-depends-on-x11-false")) }
let(:x11_installed) { false }
it { is_expected.not_to raise_error }
diff --git a/Library/Homebrew/test/cask/download_strategy_spec.rb b/Library/Homebrew/test/cask/download_strategy_spec.rb
index 222352c07..17da1e36e 100644
--- a/Library/Homebrew/test/cask/download_strategy_spec.rb
+++ b/Library/Homebrew/test/cask/download_strategy_spec.rb
@@ -26,9 +26,12 @@ describe "download strategies", :cask do
downloader.fetch
expect(downloader).to have_received(:curl).with(
+ "--location",
+ "--remote-time",
+ "--continue-at", "-",
+ "--output", kind_of(Pathname),
cask.url.to_s,
- "-C", 0,
- "-o", kind_of(Pathname)
+ user_agent: :default
)
end
@@ -36,25 +39,25 @@ describe "download strategies", :cask do
let(:url_options) { { user_agent: "Mozilla/25.0.1" } }
it "adds the appropriate curl args" do
- curl_args = []
- allow(downloader).to receive(:curl) { |*args| curl_args = args }
+ expect(downloader).to receive(:safe_system) { |*args|
+ expect(args.each_cons(2)).to include(["--user-agent", "Mozilla/25.0.1"])
+ }
downloader.fetch
-
- expect(curl_args.each_cons(2)).to include(["-A", "Mozilla/25.0.1"])
end
end
context "with a generalized fake user agent" do
+ alias_matcher :a_string_matching, :match
+
let(:url_options) { { user_agent: :fake } }
it "adds the appropriate curl args" do
- curl_args = []
- allow(downloader).to receive(:curl) { |*args| curl_args = args }
+ expect(downloader).to receive(:safe_system) { |*args|
+ expect(args.each_cons(2).to_a).to include(["--user-agent", a_string_matching(/Mozilla.*Mac OS X 10.*AppleWebKit/)])
+ }
downloader.fetch
-
- expect(curl_args.each_cons(2)).to include(["-A", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10) https://caskroom.github.io"])
end
end
@@ -138,7 +141,7 @@ describe "download strategies", :cask do
describe Hbc::SubversionDownloadStrategy do
let(:url_options) { { using: :svn } }
let(:fake_system_command) { class_double(Hbc::SystemCommand) }
- let(:downloader) { Hbc::SubversionDownloadStrategy.new(cask, fake_system_command) }
+ let(:downloader) { Hbc::SubversionDownloadStrategy.new(cask, command: fake_system_command) }
before do
allow(fake_system_command).to receive(:run!)
end
@@ -147,7 +150,7 @@ describe "download strategies", :cask do
allow(downloader).to receive(:compress)
allow(downloader).to receive(:fetch_repo)
- expect(downloader.fetch).to equal(downloader.tarball_path)
+ expect(downloader.fetch).to equal(downloader.cached_location)
end
it "calls fetch_repo with default arguments for a simple Cask" do
@@ -237,44 +240,5 @@ describe "download strategies", :cask do
)
end
end
-
- it "runs tar to serialize svn downloads" do
- # sneaky stub to remake the directory, since homebrew code removes it
- # before tar is called
- allow(downloader).to receive(:fetch_repo) {
- downloader.cached_location.mkdir
- }
-
- downloader.fetch
-
- expect(fake_system_command).to have_received(:run!).with(
- "/usr/bin/tar",
- hash_including(args: [
- '-s/^\\.//',
- "--exclude",
- ".svn",
- "-cf",
- downloader.tarball_path,
- "--",
- ".",
- ]),
- )
- end
end
-
- # does not work yet, because (for unknown reasons), the tar command
- # returns an error code when running under the test suite
- # it 'creates a tarball matching the expected checksum' do
- # cask = Hbc::CaskLoader.load('svn-download-check-cask')
- # downloader = Hbc::SubversionDownloadStrategy.new(cask)
- # # special mocking required for tar to have something to work with
- # def downloader.fetch_repo(target, url, revision = nil, ignore_externals=false)
- # target.mkpath
- # FileUtils.touch(target.join('empty_file.txt'))
- # File.utime(1000,1000,target.join('empty_file.txt'))
- # end
- # expect(downloader.fetch).to equal(downloader.tarball_path)
- # d = Hbc::Download.new(cask)
- # d.send(:_check_sums, downloader.tarball_path, cask.sums)
- # end
end
diff --git a/Library/Homebrew/test/cask/dsl/appcast_spec.rb b/Library/Homebrew/test/cask/dsl/appcast_spec.rb
index b8903b1be..bf703eba2 100644
--- a/Library/Homebrew/test/cask/dsl/appcast_spec.rb
+++ b/Library/Homebrew/test/cask/dsl/appcast_spec.rb
@@ -4,7 +4,7 @@ describe Hbc::DSL::Appcast do
subject { described_class.new(url, params) }
let(:url) { "http://example.com" }
- let(:uri) { Hbc::UnderscoreSupportingURI.parse(url) }
+ let(:uri) { URI(url) }
let(:params) { {} }
describe "#to_s" do
@@ -33,13 +33,18 @@ describe Hbc::DSL::Appcast do
describe "#calculate_checkpoint" do
before do
- expect(Hbc::SystemCommand).to receive(:run).with(*cmd_args).and_return(cmd_result)
+ expect(Hbc::SystemCommand).to receive(:run) do |executable, **options|
+ expect(executable).to eq "/usr/bin/curl"
+ expect(options[:args]).to include(*cmd_args)
+ expect(options[:print_stderr]).to be false
+ cmd_result
+ end
allow(cmd_result).to receive(:success?).and_return(cmd_success)
allow(cmd_result).to receive(:stdout).and_return(cmd_stdout)
end
context "when server returns a successful HTTP status" do
- let(:cmd_args) { ["/usr/bin/curl", args: ["--compressed", "--location", "--user-agent", Hbc::URL::FAKE_USER_AGENT, "--fail", uri], print_stderr: false] }
+ let(:cmd_args) { [HOMEBREW_USER_AGENT_FAKE_SAFARI, "--compressed", "--location", "--fail", uri] }
let(:cmd_result) { double("Hbc::SystemCommand::Result") }
let(:cmd_success) { true }
let(:cmd_stdout) { "hello world" }
@@ -56,7 +61,7 @@ describe Hbc::DSL::Appcast do
end
context "when server returns a non-successful HTTP status" do
- let(:cmd_args) { ["/usr/bin/curl", args: ["--compressed", "--location", "--user-agent", Hbc::URL::FAKE_USER_AGENT, "--fail", uri], print_stderr: false] }
+ let(:cmd_args) { [HOMEBREW_USER_AGENT_FAKE_SAFARI, "--compressed", "--location", "--fail", uri] }
let(:cmd_result) { double("Hbc::SystemCommand::Result") }
let(:cmd_success) { false }
let(:cmd_stdout) { "some error message from the server" }
diff --git a/Library/Homebrew/test/cask/dsl/caveats_spec.rb b/Library/Homebrew/test/cask/dsl/caveats_spec.rb
index aa662e4d0..1b82d9821 100644
--- a/Library/Homebrew/test/cask/dsl/caveats_spec.rb
+++ b/Library/Homebrew/test/cask/dsl/caveats_spec.rb
@@ -1,7 +1,7 @@
require "test/support/helper/spec/shared_examples/hbc_dsl_base"
describe Hbc::DSL::Caveats, :cask do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/basic-cask.rb") }
+ let(:cask) { Hbc::CaskLoader.load(cask_path("basic-cask")) }
let(:dsl) { Hbc::DSL::Caveats.new(cask) }
it_behaves_like Hbc::DSL::Base
diff --git a/Library/Homebrew/test/cask/dsl/postflight_spec.rb b/Library/Homebrew/test/cask/dsl/postflight_spec.rb
index d2b080ca3..4ac3ae7cf 100644
--- a/Library/Homebrew/test/cask/dsl/postflight_spec.rb
+++ b/Library/Homebrew/test/cask/dsl/postflight_spec.rb
@@ -2,7 +2,7 @@ require "test/support/helper/spec/shared_examples/hbc_dsl_base"
require "test/support/helper/spec/shared_examples/hbc_staged"
describe Hbc::DSL::Postflight, :cask do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/basic-cask.rb") }
+ let(:cask) { Hbc::CaskLoader.load(cask_path("basic-cask")) }
let(:dsl) { Hbc::DSL::Postflight.new(cask, Hbc::FakeSystemCommand) }
it_behaves_like Hbc::DSL::Base
diff --git a/Library/Homebrew/test/cask/dsl/preflight_spec.rb b/Library/Homebrew/test/cask/dsl/preflight_spec.rb
index b93be95ff..f78944c50 100644
--- a/Library/Homebrew/test/cask/dsl/preflight_spec.rb
+++ b/Library/Homebrew/test/cask/dsl/preflight_spec.rb
@@ -2,7 +2,7 @@ require "test/support/helper/spec/shared_examples/hbc_dsl_base"
require "test/support/helper/spec/shared_examples/hbc_staged"
describe Hbc::DSL::Preflight, :cask do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/basic-cask.rb") }
+ let(:cask) { Hbc::CaskLoader.load(cask_path("basic-cask")) }
let(:dsl) { Hbc::DSL::Preflight.new(cask, Hbc::FakeSystemCommand) }
it_behaves_like Hbc::DSL::Base
diff --git a/Library/Homebrew/test/cask/dsl/uninstall_postflight_spec.rb b/Library/Homebrew/test/cask/dsl/uninstall_postflight_spec.rb
index f89a181ce..b2af700db 100644
--- a/Library/Homebrew/test/cask/dsl/uninstall_postflight_spec.rb
+++ b/Library/Homebrew/test/cask/dsl/uninstall_postflight_spec.rb
@@ -1,7 +1,7 @@
require "test/support/helper/spec/shared_examples/hbc_dsl_base"
describe Hbc::DSL::UninstallPostflight, :cask do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/basic-cask.rb") }
+ let(:cask) { Hbc::CaskLoader.load(cask_path("basic-cask")) }
let(:dsl) { Hbc::DSL::UninstallPostflight.new(cask, Hbc::FakeSystemCommand) }
it_behaves_like Hbc::DSL::Base
diff --git a/Library/Homebrew/test/cask/dsl/uninstall_preflight_spec.rb b/Library/Homebrew/test/cask/dsl/uninstall_preflight_spec.rb
index 15a0ea156..8e7fa47eb 100644
--- a/Library/Homebrew/test/cask/dsl/uninstall_preflight_spec.rb
+++ b/Library/Homebrew/test/cask/dsl/uninstall_preflight_spec.rb
@@ -2,7 +2,7 @@ require "test/support/helper/spec/shared_examples/hbc_dsl_base"
require "test/support/helper/spec/shared_examples/hbc_staged"
describe Hbc::DSL::UninstallPreflight, :cask do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/basic-cask.rb") }
+ let(:cask) { Hbc::CaskLoader.load(cask_path("basic-cask")) }
let(:dsl) { Hbc::DSL::UninstallPreflight.new(cask, Hbc::FakeSystemCommand) }
it_behaves_like Hbc::DSL::Base
diff --git a/Library/Homebrew/test/cask/dsl_spec.rb b/Library/Homebrew/test/cask/dsl_spec.rb
index 7f2207a87..28cf6f4b2 100644
--- a/Library/Homebrew/test/cask/dsl_spec.rb
+++ b/Library/Homebrew/test/cask/dsl_spec.rb
@@ -1,5 +1,5 @@
describe Hbc::DSL, :cask do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/#{token}.rb") }
+ let(:cask) { Hbc::CaskLoader.load(cask_path(token.to_s)) }
let(:token) { "basic-cask" }
context "stanzas" do
@@ -177,6 +177,36 @@ describe Hbc::DSL, :cask do
expect(cask.call.sha256).to eq("xyz789")
expect(cask.call.url.to_s).to eq("https://example.org/en-US.zip")
end
+
+ it "returns an empty array if no languages are specified" do
+ cask = lambda do
+ Hbc::Cask.new("cask-with-apps") do
+ url "https://example.org/file.zip"
+ end
+ end
+
+ expect(cask.call.languages).to be_empty
+ end
+
+ it "returns an array of available languages" do
+ cask = lambda do
+ Hbc::Cask.new("cask-with-apps") do
+ language "zh" do
+ sha256 "abc123"
+ "zh-CN"
+ end
+
+ language "en-US", default: true do
+ sha256 "xyz789"
+ "en-US"
+ end
+
+ url "https://example.org/file.zip"
+ end
+ end
+
+ expect(cask.call.languages).to eq(["zh", "en-US"])
+ end
end
describe "app stanza" do
@@ -186,12 +216,12 @@ describe Hbc::DSL, :cask do
app "Bar.app"
end
- expect(Array(cask.artifacts[:app])).to eq([["Foo.app"], ["Bar.app"]])
+ expect(cask.artifacts.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).to be_empty
end
end
@@ -219,7 +249,7 @@ describe Hbc::DSL, :cask do
pkg "Bar.pkg"
end
- expect(Array(cask.artifacts[:pkg])).to eq([["Foo.pkg"], ["Bar.pkg"]])
+ expect(cask.artifacts.map(&:to_s)).to eq(["Foo.pkg (Pkg)", "Bar.pkg (Pkg)"])
end
end
@@ -471,10 +501,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.to_a[0].path).to eq(Pathname("/usr/bin/true"))
+ expect(cask.artifacts.to_a[0].args[:args]).to eq(["--flag"])
+ expect(cask.artifacts.to_a[1].path).to eq(Pathname("/usr/bin/false"))
+ expect(cask.artifacts.to_a[1].args[:args]).to eq(["--flag"])
end
end
@@ -482,7 +512,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.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 +524,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).to contain_exactly a_kind_of Hbc::Artifact::StageOnly
end
end
@@ -513,12 +545,12 @@ describe Hbc::DSL, :cask do
end
end
- describe "appdir" do
+ describe "#appdir" do
context "interpolation of the appdir in stanzas" do
let(:token) { "appdir-interpolation" }
it "is allowed" do
- expect(cask.artifacts[:binary].first).to eq(["#{Hbc.appdir}/some/path"])
+ expect(cask.artifacts.first.source).to eq(Hbc.appdir/"some/path")
end
end
@@ -531,10 +563,35 @@ describe Hbc::DSL, :cask do
binary "#{appdir}/some/path"
end
- expect(cask.artifacts[:binary].first).to eq(["#{original_appdir}/some/path"])
+ expect(cask.artifacts.first.source).to eq(original_appdir/"some/path")
ensure
Hbc.appdir = original_appdir
end
end
end
+
+ describe "#artifacts" do
+ it "sorts artifacts according to the preferable installation order" do
+ cask = Hbc::Cask.new("appdir-trailing-slash") do
+ postflight do
+ next
+ end
+
+ preflight do
+ next
+ end
+
+ binary "binary"
+
+ app "App.app"
+ end
+
+ expect(cask.artifacts.map(&:class).map(&:dsl_key)).to eq [
+ :preflight,
+ :app,
+ :binary,
+ :postflight,
+ ]
+ end
+ end
end
diff --git a/Library/Homebrew/test/cask/installer_spec.rb b/Library/Homebrew/test/cask/installer_spec.rb
index 6f7c6d3d7..2dc27f04c 100644
--- a/Library/Homebrew/test/cask/installer_spec.rb
+++ b/Library/Homebrew/test/cask/installer_spec.rb
@@ -5,7 +5,7 @@ describe Hbc::Installer, :cask do
}
it "downloads and installs a nice fresh Cask" do
- caffeine = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb")
+ caffeine = Hbc::CaskLoader.load(cask_path("local-caffeine"))
Hbc::Installer.new(caffeine).install
@@ -14,7 +14,7 @@ describe Hbc::Installer, :cask do
end
it "works with dmg-based Casks" do
- asset = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/container-dmg.rb")
+ asset = Hbc::CaskLoader.load(cask_path("container-dmg"))
Hbc::Installer.new(asset).install
@@ -23,7 +23,7 @@ describe Hbc::Installer, :cask do
end
it "works with tar-gz-based Casks" do
- asset = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/container-tar-gz.rb")
+ asset = Hbc::CaskLoader.load(cask_path("container-tar-gz"))
Hbc::Installer.new(asset).install
@@ -32,7 +32,7 @@ describe Hbc::Installer, :cask do
end
it "works with xar-based Casks" do
- asset = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/container-xar.rb")
+ asset = Hbc::CaskLoader.load(cask_path("container-xar"))
Hbc::Installer.new(asset).install
@@ -41,7 +41,7 @@ describe Hbc::Installer, :cask do
end
it "works with pure bzip2-based Casks" do
- asset = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/container-bzip2.rb")
+ asset = Hbc::CaskLoader.load(cask_path("container-bzip2"))
Hbc::Installer.new(asset).install
@@ -50,7 +50,7 @@ describe Hbc::Installer, :cask do
end
it "works with pure gzip-based Casks" do
- asset = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/container-gzip.rb")
+ asset = Hbc::CaskLoader.load(cask_path("container-gzip"))
Hbc::Installer.new(asset).install
@@ -59,21 +59,21 @@ describe Hbc::Installer, :cask do
end
it "blows up on a bad checksum" do
- bad_checksum = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/bad-checksum.rb")
+ bad_checksum = Hbc::CaskLoader.load(cask_path("bad-checksum"))
expect {
Hbc::Installer.new(bad_checksum).install
}.to raise_error(Hbc::CaskSha256MismatchError)
end
it "blows up on a missing checksum" do
- missing_checksum = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/missing-checksum.rb")
+ missing_checksum = Hbc::CaskLoader.load(cask_path("missing-checksum"))
expect {
Hbc::Installer.new(missing_checksum).install
}.to raise_error(Hbc::CaskSha256MissingError)
end
it "installs fine if sha256 :no_check is used" do
- no_checksum = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/no-checksum.rb")
+ no_checksum = Hbc::CaskLoader.load(cask_path("no-checksum"))
Hbc::Installer.new(no_checksum).install
@@ -81,14 +81,14 @@ describe Hbc::Installer, :cask do
end
it "fails to install if sha256 :no_check is used with --require-sha" do
- no_checksum = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/no-checksum.rb")
+ no_checksum = Hbc::CaskLoader.load(cask_path("no-checksum"))
expect {
Hbc::Installer.new(no_checksum, require_sha: true).install
}.to raise_error(Hbc::CaskNoShasumError)
end
it "installs fine if sha256 :no_check is used with --require-sha and --force" do
- no_checksum = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/no-checksum.rb")
+ no_checksum = Hbc::CaskLoader.load(cask_path("no-checksum"))
Hbc::Installer.new(no_checksum, require_sha: true, force: true).install
@@ -96,7 +96,7 @@ describe Hbc::Installer, :cask do
end
it "prints caveats if they're present" do
- with_caveats = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-caveats.rb")
+ with_caveats = Hbc::CaskLoader.load(cask_path("with-caveats"))
expect {
Hbc::Installer.new(with_caveats).install
@@ -106,7 +106,7 @@ describe Hbc::Installer, :cask do
end
it "prints installer :manual instructions when present" do
- with_installer_manual = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-installer-manual.rb")
+ with_installer_manual = Hbc::CaskLoader.load(cask_path("with-installer-manual"))
expect {
Hbc::Installer.new(with_installer_manual).install
@@ -116,7 +116,7 @@ describe Hbc::Installer, :cask do
end
it "does not extract __MACOSX directories from zips" do
- with_macosx_dir = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/with-macosx-dir.rb")
+ with_macosx_dir = Hbc::CaskLoader.load(cask_path("with-macosx-dir"))
Hbc::Installer.new(with_macosx_dir).install
@@ -124,7 +124,7 @@ describe Hbc::Installer, :cask do
end
it "allows already-installed Casks which auto-update to be installed if force is provided" do
- with_auto_updates = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/auto-updates.rb")
+ with_auto_updates = Hbc::CaskLoader.load(cask_path("auto-updates"))
expect(with_auto_updates).not_to be_installed
@@ -137,7 +137,7 @@ describe Hbc::Installer, :cask do
# unlike the CLI, the internal interface throws exception on double-install
it "installer method raises an exception when already-installed Casks are attempted" do
- transmission = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb")
+ transmission = Hbc::CaskLoader.load(cask_path("local-transmission"))
expect(transmission).not_to be_installed
@@ -151,7 +151,7 @@ describe Hbc::Installer, :cask do
end
it "allows already-installed Casks to be installed if force is provided" do
- transmission = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb")
+ transmission = Hbc::CaskLoader.load(cask_path("local-transmission"))
expect(transmission).not_to be_installed
@@ -163,7 +163,7 @@ describe Hbc::Installer, :cask do
end
it "works naked-pkg-based Casks" do
- naked_pkg = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/container-pkg.rb")
+ naked_pkg = Hbc::CaskLoader.load(cask_path("container-pkg"))
Hbc::Installer.new(naked_pkg).install
@@ -171,7 +171,7 @@ describe Hbc::Installer, :cask do
end
it "works properly with an overridden container :type" do
- naked_executable = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/naked-executable.rb")
+ naked_executable = Hbc::CaskLoader.load(cask_path("naked-executable"))
Hbc::Installer.new(naked_executable).install
@@ -179,7 +179,7 @@ describe Hbc::Installer, :cask do
end
it "works fine with a nested container" do
- nested_app = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/nested-app.rb")
+ nested_app = Hbc::CaskLoader.load(cask_path("nested-app"))
Hbc::Installer.new(nested_app).install
@@ -187,7 +187,7 @@ describe Hbc::Installer, :cask do
end
it "generates and finds a timestamped metadata directory for an installed Cask" do
- caffeine = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb")
+ caffeine = Hbc::CaskLoader.load(cask_path("local-caffeine"))
Hbc::Installer.new(caffeine).install
@@ -196,7 +196,7 @@ describe Hbc::Installer, :cask do
end
it "generates and finds a metadata subdirectory for an installed Cask" do
- caffeine = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb")
+ caffeine = Hbc::CaskLoader.load(cask_path("local-caffeine"))
Hbc::Installer.new(caffeine).install
@@ -208,7 +208,7 @@ describe Hbc::Installer, :cask do
describe "uninstall" do
it "fully uninstalls a Cask" do
- caffeine = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb")
+ caffeine = Hbc::CaskLoader.load(cask_path("local-caffeine"))
installer = Hbc::Installer.new(caffeine)
installer.install
@@ -220,7 +220,7 @@ describe Hbc::Installer, :cask do
end
it "uninstalls all versions if force is set" do
- caffeine = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb")
+ caffeine = Hbc::CaskLoader.load(cask_path("local-caffeine"))
mutated_version = caffeine.version + ".1"
Hbc::Installer.new(caffeine).install
diff --git a/Library/Homebrew/test/cask/staged_spec.rb b/Library/Homebrew/test/cask/staged_spec.rb
index 73a909f35..0229018c7 100644
--- a/Library/Homebrew/test/cask/staged_spec.rb
+++ b/Library/Homebrew/test/cask/staged_spec.rb
@@ -3,7 +3,7 @@
# to be invoking bundle_identifier off of the installer instance.
describe "Operations on staged Casks", :cask do
describe "bundle ID" do
- let(:cask) { Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-transmission.rb") }
+ let(:cask) { Hbc::CaskLoader.load(cask_path("local-transmission")) }
let(:installer) { Hbc::Installer.new(cask) }
it "fetches the bundle ID from a staged cask" do
installer.install
diff --git a/Library/Homebrew/test/cask/underscore_supporting_uri_spec.rb b/Library/Homebrew/test/cask/underscore_supporting_uri_spec.rb
deleted file mode 100644
index 49d3ea63f..000000000
--- a/Library/Homebrew/test/cask/underscore_supporting_uri_spec.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-describe Hbc::UnderscoreSupportingURI, :cask do
- describe "parse" do
- it "works like normal on normal URLs" do
- uri = Hbc::UnderscoreSupportingURI.parse("http://example.com/TestCask.dmg")
- expect(uri).to eq(URI("http://example.com/TestCask.dmg"))
- end
-
- it "works just fine on URIs with underscores" do
- uri = Hbc::UnderscoreSupportingURI.parse("http://dl_dir.qq.com/qqfile/qq/QQforMac/QQ_V3.0.0.dmg")
- expect(uri.host).to include("_")
- expect(uri.to_s).to eq("http://dl_dir.qq.com/qqfile/qq/QQforMac/QQ_V3.0.0.dmg")
- end
- end
-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/cmd/search_spec.rb b/Library/Homebrew/test/cmd/search_spec.rb
index 06b7073d8..36ddde3e1 100644
--- a/Library/Homebrew/test/cmd/search_spec.rb
+++ b/Library/Homebrew/test/cmd/search_spec.rb
@@ -1,6 +1,7 @@
describe "brew search", :integration_test do
before(:each) do
setup_test_formula "testball"
+ setup_remote_tap "caskroom/cask"
end
it "lists all available Formulae when no argument is given" do
@@ -13,7 +14,7 @@ describe "brew search", :integration_test do
it "supports searching by name" do
expect { brew "search", "testball" }
.to output(/testball/).to_stdout
- .and not_to_output.to_stderr
+ .and output(/Searching/).to_stderr
.and be_a_success
end
@@ -24,6 +25,13 @@ describe "brew search", :integration_test do
.and be_a_success
end
+ it "falls back to a GitHub tap search when no formula is found", :needs_network do
+ expect { brew "search", "caskroom/cask/firefox" }
+ .to output(/firefox/).to_stdout
+ .and output(/Searching/).to_stderr
+ .and be_a_success
+ end
+
describe "--desc" do
let(:desc_cache) { HOMEBREW_CACHE/"desc_cache.json" }
@@ -44,8 +52,8 @@ describe "brew search", :integration_test do
"fink" => "http://pdb.finkproject.org/pdb/browse.php?summary=testball",
"debian" => "https://packages.debian.org/search?keywords=testball&searchon=names&suite=all&section=all",
"opensuse" => "https://software.opensuse.org/search?q=testball",
- "fedora" => "https://admin.fedoraproject.org/pkgdb/packages/%2Atestball%2A/",
- "ubuntu" => "http://packages.ubuntu.com/search?keywords=testball&searchon=names&suite=all&section=all",
+ "fedora" => "https://apps.fedoraproject.org/packages/s/testball",
+ "ubuntu" => "https://packages.ubuntu.com/search?keywords=testball&searchon=names&suite=all&section=all",
}.each do |flag, url|
specify "--#{flag}" do
expect { brew "search", "--#{flag}", "testball", "HOMEBREW_BROWSER" => "echo" }
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/download_strategies_spec.rb b/Library/Homebrew/test/download_strategies_spec.rb
index 8c376a649..06d6fa855 100644
--- a/Library/Homebrew/test/download_strategies_spec.rb
+++ b/Library/Homebrew/test/download_strategies_spec.rb
@@ -200,6 +200,17 @@ describe GitDownloadStrategy do
end
end
+describe CurlDownloadStrategy do
+ subject { described_class.new(name, resource) }
+ let(:name) { "foo" }
+ let(:url) { "http://example.com/foo.tar.gz" }
+ let(:resource) { double(Resource, url: url, mirrors: [], specs: { user: "download:123456" }, version: nil) }
+
+ it "parses the opts and sets the corresponding args" do
+ expect(subject.send(:_curl_opts)).to eq(["--user", "download:123456"])
+ end
+end
+
describe DownloadStrategyDetector do
describe "::detect" do
subject { described_class.detect(url) }
diff --git a/Library/Homebrew/test/exceptions_spec.rb b/Library/Homebrew/test/exceptions_spec.rb
index 33547ea32..0a8313355 100644
--- a/Library/Homebrew/test/exceptions_spec.rb
+++ b/Library/Homebrew/test/exceptions_spec.rb
@@ -181,8 +181,8 @@ describe DuplicateResourceError do
its(:to_s) { is_expected.to eq("Resource <resource foo> is defined more than once") }
end
-describe BottleVersionMismatchError do
- subject { described_class.new("/foo.bottle.tar.gz", "1.0", formula, "1.1") }
+describe BottleFormulaUnavailableError do
+ subject { described_class.new("/foo.bottle.tar.gz", "foo/1.0/.brew/foo.rb") }
let(:formula) { double(Formula, full_name: "foo") }
- its(:to_s) { is_expected.to match(/Bottle version mismatch/) }
+ its(:to_s) { is_expected.to match(/This bottle does not contain the formula file/) }
end
diff --git a/Library/Homebrew/test/formula_installer_spec.rb b/Library/Homebrew/test/formula_installer_spec.rb
index 7365b2758..7b729312b 100644
--- a/Library/Homebrew/test/formula_installer_spec.rb
+++ b/Library/Homebrew/test/formula_installer_spec.rb
@@ -107,7 +107,7 @@ describe FormulaInstaller do
end
EOS
- Formulary::FORMULAE.delete(dep_path)
+ Formulary.cache.delete(dep_path)
dependency = Formulary.factory(dep_name)
dependent = formula do
diff --git a/Library/Homebrew/test/formulary_spec.rb b/Library/Homebrew/test/formulary_spec.rb
index 234ebc93c..3180ad9a7 100644
--- a/Library/Homebrew/test/formulary_spec.rb
+++ b/Library/Homebrew/test/formulary_spec.rb
@@ -14,7 +14,7 @@ describe Formulary do
bottle do
cellar :any_skip_relocation
root_url "file://#{bottle_dir}"
- sha256 "9abc8ce779067e26556002c4ca6b9427b9874d25f0cafa7028e05b5c5c410cb4" => :#{Utils::Bottles.tag}
+ sha256 "d48bbbe583dcfbfa608579724fc6f0328b3cd316935c6ea22f134610aaf2952f" => :#{Utils::Bottles.tag}
end
def install
diff --git a/Library/Homebrew/test/locale_spec.rb b/Library/Homebrew/test/locale_spec.rb
index 9e4d09e83..9c684f0e7 100644
--- a/Library/Homebrew/test/locale_spec.rb
+++ b/Library/Homebrew/test/locale_spec.rb
@@ -9,6 +9,10 @@ describe Locale do
expect(described_class.parse("zh-CN-Hans")).to eql(described_class.new("zh", "CN", "Hans"))
end
+ it "correctly parses a string with a UN M.49 region code" do
+ expect(described_class.parse("es-419")).to eql(described_class.new("es", "419", nil))
+ end
+
context "raises a ParserError when given" do
it "an empty string" do
expect { described_class.parse("") }.to raise_error(Locale::ParserError)
diff --git a/Library/Homebrew/test/missing_formula_spec.rb b/Library/Homebrew/test/missing_formula_spec.rb
index a48f12ecd..0a905004b 100644
--- a/Library/Homebrew/test/missing_formula_spec.rb
+++ b/Library/Homebrew/test/missing_formula_spec.rb
@@ -82,12 +82,6 @@ describe Homebrew::MissingFormula do
it { is_expected.to be_blacklisted }
end
- context "clojure" do
- subject { "clojure" }
-
- it { is_expected.to be_blacklisted }
- end
-
context "gfortran" do
subject { "gfortran" }
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/bottle_block_cop_spec.rb b/Library/Homebrew/test/rubocops/bottle_block_cop_spec.rb
index 563f7ad4b..b1afdc3f9 100644
--- a/Library/Homebrew/test/rubocops/bottle_block_cop_spec.rb
+++ b/Library/Homebrew/test/rubocops/bottle_block_cop_spec.rb
@@ -24,7 +24,7 @@ describe RuboCop::Cop::FormulaAuditStrict::BottleBlock do
column: 4,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -60,7 +60,7 @@ describe RuboCop::Cop::FormulaAuditStrict::BottleBlock do
end
EOS
- new_source = autocorrect_source(cop, source)
+ new_source = autocorrect_source(source)
expect(new_source).to eq(corrected_source)
end
end
diff --git a/Library/Homebrew/test/rubocops/caveats_cop_spec.rb b/Library/Homebrew/test/rubocops/caveats_cop_spec.rb
index d44808a5d..4dbe65cfb 100644
--- a/Library/Homebrew/test/rubocops/caveats_cop_spec.rb
+++ b/Library/Homebrew/test/rubocops/caveats_cop_spec.rb
@@ -25,7 +25,7 @@ describe RuboCop::Cop::FormulaAudit::Caveats do
column: 5,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
diff --git a/Library/Homebrew/test/rubocops/checksum_cop_spec.rb b/Library/Homebrew/test/rubocops/checksum_cop_spec.rb
index 644152c32..2f508bbf5 100644
--- a/Library/Homebrew/test/rubocops/checksum_cop_spec.rb
+++ b/Library/Homebrew/test/rubocops/checksum_cop_spec.rb
@@ -34,7 +34,7 @@ describe RuboCop::Cop::FormulaAudit::Checksum do
column: 14,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -68,7 +68,7 @@ describe RuboCop::Cop::FormulaAudit::Checksum do
column: 14,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -102,7 +102,7 @@ describe RuboCop::Cop::FormulaAudit::Checksum do
column: 31,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -142,7 +142,7 @@ describe RuboCop::Cop::FormulaAudit::ChecksumCase do
column: 20,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -175,7 +175,7 @@ describe RuboCop::Cop::FormulaAudit::ChecksumCase do
column: 12,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -215,7 +215,7 @@ describe RuboCop::Cop::FormulaAudit::ChecksumCase do
end
EOS
- new_source = autocorrect_source(cop, source)
+ new_source = autocorrect_source(source)
expect(new_source).to eq(corrected_source)
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..59252587c
--- /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(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(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(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/components_order_cop_spec.rb b/Library/Homebrew/test/rubocops/components_order_cop_spec.rb
index 25467c635..f093f4927 100644
--- a/Library/Homebrew/test/rubocops/components_order_cop_spec.rb
+++ b/Library/Homebrew/test/rubocops/components_order_cop_spec.rb
@@ -21,7 +21,7 @@ describe RuboCop::Cop::FormulaAuditStrict::ComponentsOrder do
column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -47,7 +47,7 @@ describe RuboCop::Cop::FormulaAuditStrict::ComponentsOrder do
column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -74,7 +74,7 @@ describe RuboCop::Cop::FormulaAuditStrict::ComponentsOrder do
column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -99,7 +99,7 @@ describe RuboCop::Cop::FormulaAuditStrict::ComponentsOrder do
column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -129,7 +129,7 @@ describe RuboCop::Cop::FormulaAuditStrict::ComponentsOrder do
end
EOS
- corrected_source = autocorrect_source(cop, source)
+ corrected_source = autocorrect_source(source)
expect(corrected_source).to eq(correct_source)
end
@@ -156,7 +156,7 @@ describe RuboCop::Cop::FormulaAuditStrict::ComponentsOrder do
end
end
EOS
- corrected_source = autocorrect_source(cop, source)
+ corrected_source = autocorrect_source(source)
expect(corrected_source).to eq(correct_source)
end
end
diff --git a/Library/Homebrew/test/rubocops/components_redundancy_cop_spec.rb b/Library/Homebrew/test/rubocops/components_redundancy_cop_spec.rb
index fd635a126..9fbe15904 100644
--- a/Library/Homebrew/test/rubocops/components_redundancy_cop_spec.rb
+++ b/Library/Homebrew/test/rubocops/components_redundancy_cop_spec.rb
@@ -23,7 +23,7 @@ describe RuboCop::Cop::FormulaAuditStrict::ComponentsRedundancy do
column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -46,7 +46,7 @@ describe RuboCop::Cop::FormulaAuditStrict::ComponentsRedundancy do
column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -70,7 +70,7 @@ describe RuboCop::Cop::FormulaAuditStrict::ComponentsRedundancy do
column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
diff --git a/Library/Homebrew/test/rubocops/conflicts_cop_spec.rb b/Library/Homebrew/test/rubocops/conflicts_cop_spec.rb
index 4fbab6c9e..8874ecc96 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(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(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..ac8893e18 100644
--- a/Library/Homebrew/test/rubocops/formula_desc_cop_spec.rb
+++ b/Library/Homebrew/test/rubocops/formula_desc_cop_spec.rb
@@ -20,7 +20,7 @@ describe RuboCop::Cop::FormulaAuditStrict::DescLength do
column: 0,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -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(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(source, "/homebrew-core/Formula/foo.rb")
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
end
@@ -96,7 +96,7 @@ describe RuboCop::Cop::FormulaAuditStrict::Desc do
column: 8,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
end
@@ -116,7 +116,7 @@ describe RuboCop::Cop::FormulaAuditStrict::Desc do
column: 8,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
end
@@ -136,7 +136,7 @@ describe RuboCop::Cop::FormulaAuditStrict::Desc do
column: 8,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
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(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(source, "/homebrew-core/Formula/foo.rb")
expect(corrected_source).to eq(correct_source)
end
end
diff --git a/Library/Homebrew/test/rubocops/homepage_cop_spec.rb b/Library/Homebrew/test/rubocops/homepage_cop_spec.rb
index c03efd825..6c7f248ba 100644
--- a/Library/Homebrew/test/rubocops/homepage_cop_spec.rb
+++ b/Library/Homebrew/test/rubocops/homepage_cop_spec.rb
@@ -20,7 +20,7 @@ describe RuboCop::Cop::FormulaAudit::Homepage do
column: 0,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -41,7 +41,7 @@ describe RuboCop::Cop::FormulaAudit::Homepage do
column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -72,7 +72,7 @@ describe RuboCop::Cop::FormulaAudit::Homepage do
end
EOS
- inspect_source(cop, source)
+ inspect_source(source)
if homepage =~ %r{http:\/\/www\.freedesktop\.org}
if homepage =~ /Software/
expected_offenses = [{ message: "#{homepage} should be styled " \
diff --git a/Library/Homebrew/test/rubocops/lines_cop_spec.rb b/Library/Homebrew/test/rubocops/lines_cop_spec.rb
index 6f1f8a48c..962827ca3 100644
--- a/Library/Homebrew/test/rubocops/lines_cop_spec.rb
+++ b/Library/Homebrew/test/rubocops/lines_cop_spec.rb
@@ -42,7 +42,7 @@ describe RuboCop::Cop::FormulaAudit::Lines do
column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses.reverse).each do |expected, actual|
expect_offense(expected, actual)
@@ -50,12 +50,6 @@ describe RuboCop::Cop::FormulaAudit::Lines do
end
end
end
- def expect_offense(expected, actual)
- expect(actual.message).to eq(expected[:message])
- expect(actual.severity).to eq(expected[:severity])
- expect(actual.line).to eq(expected[:line])
- expect(actual.column).to eq(expected[:column])
- end
end
describe RuboCop::Cop::FormulaAudit::ClassInheritance do
@@ -76,19 +70,13 @@ describe RuboCop::Cop::FormulaAudit::ClassInheritance do
column: 10,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source, '/homebrew-core/Formula/foo.rb')
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
end
end
end
- def expect_offense(expected, actual)
- expect(actual.message).to eq(expected[:message])
- expect(actual.severity).to eq(expected[:severity])
- expect(actual.line).to eq(expected[:line])
- expect(actual.column).to eq(expected[:column])
- end
end
describe RuboCop::Cop::FormulaAudit::Comments do
@@ -104,13 +92,13 @@ describe RuboCop::Cop::FormulaAudit::Comments do
end
EOS
- expected_offenses = [{ message: "Commented cmake call found",
+ expected_offenses = [{ message: "Please remove default template comments",
severity: :convention,
line: 4,
column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -132,7 +120,7 @@ describe RuboCop::Cop::FormulaAudit::Comments do
column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -148,25 +136,19 @@ describe RuboCop::Cop::FormulaAudit::Comments do
end
EOS
- expected_offenses = [{ message: 'Commented-out dep "foo"',
+ expected_offenses = [{ message: 'Commented-out dependency "foo"',
severity: :convention,
line: 4,
column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
end
end
end
- def expect_offense(expected, actual)
- expect(actual.message).to eq(expected[:message])
- expect(actual.severity).to eq(expected[:severity])
- expect(actual.line).to eq(expected[:line])
- expect(actual.column).to eq(expected[:column])
- end
end
describe RuboCop::Cop::FormulaAudit::Miscellaneous do
@@ -188,7 +170,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -212,7 +194,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -237,7 +219,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 4,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -264,7 +246,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 7,
source: source }]
- inspect_source(cop, source, "/homebrew-core/")
+ inspect_source(source, "/homebrew-core/")
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -292,7 +274,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -317,7 +299,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -342,7 +324,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -358,14 +340,16 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
end
EOS
- expected_offenses = [{ message: "`skip_clean :all` is deprecated; brew no longer strips symbols\n" \
- "\tPass explicit paths to prevent Homebrew from removing empty folders.",
+ 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)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -383,19 +367,34 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
end
EOS
- expected_offenses = [{ message: "macOS has been 64-bit only so build.universal? is deprecated.",
+ 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)
+ inspect_source(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(source, "/homebrew-core/Formula/wine.rb")
+ expect(cop.offenses).to eq([])
+ end
+
it "with ENV.universal_binary" do
source = <<-EOS.undent
class Foo < Formula
@@ -413,14 +412,14 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 5,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
end
end
- it "with ENV.universal_binary" do
+ it "with ENV.universal_binary 2" do
source = <<-EOS.undent
class Foo < Formula
desc "foo"
@@ -437,7 +436,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 5,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -459,13 +458,26 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 10,
source: source }]
- inspect_source(cop, source)
+ inspect_source(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(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
@@ -478,16 +490,29 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
expected_offenses = [{ message: "Use Language::Node for npm install args",
severity: :convention,
line: 4,
- column: 17,
+ column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(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(source, "/homebrew-core/Formula/kibana@4.4.rb")
+ expect(cop.offenses).to eq([])
+ end
+
it "with assert include" do
source = <<-EOS.undent
class Foo < Formula
@@ -503,7 +528,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 9,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -525,12 +550,13 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 13,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
end
end
+
it "with old style OS check" do
source = <<-EOS.undent
class Foo < Formula
@@ -546,7 +572,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 21,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -569,12 +595,13 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 13,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
end
end
+
it "with system call to fileUtils Method" do
source = <<-EOS.undent
class Foo < Formula
@@ -590,12 +617,13 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 10,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
end
end
+
it "with a top-level function def " do
source = <<-EOS.undent
def test
@@ -613,7 +641,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 0,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -637,7 +665,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 18,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -661,7 +689,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 18,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -685,7 +713,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 14,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -709,7 +737,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 14,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -733,7 +761,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 30,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -757,7 +785,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 27,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -781,7 +809,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 30,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -805,7 +833,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 30,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -829,7 +857,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 14,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -853,7 +881,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 22,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -877,7 +905,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 12,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -901,7 +929,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 12,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -925,7 +953,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 28,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -949,7 +977,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 28,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -973,7 +1001,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 17,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -997,7 +1025,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 18,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -1021,12 +1049,13 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 47,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
end
end
+
it "with formula path shortcut long form 3" do
source = <<-EOS.undent
class Foo < Formula
@@ -1044,7 +1073,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 46,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -1066,7 +1095,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 24,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -1088,7 +1117,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 10,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -1110,7 +1139,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 13,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -1134,7 +1163,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 5,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -1158,7 +1187,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 4,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -1182,7 +1211,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 26,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -1206,7 +1235,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 14,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -1228,7 +1257,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -1250,7 +1279,7 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -1272,18 +1301,11 @@ describe RuboCop::Cop::FormulaAudit::Miscellaneous do
column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
end
end
-
- end
- def expect_offense(expected, actual)
- expect(actual.message).to eq(expected[:message])
- expect(actual.severity).to eq(expected[:severity])
- expect(actual.line).to eq(expected[:line])
- expect(actual.column).to eq(expected[:column])
end
end
diff --git a/Library/Homebrew/test/rubocops/options_cop_spec.rb b/Library/Homebrew/test/rubocops/options_cop_spec.rb
index b89b3d9b5..c27389a68 100644
--- a/Library/Homebrew/test/rubocops/options_cop_spec.rb
+++ b/Library/Homebrew/test/rubocops/options_cop_spec.rb
@@ -21,7 +21,7 @@ describe RuboCop::Cop::FormulaAudit::Options do
column: 10,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -48,7 +48,7 @@ describe RuboCop::Cop::FormulaAuditStrict::Options do
column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -72,7 +72,7 @@ describe RuboCop::Cop::FormulaAuditStrict::Options do
column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -95,7 +95,7 @@ describe RuboCop::Cop::FormulaAuditStrict::Options do
column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -122,7 +122,7 @@ describe RuboCop::Cop::NewFormulaAudit::Options do
column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
diff --git a/Library/Homebrew/test/rubocops/patches_cop_spec.rb b/Library/Homebrew/test/rubocops/patches_cop_spec.rb
index 4bd79bf35..4f9ca2df8 100644
--- a/Library/Homebrew/test/rubocops/patches_cop_spec.rb
+++ b/Library/Homebrew/test/rubocops/patches_cop_spec.rb
@@ -13,7 +13,7 @@ describe RuboCop::Cop::FormulaAudit::Patches do
url 'http://example.com/foo-1.0.tgz'
end
EOS
- inspect_source(cop, source)
+ inspect_source(source)
expect(cop.offenses).to eq([])
end
@@ -28,13 +28,13 @@ describe RuboCop::Cop::FormulaAudit::Patches do
end
EOS
- expected_offenses = [{ message: "Use the patch DSL instead of defining a 'patches' method",
- severity: :convention,
- line: 4,
- column: 2,
- source: source }]
+ expected_offenses = [{ message: "Use the patch DSL instead of defining a 'patches' method",
+ severity: :convention,
+ line: 4,
+ column: 2,
+ source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -48,6 +48,7 @@ describe RuboCop::Cop::FormulaAudit::Patches do
"http://trac.macports.org/export/102865/trunk/dports/mail/uudeview/files/inews.c.patch",
"http://bugs.debian.org/cgi-bin/bugreport.cgi?msg=5;filename=patch-libunac1.txt;att=1;bug=623340",
"https://patch-diff.githubusercontent.com/raw/foo/foo-bar/pull/100.patch",
+ "https://github.com/dlang/dub/pull/1221.patch",
]
patch_urls.each do |patch_url|
source = <<-EOS.undent
@@ -60,42 +61,65 @@ describe RuboCop::Cop::FormulaAudit::Patches do
end
EOS
- inspect_source(cop, source)
- if patch_url =~ %r{/raw\.github\.com/}
- expected_offenses = [{ message: "GitHub/Gist patches should specify a revision:\n#{patch_url}",
- severity: :convention,
- line: 5,
- column: 12,
- source: source }]
+ inspect_source(source)
+ expected_offense = if patch_url =~ %r{/raw\.github\.com/}
+ [{ message: <<-EOS.undent.chomp,
+ GitHub/Gist patches should specify a revision:
+ #{patch_url}
+ EOS
+ severity: :convention,
+ line: 5,
+ column: 12,
+ source: source }]
elsif patch_url =~ %r{macports/trunk}
- expected_offenses = [{ message: "MacPorts patches should specify a revision instead of trunk:\n#{patch_url}",
- severity: :convention,
- line: 5,
- column: 33,
- source: source }]
+ [{ message: <<-EOS.undent.chomp,
+ MacPorts patches should specify a revision instead of trunk:
+ #{patch_url}
+ EOS
+ severity: :convention,
+ line: 5,
+ column: 33,
+ source: source }]
elsif patch_url =~ %r{^http://trac\.macports\.org}
- expected_offenses = [{ message: "Patches from MacPorts Trac should be https://, not http:\n#{patch_url}",
- severity: :convention,
- line: 5,
- column: 5,
- source: source }]
+ [{ message: <<-EOS.undent.chomp,
+ Patches from MacPorts Trac should be https://, not http:
+ #{patch_url}
+ EOS
+ severity: :convention,
+ line: 5,
+ column: 5,
+ source: source }]
elsif patch_url =~ %r{^http://bugs\.debian\.org}
- expected_offenses = [{ message: "Patches from Debian should be https://, not http:\n#{patch_url}",
- severity: :convention,
- line: 5,
- column: 5,
- source: source }]
+ [{ message: <<-EOS.undent.chomp,
+ Patches from Debian should be https://, not http:
+ #{patch_url}
+ EOS
+ severity: :convention,
+ line: 5,
+ column: 5,
+ source: source }]
elsif patch_url =~ %r{https?://patch-diff\.githubusercontent\.com/raw/(.+)/(.+)/pull/(.+)\.(?:diff|patch)}
- expected_offenses = [{ message: "use GitHub pull request URLs:\n"\
- " https://github.com/foo/foo-bar/pull/100.patch\n"\
- "Rather than patch-diff:\n"\
- " https://patch-diff.githubusercontent.com/raw/foo/foo-bar/pull/100.patch\n",
- severity: :convention,
- line: 5,
- column: 5,
- source: source }]
+ [{ message: <<-EOS.undent,
+ use GitHub pull request URLs:
+ https://github.com/foo/foo-bar/pull/100.patch
+ Rather than patch-diff:
+ https://patch-diff.githubusercontent.com/raw/foo/foo-bar/pull/100.patch
+ EOS
+ severity: :convention,
+ line: 5,
+ column: 5,
+ source: source }]
+ elsif patch_url =~ %r{https?://github\.com/.+/.+/(?:commit|pull)/[a-fA-F0-9]*.(?:patch|diff)}
+ [{ message: <<-EOS.undent,
+ GitHub patches should use the full_index parameter:
+ #{patch_url}?full_index=1
+ EOS
+ severity: :convention,
+ line: 5,
+ column: 5,
+ source: source }]
end
- expected_offenses.zip([cop.offenses.last]).each do |expected, actual|
+ expected_offense.zip([cop.offenses.last]).each do |expected, actual|
expect_offense(expected, actual)
end
end
@@ -116,19 +140,21 @@ describe RuboCop::Cop::FormulaAudit::Patches do
end
EOS
- expected_offenses = [{ message: "Use the patch DSL instead of defining a 'patches' method",
- severity: :convention,
- line: 4,
- column: 2,
- source: source },
- { message: "Patches from MacPorts Trac should be https://, not http:\n"\
- "http://trac.macports.org/export/68507/trunk/dports/net/trafshow/files/",
- severity: :convention,
- line: 8,
- column: 26,
- source: source }]
+ expected_offenses = [{ message: "Use the patch DSL instead of defining a 'patches' method",
+ severity: :convention,
+ line: 4,
+ column: 2,
+ source: source },
+ { message: <<-EOS.undent.chomp,
+ Patches from MacPorts Trac should be https://, not http:
+ http://trac.macports.org/export/68507/trunk/dports/net/trafshow/files/
+ EOS
+ severity: :convention,
+ line: 8,
+ column: 26,
+ source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -157,42 +183,56 @@ describe RuboCop::Cop::FormulaAudit::Patches do
end
EOS
- inspect_source(cop, source)
- if patch_url =~ %r{/raw\.github\.com/}
- expected_offenses = [{ message: "GitHub/Gist patches should specify a revision:\n#{patch_url}",
- severity: :convention,
- line: 5,
- column: 16,
- source: source }]
+ inspect_source(source)
+ expected_offense = if patch_url =~ %r{/raw\.github\.com/}
+ [{ message: <<-EOS.undent.chomp,
+ GitHub/Gist patches should specify a revision:
+ #{patch_url}
+ EOS
+ severity: :convention,
+ line: 5,
+ column: 16,
+ source: source }]
elsif patch_url =~ %r{macports/trunk}
- expected_offenses = [{ message: "MacPorts patches should specify a revision instead of trunk:\n#{patch_url}",
- severity: :convention,
- line: 5,
- column: 37,
- source: source }]
+ [{ message: <<-EOS.undent.chomp,
+ MacPorts patches should specify a revision instead of trunk:
+ #{patch_url}
+ EOS
+ severity: :convention,
+ line: 5,
+ column: 37,
+ source: source }]
elsif patch_url =~ %r{^http://trac\.macports\.org}
- expected_offenses = [{ message: "Patches from MacPorts Trac should be https://, not http:\n#{patch_url}",
- severity: :convention,
- line: 5,
- column: 9,
- source: source }]
+ [{ message: <<-EOS.undent.chomp,
+ Patches from MacPorts Trac should be https://, not http:
+ #{patch_url}
+ EOS
+ severity: :convention,
+ line: 5,
+ column: 9,
+ source: source }]
elsif patch_url =~ %r{^http://bugs\.debian\.org}
- expected_offenses = [{ message: "Patches from Debian should be https://, not http:\n#{patch_url}",
- severity: :convention,
- line: 5,
- column: 9,
- source: source }]
+ [{ message: <<-EOS.undent.chomp,
+ Patches from Debian should be https://, not http:
+ #{patch_url}
+ EOS
+ severity: :convention,
+ line: 5,
+ column: 9,
+ source: source }]
elsif patch_url =~ %r{https?://patch-diff\.githubusercontent\.com/raw/(.+)/(.+)/pull/(.+)\.(?:diff|patch)}
- expected_offenses = [{ message: "use GitHub pull request URLs:\n"\
- " https://github.com/foo/foo-bar/pull/100.patch\n"\
- "Rather than patch-diff:\n"\
- " https://patch-diff.githubusercontent.com/raw/foo/foo-bar/pull/100.patch\n",
- severity: :convention,
- line: 5,
- column: 9,
- source: source }]
+ [{ message: <<-EOS.undent,
+ use GitHub pull request URLs:
+ https://github.com/foo/foo-bar/pull/100.patch
+ Rather than patch-diff:
+ https://patch-diff.githubusercontent.com/raw/foo/foo-bar/pull/100.patch
+ EOS
+ severity: :convention,
+ line: 5,
+ column: 9,
+ source: source }]
end
- expected_offenses.zip([cop.offenses.last]).each do |expected, actual|
+ expected_offense.zip([cop.offenses.last]).each do |expected, actual|
expect_offense(expected, actual)
end
end
diff --git a/Library/Homebrew/test/rubocops/text_cop_spec.rb b/Library/Homebrew/test/rubocops/text_cop_spec.rb
index b218e9c25..490801770 100644
--- a/Library/Homebrew/test/rubocops/text_cop_spec.rb
+++ b/Library/Homebrew/test/rubocops/text_cop_spec.rb
@@ -7,6 +7,54 @@ describe RuboCop::Cop::FormulaAudit::Text do
subject(:cop) { described_class.new }
context "When auditing formula text" do
+ it "with both openssl and libressl optional dependencies" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ url "http://example.com/foo-1.0.tgz"
+ homepage "http://example.com"
+
+ depends_on "openssl"
+ depends_on "libressl" => :optional
+ end
+ EOS
+
+ expected_offenses = [{ message: "Formulae should not depend on both OpenSSL and LibreSSL (even optionally).",
+ severity: :convention,
+ line: 6,
+ column: 2,
+ source: source }]
+
+ inspect_source(source)
+
+ expected_offenses.zip(cop.offenses).each do |expected, actual|
+ expect_offense(expected, actual)
+ end
+ end
+
+ it "with both openssl and libressl dependencies" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ url "http://example.com/foo-1.0.tgz"
+ homepage "http://example.com"
+
+ depends_on "openssl"
+ depends_on "libressl"
+ end
+ EOS
+
+ expected_offenses = [{ message: "Formulae should not depend on both OpenSSL and LibreSSL (even optionally).",
+ severity: :convention,
+ line: 6,
+ column: 2,
+ source: source }]
+
+ inspect_source(source)
+
+ expected_offenses.zip(cop.offenses).each do |expected, actual|
+ expect_offense(expected, actual)
+ end
+ end
+
it "When xcodebuild is called without SYMROOT" do
source = <<-EOS.undent
class Foo < Formula
@@ -25,7 +73,7 @@ describe RuboCop::Cop::FormulaAudit::Text do
column: 4,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -50,7 +98,7 @@ describe RuboCop::Cop::FormulaAudit::Text do
column: 4,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -75,7 +123,7 @@ describe RuboCop::Cop::FormulaAudit::Text do
column: 4,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -100,7 +148,7 @@ describe RuboCop::Cop::FormulaAudit::Text do
column: 4,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -125,7 +173,7 @@ describe RuboCop::Cop::FormulaAudit::Text do
column: 4,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -162,7 +210,7 @@ describe RuboCop::Cop::FormulaAudit::Text do
column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -189,7 +237,7 @@ describe RuboCop::Cop::FormulaAudit::Text do
column: 0,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -219,7 +267,7 @@ describe RuboCop::Cop::FormulaAudit::Text do
column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
@@ -244,7 +292,7 @@ describe RuboCop::Cop::FormulaAudit::Text do
column: 4,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses).each do |expected, actual|
expect_offense(expected, actual)
diff --git a/Library/Homebrew/test/rubocops/urls_cop_spec.rb b/Library/Homebrew/test/rubocops/urls_cop_spec.rb
index 280da6314..ad939a1a2 100644
--- a/Library/Homebrew/test/rubocops/urls_cop_spec.rb
+++ b/Library/Homebrew/test/rubocops/urls_cop_spec.rb
@@ -54,8 +54,10 @@ describe RuboCop::Cop::FormulaAudit::Urls do
"col" => 2,
}, {
"url" => "http://prdownloads.sourceforge.net/foo/foo-1.tar.gz",
- "msg" => "Don't use prdownloads in SourceForge urls (url is http://prdownloads.sourceforge.net/foo/foo-1.tar.gz).\n" \
- "\tSee: http://librelist.com/browser/homebrew/2011/1/12/prdownloads-is-bad/",
+ "msg" => <<-EOS.undent.chomp,
+ Don't use prdownloads in SourceForge urls (url is http://prdownloads.sourceforge.net/foo/foo-1.tar.gz).
+ See: http://librelist.com/browser/homebrew/2011/1/12/prdownloads-is-bad/
+ EOS
"col" => 2,
}, {
"url" => "http://foo.dl.sourceforge.net/sourceforge/foozip/foozip_1.0.tar.bz2",
@@ -67,8 +69,11 @@ describe RuboCop::Cop::FormulaAudit::Urls do
"col" => 2,
}, {
"url" => "http://http.debian.net/debian/dists/foo/",
- "msg" => "Please use a secure mirror for Debian URLs.\nWe recommend:\n"\
- " https://mirrors.ocf.berkeley.edu/debian/dists/foo/\n",
+ "msg" => <<-EOS.undent,
+ Please use a secure mirror for Debian URLs.
+ We recommend:
+ https://mirrors.ocf.berkeley.edu/debian/dists/foo/
+ EOS
"col" => 2,
}, {
"url" => "http://foo.googlecode.com/files/foo-1.0.zip",
@@ -96,8 +101,12 @@ describe RuboCop::Cop::FormulaAudit::Urls do
"col" => 2,
}, {
"url" => "https://codeload.github.com/foo/bar/tar.gz/v0.1.1",
- "msg" => "Use GitHub archive URLs:\n https://github.com/foo/bar/archive/v0.1.1.tar.gz\n"\
- "Rather than codeload:\n https://codeload.github.com/foo/bar/tar.gz/v0.1.1\n",
+ "msg" => <<-EOS.undent,
+ Use GitHub archive URLs:
+ https://github.com/foo/bar/archive/v0.1.1.tar.gz
+ Rather than codeload:
+ https://codeload.github.com/foo/bar/tar.gz/v0.1.1
+ EOS
"col" => 2,
}, {
"url" => "https://central.maven.org/maven2/com/bar/foo/1.1/foo-1.1.jar",
@@ -117,7 +126,7 @@ describe RuboCop::Cop::FormulaAudit::Urls do
column: formula["col"],
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses.reverse).each do |expected, actual|
expect_offense(expected, actual)
@@ -151,7 +160,7 @@ describe RuboCop::Cop::FormulaAudit::Urls do
column: formula["col"],
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses.reverse).each do |expected, actual|
expect_offense(expected, actual)
@@ -174,7 +183,7 @@ describe RuboCop::Cop::FormulaAudit::Urls do
column: 2,
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
expected_offenses.zip(cop.offenses.reverse).each do |expected, actual|
expect_offense(expected, actual)
@@ -213,13 +222,13 @@ describe RuboCop::Cop::FormulaAuditStrict::PyPiUrls do
column: formula["col"],
source: source }]
- inspect_source(cop, source)
+ inspect_source(source)
# Check for expected offenses
expected_offenses.zip(cop.offenses.reverse).each do |expected, actual|
expect_offense(expected, actual)
end
# Check for expected auto corrected source
- new_source = autocorrect_source(cop, source)
+ new_source = autocorrect_source(source)
expect(new_source).to eq(corrected_source)
end
end
diff --git a/Library/Homebrew/test/support/fixtures/bottles/testball_bottle-0.1.yosemite.bottle.tar.gz b/Library/Homebrew/test/support/fixtures/bottles/testball_bottle-0.1.yosemite.bottle.tar.gz
index d88838a94..62ea6c264 100644
--- a/Library/Homebrew/test/support/fixtures/bottles/testball_bottle-0.1.yosemite.bottle.tar.gz
+++ b/Library/Homebrew/test/support/fixtures/bottles/testball_bottle-0.1.yosemite.bottle.tar.gz
Binary files differ
diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/with-conflicts-with.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-conflicts-with.rb
index ab3631743..13d1fc4fc 100644
--- a/Library/Homebrew/test/support/fixtures/cask/Casks/with-conflicts-with.rb
+++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-conflicts-with.rb
@@ -5,7 +5,7 @@ cask 'with-conflicts-with' do
url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
homepage 'http://example.com/with-conflicts-with'
- conflicts_with formula: 'unar'
+ conflicts_with cask: 'local-caffeine'
app 'Caffeine.app'
end
diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/with-languages.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-languages.rb
new file mode 100644
index 000000000..90ff63846
--- /dev/null
+++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-languages.rb
@@ -0,0 +1,18 @@
+cask 'with-languages' do
+ version '1.2.3'
+
+ language "zh" do
+ sha256 "abc123"
+ "zh-CN"
+ end
+
+ language "en-US", default: true do
+ sha256 "xyz789"
+ "en-US"
+ end
+
+ url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
+ homepage 'http://example.com/local-caffeine'
+
+ app 'Caffeine.app'
+end
diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/without-languages.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/without-languages.rb
new file mode 100644
index 000000000..4c0ce955a
--- /dev/null
+++ b/Library/Homebrew/test/support/fixtures/cask/Casks/without-languages.rb
@@ -0,0 +1,9 @@
+cask 'without-languages' do
+ version '1.2.3'
+ sha256 '67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94'
+
+ url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
+ homepage 'http://example.com/local-caffeine'
+
+ app 'Caffeine.app'
+end
diff --git a/Library/Homebrew/test/support/fixtures/testball_bottle.rb b/Library/Homebrew/test/support/fixtures/testball_bottle.rb
index 9453255e6..5a6be7c5f 100644
--- a/Library/Homebrew/test/support/fixtures/testball_bottle.rb
+++ b/Library/Homebrew/test/support/fixtures/testball_bottle.rb
@@ -6,7 +6,7 @@ class TestballBottle < Formula
stable.bottle do
cellar :any_skip_relocation
root_url "file://#{TEST_FIXTURE_DIR}/bottles"
- sha256 "9abc8ce779067e26556002c4ca6b9427b9874d25f0cafa7028e05b5c5c410cb4" => Utils::Bottles.tag
+ sha256 "d48bbbe583dcfbfa608579724fc6f0328b3cd316935c6ea22f134610aaf2952f" => Utils::Bottles.tag
end
cxxstdlib_check :skip
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/fixtures.rb b/Library/Homebrew/test/support/helper/fixtures.rb
index 716fe2008..460fb4aef 100644
--- a/Library/Homebrew/test/support/helper/fixtures.rb
+++ b/Library/Homebrew/test/support/helper/fixtures.rb
@@ -8,6 +8,10 @@ module Test
def bundle_path(name)
Pathname.new("#{TEST_FIXTURE_DIR}/mach/#{name}.bundle")
end
+
+ def cask_path(name)
+ Pathname.new("#{TEST_FIXTURE_DIR}/cask/Casks/#{name}.rb")
+ end
end
end
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 9b539262f..a132894f9 100644
--- a/Library/Homebrew/test/utils/github_spec.rb
+++ b/Library/Homebrew/test/utils/github_spec.rb
@@ -2,12 +2,38 @@ require "utils/github"
describe GitHub do
describe "::search_code", :needs_network do
- it "searches code" do
- results = subject.search_code("repo:Homebrew/brew", "path:/", "filename:readme", "language:markdown")
+ it "queries GitHub code with the passed parameters" do
+ results = subject.search_code(repo: "Homebrew/brew", path: "/",
+ filename: "readme", language: "markdown")
expect(results.count).to eq(1)
expect(results.first["name"]).to eq("README.md")
expect(results.first["path"]).to eq("README.md")
end
end
+
+ describe "::query_string" do
+ it "builds a query with the given hash parameters formatted as key:value" do
+ query = subject.query_string(user: "Homebrew", repo: "brew")
+ expect(query).to eq("q=user%3AHomebrew+repo%3Abrew&per_page=100")
+ end
+
+ it "adds a variable number of top-level string parameters to the query when provided" do
+ query = subject.query_string("value1", "value2", user: "Homebrew")
+ expect(query).to eq("q=value1+value2+user%3AHomebrew&per_page=100")
+ end
+
+ it "turns array values into multiple key:value parameters" do
+ query = subject.query_string(user: ["Homebrew", "caskroom"])
+ expect(query).to eq("q=user%3AHomebrew+user%3Acaskroom&per_page=100")
+ end
+ end
+
+ describe "::search_issues", :needs_network do
+ it "queries GitHub issues with the passed parameters" do
+ results = subject.search_issues("brew search", repo: "Homebrew/brew", author: "avetamine", is: "closed")
+ expect(results).not_to be_empty
+ expect(results.last["title"]).to eq("brew search : 422 Unprocessable Entity")
+ end
+ end
end
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..d0393afa6 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
@@ -639,6 +649,11 @@ describe Version do
.to be_detected_from("ftp://gcc.gnu.org/pub/gcc/snapshots/6-20151227/gcc-6-20151227.tar.bz2")
end
+ specify "semver in middle of URL" do
+ expect(Version.create("7.1.10"))
+ .to be_detected_from("https://php.net/get/php-7.1.10.tar.gz/from/this/mirror")
+ end
+
specify "from URL" do
expect(Version.create("1.2.3"))
.to be_detected_from("http://github.com/foo/bar.git", tag: "v1.2.3")
diff --git a/Library/Homebrew/utils.rb b/Library/Homebrew/utils.rb
index e3137ac49..237ffa74e 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
@@ -229,10 +229,9 @@ module Homebrew
EOS
end
- # Hash of Module => Set(method_names)
- @injected_dump_stat_modules = {}
-
+ # rubocop:disable Style/GlobalVars
def inject_dump_stats!(the_module, pattern)
+ @injected_dump_stat_modules ||= {}
@injected_dump_stat_modules[the_module] ||= []
injected_methods = @injected_dump_stat_modules[the_module]
the_module.module_eval do
@@ -260,11 +259,12 @@ module Homebrew
end
end
end
+ # rubocop:enable Style/GlobalVars
end
def with_system_path
old_path = ENV["PATH"]
- ENV["PATH"] = "/usr/bin:/bin"
+ ENV["PATH"] = PATH.new("/usr/bin", "/bin")
yield
ensure
ENV["PATH"] = old_path
@@ -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/bottles.rb b/Library/Homebrew/utils/bottles.rb
index 927963bc1..66b5fb640 100644
--- a/Library/Homebrew/utils/bottles.rb
+++ b/Library/Homebrew/utils/bottles.rb
@@ -29,9 +29,11 @@ module Utils
end
def receipt_path(bottle_file)
- Utils.popen_read("tar", "-tzf", bottle_file).lines.map(&:chomp).find do |line|
+ path = Utils.popen_read("tar", "-tzf", bottle_file).lines.map(&:chomp).find do |line|
line =~ %r{.+/.+/INSTALL_RECEIPT.json}
end
+ raise "This bottle does not contain the file INSTALL_RECEIPT.json: #{bottle_file}" unless path
+ path
end
def resolve_formula_names(bottle_file)
@@ -52,6 +54,15 @@ module Utils
def resolve_version(bottle_file)
PkgVersion.parse receipt_path(bottle_file).split("/")[1]
end
+
+ def formula_contents(bottle_file,
+ name: resolve_formula_names(bottle_file)[0])
+ bottle_version = resolve_version bottle_file
+ formula_path = "#{name}/#{bottle_version}/.brew/#{name}.rb"
+ contents = Utils.popen_read "tar", "-xOzf", bottle_file, formula_path
+ raise BottleFormulaUnavailableError.new(bottle_file, formula_path) unless $CHILD_STATUS.success?
+ contents
+ end
end
class Bintray
diff --git a/Library/Homebrew/utils/curl.rb b/Library/Homebrew/utils/curl.rb
index 5a40ae846..7807d2034 100644
--- a/Library/Homebrew/utils/curl.rb
+++ b/Library/Homebrew/utils/curl.rb
@@ -1,42 +1,57 @@
require "pathname"
require "open3"
-def curl_args(options = {})
+def curl_executable
curl = Pathname.new ENV["HOMEBREW_CURL"]
curl = Pathname.new "/usr/bin/curl" unless curl.exist?
- raise "#{curl} is not executable" unless curl.exist? && curl.executable?
+ return curl if curl.executable?
+ raise "#{curl} is not executable"
+end
+def curl_args(*extra_args, show_output: false, user_agent: :default)
args = [
- curl.to_s,
- "--remote-time",
- "--location",
+ curl_executable.to_s,
+ "--show-error",
]
- case options[:user_agent]
- when :browser
- args << "--user-agent" << HOMEBREW_USER_AGENT_FAKE_SAFARI
+ args << "--user-agent" << case user_agent
+ when :browser, :fake
+ HOMEBREW_USER_AGENT_FAKE_SAFARI
+ when :default
+ HOMEBREW_USER_AGENT_CURL
else
- args << "--user-agent" << HOMEBREW_USER_AGENT_CURL
+ user_agent
end
- unless options[:show_output]
+ unless show_output
+ args << "--fail"
args << "--progress-bar" unless ARGV.verbose?
args << "--verbose" if ENV["HOMEBREW_CURL_VERBOSE"]
- args << "--fail"
args << "--silent" if !$stdout.tty? || ENV["TRAVIS"]
end
- args += options[:extra_args] if options[:extra_args]
- args
+ args + extra_args
end
def curl(*args)
- safe_system(*curl_args(extra_args: args))
+ safe_system(*curl_args(*args))
end
-def curl_output(*args)
- curl_args = curl_args(extra_args: args, show_output: true)
- Open3.popen3(*curl_args) do |_, stdout, stderr, wait_thread|
- [stdout.read, stderr.read, wait_thread.value]
+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.
+ # 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
+
+ raise
+end
+
+def curl_output(*args, **options)
+ Open3.capture3(*curl_args(*args, show_output: true, **options))
end
diff --git a/Library/Homebrew/utils/fork.rb b/Library/Homebrew/utils/fork.rb
index 92f5bf899..57ddbfae2 100644
--- a/Library/Homebrew/utils/fork.rb
+++ b/Library/Homebrew/utils/fork.rb
@@ -14,7 +14,7 @@ module Utils
read.close
write.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
yield
- rescue Exception => e
+ rescue Exception => e # rubocop:disable Lint/RescueException
Marshal.dump(e, write)
write.close
exit!
@@ -26,8 +26,11 @@ module Utils
ignore_interrupts(:quietly) do # the child will receive the interrupt and marshal it back
begin
socket = server.accept_nonblock
+ # rubocop:disable Lint/ShadowedException
+ # FIXME: https://github.com/bbatsov/rubocop/issues/4843
rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
retry unless Process.waitpid(pid, Process::WNOHANG)
+ # rubocop:enable Lint/ShadowedException
else
socket.send_io(write)
socket.close
@@ -36,9 +39,9 @@ module Utils
data = read.read
read.close
Process.wait(pid) unless socket.nil?
- raise Marshal.load(data) unless data.nil? || data.empty?
+ raise Marshal.load(data) unless data.nil? || data.empty? # rubocop:disable Security/MarshalLoad
raise Interrupt if $CHILD_STATUS.exitstatus == 130
- raise "Suspicious failure" unless $CHILD_STATUS.success?
+ raise "Forked child process failed: #{$CHILD_STATUS}" unless $CHILD_STATUS.success?
end
end
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 1a781cee6..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)
@@ -133,7 +127,7 @@ module GitHub
def open(url, data: nil, scopes: [].freeze)
# This is a no-op if the user is opting out of using the GitHub API.
- return if ENV["HOMEBREW_NO_GITHUB_API"]
+ return block_given? ? yield({}) : {} if ENV["HOMEBREW_NO_GITHUB_API"]
args = %W[--header application/vnd.github.v3+json --write-out \n%{http_code}]
args += curl_args
@@ -166,7 +160,7 @@ module GitHub
args += ["--dump-header", headers_tmpfile.path]
- output, errors, status = curl_output(url.to_s, *args)
+ output, errors, status = curl_output(url.to_s, "--location", *args)
output, _, http_code = output.rpartition("\n")
output, _, http_code = output.rpartition("\n") if http_code == "000"
headers = headers_tmpfile.read
@@ -227,72 +221,60 @@ module GitHub
end
end
- def issues_matching(query, qualifiers = {})
- uri = URI.parse("#{API_URL}/search/issues")
- uri.query = build_query_string(query, qualifiers)
- open(uri) { |json| json["items"] }
+ def search_issues(query, **qualifiers)
+ search("issues", query, **qualifiers)
end
def repository(user, repo)
- open(URI.parse("#{API_URL}/repos/#{user}/#{repo}"))
- end
-
- def search_code(*params)
- uri = URI.parse("#{API_URL}/search/code")
- uri.query = "q=#{uri_escape(params.join(" "))}"
- open(uri) { |json| json["items"] }
+ open(url_to("repos", user, repo))
end
- def build_query_string(query, qualifiers)
- s = "q=#{uri_escape(query)}+"
- s << build_search_qualifier_string(qualifiers)
- s << "&per_page=100"
- end
-
- def build_search_qualifier_string(qualifiers)
- {
- repo: "Homebrew/homebrew-core",
- in: "title",
- }.update(qualifiers).map do |qualifier, value|
- "#{qualifier}:#{value}"
- end.join("+")
- end
-
- def uri_escape(query)
- if URI.respond_to?(:encode_www_form_component)
- URI.encode_www_form_component(query)
- else
- require "erb"
- ERB::Util.url_encode(query)
- end
+ def search_code(**qualifiers)
+ search("code", **qualifiers)
end
def issues_for_formula(name, options = {})
tap = options[:tap] || CoreTap.instance
- issues_matching(name, state: "open", repo: "#{tap.user}/homebrew-#{tap.repo}")
+ search_issues(name, state: "open", repo: "#{tap.user}/homebrew-#{tap.repo}")
end
def print_pull_requests_matching(query)
- return [] if ENV["HOMEBREW_NO_GITHUB_API"]
-
- open_or_closed_prs = issues_matching(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" }
- if !open_prs.empty?
+ prs = if !open_prs.empty?
puts "Open pull requests:"
- prs = open_prs
- elsif !open_or_closed_prs.empty?
- puts "Closed pull requests:"
- prs = open_or_closed_prs
+ open_prs
else
- return
+ puts "Closed pull requests:" unless open_or_closed_prs.empty?
+ open_or_closed_prs
end
prs.each { |i| puts "#{i["title"]} (#{i["html_url"]})" }
end
def private_repo?(full_name)
- uri = URI.parse("#{API_URL}/repos/#{full_name}")
+ uri = url_to "repos", full_name
open(uri) { |json| json["private"] }
end
+
+ def query_string(*main_params, **qualifiers)
+ params = main_params
+
+ params += qualifiers.flat_map do |key, value|
+ Array(value).map { |v| "#{key}:#{v}" }
+ end
+
+ "q=#{URI.encode_www_form_component(params.join(" "))}&per_page=100"
+ end
+
+ def url_to(*subroutes)
+ URI.parse([API_URL, *subroutes].join("/"))
+ end
+
+ def search(entity, *queries, **qualifiers)
+ uri = url_to "search", entity
+ uri.query = query_string(*queries, **qualifiers)
+ open(uri) { |json| json.fetch("items", []) }
+ end
end
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/Library/Homebrew/version.rb b/Library/Homebrew/version.rb
index b03a4bc33..d43e0c665 100644
--- a/Library/Homebrew/version.rb
+++ b/Library/Homebrew/version.rb
@@ -213,110 +213,6 @@ class Version
end
end
- def initialize(val)
- unless val.respond_to?(:to_str)
- raise TypeError, "Version value must be a string; got a #{val.class} (#{val})"
- end
- @version = val.to_str
- end
-
- def detected_from_url?
- false
- end
-
- def head?
- false
- end
-
- def null?
- false
- end
-
- def <=>(other)
- # Needed to retain API compatibility with older string comparisons
- # for compiler versions, etc.
- other = Version.new(other) if other.is_a? String
- # Used by the *_build_version comparisons, which formerly returned Fixnum
- other = Version.new(other.to_s) if other.is_a? Integer
- return 1 if other.nil?
-
- return unless other.is_a?(Version)
- return 0 if version == other.version
- return 1 if head? && !other.head?
- return -1 if !head? && other.head?
- return 0 if head? && other.head?
-
- ltokens = tokens
- rtokens = other.tokens
- max = max(ltokens.length, rtokens.length)
- l = r = 0
-
- while l < max
- a = ltokens[l] || NULL_TOKEN
- b = rtokens[r] || NULL_TOKEN
-
- if a == b
- l += 1
- r += 1
- next
- elsif a.numeric? && b.numeric?
- return a <=> b
- elsif a.numeric?
- return 1 if a > NULL_TOKEN
- l += 1
- elsif b.numeric?
- return -1 if b > NULL_TOKEN
- r += 1
- else
- return a <=> b
- end
- end
-
- 0
- end
- alias eql? ==
-
- def hash
- version.hash
- end
-
- def to_f
- version.to_f
- end
-
- def to_s
- version.dup
- end
- alias to_str to_s
-
- protected
-
- attr_reader :version
-
- def tokens
- @tokens ||= tokenize
- end
-
- private
-
- def max(a, b)
- (a > b) ? a : b
- end
-
- def tokenize
- version.scan(SCAN_PATTERN).map! do |token|
- case token
- when /\A#{AlphaToken::PATTERN}\z/o then AlphaToken
- when /\A#{BetaToken::PATTERN}\z/o then BetaToken
- when /\A#{RCToken::PATTERN}\z/o then RCToken
- when /\A#{PreToken::PATTERN}\z/o then PreToken
- when /\A#{PatchToken::PATTERN}\z/o then PatchToken
- when /\A#{NumericToken::PATTERN}\z/o then NumericToken
- when /\A#{StringToken::PATTERN}\z/o then StringToken
- end.new(token)
- end
- end
-
def self.parse(spec)
version = _parse(spec)
version.nil? ? NULL : new(version)
@@ -456,6 +352,116 @@ class Version
# e.g. http://www.ijg.org/files/jpegsrc.v8d.tar.gz
m = /\.v(\d+[a-z]?)/.match(stem)
return m.captures.first unless m.nil?
+
+ # e.g. https://secure.php.net/get/php-7.1.10.tar.bz2/from/this/mirror
+ m = /[-.vV]?((?:\d+\.)+\d+(?:[-_.]?(?i:alpha|beta|pre|rc)\.?\d{,2})?)/.match(spec_s)
+ return m.captures.first unless m.nil?
+ end
+
+ private_class_method :_parse
+
+ def initialize(val)
+ unless val.respond_to?(:to_str)
+ raise TypeError, "Version value must be a string; got a #{val.class} (#{val})"
+ end
+ @version = val.to_str
+ end
+
+ def detected_from_url?
+ false
+ end
+
+ def head?
+ false
+ end
+
+ def null?
+ false
+ end
+
+ def <=>(other)
+ # Needed to retain API compatibility with older string comparisons
+ # for compiler versions, etc.
+ other = Version.new(other) if other.is_a? String
+ # Used by the *_build_version comparisons, which formerly returned Fixnum
+ other = Version.new(other.to_s) if other.is_a? Integer
+ return 1 if other.nil?
+
+ return unless other.is_a?(Version)
+ return 0 if version == other.version
+ return 1 if head? && !other.head?
+ return -1 if !head? && other.head?
+ return 0 if head? && other.head?
+
+ ltokens = tokens
+ rtokens = other.tokens
+ max = max(ltokens.length, rtokens.length)
+ l = r = 0
+
+ while l < max
+ a = ltokens[l] || NULL_TOKEN
+ b = rtokens[r] || NULL_TOKEN
+
+ if a == b
+ l += 1
+ r += 1
+ next
+ elsif a.numeric? && b.numeric?
+ return a <=> b
+ elsif a.numeric?
+ return 1 if a > NULL_TOKEN
+ l += 1
+ elsif b.numeric?
+ return -1 if b > NULL_TOKEN
+ r += 1
+ else
+ return a <=> b
+ end
+ end
+
+ 0
+ end
+ alias eql? ==
+
+ def hash
+ version.hash
+ end
+
+ def to_f
+ version.to_f
+ end
+
+ def to_s
+ version.dup
+ end
+ alias to_str to_s
+
+ protected
+
+ attr_reader :version
+
+ def tokens
+ @tokens ||= tokenize
+ end
+
+ private
+
+ def max(a, b)
+ (a > b) ? a : b
+ end
+
+ def tokenize
+ version.scan(SCAN_PATTERN).map! do |token|
+ case token
+ when /\A#{AlphaToken::PATTERN}\z/o then AlphaToken
+ when /\A#{BetaToken::PATTERN}\z/o then BetaToken
+ when /\A#{RCToken::PATTERN}\z/o then RCToken
+ when /\A#{PreToken::PATTERN}\z/o then PreToken
+ when /\A#{PatchToken::PATTERN}\z/o then PatchToken
+ when /\A#{NumericToken::PATTERN}\z/o then NumericToken
+ when /\A#{StringToken::PATTERN}\z/o then StringToken
+ end.new(token)
+ end
end
end
diff --git a/README.md b/README.md
index 4d63942ae..2ff99df3a 100644
--- a/README.md
+++ b/README.md
@@ -22,7 +22,7 @@ Second, read the [Troubleshooting Checklist](https://docs.brew.sh/Troubleshootin
[![Travis](https://img.shields.io/travis/Homebrew/brew.svg)](https://travis-ci.org/Homebrew/brew)
[![Codecov](https://img.shields.io/codecov/c/github/Homebrew/brew.svg)](https://codecov.io/gh/Homebrew/brew)
-We'd love you to contribute to Homebrew. First, please read our [Contribution Guide](https://github.com/Homebrew/brew/blob/master/CONTRIBUTING.md) and [Code of Conduct](https://github.com/Homebrew/brew/blob/master/CODEOFCONDUCT.md#code-of-conduct).
+We'd love you to contribute to Homebrew. First, please read our [Contribution Guide](https://github.com/Homebrew/brew/blob/master/CONTRIBUTING.md) and [Code of Conduct](https://github.com/Homebrew/brew/blob/master/CODE_OF_CONDUCT.md#code-of-conduct).
We explicitly welcome contributions from people who have never contributed to open-source before: we were all beginners once! We can help build on a partially working pull request with the aim of getting it merged. We are also actively seeking to diversify our contributors and especially welcome contributions from women from all backgrounds and people of colour.
@@ -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/bash/brew b/completions/bash/brew
index 03a05cb37..60c272f73 100644
--- a/completions/bash/brew
+++ b/completions/bash/brew
@@ -563,10 +563,10 @@ _brew() {
if [[ "$i" -eq "$COMP_CWORD" ]]
then
- # Do not auto-complete "instal" abbreviation for "install" command.
+ # Do not auto-complete "*instal" or "*uninstal" aliases for "*install" commands.
# Prefix newline to prevent not checking the first command.
- local cmds=$'\n'"$(brew commands --quiet --include-aliases)"
- __brewcomp "${cmds/$'\n'instal$'\n'/$'\n'}"
+ local cmds=$'\n'"$(brew commands --quiet --include-aliases | grep -v instal$)"
+ __brewcomp "${cmds}"
return
fi
diff --git a/completions/zsh/_brew b/completions/zsh/_brew
index 61dc26b42..22792860d 100644
--- a/completions/zsh/_brew
+++ b/completions/zsh/_brew
@@ -284,8 +284,8 @@ _brew_create() {
':url:_urls'
}
-# brew deps [--1] [-n] [--union] [--full-name] [--installed] [--include-build] [--include-optional] [--skip-recommended] formulae
-# brew deps --tree [filters] (formulae|--installed)
+# brew deps [--1] [-n] [--union] [--full-name] [--installed] [--include-build] [--include-optional] [--skip-recommended] [--include-requirements] formulae
+# brew deps --tree [--1] [filters] (formulae|--installed)
# brew deps [filters] (--installed|--all)
# The filters placeholder is any combination of options --include-build, --include-optional, and --skip-recommended as documented above.
_brew_deps() {
@@ -294,6 +294,7 @@ _brew_deps() {
'--include-build[include \:build dependencies]' \
'--include-optional[include \:optional dependencies]' \
'--skip-recommended[skip \:recommended type dependencies]' \
+ '--include-requirements[include requirements]' \
'--1[only show dependencies one level down, instead of recursing]' \
'-n[show dependencies in topological order]' \
'--union[show the union of dependencies for formulae, instead of the intersection]' \
@@ -303,6 +304,11 @@ _brew_deps() {
- tree-deps \
'--tree[show dependencies as a tree]' \
'(*)--installed[show dependencies for all installed formulae]' \
+ '--include-build[include \:build dependencies]' \
+ '--include-optional[include \:optional dependencies]' \
+ '--skip-recommended[skip \:recommended type dependencies]' \
+ '--include-requirements[include requirements]' \
+ '--1[only show dependencies one level down, instead of recursing]' \
'(--installed)*:formulae:__brew_formulae' \
- installed-all \
'--include-build[include \:build dependencies]' \
@@ -586,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/FAQ.md b/docs/FAQ.md
index 23f53d54c..9d76bf4ab 100644
--- a/docs/FAQ.md
+++ b/docs/FAQ.md
@@ -26,6 +26,8 @@ To allow that formulae to update again:
brew unpin <formula>
+Note that pinned, outdated formulae that are depended on by another formula will be upgraded when required as we do not allow formulae to be built against non-latest versions.
+
## How do I uninstall old versions of a formula?
By default, Homebrew does not uninstall old versions of a formula, so
over time you will accumulate old versions. To remove them, simply use:
@@ -66,13 +68,12 @@ Be careful as this is a destructive operation.
Which is usually: `~/Library/Caches/Homebrew`
## My Mac `.app`s don’t find `/usr/local/bin` utilities!
-GUI apps on macOS don’t have `/usr/local/bin` in their `PATH` by default.
-If you’re on Mountain Lion, you can fix this by running
-`launchctl setenv PATH "/usr/local/bin:$PATH"`. [More details
-here](https://stackoverflow.com/questions/135688/setting-environment-variables-in-os-x/5444960#5444960),
-including how to set this across reboots. If you’re pre-Mountain Lion,
-[here’s an official
-alternative](https://developer.apple.com/legacy/library/qa/qa1067/_index.html).
+GUI apps on macOS don’t have `/usr/local/bin` in their `PATH` by
+default. If you’re on Mountain Lion or later, you can fix this by
+running `sudo launchctl config user path "/usr/local/bin:$PATH"` and
+then rebooting, as documented in `man launchctl`. Note that this sets
+the launchctl PATH for _all users_. For earlier versions of macOS, see
+[this page](https://developer.apple.com/legacy/library/qa/qa1067/_index.html).
## How do I contribute to Homebrew?
Read [CONTRIBUTING.md](https://github.com/Homebrew/brew/blob/master/CONTRIBUTING.md).
diff --git a/docs/Formula-Cookbook.md b/docs/Formula-Cookbook.md
index e60afe071..0266d39e5 100644
--- a/docs/Formula-Cookbook.md
+++ b/docs/Formula-Cookbook.md
@@ -693,7 +693,7 @@ Note that [`option`](http://www.rubydoc.info/github/Homebrew/brew/master/Formula
### File level operations
-You can use the file utilities provided by Ruby's [`FileUtils`](http://www.ruby-doc.org/stdlib/libdoc/fileutils/rdoc/index.html). These are included in the `Formula` class, so you do not need the `FileUtils.` prefix to use them.
+You can use the file utilities provided by Ruby's [`FileUtils`](https://www.ruby-doc.org/stdlib/libdoc/fileutils/rdoc/index.html). These are included in the `Formula` class, so you do not need the `FileUtils.` prefix to use them.
When creating symlinks, take special care to ensure they are *relative* symlinks. This makes it easier to create a relocatable bottle. For example, to create a symlink in `bin` to an executable in `libexec`, use
diff --git a/docs/Homebrew-and-Python.md b/docs/Homebrew-and-Python.md
index 692e5c617..8b263cb38 100644
--- a/docs/Homebrew-and-Python.md
+++ b/docs/Homebrew-and-Python.md
@@ -24,13 +24,13 @@ The Python formulae install [pip](http://www.pip-installer.org) (as `pip2` or `p
Setuptools can be updated via pip, without having to re-brew Python:
```sh
-pip install --upgrade setuptools
+python2 -m pip --upgrade setuptools
```
Similarly, pip can be used to upgrade itself via:
```sh
-pip install --upgrade pip
+python2 -m pip install --upgrade pip
```
### Note on `pip install --user`
@@ -39,7 +39,7 @@ The normal `pip install --user` is disabled for brewed Python. This is because o
A possible workaround (which puts executable scripts in `~/Library/Python/<X>.<Y>/bin`) is:
```sh
-pip install --user --install-option="--prefix=" <package-name>
+python2 -m pip install --user --install-option="--prefix=" <package-name>
```
## `site-packages` and the `PYTHONPATH`
@@ -86,7 +86,7 @@ CFLAGS=-I$(brew --prefix)/include LDFLAGS=-L$(brew --prefix)/lib pip install <pa
Activate the virtualenv *after* you've brewed, or brew in a fresh Terminal window.
Homebrew will still install Python modules into Homebrew's `site-packages` and *not* into the virtual environment's site-package.
-Virtualenv has a switch to allow "global" (i.e. Homebrew's) `site-packages` to be accessible from within the virtualenv.
+Virtualenv has a `--system-site-packages` switch to allow "global" (i.e. Homebrew's) `site-packages` to be accessible from within the virtualenv.
## Why is Homebrew's Python being installed as a dependency?
Formulae that depend on the special `:python` target are bottled against the Homebrew Python and require it to be installed. You can avoid installing Homebrew's Python by building these formulae with `--build-from-source`.
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/docs/Interesting-Taps-and-Forks.md b/docs/Interesting-Taps-and-Forks.md
index 6b70fadec..5e3fc19d2 100644
--- a/docs/Interesting-Taps-and-Forks.md
+++ b/docs/Interesting-Taps-and-Forks.md
@@ -5,11 +5,9 @@ Homebrew has the capability to add (and remove) multiple taps to your local inst
## Main taps
-* [homebrew/apache](https://github.com/Homebrew/homebrew-apache): A tap for Apache modules, extending macOS's built-in Apache. These brews may require unconventional additional setup, as explained in the caveats.
+* [homebrew/nginx](https://github.com/Homebrew/homebrew-nginx): A tap for NGINX modules, intended for its `nginx-full` formula which includes more module options.
-* [homebrew/nginx](https://github.com/Homebrew/homebrew-nginx): Feature rich Nginx tap for modules.
-
-* [homebrew/php](https://github.com/Homebrew/homebrew-php): Repository for php-related formulae.
+* [homebrew/php](https://github.com/Homebrew/homebrew-php): Repository for PHP-related formulae.
* [homebrew/science](https://github.com/Homebrew/homebrew-science): A collection of scientific libraries and tools.
@@ -21,8 +19,6 @@ You can be added as a maintainer for one of the Homebrew organization taps and a
* [InstantClientTap/instantclient](https://github.com/InstantClientTap/homebrew-instantclient): A tap for Oracle Instant Client. The packages need to be downloaded manually.
-* [besport/ocaml](https://github.com/besport/homebrew-ocaml): A tap for Ocaml libraries, though with caveats, it requires you install its customized ocaml formula. Perhaps a template for more work.
-
* [osx-cross/avr](https://github.com/osx-cross/homebrew-avr): GNU AVR toolchain (Libc, compilers and other tools for Atmel MCUs, useful for Arduino hackers and AVR programmers).
* [petere/postgresql](https://github.com/petere/homebrew-postgresql): Allows installing multiple PostgreSQL versions in parallel.
@@ -31,6 +27,10 @@ You can be added as a maintainer for one of the Homebrew organization taps and a
* [dunn/emacs](https://github.com/dunn/homebrew-emacs): A tap for Emacs packages.
+* [sidaf/pentest](https://github.com/sidaf/homebrew-pentest): Tools for penetration testing.
+
+* [osrf/simulation](https://github.com/osrf/homebrew-simulation): Tools for robotics simulation.
+
## Interesting forks
* [mistydemeo/tigerbrew](https://github.com/mistydemeo/tigerbrew): Experimental Tiger PowerPC version
diff --git a/docs/Kickstarter-Supporters.md b/docs/Kickstarter-Supporters.md
index 84ba662b4..146718aec 100644
--- a/docs/Kickstarter-Supporters.md
+++ b/docs/Kickstarter-Supporters.md
@@ -379,7 +379,7 @@ These wonderful people supported our Kickstarter by giving us ÂŁ10 or more:
* [Andrew Brown](http://pvalu.es)
* [Bethany Sumner](http://www.bethanysumner.com/)
* [Orta](http://orta.io)
-* [Michał Gołębiowski](https://github.com/mgol)
+* [Michał Gołębiowski-Owczarek](https://github.com/mgol)
* [Adam C. Foltzer](http://www.acfoltzer.net/)
* [Steve Hiemstra](https://www.speg.com)
* [Anton Sipos](http://www.softwarefuturism.com)
diff --git a/docs/Manpage.md b/docs/Manpage.md
index 49f6bb5ae..f92991147 100644
--- a/docs/Manpage.md
+++ b/docs/Manpage.md
@@ -77,7 +77,7 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note
a bug report, you will likely be asked for this information if you do not
provide it.
- * `deps` [`--1`] [`-n`] [`--union`] [`--full-name`] [`--installed`] [`--include-build`] [`--include-optional`] [`--skip-recommended`] `formulae`:
+ * `deps` [`--1`] [`-n`] [`--union`] [`--full-name`] [`--installed`] [`--include-build`] [`--include-optional`] [`--skip-recommended`] [`--include-requirements`] `formulae`:
Show dependencies for `formulae`. When given multiple formula arguments,
show the intersection of dependencies for `formulae`.
@@ -98,15 +98,22 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note
`formulae`. To include the `:build` type dependencies, pass `--include-build`.
Similarly, pass `--include-optional` to include `:optional` dependencies.
To skip `:recommended` type dependencies, pass `--skip-recommended`.
+ To include requirements in addition to dependencies, pass `--include-requirements`.
- * `deps` `--tree` [`filters`] (`formulae`|`--installed`):
+ * `deps` `--tree` [`--1`] [`filters`] [`--annotate`] (`formulae`|`--installed`):
Show dependencies as a tree. When given multiple formula arguments, output
individual trees for every formula.
+ If `--1` is passed, only one level of children is displayed.
+
If `--installed` is passed, output a tree for every installed formula.
The `filters` placeholder is any combination of options `--include-build`,
- `--include-optional`, and `--skip-recommended` as documented above.
+ `--include-optional`, `--skip-recommended`, and `--include-requirements` as
+ documented above.
+
+ If `--annotate` is passed, the build, optional, and recommended dependencies
+ are marked as such in the output.
* `deps` [`filters`] (`--installed`|`--all`):
Show dependencies for installed or all available formulae. Every line of
@@ -364,7 +371,8 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note
* `pin` `formulae`:
Pin the specified `formulae`, preventing them from being upgraded when
- issuing the `brew upgrade` command. See also `unpin`.
+ issuing the `brew upgrade `formulae`` command (but can still be upgraded
+ as dependencies for other formulae). See also `unpin`.
* `postinstall` `formula`:
Rerun the post-install steps for `formula`.
@@ -529,8 +537,8 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note
source. This is useful for creating patches for the software.
* `unpin` `formulae`:
- Unpin `formulae`, allowing them to be upgraded by `brew upgrade`. See also
- `pin`.
+ Unpin `formulae`, allowing them to be upgraded by `brew upgrade `formulae``.
+ See also `pin`.
* `untap` `tap`:
Remove a tapped repository.
diff --git a/docs/Prose-Style-Guidelines.md b/docs/Prose-Style-Guidelines.md
index 232ccb1be..4fe19bdb8 100644
--- a/docs/Prose-Style-Guidelines.md
+++ b/docs/Prose-Style-Guidelines.md
@@ -16,7 +16,7 @@ Homebrew's audience includes users with a wide range of education and experience
We strive for "correct" but not "fancy" usage. Think newspaper article, not academic paper.
-This is a set of guidelines to be applied using human judgment, not a set of hard and fast rules. It is like [The Economist's Style Guide](http://www.economist.com/styleguide/introduction) or [Garner's Modern American Usage](https://en.wikipedia.org/wiki/Garner's_Modern_American_Usage). It is less like the [Ruby Style Guide](https://github.com/bbatsov/ruby-style-guide). All guidelines here are open to interpretation and discussion. 100% conformance to these guidelines is *not* a goal.
+This is a set of guidelines to be applied using human judgment, not a set of hard and fast rules. It is like [The Economist's Style Guide](https://www.economist.com/styleguide/introduction) or [Garner's Modern American Usage](https://en.wikipedia.org/wiki/Garner's_Modern_American_Usage). It is less like the [Ruby Style Guide](https://github.com/bbatsov/ruby-style-guide). All guidelines here are open to interpretation and discussion. 100% conformance to these guidelines is *not* a goal.
The intent of this document is to help authors make decisions about clarity, style, and consistency. It is not to help settle arguments about who knows English better. Don't use this document to be a jerk.
diff --git a/docs/Python-for-Formula-Authors.md b/docs/Python-for-Formula-Authors.md
index 5b9d6ced6..129f5ba5e 100644
--- a/docs/Python-for-Formula-Authors.md
+++ b/docs/Python-for-Formula-Authors.md
@@ -10,33 +10,7 @@ Bindings are a special case of libraries that allow Python code to interact with
Homebrew is happy to accept applications that are built in Python, whether the apps are available from PyPI or not. Homebrew generally won't accept libraries that can be installed correctly with `pip install foo`. Bindings may be installed for packages that provide them, especially if equivalent functionality isn't available through pip.
-## Running `setup.py`
-
-Homebrew provides a helper method, `Language::Python.setup_install_args`, which returns arguments for invoking `setup.py`. Your formula should use this instead of invoking `setup.py` explicitly. The syntax is:
-
-```ruby
-system "python", *Language::Python.setup_install_args(prefix)
-```
-
-where `prefix` is the destination prefix (usually `libexec` or `prefix`).
-
-## Python module dependencies
-
-In general, applications should unconditionally bundle all of their dependencies and libraries and should install any unsatisfied dependencies; these strategies are discussed in depth in the following sections.
-
-In the rare instance that this proves impractical, you can specify a Python module as an external dependency using this syntax:
-
-```ruby
-depends_on "numpy" => :python
-```
-
-Or if the import name is different from the module name:
-
-```ruby
-depends_on "MacFSEvents" => [:python, "fsevents"]
-```
-
-If you submit a formula with this syntax to core, you may be asked to rewrite it as a `Requirement`.
+Applications should unconditionally bundle all of their Python-language dependencies and libraries and should install any unsatisfied dependencies; these strategies are discussed in depth in the following sections.
## Applications
@@ -147,9 +121,9 @@ in case you need to do different things for different resources.
## Bindings
-To add an option to a formula to build Python bindings, use `depends_on :python => :recommended` and install the bindings conditionally on `build.with? "python"` in your `install` method.
+Build bindings with system Python by default (don't add an option) and they should be usable with any binary-compatible Python. If that isn't the case, it's an upstream bug; [here's some advice for resolving it](http://blog.tim-smith.us/2015/09/python-extension-modules-os-x/).
-Python bindings should be optional because if the formula is bottled, any `:recommended` or mandatory dependencies on `:python` are always resolved by installing the Homebrew `python` formula, which will upset users that prefer to use the system Python. This is because we cannot generally create a binary package that works against both versions of Python.
+To add bindings for Python 3, please add `depends_on :python3 => :optional` and make the bindings conditional on `build.with?("python3")`.
### Dependencies
@@ -179,9 +153,7 @@ Sometimes we have to `inreplace` a `Makefile` to use our prefix for the Python b
### Python declarations
-Libraries **should** declare a dependency on `:python` or `:python3` as appropriate, which will respectively cause the formula to use the first python or python3 discovered in `PATH` at install time. If a library supports both Python 2.x and Python 3.x, the `:python` dependency **should** be `:recommended` (i.e. built by default) and the `:python3` dependency should be `:optional`. Python 2.x libraries **must** function when they are installed against either the system Python or Homebrew Python.
-
-Formulae that declare a dependency on `:python` will always be bottled against Homebrew's python, since we cannot in general build binary packages that can be imported from both Pythons. Users can add `--build-from-source` after `brew install` to compile against whichever python is in `PATH`.
+Python 2 libraries do not need a `depends_on :python` declaration; they will be built with system Python, but should still be usable with any other Python 2.7. If this is not the case, it is an upstream bug; [here is some advice for resolving it](http://blog.tim-smith.us/2015/09/python-extension-modules-os-x/). Libraries built for Python 3 should include `depends_on :python3`, which will bottle against Homebrew's python3, and use the first python3 discovered in `PATH` at build time when installing from source with `brew install --build-from-source`. If a library supports both Python 2.x and Python 3.x, the `:python3` dependency should be `:optional`. Python 2.x libraries must function when they are installed against either the system Python or Homebrew Python.
### Installing
@@ -191,7 +163,7 @@ Most formulae presently just install to `prefix`.
### Dependencies
-The dependencies of libraries must be installed so that they are importable. The principle of minimum surprise suggests that installing a Homebrew library should not alter the other libraries in a user's `sys.path`. The best way to achieve this is to only install dependencies if they are not already installed. To minimize the potential for linking conflicts, dependencies should be installed to `libexec/"vendor"` and added to `sys.path` by writing a second .pth file (named like "homebrew-foo-dependencies.pth") to the `prefix` site-packages.
+The dependencies of libraries must be installed so that they are importable. To minimize the potential for linking conflicts, dependencies should be installed to `libexec/"vendor"` and added to `sys.path` by writing a second .pth file (named like "homebrew-foo-dependencies.pth") to the `prefix` site-packages.
The [matplotlib](https://github.com/Homebrew/homebrew-science/blob/master/matplotlib.rb) formula in [homebrew/science](https://github.com/Homebrew/homebrew-science) deploys this strategy.
@@ -209,6 +181,16 @@ Distutils and pip use a "flat" installation hierarchy that installs modules as i
Distribute (not to be confused with distutils) is an obsolete fork of setuptools. Distlib is a package maintained outside the standard library which is used by pip for some low-level packaging operations and is not relevant to most `setup.py` users.
+### Running `setup.py`
+
+In the event that a formula needs to interact with `setup.py` instead of calling `pip`, Homebrew provides a helper method, `Language::Python.setup_install_args`, which returns useful arguments for invoking `setup.py`. Your formula should use this instead of invoking `setup.py` explicitly. The syntax is:
+
+```ruby
+system "python", *Language::Python.setup_install_args(prefix)
+```
+
+where `prefix` is the destination prefix (usually `libexec` or `prefix`).
+
### What is `--single-version-externally-managed`?
`--single-version-externally-managed` ("SVEM") is a setuptools-only [argument to `setup.py install`](https://setuptools.readthedocs.io/en/latest/setuptools.html?#install-run-easy-install-or-old-style-installation). The primary effect of SVEM is to use distutils to perform the install instead of using setuptools' `easy_install`.
diff --git a/manpages/brew-cask.1 b/manpages/brew-cask.1
index f11d48c09..f2acf1842 100644
--- a/manpages/brew-cask.1
+++ b/manpages/brew-cask.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BREW\-CASK" "1" "July 2017" "Homebrew" "brew-cask"
+.TH "BREW\-CASK" "1" "September 2017" "Homebrew" "brew-cask"
.
.SH "NAME"
\fBbrew\-cask\fR \- a friendly binary installer for macOS
@@ -18,7 +18,7 @@ Homebrew\-Cask works robustly enough that we welcome new users, but the project
.SH "FREQUENTLY USED COMMANDS"
.
.TP
-\fBinstall\fR [\-\-force] [\-\-skip\-cask\-deps] [\-\-require\-sha] \fItoken\fR [ \fItoken\fR \.\.\. ]
+\fBinstall\fR [\-\-force] [\-\-skip\-cask\-deps] [\-\-require\-sha] [\-\-language=\fIiso\-language\fR[,\fIiso\-language\fR \.\.\. ]] \fItoken\fR [ \fItoken\fR \.\.\. ]
Install Cask identified by \fItoken\fR\.
.
.TP
@@ -35,7 +35,7 @@ The tokens returned by \fBsearch\fR are suitable as arguments for most other com
.SH "COMMANDS"
.
.TP
-\fBaudit\fR [ \fItoken\fR \.\.\. ]
+\fBaudit\fR [\-\-language=\fIiso\-language\fR[,\fIiso\-language\fR \.\.\. ]] [ \fItoken\fR \.\.\. ]
Check the given Casks for installability\. If no tokens are given on the command line, all Casks are audited\.
.
.TP
@@ -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 \.\.\. ]
@@ -169,6 +169,10 @@ Give additional feedback during installation\.
Target location for Applications\. The default value is \fB/Applications\fR\.
.
.TP
+\fB\-\-language=<iso\-language>[,<iso\-language> \.\.\. ]]\fR
+Set language of the Cask to install\. The first matching language is used, otherwise the default language on the Cask\. The default value is the \fBlanguage of your system\fR\.
+.
+.TP
\fB\-\-colorpickerdir=<path>\fR
Target location for Color Pickers\. The default value is \fB~/Library/ColorPickers\fR\.
.
diff --git a/manpages/brew.1 b/manpages/brew.1
index 2d8ba3f09..b3d840275 100644
--- a/manpages/brew.1
+++ b/manpages/brew.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BREW" "1" "July 2017" "Homebrew" "brew"
+.TH "BREW" "1" "September 2017" "Homebrew" "brew"
.
.SH "NAME"
\fBbrew\fR \- The missing package manager for macOS
@@ -88,7 +88,7 @@ If \fB\-\-quiet\fR is passed, list only the names of commands without the header
Show Homebrew and system configuration useful for debugging\. If you file a bug report, you will likely be asked for this information if you do not provide it\.
.
.TP
-\fBdeps\fR [\fB\-\-1\fR] [\fB\-n\fR] [\fB\-\-union\fR] [\fB\-\-full\-name\fR] [\fB\-\-installed\fR] [\fB\-\-include\-build\fR] [\fB\-\-include\-optional\fR] [\fB\-\-skip\-recommended\fR] \fIformulae\fR
+\fBdeps\fR [\fB\-\-1\fR] [\fB\-n\fR] [\fB\-\-union\fR] [\fB\-\-full\-name\fR] [\fB\-\-installed\fR] [\fB\-\-include\-build\fR] [\fB\-\-include\-optional\fR] [\fB\-\-skip\-recommended\fR] [\fB\-\-include\-requirements\fR] \fIformulae\fR
Show dependencies for \fIformulae\fR\. When given multiple formula arguments, show the intersection of dependencies for \fIformulae\fR\.
.
.IP
@@ -107,17 +107,23 @@ If \fB\-\-full\-name\fR is passed, list dependencies by their full name\.
If \fB\-\-installed\fR is passed, only list those dependencies that are currently installed\.
.
.IP
-By default, \fBdeps\fR shows required and recommended dependencies for \fIformulae\fR\. To include the \fB:build\fR type dependencies, pass \fB\-\-include\-build\fR\. Similarly, pass \fB\-\-include\-optional\fR to include \fB:optional\fR dependencies\. To skip \fB:recommended\fR type dependencies, pass \fB\-\-skip\-recommended\fR\.
+By default, \fBdeps\fR shows required and recommended dependencies for \fIformulae\fR\. To include the \fB:build\fR type dependencies, pass \fB\-\-include\-build\fR\. Similarly, pass \fB\-\-include\-optional\fR to include \fB:optional\fR dependencies\. To skip \fB:recommended\fR type dependencies, pass \fB\-\-skip\-recommended\fR\. To include requirements in addition to dependencies, pass \fB\-\-include\-requirements\fR\.
.
.TP
-\fBdeps\fR \fB\-\-tree\fR [\fIfilters\fR] (\fIformulae\fR|\fB\-\-installed\fR)
+\fBdeps\fR \fB\-\-tree\fR [\fB\-\-1\fR] [\fIfilters\fR] [\fB\-\-annotate\fR] (\fIformulae\fR|\fB\-\-installed\fR)
Show dependencies as a tree\. When given multiple formula arguments, output individual trees for every formula\.
.
.IP
+If \fB\-\-1\fR is passed, only one level of children is displayed\.
+.
+.IP
If \fB\-\-installed\fR is passed, output a tree for every installed formula\.
.
.IP
-The \fIfilters\fR placeholder is any combination of options \fB\-\-include\-build\fR, \fB\-\-include\-optional\fR, and \fB\-\-skip\-recommended\fR as documented above\.
+The \fIfilters\fR placeholder is any combination of options \fB\-\-include\-build\fR, \fB\-\-include\-optional\fR, \fB\-\-skip\-recommended\fR, and \fB\-\-include\-requirements\fR as documented above\.
+.
+.IP
+If \fB\-\-annotate\fR is passed, the build, optional, and recommended dependencies are marked as such in the output\.
.
.TP
\fBdeps\fR [\fIfilters\fR] (\fB\-\-installed\fR|\fB\-\-all\fR)
@@ -378,7 +384,7 @@ If \fB\-\-fetch\-HEAD\fR is passed, fetch the upstream repository to detect if t
.
.TP
\fBpin\fR \fIformulae\fR
-Pin the specified \fIformulae\fR, preventing them from being upgraded when issuing the \fBbrew upgrade\fR command\. See also \fBunpin\fR\.
+Pin the specified \fIformulae\fR, preventing them from being upgraded when issuing the \fBbrew upgrade <formulae>\fR command (but can still be upgraded as dependencies for other formulae)\. See also \fBunpin\fR\.
.
.TP
\fBpostinstall\fR \fIformula\fR
@@ -549,7 +555,7 @@ If \fB\-\-git\fR (or \fB\-g\fR) is passed, a Git repository will be initialized
.
.TP
\fBunpin\fR \fIformulae\fR
-Unpin \fIformulae\fR, allowing them to be upgraded by \fBbrew upgrade\fR\. See also \fBpin\fR\.
+Unpin \fIformulae\fR, allowing them to be upgraded by \fBbrew upgrade <formulae>\fR\. See also \fBpin\fR\.
.
.TP
\fBuntap\fR \fItap\fR