aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE.md10
-rw-r--r--.gitignore1
-rw-r--r--.travis.yml14
-rw-r--r--Library/.rubocop.yml18
-rw-r--r--Library/Homebrew/PATH.rb74
-rw-r--r--Library/Homebrew/brew.rb17
-rw-r--r--Library/Homebrew/brew.sh7
-rw-r--r--Library/Homebrew/build_options.rb1
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/binary.rb7
-rw-r--r--Library/Homebrew/cask/lib/hbc/cask.rb52
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/doctor.rb2
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/reinstall.rb28
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/search.rb36
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/uninstall.rb10
-rw-r--r--Library/Homebrew/cask/lib/hbc/container.rb2
-rw-r--r--Library/Homebrew/cask/lib/hbc/dsl/container.rb9
-rw-r--r--Library/Homebrew/cask/lib/hbc/installer.rb41
-rw-r--r--Library/Homebrew/cask/lib/hbc/metadata.rb73
-rw-r--r--Library/Homebrew/cask/lib/hbc/pkg.rb7
-rw-r--r--Library/Homebrew/cask/lib/hbc/scopes.rb3
-rw-r--r--Library/Homebrew/cask/lib/hbc/utils.rb13
-rw-r--r--Library/Homebrew/caveats.rb10
-rw-r--r--Library/Homebrew/cmd/--env.rb4
-rw-r--r--Library/Homebrew/cmd/install.rb5
-rw-r--r--Library/Homebrew/cmd/link.rb4
-rw-r--r--Library/Homebrew/cmd/postinstall.rb5
-rw-r--r--Library/Homebrew/cmd/search.rb95
-rw-r--r--Library/Homebrew/cmd/sh.rb2
-rw-r--r--Library/Homebrew/cmd/style.rb42
-rw-r--r--Library/Homebrew/cmd/tap.rb13
-rw-r--r--Library/Homebrew/cmd/update.sh2
-rw-r--r--Library/Homebrew/cmd/uses.rb12
-rw-r--r--Library/Homebrew/compat.rb1
-rw-r--r--Library/Homebrew/compat/ARGV.rb2
-rw-r--r--Library/Homebrew/compat/build_options.rb7
-rw-r--r--Library/Homebrew/compat/dependency_collector.rb1
-rw-r--r--Library/Homebrew/compat/global.rb2
-rw-r--r--Library/Homebrew/compat/software_spec.rb2
-rw-r--r--Library/Homebrew/compat/tab.rb2
-rw-r--r--Library/Homebrew/compat/tap.rb2
-rw-r--r--Library/Homebrew/compat/utils.rb11
-rw-r--r--Library/Homebrew/compat/utils/shell.rb8
-rw-r--r--Library/Homebrew/dependable.rb2
-rw-r--r--Library/Homebrew/dev-cmd/audit.rb460
-rw-r--r--Library/Homebrew/dev-cmd/create.rb56
-rw-r--r--Library/Homebrew/dev-cmd/mirror.rb6
-rw-r--r--Library/Homebrew/dev-cmd/pull.rb6
-rw-r--r--Library/Homebrew/dev-cmd/tap-new.rb6
-rw-r--r--Library/Homebrew/dev-cmd/tests.rb39
-rw-r--r--Library/Homebrew/diagnostic.rb13
-rw-r--r--Library/Homebrew/download_strategy.rb3
-rw-r--r--Library/Homebrew/exceptions.rb84
-rw-r--r--Library/Homebrew/extend/ENV.rb7
-rw-r--r--Library/Homebrew/extend/ENV/shared.rb40
-rw-r--r--Library/Homebrew/extend/ENV/std.rb13
-rw-r--r--Library/Homebrew/extend/ENV/super.rb88
-rw-r--r--Library/Homebrew/extend/io.rb15
-rw-r--r--Library/Homebrew/extend/os/linux/requirements/osxfuse_requirement.rb39
-rw-r--r--Library/Homebrew/extend/os/mac/diagnostic.rb2
-rw-r--r--Library/Homebrew/extend/os/mac/formula_cellar_checks.rb8
-rw-r--r--Library/Homebrew/extend/os/mac/hardware/cpu.rb43
-rw-r--r--Library/Homebrew/extend/os/mac/requirements/osxfuse_requirement.rb34
-rw-r--r--Library/Homebrew/extend/os/requirements/osxfuse_requirement.rb7
-rw-r--r--Library/Homebrew/extend/pathname.rb6
-rw-r--r--Library/Homebrew/formula.rb47
-rw-r--r--Library/Homebrew/formula_cellar_checks.rb24
-rw-r--r--Library/Homebrew/formula_installer.rb93
-rw-r--r--Library/Homebrew/formula_support.rb16
-rw-r--r--Library/Homebrew/formula_versions.rb45
-rw-r--r--Library/Homebrew/formulary.rb23
-rw-r--r--Library/Homebrew/global.rb6
-rw-r--r--Library/Homebrew/gpg.rb5
-rw-r--r--Library/Homebrew/hardware.rb12
-rw-r--r--Library/Homebrew/keg.rb5
-rw-r--r--Library/Homebrew/language/python.rb23
-rw-r--r--Library/Homebrew/manpages/brew.1.md.erb39
-rw-r--r--Library/Homebrew/missing_formula.rb2
-rw-r--r--Library/Homebrew/official_taps.rb21
-rw-r--r--Library/Homebrew/os/mac.rb2
-rw-r--r--Library/Homebrew/os/mac/xcode.rb15
-rw-r--r--Library/Homebrew/os/mac/xquartz.rb1
-rw-r--r--Library/Homebrew/readall.rb23
-rw-r--r--Library/Homebrew/requirement.rb10
-rw-r--r--Library/Homebrew/requirements/osxfuse_requirement.rb30
-rw-r--r--Library/Homebrew/rubocops.rb3
-rw-r--r--Library/Homebrew/rubocops/bottle_block_cop.rb6
-rw-r--r--Library/Homebrew/rubocops/components_order_cop.rb114
-rw-r--r--Library/Homebrew/rubocops/components_redundancy_cop.rb33
-rw-r--r--Library/Homebrew/rubocops/extend/formula_cop.rb303
-rw-r--r--Library/Homebrew/rubocops/formula_desc_cop.rb4
-rw-r--r--Library/Homebrew/rubocops/homepage_cop.rb82
-rw-r--r--Library/Homebrew/sandbox.rb4
-rwxr-xr-xLibrary/Homebrew/shims/scm/git1
-rw-r--r--Library/Homebrew/software_spec.rb9
-rw-r--r--Library/Homebrew/tap.rb16
-rw-r--r--Library/Homebrew/test/.bundle/config1
-rw-r--r--Library/Homebrew/test/Gemfile.lock42
-rw-r--r--Library/Homebrew/test/PATH_spec.rb115
-rw-r--r--Library/Homebrew/test/cask/artifact/binary_spec.rb31
-rw-r--r--Library/Homebrew/test/cask/cask_spec.rb4
-rw-r--r--Library/Homebrew/test/cask/cli/install_spec.rb14
-rw-r--r--Library/Homebrew/test/cask/cli/reinstall_spec.rb23
-rw-r--r--Library/Homebrew/test/cask/cli/search_spec.rb6
-rw-r--r--Library/Homebrew/test/cask/cli/style_spec.rb2
-rw-r--r--Library/Homebrew/test/cask/cli/uninstall_spec.rb21
-rw-r--r--Library/Homebrew/test/cask/installer_spec.rb10
-rw-r--r--Library/Homebrew/test/cask/pkg_spec.rb9
-rw-r--r--Library/Homebrew/test/cmd/bundle_spec.rb2
-rw-r--r--Library/Homebrew/test/cmd/install_spec.rb12
-rw-r--r--Library/Homebrew/test/cmd/search_remote_tap_spec.rb14
-rw-r--r--Library/Homebrew/test/compiler_selector_spec.rb12
-rw-r--r--Library/Homebrew/test/dev-cmd/audit_spec.rb426
-rw-r--r--Library/Homebrew/test/dev-cmd/pull_spec.rb4
-rw-r--r--Library/Homebrew/test/diagnostic_spec.rb25
-rw-r--r--Library/Homebrew/test/formula_spec.rb18
-rw-r--r--Library/Homebrew/test/gpg2_requirement_spec.rb2
-rw-r--r--Library/Homebrew/test/gpg_spec.rb7
-rw-r--r--Library/Homebrew/test/hardware_spec.rb47
-rw-r--r--Library/Homebrew/test/missing_formula_spec.rb2
-rw-r--r--Library/Homebrew/test/os/linux/osxfuse_requirement_spec.rb9
-rw-r--r--Library/Homebrew/test/os/mac/hardware_spec.rb56
-rw-r--r--Library/Homebrew/test/os/mac/osxfuse_requirement_spec.rb36
-rw-r--r--Library/Homebrew/test/requirement_spec.rb10
-rw-r--r--Library/Homebrew/test/rubocops/bottle_block_cop_spec.rb2
-rw-r--r--Library/Homebrew/test/rubocops/components_order_cop_spec.rb163
-rw-r--r--Library/Homebrew/test/rubocops/components_redundancy_cop_spec.rb87
-rw-r--r--Library/Homebrew/test/rubocops/formula_desc_cop_spec.rb27
-rw-r--r--Library/Homebrew/test/rubocops/homepage_cop_spec.rb124
-rw-r--r--Library/Homebrew/test/spec_helper.rb5
-rw-r--r--Library/Homebrew/test/support/fixtures/cask/Casks/with-non-executable-binary.rb9
-rw-r--r--Library/Homebrew/test/support/fixtures/cask/naked_non_executable2
-rw-r--r--Library/Homebrew/test/support/helper/spec/shared_context/integration_test.rb1
-rw-r--r--Library/Homebrew/test/utils/github_spec.rb13
-rw-r--r--Library/Homebrew/test/utils/shell_spec.rb56
-rw-r--r--Library/Homebrew/test/utils_spec.rb8
-rw-r--r--Library/Homebrew/test/version_spec.rb5
-rw-r--r--Library/Homebrew/utils.rb41
-rw-r--r--Library/Homebrew/utils/analytics.sh2
-rw-r--r--Library/Homebrew/utils/github.rb14
-rw-r--r--Library/Homebrew/utils/shell.rb106
-rw-r--r--Library/Homebrew/vendor/README.md2
-rwxr-xr-xLibrary/Homebrew/vendor/plist/plist.rb6
-rwxr-xr-x[-rw-r--r--]Library/Homebrew/vendor/plist/plist/generator.rb10
-rwxr-xr-x[-rw-r--r--]Library/Homebrew/vendor/plist/plist/parser.rb37
-rwxr-xr-xLibrary/Homebrew/vendor/plist/plist/version.rb5
-rw-r--r--Library/Homebrew/version.rb5
-rw-r--r--README.md15
-rwxr-xr-xbin/brew14
-rw-r--r--docs/.well-known/acme-challenge/CgQNmjNTd6fUriinp4XpuRI5PBGp7zEXbEEsQceSD0k1
-rw-r--r--docs/Acceptable-Formulae.md13
-rw-r--r--docs/Interesting-Taps-&-Forks.md2
-rw-r--r--docs/Manpage.md60
-rw-r--r--docs/Python-for-Formula-Authors.md2
-rw-r--r--docs/Troubleshooting.md3
-rw-r--r--docs/Xcode.md4
-rw-r--r--docs/_config.yml1
-rw-r--r--docs/_layouts/index.html2
-rw-r--r--docs/css/reset.css53
-rw-r--r--docs/css/screen.css362
-rw-r--r--docs/css/screen.scss488
-rw-r--r--manpages/brew-cask.12
-rw-r--r--manpages/brew.170
162 files changed, 3536 insertions, 1897 deletions
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index 9eca6149b..6816a3ae3 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -1,17 +1,17 @@
# Please always follow these steps:
-- [ ] Confirmed this is a problem with Homebrew/brew and not 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 just `brew install`ing one or more formulae? If it's a formulae-specific problem please file this issue at https://github.com/Homebrew/homebrew-core/issues/new
- [ ] Ran `brew update` and retried your prior step?
-- [ ] Ran `brew doctor`, fixed as many issues as possible 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 may immediately 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)
-**Please note we may immediately close your issue without comment if you do not fill out the issue template and provide ALL the requested information.**
-
# Or propose a feature:
-Please replace this section with a detailed description of your proposed feature, the motivation for it and alternatives considered.
+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 may 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/.gitignore b/.gitignore
index 31dedcc93..f7770612e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -44,6 +44,7 @@
/docs/bin
/docs/vendor
/docs/Gemfile.lock
+/docs/.jekyll-metadata
# Unignore our shell completion
!/completions
diff --git a/.travis.yml b/.travis.yml
index dda1644cf..c6c42a08b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,17 +1,26 @@
language: ruby
+cache:
+ directories:
+ - $HOME/.gem/ruby
+ - Library/Homebrew/vendor/bundle
+ # For parallel_rspec
+ - Library/Homebrew/tmp
matrix:
include:
- os: osx
- osx_image: xcode8.1
+ osx_image: xcode8.3
rvm: system
- os: linux
+ sudo: false
rvm: 2.0.0
before_install:
- export HOMEBREW_DEVELOPER=1
- 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";
else
@@ -21,3 +30,6 @@ before_install:
script:
- brew test-bot
+
+notifications:
+ slack: machomebrew:1XNF7p1JRCdBUuKaeSwsWEc1
diff --git a/Library/.rubocop.yml b/Library/.rubocop.yml
index a782c1117..12886a508 100644
--- a/Library/.rubocop.yml
+++ b/Library/.rubocop.yml
@@ -8,10 +8,19 @@ AllCops:
require: ./Homebrew/rubocops.rb
-Homebrew/CorrectBottleBlock:
+FormulaAuditStrict/BottleBlock:
Enabled: true
-Homebrew/FormulaDesc:
+FormulaAuditStrict/Desc:
+ Enabled: true
+
+FormulaAuditStrict/ComponentsOrder:
+ Enabled: true
+
+FormulaAuditStrict/ComponentsRedundancy:
+ Enabled: true
+
+FormulaAudit/Homepage:
Enabled: true
Metrics/AbcSize:
@@ -34,6 +43,11 @@ Metrics/MethodLength:
Metrics/ModuleLength:
CountComments: false
+ Exclude:
+ - '**/bin/**/*'
+ - '**/cmd/**/*'
+ - '**/lib/**/*'
+ - '**/spec/**/*'
Metrics/PerceivedComplexity:
Enabled: false
diff --git a/Library/Homebrew/PATH.rb b/Library/Homebrew/PATH.rb
new file mode 100644
index 000000000..de7167eb4
--- /dev/null
+++ b/Library/Homebrew/PATH.rb
@@ -0,0 +1,74 @@
+class PATH
+ include Enumerable
+ extend Forwardable
+
+ def_delegator :@paths, :each
+
+ def initialize(*paths)
+ @paths = parse(*paths)
+ end
+
+ def prepend(*paths)
+ @paths = parse(*paths, *@paths)
+ self
+ end
+
+ def append(*paths)
+ @paths = parse(*@paths, *paths)
+ self
+ end
+
+ def insert(index, *paths)
+ @paths = parse(*@paths.insert(index, *paths))
+ self
+ end
+
+ def select(&block)
+ self.class.new(@paths.select(&block))
+ end
+
+ def reject(&block)
+ self.class.new(@paths.reject(&block))
+ end
+
+ def to_ary
+ @paths
+ end
+ alias to_a to_ary
+
+ def to_str
+ @paths.join(File::PATH_SEPARATOR)
+ end
+ alias to_s to_str
+
+ def ==(other)
+ if other.respond_to?(:to_ary)
+ return true if to_ary == other.to_ary
+ end
+
+ if other.respond_to?(:to_str)
+ return true if to_str == other.to_str
+ end
+
+ false
+ end
+
+ def empty?
+ @paths.empty?
+ end
+
+ def existing
+ existing_path = select(&File.method(:directory?))
+ # return nil instead of empty PATH, to unset environment variables
+ existing_path unless existing_path.empty?
+ end
+
+ private
+
+ def parse(*paths)
+ paths.flatten
+ .compact
+ .flat_map { |p| Pathname.new(p).to_path.split(File::PATH_SEPARATOR) }
+ .uniq
+ end
+end
diff --git a/Library/Homebrew/brew.rb b/Library/Homebrew/brew.rb
index aa38b54f4..e07599ac6 100644
--- a/Library/Homebrew/brew.rb
+++ b/Library/Homebrew/brew.rb
@@ -12,9 +12,9 @@ require "pathname"
HOMEBREW_LIBRARY_PATH = Pathname.new(__FILE__).realpath.parent
$:.unshift(HOMEBREW_LIBRARY_PATH.to_s)
require "global"
+require "tap"
if ARGV == %w[--version] || ARGV == %w[-v]
- require "tap"
puts "Homebrew #{HOMEBREW_VERSION}"
puts "Homebrew/homebrew-core #{CoreTap.instance.version_string}"
exit 0
@@ -23,8 +23,7 @@ end
def require?(path)
require path
rescue LoadError => e
- # HACK: ( because we should raise on syntax errors but
- # not if the file doesn't exist. TODO make robust!
+ # we should raise on syntax errors but not if the file doesn't exist.
raise unless e.to_s.include? path
end
@@ -48,13 +47,15 @@ begin
end
end
+ path = PATH.new(ENV["PATH"])
+
# Add contributed commands to PATH before checking.
- Dir["#{HOMEBREW_LIBRARY}/Taps/*/*/cmd"].each do |tap_cmd_dir|
- ENV["PATH"] += "#{File::PATH_SEPARATOR}#{tap_cmd_dir}"
- end
+ path.append(Pathname.glob(Tap::TAP_DIRECTORY/"*/*/cmd"))
# Add SCM wrappers.
- ENV["PATH"] += "#{File::PATH_SEPARATOR}#{HOMEBREW_SHIMS_PATH}/scm"
+ path.append(HOMEBREW_SHIMS_PATH/"scm")
+
+ ENV["PATH"] = path
if cmd
internal_cmd = require? HOMEBREW_LIBRARY_PATH.join("cmd", cmd)
@@ -122,7 +123,7 @@ rescue SystemExit => e
onoe "Kernel.exit" if ARGV.verbose? && !e.success?
$stderr.puts e.backtrace if ARGV.debug?
raise
-rescue Interrupt => e
+rescue Interrupt
$stderr.puts # seemingly a newline is typical
exit 130
rescue BuildError => e
diff --git a/Library/Homebrew/brew.sh b/Library/Homebrew/brew.sh
index 11c1a6c59..02ce5e1c1 100644
--- a/Library/Homebrew/brew.sh
+++ b/Library/Homebrew/brew.sh
@@ -2,7 +2,7 @@ HOMEBREW_VERSION="$(git -C "$HOMEBREW_REPOSITORY" describe --tags --dirty 2>/dev
HOMEBREW_USER_AGENT_VERSION="$HOMEBREW_VERSION"
if [[ -z "$HOMEBREW_VERSION" ]]
then
- HOMEBREW_VERSION=">1.1.0 (no git repository)"
+ HOMEBREW_VERSION=">1.2.0 (no git repository)"
HOMEBREW_USER_AGENT_VERSION="1.X.Y"
fi
@@ -101,6 +101,8 @@ then
[[ "$HOMEBREW_PROCESSOR" = "i386" ]] && HOMEBREW_PROCESSOR="Intel"
HOMEBREW_MACOS_VERSION="$(/usr/bin/sw_vers -productVersion)"
HOMEBREW_OS_VERSION="macOS $HOMEBREW_MACOS_VERSION"
+ # Don't change this from Mac OS X to match what macOS itself does in Safari on 10.12
+ 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" &&
@@ -113,8 +115,9 @@ else
HOMEBREW_PRODUCT="${HOMEBREW_SYSTEM}brew"
[[ -n "$HOMEBREW_LINUX" ]] && HOMEBREW_OS_VERSION="$(lsb_release -sd 2>/dev/null)"
: "${HOMEBREW_OS_VERSION:=$(uname -r)}"
+ HOMEBREW_OS_USER_AGENT_VERSION="$HOMEBREW_OS_VERSION"
fi
-HOMEBREW_USER_AGENT="$HOMEBREW_PRODUCT/$HOMEBREW_USER_AGENT_VERSION ($HOMEBREW_SYSTEM; $HOMEBREW_PROCESSOR $HOMEBREW_OS_VERSION)"
+HOMEBREW_USER_AGENT="$HOMEBREW_PRODUCT/$HOMEBREW_USER_AGENT_VERSION ($HOMEBREW_SYSTEM; $HOMEBREW_PROCESSOR $HOMEBREW_OS_USER_AGENT_VERSION)"
HOMEBREW_CURL_VERSION="$("$HOMEBREW_CURL" --version 2>/dev/null | head -n1 | /usr/bin/awk '{print $1"/"$2}')"
HOMEBREW_USER_AGENT_CURL="$HOMEBREW_USER_AGENT $HOMEBREW_CURL_VERSION"
diff --git a/Library/Homebrew/build_options.rb b/Library/Homebrew/build_options.rb
index d9020ecba..6c6952d71 100644
--- a/Library/Homebrew/build_options.rb
+++ b/Library/Homebrew/build_options.rb
@@ -47,7 +47,6 @@ class BuildOptions
def bottle?
include? "build-bottle"
end
- alias build_bottle? bottle?
# True if a {Formula} is being built with {Formula.head} instead of {Formula.stable}.
# <pre>args << "--some-new-stuff" if build.head?</pre>
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/binary.rb b/Library/Homebrew/cask/lib/hbc/artifact/binary.rb
index 06bdfe157..21d123ab9 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/binary.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/binary.rb
@@ -9,7 +9,12 @@ module Hbc
def link
super
- FileUtils.chmod "+x", source
+ return if source.executable?
+ if source.writable?
+ FileUtils.chmod "+x", source
+ else
+ @command.run!("/bin/chmod", args: ["+x", source], sudo: true)
+ end
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/cask.rb b/Library/Homebrew/cask/lib/hbc/cask.rb
index cf5f2b37a..a193a394e 100644
--- a/Library/Homebrew/cask/lib/hbc/cask.rb
+++ b/Library/Homebrew/cask/lib/hbc/cask.rb
@@ -1,10 +1,12 @@
require "forwardable"
require "hbc/dsl"
+require "hbc/metadata"
module Hbc
class Cask
extend Forwardable
+ include Metadata
attr_reader :token, :sourcefile_path
def initialize(token, sourcefile_path: nil, &block)
@@ -20,55 +22,9 @@ module Hbc
define_method(method_name) { @dsl.send(method_name) }
end
- METADATA_SUBDIR = ".metadata".freeze
-
- def metadata_master_container_path
- @metadata_master_container_path ||= caskroom_path.join(METADATA_SUBDIR)
- end
-
- def metadata_versioned_container_path
- cask_version = version ? version : :unknown
- metadata_master_container_path.join(cask_version.to_s)
- end
-
- def metadata_path(timestamp = :latest, create = false)
- if create && timestamp == :latest
- raise CaskError, "Cannot create metadata path when timestamp is :latest"
- end
- path = if timestamp == :latest
- Pathname.glob(metadata_versioned_container_path.join("*")).sort.last
- elsif timestamp == :now
- Utils.nowstamp_metadata_path(metadata_versioned_container_path)
- else
- metadata_versioned_container_path.join(timestamp)
- end
- if create
- odebug "Creating metadata directory #{path}"
- FileUtils.mkdir_p path
- end
- path
- end
-
- def metadata_subdir(leaf, timestamp = :latest, create = false)
- if create && timestamp == :latest
- raise CaskError, "Cannot create metadata subdir when timestamp is :latest"
- end
- unless leaf.respond_to?(:length) && !leaf.empty?
- raise CaskError, "Cannot create metadata subdir for empty leaf"
- end
- parent = metadata_path(timestamp, create)
- return nil unless parent.respond_to?(:join)
- subdir = parent.join(leaf)
- if create
- odebug "Creating metadata subdirectory #{subdir}"
- FileUtils.mkdir_p subdir
- end
- subdir
- end
-
def timestamped_versions
- Pathname.glob(metadata_master_container_path.join("*", "*"))
- .map { |p| p.relative_path_from(metadata_master_container_path) }
+ Pathname.glob(metadata_timestamped_path(version: "*", timestamp: "*"))
+ .map { |p| p.relative_path_from(p.parent.parent) }
.sort_by(&:basename) # sort by timestamp
.map { |p| p.split.map(&:to_s) }
end
diff --git a/Library/Homebrew/cask/lib/hbc/cli/doctor.rb b/Library/Homebrew/cask/lib/hbc/cli/doctor.rb
index 6b2f4caab..031f78824 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/doctor.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/doctor.rb
@@ -92,7 +92,7 @@ module Hbc
def self.render_staging_location(path)
path = Pathname.new(user_tilde(path.to_s))
if !path.exist?
- "#{path} #{error_string "error: path does not exist"}}"
+ "#{path} #{error_string "error: path does not exist"}"
elsif !path.writable?
"#{path} #{error_string "error: not writable by current user"}"
else
diff --git a/Library/Homebrew/cask/lib/hbc/cli/reinstall.rb b/Library/Homebrew/cask/lib/hbc/cli/reinstall.rb
index b52c43328..c2ed8f462 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/reinstall.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/reinstall.rb
@@ -7,30 +7,10 @@ module Hbc
begin
cask = CaskLoader.load(cask_token)
- installer = Installer.new(cask,
- force: force,
- skip_cask_deps: skip_cask_deps,
- require_sha: require_sha)
- installer.print_caveats
- installer.fetch
-
- if cask.installed?
- # use copy of cask for uninstallation to avoid 'No such file or directory' bug
- installed_cask = cask
-
- # use the same cask file that was used for installation, if possible
- if (installed_caskfile = installed_cask.installed_caskfile).exist?
- installed_cask = CaskLoader.load_from_file(installed_caskfile)
- end
-
- # Always force uninstallation, ignore method parameter
- Installer.new(installed_cask, force: true).uninstall
- end
-
- installer.stage
- installer.install_artifacts
- installer.enable_accessibility_access
- puts installer.summary
+ Installer.new(cask,
+ force: force,
+ skip_cask_deps: skip_cask_deps,
+ require_sha: require_sha).reinstall
count += 1
rescue CaskUnavailableError => e
diff --git a/Library/Homebrew/cask/lib/hbc/cli/search.rb b/Library/Homebrew/cask/lib/hbc/cli/search.rb
index 992aca583..7abd744e4 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/search.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/search.rb
@@ -13,6 +13,15 @@ module Hbc
end
end
+ def self.search_remote(query)
+ matches = GitHub.search_code("user:caskroom", "path:Casks", "filename:#{query}", "extension:rb")
+ [*matches].map do |match|
+ tap = Tap.fetch(match["repository"]["full_name"])
+ next if tap.installed?
+ "#{tap.name}/#{File.basename(match["path"], ".rb")}"
+ end.compact
+ end
+
def self.search(*arguments)
exact_match = nil
partial_matches = []
@@ -29,27 +38,34 @@ module Hbc
partial_matches = simplified_tokens.grep(/#{simplified_search_term}/i) { |t| all_tokens[simplified_tokens.index(t)] }
partial_matches.delete(exact_match)
end
- [exact_match, partial_matches, search_term]
+
+ remote_matches = search_remote(search_term)
+
+ [exact_match, partial_matches, remote_matches, search_term]
end
- def self.render_results(exact_match, partial_matches, search_term)
+ def self.render_results(exact_match, partial_matches, remote_matches, search_term)
if !exact_match && partial_matches.empty?
puts "No Cask found for \"#{search_term}\"."
return
end
if exact_match
- ohai "Exact match"
+ ohai "Exact Match"
puts highlight_installed exact_match
end
- return if partial_matches.empty?
-
- if extract_regexp search_term
- ohai "Regexp matches"
- else
- ohai "Partial matches"
+ unless partial_matches.empty?
+ if extract_regexp search_term
+ ohai "Regexp Matches"
+ else
+ ohai "Partial Matches"
+ end
+ puts Formatter.columns(partial_matches.map(&method(:highlight_installed)))
end
- puts Formatter.columns(partial_matches.map(&method(:highlight_installed)))
+
+ return if remote_matches.empty?
+ ohai "Remote Matches"
+ puts Formatter.columns(remote_matches.map(&method(:highlight_installed)))
end
def self.highlight_installed(token)
diff --git a/Library/Homebrew/cask/lib/hbc/cli/uninstall.rb b/Library/Homebrew/cask/lib/hbc/cli/uninstall.rb
index 6887aaf4f..1ee3230ad 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/uninstall.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/uninstall.rb
@@ -12,15 +12,9 @@ module Hbc
raise CaskNotInstalledError, cask unless cask.installed? || force
- latest_installed_version = cask.timestamped_versions.last
-
- unless latest_installed_version.nil?
- latest_installed_cask_file = cask.metadata_master_container_path
- .join(latest_installed_version.join(File::Separator),
- "Casks", "#{cask_token}.rb")
-
+ if cask.installed? && !cask.installed_caskfile.nil?
# use the same cask file that was used for installation, if possible
- cask = CaskLoader.load_from_file(latest_installed_cask_file) if latest_installed_cask_file.exist?
+ cask = CaskLoader.load_from_file(cask.installed_caskfile) if cask.installed_caskfile.exist?
end
Installer.new(cask, force: force).uninstall
diff --git a/Library/Homebrew/cask/lib/hbc/container.rb b/Library/Homebrew/cask/lib/hbc/container.rb
index c6b2c3c37..961e31968 100644
--- a/Library/Homebrew/cask/lib/hbc/container.rb
+++ b/Library/Homebrew/cask/lib/hbc/container.rb
@@ -61,7 +61,7 @@ module Hbc
begin
const_get(type.to_s.split("_").map(&:capitalize).join)
rescue NameError
- false
+ nil
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/dsl/container.rb b/Library/Homebrew/cask/lib/hbc/dsl/container.rb
index ab260c98c..caaf25bca 100644
--- a/Library/Homebrew/cask/lib/hbc/dsl/container.rb
+++ b/Library/Homebrew/cask/lib/hbc/dsl/container.rb
@@ -1,3 +1,5 @@
+require "hbc/container"
+
module Hbc
class DSL
class Container
@@ -13,9 +15,12 @@ module Hbc
@pairs = pairs
pairs.each do |key, value|
raise "invalid container key: '#{key.inspect}'" unless VALID_KEYS.include?(key)
- writer_method = "#{key}=".to_sym
- send(writer_method, value)
+ send(:"#{key}=", value)
end
+
+ return if type.nil?
+ return unless Hbc::Container.from_type(type).nil?
+ raise "invalid container type: #{type.inspect}"
end
def to_yaml
diff --git a/Library/Homebrew/cask/lib/hbc/installer.rb b/Library/Homebrew/cask/lib/hbc/installer.rb
index 824c1b1be..f02f07806 100644
--- a/Library/Homebrew/cask/lib/hbc/installer.rb
+++ b/Library/Homebrew/cask/lib/hbc/installer.rb
@@ -24,6 +24,7 @@ module Hbc
@force = force
@skip_cask_deps = skip_cask_deps
@require_sha = require_sha
+ @reinstall = false
end
def self.print_caveats(cask)
@@ -76,13 +77,16 @@ module Hbc
def install
odebug "Hbc::Installer#install"
- if @cask.installed? && !force
+ if @cask.installed? && !force && !@reinstall
raise CaskAlreadyInstalledAutoUpdatesError, @cask if @cask.auto_updates
raise CaskAlreadyInstalledError, @cask
end
print_caveats
fetch
+ uninstall_existing_cask if @reinstall
+
+ oh1 "Installing Cask #{@cask}"
stage
install_artifacts
enable_accessibility_access
@@ -90,6 +94,23 @@ module Hbc
puts summary
end
+ def reinstall
+ odebug "Hbc::Installer#reinstall"
+ @reinstall = true
+ install
+ end
+
+ def uninstall_existing_cask
+ return unless @cask.installed?
+
+ # 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
+
+ # Always force uninstallation, ignore method parameter
+ Installer.new(installed_cask, force: true).uninstall
+ end
+
def summary
s = ""
s << "#{Emoji.install_badge} " if Emoji.enabled?
@@ -295,19 +316,17 @@ module Hbc
end
def save_caskfile
- unless (old_savedirs = Pathname.glob(@cask.metadata_path("*"))).empty?
- old_savedirs.each(&:rmtree)
- end
+ old_savedir = @cask.metadata_timestamped_path
return unless @cask.sourcefile_path
- savedir = @cask.metadata_subdir("Casks", :now, true)
- savedir.mkpath
+ savedir = @cask.metadata_subdir("Casks", timestamp: :now, create: true)
FileUtils.copy @cask.sourcefile_path, savedir
+ old_savedir.rmtree unless old_savedir.nil?
end
def uninstall
- odebug "Hbc::Installer#uninstall"
+ oh1 "Uninstalling Cask #{@cask}"
disable_accessibility_access
uninstall_artifacts
purge_versioned_files
@@ -355,15 +374,15 @@ module Hbc
gain_permissions_remove(@cask.staged_path) if !@cask.staged_path.nil? && @cask.staged_path.exist?
# Homebrew-Cask metadata
- if @cask.metadata_versioned_container_path.respond_to?(:children) &&
- @cask.metadata_versioned_container_path.exist?
- @cask.metadata_versioned_container_path.children.each do |subdir|
+ if @cask.metadata_versioned_path.respond_to?(:children) &&
+ @cask.metadata_versioned_path.exist?
+ @cask.metadata_versioned_path.children.each do |subdir|
unless PERSISTENT_METADATA_SUBDIRS.include?(subdir.basename)
gain_permissions_remove(subdir)
end
end
end
- @cask.metadata_versioned_container_path.rmdir_if_possible
+ @cask.metadata_versioned_path.rmdir_if_possible
@cask.metadata_master_container_path.rmdir_if_possible
# toplevel staged distribution
diff --git a/Library/Homebrew/cask/lib/hbc/metadata.rb b/Library/Homebrew/cask/lib/hbc/metadata.rb
new file mode 100644
index 000000000..344c38cee
--- /dev/null
+++ b/Library/Homebrew/cask/lib/hbc/metadata.rb
@@ -0,0 +1,73 @@
+module Hbc
+ module Metadata
+ METADATA_SUBDIR = ".metadata".freeze
+
+ def metadata_master_container_path
+ @metadata_master_container_path ||= caskroom_path.join(METADATA_SUBDIR)
+ end
+
+ def metadata_versioned_path(version: self.version)
+ cask_version = (version || :unknown).to_s
+
+ if cask_version.empty?
+ raise CaskError, "Cannot create metadata path with empty version."
+ end
+
+ metadata_master_container_path.join(cask_version)
+ end
+
+ def metadata_timestamped_path(version: self.version, timestamp: :latest, create: false)
+ if create && timestamp == :latest
+ raise CaskError, "Cannot create metadata path when timestamp is :latest."
+ end
+
+ path = if timestamp == :latest
+ Pathname.glob(metadata_versioned_path(version: version).join("*")).sort.last
+ else
+ timestamp = new_timestamp if timestamp == :now
+ metadata_versioned_path(version: version).join(timestamp)
+ end
+
+ if create && !path.directory?
+ odebug "Creating metadata directory #{path}."
+ path.mkpath
+ end
+
+ path
+ end
+
+ def metadata_subdir(leaf, version: self.version, timestamp: :latest, create: false)
+ if create && timestamp == :latest
+ raise CaskError, "Cannot create metadata subdir when timestamp is :latest."
+ end
+
+ unless leaf.respond_to?(:empty?) && !leaf.empty?
+ raise CaskError, "Cannot create metadata subdir for empty leaf."
+ end
+
+ parent = metadata_timestamped_path(version: version, timestamp: timestamp, create: create)
+
+ return nil if parent.nil?
+
+ subdir = parent.join(leaf)
+
+ if create && !subdir.directory?
+ odebug "Creating metadata subdirectory #{subdir}."
+ subdir.mkpath
+ end
+
+ subdir
+ end
+
+ private
+
+ def new_timestamp(time = Time.now)
+ time = time.utc
+
+ timestamp = time.strftime("%Y%m%d%H%M%S")
+ fraction = format("%.3f", time.to_f - time.to_i)[1..-1]
+
+ timestamp.concat(fraction)
+ end
+ end
+end
diff --git a/Library/Homebrew/cask/lib/hbc/pkg.rb b/Library/Homebrew/cask/lib/hbc/pkg.rb
index 902d56449..c9aa3180f 100644
--- a/Library/Homebrew/cask/lib/hbc/pkg.rb
+++ b/Library/Homebrew/cask/lib/hbc/pkg.rb
@@ -63,7 +63,10 @@ module Hbc
end
def pkgutil_bom_all
- @pkgutil_bom_all ||= info.fetch("paths").keys.map { |p| root.join(p) }
+ @pkgutil_bom_all ||= @command.run!("/usr/sbin/pkgutil", args: ["--files", package_id])
+ .stdout
+ .split("\n")
+ .map { |path| root.join(path) }
end
def root
@@ -71,7 +74,7 @@ module Hbc
end
def info
- @info ||= @command.run!("/usr/sbin/pkgutil", args: ["--export-plist", package_id])
+ @info ||= @command.run!("/usr/sbin/pkgutil", args: ["--pkg-info-plist", package_id])
.plist
end
diff --git a/Library/Homebrew/cask/lib/hbc/scopes.rb b/Library/Homebrew/cask/lib/hbc/scopes.rb
index db12409e5..149c2c343 100644
--- a/Library/Homebrew/cask/lib/hbc/scopes.rb
+++ b/Library/Homebrew/cask/lib/hbc/scopes.rb
@@ -6,8 +6,7 @@ module Hbc
module ClassMethods
def all
- @all_casks ||= {}
- all_tokens.map { |t| @all_casks[t] ||= load(t) }
+ all_tokens.map(&CaskLoader.public_method(:load))
end
def all_tapped_cask_dirs
diff --git a/Library/Homebrew/cask/lib/hbc/utils.rb b/Library/Homebrew/cask/lib/hbc/utils.rb
index ecb565e8e..b2b65a08e 100644
--- a/Library/Homebrew/cask/lib/hbc/utils.rb
+++ b/Library/Homebrew/cask/lib/hbc/utils.rb
@@ -43,7 +43,7 @@ module Hbc
p.rmtree
else
command.run("/bin/rm",
- args: command_args + ["-r", "-f", "--", p],
+ args: ["-r", "-f", "--", p],
sudo: true)
end
end
@@ -115,16 +115,5 @@ module Hbc
opoo(poo.join(" ") + "\n" + error_message_with_suggestions)
end
-
- def self.nowstamp_metadata_path(container_path)
- @timenow ||= Time.now.gmtime
- return unless container_path.respond_to?(:join)
-
- precision = 3
- timestamp = @timenow.strftime("%Y%m%d%H%M%S")
- fraction = format("%.#{precision}f", @timenow.to_f - @timenow.to_i)[1..-1]
- timestamp.concat(fraction)
- container_path.join(timestamp)
- end
end
end
diff --git a/Library/Homebrew/caveats.rb b/Library/Homebrew/caveats.rb
index 61b703469..ee09063fd 100644
--- a/Library/Homebrew/caveats.rb
+++ b/Library/Homebrew/caveats.rb
@@ -44,15 +44,17 @@ class Caveats
def keg_only_text
return unless f.keg_only?
- s = "This formula is keg-only, which means it was not symlinked into #{HOMEBREW_PREFIX}."
- s << "\n\n#{f.keg_only_reason}\n"
+ s = <<-EOS.undent
+ This formula is keg-only, which means it was not symlinked into #{HOMEBREW_PREFIX},
+ because #{f.keg_only_reason.to_s.chomp}.
+ EOS
if f.bin.directory? || f.sbin.directory?
s << "\nIf you need to have this software first in your PATH run:\n"
if f.bin.directory?
- s << " #{Utils::Shell.prepend_path_in_shell_profile(f.opt_bin.to_s)}\n"
+ s << " #{Utils::Shell.prepend_path_in_profile(f.opt_bin.to_s)}\n"
end
if f.sbin.directory?
- s << " #{Utils::Shell.prepend_path_in_shell_profile(f.opt_sbin.to_s)}\n"
+ s << " #{Utils::Shell.prepend_path_in_profile(f.opt_sbin.to_s)}\n"
end
end
diff --git a/Library/Homebrew/cmd/--env.rb b/Library/Homebrew/cmd/--env.rb
index 323964dad..90beee89c 100644
--- a/Library/Homebrew/cmd/--env.rb
+++ b/Library/Homebrew/cmd/--env.rb
@@ -22,9 +22,9 @@ module Homebrew
# legacy behavior
shell = :bash unless $stdout.tty?
elsif shell_value == "auto"
- shell = Utils::Shell.parent_shell || Utils::Shell.preferred_shell
+ shell = Utils::Shell.parent || Utils::Shell.preferred
elsif shell_value
- shell = Utils::Shell.path_to_shell(shell_value)
+ shell = Utils::Shell.from_path(shell_value)
end
env_keys = build_env_keys(ENV)
diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb
index 1808c4d9c..394b31db0 100644
--- a/Library/Homebrew/cmd/install.rb
+++ b/Library/Homebrew/cmd/install.rb
@@ -206,7 +206,8 @@ module Homebrew
Migrator.migrate_if_needed(f)
install_formula(f)
end
- rescue FormulaClassUnavailableError => e
+ rescue FormulaUnreadableError, FormulaClassUnavailableError,
+ TapFormulaUnreadableError, TapFormulaClassUnavailableError => e
# Need to rescue before `FormulaUnavailableError` (superclass of this)
# is handled, as searching for a formula doesn't make sense here (the
# formula was found, but there's a problem with its implementation).
@@ -240,6 +241,8 @@ module Homebrew
puts "To install one of them, run (for example):\n brew install #{formulae_search_results.first}"
end
+ # Do not search taps if the formula name is qualified
+ return if e.name.include?("/")
ohai "Searching taps..."
taps_search_results = search_taps(query)
case taps_search_results.length
diff --git a/Library/Homebrew/cmd/link.rb b/Library/Homebrew/cmd/link.rb
index 5ce6bea48..b8bd135e0 100644
--- a/Library/Homebrew/cmd/link.rb
+++ b/Library/Homebrew/cmd/link.rb
@@ -86,8 +86,8 @@ module Homebrew
opt = HOMEBREW_PREFIX/"opt/#{keg.name}"
puts "\nIf you need to have this software first in your PATH instead consider running:"
- puts " #{Utils::Shell.prepend_path_in_shell_profile(opt/"bin")}" if bin.directory?
- puts " #{Utils::Shell.prepend_path_in_shell_profile(opt/"sbin")}" if sbin.directory?
+ puts " #{Utils::Shell.prepend_path_in_profile(opt/"bin")}" if bin.directory?
+ puts " #{Utils::Shell.prepend_path_in_profile(opt/"sbin")}" if sbin.directory?
end
def keg_only?(rack)
diff --git a/Library/Homebrew/cmd/postinstall.rb b/Library/Homebrew/cmd/postinstall.rb
index 8808a2602..f5d091227 100644
--- a/Library/Homebrew/cmd/postinstall.rb
+++ b/Library/Homebrew/cmd/postinstall.rb
@@ -7,7 +7,10 @@ module Homebrew
module_function
def postinstall
- ARGV.resolved_formulae.each { |f| run_post_install(f) if f.post_install_defined? }
+ ARGV.resolved_formulae.each do |f|
+ ohai "Postinstalling #{f}"
+ run_post_install(f)
+ end
end
def run_post_install(formula)
diff --git a/Library/Homebrew/cmd/search.rb b/Library/Homebrew/cmd/search.rb
index 443739f8c..f71a14ba1 100644
--- a/Library/Homebrew/cmd/search.rb
+++ b/Library/Homebrew/cmd/search.rb
@@ -16,15 +16,12 @@
require "formula"
require "missing_formula"
require "utils"
-require "thread"
require "official_taps"
require "descriptions"
module Homebrew
module_function
- SEARCH_ERROR_QUEUE = Queue.new
-
def search
if ARGV.empty?
puts Formatter.columns(Formula.full_names)
@@ -61,7 +58,7 @@ module Homebrew
regex = query_regexp(query)
local_results = search_formulae(regex)
puts Formatter.columns(local_results) unless local_results.empty?
- tap_results = search_taps(regex)
+ tap_results = search_taps(query)
puts Formatter.columns(tap_results) unless tap_results.empty?
if $stdout.tty?
@@ -75,36 +72,25 @@ module Homebrew
puts reason
elsif count.zero?
puts "No formula found for #{query.inspect}."
- begin
- GitHub.print_pull_requests_matching(query)
- rescue GitHub::Error => e
- SEARCH_ERROR_QUEUE << e
- end
+ GitHub.print_pull_requests_matching(query)
end
end
end
- if $stdout.tty?
- metacharacters = %w[\\ | ( ) [ ] { } ^ $ * + ?]
- bad_regex = metacharacters.any? do |char|
- ARGV.any? do |arg|
- arg.include?(char) && !arg.start_with?("/")
- end
- end
- if !ARGV.empty? && bad_regex
- ohai "Did you mean to perform a regular expression search?"
- ohai "Surround your query with /slashes/ to search by regex."
+ return unless $stdout.tty?
+ return if ARGV.empty?
+ metacharacters = %w[\\ | ( ) [ ] { } ^ $ * + ?].freeze
+ return unless metacharacters.any? do |char|
+ ARGV.any? do |arg|
+ arg.include?(char) && !arg.start_with?("/")
end
end
-
- raise SEARCH_ERROR_QUEUE.pop unless SEARCH_ERROR_QUEUE.empty?
+ ohai <<-EOS.undent
+ Did you mean to perform a regular expression search?
+ Surround your query with /slashes/ to search locally by regex.
+ EOS
end
- SEARCHABLE_TAPS = OFFICIAL_TAPS.map { |tap| ["Homebrew", tap] } + [
- %w[Caskroom cask],
- %w[Caskroom versions],
- ]
-
def query_regexp(query)
case query
when %r{^/(.*)/$} then Regexp.new($1)
@@ -114,53 +100,16 @@ module Homebrew
odie "#{query} is not a valid regex"
end
- def search_taps(regex_or_string)
- SEARCHABLE_TAPS.map do |user, repo|
- Thread.new { search_tap(user, repo, regex_or_string) }
- end.inject([]) do |results, t|
- results.concat(t.value)
- end
- end
-
- def search_tap(user, repo, regex_or_string)
- regex = regex_or_string.is_a?(String) ? /^#{Regexp.escape(regex_or_string)}$/ : regex_or_string
-
- if (HOMEBREW_LIBRARY/"Taps/#{user.downcase}/homebrew-#{repo.downcase}").directory? && \
- user != "Caskroom"
- return []
- end
-
- remote_tap_formulae = Hash.new do |cache, key|
- user, repo = key.split("/", 2)
- tree = {}
-
- GitHub.open "https://api.github.com/repos/#{user}/homebrew-#{repo}/git/trees/HEAD?recursive=1" do |json|
- json["tree"].each do |object|
- next unless object["type"] == "blob"
-
- subtree, file = File.split(object["path"])
-
- if File.extname(file) == ".rb"
- tree[subtree] ||= []
- tree[subtree] << file
- end
- end
- end
-
- paths = tree["Formula"] || tree["HomebrewFormula"] || tree["."] || []
- paths += tree["Casks"] || []
- cache[key] = paths.map { |path| File.basename(path, ".rb") }
- end
-
- names = remote_tap_formulae["#{user}/#{repo}"]
- user = user.downcase if user == "Homebrew" # special handling for the Homebrew organization
- names.select { |name| name =~ regex }.map { |name| "#{user}/#{repo}/#{name}" }
- rescue GitHub::HTTPNotFoundError
- opoo "Failed to search tap: #{user}/#{repo}. Please run `brew update`"
- []
- rescue GitHub::Error => e
- SEARCH_ERROR_QUEUE << e
- []
+ def search_taps(query)
+ valid_dirnames = ["Formula", "HomebrewFormula", "Casks", "."].freeze
+ matches = GitHub.search_code("user:Homebrew", "user: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"])
+ next if tap.installed?
+ "#{tap.name}/#{File.basename(filename, ".rb")}"
+ end.compact
end
def search_formulae(regex)
diff --git a/Library/Homebrew/cmd/sh.rb b/Library/Homebrew/cmd/sh.rb
index 249753355..69f329cb3 100644
--- a/Library/Homebrew/cmd/sh.rb
+++ b/Library/Homebrew/cmd/sh.rb
@@ -23,7 +23,7 @@ module Homebrew
ENV.setup_build_environment
if superenv?
# superenv stopped adding brew's bin but generally users will want it
- ENV["PATH"] = ENV["PATH"].split(File::PATH_SEPARATOR).insert(1, "#{HOMEBREW_PREFIX}/bin").join(File::PATH_SEPARATOR)
+ ENV["PATH"] = PATH.new(ENV["PATH"]).insert(1, HOMEBREW_PREFIX/"bin")
end
ENV["PS1"] = 'brew \[\033[1;32m\]\w\[\033[0m\]$ '
ENV["VERBOSE"] = "1"
diff --git a/Library/Homebrew/cmd/style.rb b/Library/Homebrew/cmd/style.rb
index 2a7f37031..cf41d91ee 100644
--- a/Library/Homebrew/cmd/style.rb
+++ b/Library/Homebrew/cmd/style.rb
@@ -1,4 +1,4 @@
-#: * `style` [`--fix`] [`--display-cop-names`] [<files>|<taps>|<formulae>]:
+#: * `style` [`--fix`] [`--display-cop-names`] [`--only-cops=`[COP1,COP2..]|`--except-cops=`[COP1,COP2..]] [<files>|<taps>|<formulae>]:
#: Check formulae or files for conformance to Homebrew style guidelines.
#:
#: <formulae> and <files> may not be combined. If both are omitted, style will run
@@ -11,6 +11,10 @@
#: If `--display-cop-names` is passed, the RuboCop cop name for each violation
#: is included in the output.
#:
+#: If `--only-cops` is passed, only the given Rubocop cop(s)' violations would be checked.
+#:
+#: If `--except-cops` is passed, the given Rubocop cop(s)' checks would be skipped.
+#:
#: Exits with a non-zero status if any style violations are found.
require "utils"
@@ -30,7 +34,20 @@ module Homebrew
ARGV.formulae.map(&:path)
end
- Homebrew.failed = check_style_and_print(target, fix: ARGV.flag?("--fix"))
+ only_cops = ARGV.value("only-cops").to_s.split(",")
+ except_cops = ARGV.value("except-cops").to_s.split(",")
+ if !only_cops.empty? && !except_cops.empty?
+ odie "--only-cops and --except-cops cannot be used simultaneously!"
+ end
+
+ options = { fix: ARGV.flag?("--fix") }
+ if !only_cops.empty?
+ options[:only_cops] = only_cops
+ elsif !except_cops.empty?
+ options[:except_cops] = except_cops
+ end
+
+ Homebrew.failed = check_style_and_print(target, options)
end
# Checks style for a list of files, printing simple RuboCop output.
@@ -47,13 +64,34 @@ module Homebrew
def check_style_impl(files, output_type, options = {})
fix = options[:fix]
+
Homebrew.install_gem_setup_path! "rubocop", HOMEBREW_RUBOCOP_VERSION
+ require "rubocop"
+ require_relative "../rubocops"
args = %w[
--force-exclusion
]
args << "--auto-correct" if fix
+ if options[:except_cops]
+ options[:except_cops].map! { |cop| RuboCop::Cop::Cop.registry.qualified_cop_name(cop.to_s, "") }
+ cops_to_exclude = options[:except_cops].select do |cop|
+ RuboCop::Cop::Cop.registry.names.include?(cop) ||
+ RuboCop::Cop::Cop.registry.departments.include?(cop.to_sym)
+ end
+
+ args << "--except" << cops_to_exclude.join(",") unless cops_to_exclude.empty?
+ elsif options[:only_cops]
+ options[:only_cops].map! { |cop| RuboCop::Cop::Cop.registry.qualified_cop_name(cop.to_s, "") }
+ cops_to_include = options[:only_cops].select do |cop|
+ RuboCop::Cop::Cop.registry.names.include?(cop) ||
+ RuboCop::Cop::Cop.registry.departments.include?(cop.to_sym)
+ end
+
+ args << "--only" << cops_to_include.join(",") unless cops_to_include.empty?
+ end
+
if files.nil?
args << "--config" << HOMEBREW_LIBRARY_PATH/".rubocop.yml"
args += [HOMEBREW_LIBRARY_PATH]
diff --git a/Library/Homebrew/cmd/tap.rb b/Library/Homebrew/cmd/tap.rb
index 114c4a8b6..2a07c1b2f 100644
--- a/Library/Homebrew/cmd/tap.rb
+++ b/Library/Homebrew/cmd/tap.rb
@@ -63,17 +63,4 @@ module Homebrew
def full_clone?
ARGV.include?("--full") || ARGV.homebrew_developer?
end
-
- # @deprecated this method will be removed in the future, if no external commands use it.
- def install_tap(user, repo, clone_target = nil)
- opoo "Homebrew.install_tap is deprecated, use Tap#install."
- tap = Tap.fetch(user, repo)
- begin
- tap.install(clone_target: clone_target, full_clone: full_clone?)
- rescue TapAlreadyTappedError
- false
- else
- true
- end
- end
end
diff --git a/Library/Homebrew/cmd/update.sh b/Library/Homebrew/cmd/update.sh
index 197a99f2e..77a5c1cd2 100644
--- a/Library/Homebrew/cmd/update.sh
+++ b/Library/Homebrew/cmd/update.sh
@@ -23,7 +23,7 @@ git() {
}
git_init_if_necessary() {
- if [[ -n "$HOMEBREW_MACOS" ]]
+ if [[ -n "$HOMEBREW_MACOS" ]] || [[ -n "$HOMEBREW_FORCE_HOMEBREW_ORG" ]]
then
BREW_OFFICIAL_REMOTE="https://github.com/Homebrew/brew"
CORE_OFFICIAL_REMOTE="https://github.com/Homebrew/homebrew-core"
diff --git a/Library/Homebrew/cmd/uses.rb b/Library/Homebrew/cmd/uses.rb
index b1122c90a..bab174184 100644
--- a/Library/Homebrew/cmd/uses.rb
+++ b/Library/Homebrew/cmd/uses.rb
@@ -28,7 +28,16 @@ module Homebrew
def uses
raise FormulaUnspecifiedError if ARGV.named.empty?
- used_formulae = ARGV.formulae
+ used_formulae_missing = false
+ used_formulae = begin
+ ARGV.formulae
+ rescue FormulaUnavailableError => e
+ opoo e
+ used_formulae_missing = true
+ # If the formula doesn't exist: fake the needed formula object name.
+ ARGV.named.map { |name| OpenStruct.new name: name, full_name: name }
+ end
+
formulae = ARGV.include?("--installed") ? Formula.installed : Formula
recursive = ARGV.flag? "--recursive"
includes = []
@@ -115,5 +124,6 @@ module Homebrew
return if uses.empty?
puts Formatter.columns(uses.map(&:full_name))
+ odie "Missing formulae should not have dependents!" if used_formulae_missing
end
end
diff --git a/Library/Homebrew/compat.rb b/Library/Homebrew/compat.rb
index 92b687725..3c080f616 100644
--- a/Library/Homebrew/compat.rb
+++ b/Library/Homebrew/compat.rb
@@ -25,3 +25,4 @@ require "compat/tab"
require "compat/ENV/shared"
require "compat/ENV/std"
require "compat/ENV/super"
+require "compat/utils/shell"
diff --git a/Library/Homebrew/compat/ARGV.rb b/Library/Homebrew/compat/ARGV.rb
index 23d02ce1a..e5fa8188f 100644
--- a/Library/Homebrew/compat/ARGV.rb
+++ b/Library/Homebrew/compat/ARGV.rb
@@ -1,6 +1,6 @@
module HomebrewArgvExtension
def build_32_bit?
- # odeprecated "ARGV.build_32_bit?"
+ odeprecated "ARGV.build_32_bit?"
include? "--32-bit"
end
end
diff --git a/Library/Homebrew/compat/build_options.rb b/Library/Homebrew/compat/build_options.rb
index 52aa9b951..73722dadb 100644
--- a/Library/Homebrew/compat/build_options.rb
+++ b/Library/Homebrew/compat/build_options.rb
@@ -1,6 +1,11 @@
class BuildOptions
def build_32_bit?
- # odeprecated "build.build_32_bit?"
+ odeprecated "build.build_32_bit?"
include?("32-bit") && option_defined?("32-bit")
end
+
+ def build_bottle?
+ odeprecated "build.build_bottle?", "build.bottle?"
+ bottle?
+ end
end
diff --git a/Library/Homebrew/compat/dependency_collector.rb b/Library/Homebrew/compat/dependency_collector.rb
index bd72c55d4..fbcf1c2a0 100644
--- a/Library/Homebrew/compat/dependency_collector.rb
+++ b/Library/Homebrew/compat/dependency_collector.rb
@@ -14,7 +14,6 @@ class DependencyCollector
output_deprecation(spec, tags)
Dependency.new(spec.to_s, tags)
when :apr
- # TODO: reenable in future when we've fixed a few of the audits.
# output_deprecation(spec, tags, "apr-util")
Dependency.new("apr-util", tags)
when :libltdl
diff --git a/Library/Homebrew/compat/global.rb b/Library/Homebrew/compat/global.rb
index 797e9ffe5..82c452cc0 100644
--- a/Library/Homebrew/compat/global.rb
+++ b/Library/Homebrew/compat/global.rb
@@ -3,7 +3,7 @@ module Homebrew
def method_missing(method, *args, &block)
if instance_methods.include?(method)
- # odeprecated "#{self}##{method}", "'module_function' or 'def self.#{method}' to convert it to a class method"
+ odeprecated "#{self}##{method}", "'module_function' or 'def self.#{method}' to convert it to a class method"
return instance_method(method).bind(self).call(*args, &block)
end
super
diff --git a/Library/Homebrew/compat/software_spec.rb b/Library/Homebrew/compat/software_spec.rb
index 51b0f3a0b..5efd2aeb4 100644
--- a/Library/Homebrew/compat/software_spec.rb
+++ b/Library/Homebrew/compat/software_spec.rb
@@ -1,7 +1,5 @@
class BottleSpecification
def revision(*args)
- # Don't announce deprecation yet as this is quite a big change
- # to a public interface.
# odeprecated "BottleSpecification.revision", "BottleSpecification.rebuild"
rebuild(*args)
end
diff --git a/Library/Homebrew/compat/tab.rb b/Library/Homebrew/compat/tab.rb
index 58fdc4913..2cf71c923 100644
--- a/Library/Homebrew/compat/tab.rb
+++ b/Library/Homebrew/compat/tab.rb
@@ -1,6 +1,6 @@
class Tab < OpenStruct
def build_32_bit?
- # odeprecated "Tab.build_32_bit?"
+ odeprecated "Tab.build_32_bit?"
include?("32-bit")
end
end
diff --git a/Library/Homebrew/compat/tap.rb b/Library/Homebrew/compat/tap.rb
index d1cf7f1d5..37b1eeac1 100644
--- a/Library/Homebrew/compat/tap.rb
+++ b/Library/Homebrew/compat/tap.rb
@@ -6,5 +6,3 @@ class Tap
core_tap?
end
end
-
-CoreFormulaRepository = CoreTap
diff --git a/Library/Homebrew/compat/utils.rb b/Library/Homebrew/compat/utils.rb
index 56b0824ba..3842e8a83 100644
--- a/Library/Homebrew/compat/utils.rb
+++ b/Library/Homebrew/compat/utils.rb
@@ -1,18 +1,13 @@
-# return the shell profile file based on users' preference shell
def shell_profile
- opoo "shell_profile has been deprecated in favor of Utils::Shell.profile"
- case ENV["SHELL"]
- when %r{/(ba)?sh} then "~/.bash_profile"
- when %r{/zsh} then "~/.zshrc"
- when %r{/ksh} then "~/.kshrc"
- else "~/.bash_profile"
- end
+ # odeprecated "shell_profile", "Utils::Shell.profile"
+ Utils::Shell.profile
end
module Tty
module_function
def white
+ odeprecated "Tty.white", "Tty.reset.bold"
reset.bold
end
end
diff --git a/Library/Homebrew/compat/utils/shell.rb b/Library/Homebrew/compat/utils/shell.rb
new file mode 100644
index 000000000..161f10ebb
--- /dev/null
+++ b/Library/Homebrew/compat/utils/shell.rb
@@ -0,0 +1,8 @@
+module Utils
+ module Shell
+ def self.shell_profile
+ odeprecated "Utils::Shell.shell_profile", "Utils::Shell.profile"
+ Utils::Shell.profile
+ end
+ end
+end
diff --git a/Library/Homebrew/dependable.rb b/Library/Homebrew/dependable.rb
index 0834b08ec..785eb94d8 100644
--- a/Library/Homebrew/dependable.rb
+++ b/Library/Homebrew/dependable.rb
@@ -20,8 +20,6 @@ module Dependable
end
def required?
- # FIXME: Should `required?` really imply `!build?`? And if so, why doesn't
- # any of `optional?` and `recommended?` equally imply `!build?`?
!build? && !optional? && !recommended?
end
diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb
index ba6c3f333..cbe26b422 100644
--- a/Library/Homebrew/dev-cmd/audit.rb
+++ b/Library/Homebrew/dev-cmd/audit.rb
@@ -1,4 +1,4 @@
-#: * `audit` [`--strict`] [`--fix`] [`--online`] [`--new-formula`] [`--display-cop-names`] [`--display-filename`] [<formulae>]:
+#: * `audit` [`--strict`] [`--fix`] [`--online`] [`--new-formula`] [`--display-cop-names`] [`--display-filename`] [`--only=`<method>|`--except=`<method>] [`--only-cops=`[COP1,COP2..]|`--except-cops=`[COP1,COP2..]] [<formulae>]:
#: Check <formulae> for Homebrew coding style violations. This should be
#: run before submitting a new formula.
#:
@@ -23,6 +23,14 @@
#: If `--display-filename` is passed, every line of output is prefixed with the
#: name of the file or formula being audited, to make the output easy to grep.
#:
+#: If `--only` is passed, only the methods named `audit_<method>` will be run.
+#:
+#: If `--except` is passed, the methods named `audit_<method>` will not be run.
+#:
+#: If `--only-cops` is passed, only the given Rubocop cop(s)' violations would be checked.
+#:
+#: If `--except-cops` is passed, the given Rubocop cop(s)' checks would be skipped.
+#:
#: `audit` exits with a non-zero status if any errors are found. This is useful,
#: for instance, for implementing pre-commit hooks.
@@ -65,15 +73,30 @@ module Homebrew
files = ARGV.resolved_formulae.map(&:path)
end
- if strict
- options = { fix: ARGV.flag?("--fix"), realpath: true }
- # Check style in a single batch run up front for performance
- style_results = check_style_json(files, options)
+ only_cops = ARGV.value("only-cops").to_s.split(",")
+ except_cops = ARGV.value("except-cops").to_s.split(",")
+ if !only_cops.empty? && !except_cops.empty?
+ odie "--only-cops and --except-cops cannot be used simultaneously!"
+ elsif (!only_cops.empty? || !except_cops.empty?) && strict
+ odie "--only-cops/--except-cops and --strict cannot be used simultaneously"
+ end
+
+ options = { fix: ARGV.flag?("--fix"), realpath: true }
+
+ if !only_cops.empty?
+ options[:only_cops] = only_cops
+ elsif !except_cops.empty?
+ options[:except_cops] = except_cops
+ elsif !strict
+ options[:except_cops] = [:FormulaAuditStrict]
end
+ # Check style in a single batch run up front for performance
+ style_results = check_style_json(files, options)
+
ff.each do |f|
options = { new_formula: new_formula, strict: strict, online: online }
- options[:style_offenses] = style_results.file_offenses(f.path) if strict
+ options[:style_offenses] = style_results.file_offenses(f.path)
fa = FormulaAuditor.new(f, options)
fa.audit
@@ -244,70 +267,6 @@ class FormulaAuditor
end
end
- def component_problem(before, after, offset = 0)
- problem "`#{before[1]}` (line #{before[0] + offset}) should be put before `#{after[1]}` (line #{after[0] + offset})"
- end
-
- # scan in the reverse direction for remaining problems but report problems
- # in the forward direction so that contributors don't reverse the order of
- # lines in the file simply by following instructions
- def audit_components(reverse = true, previous_pair = nil)
- component_list = [
- [/^ include Language::/, "include directive"],
- [/^ desc ["'][\S\ ]+["']/, "desc"],
- [/^ homepage ["'][\S\ ]+["']/, "homepage"],
- [/^ url ["'][\S\ ]+["']/, "url"],
- [/^ mirror ["'][\S\ ]+["']/, "mirror"],
- [/^ version ["'][\S\ ]+["']/, "version"],
- [/^ (sha1|sha256) ["'][\S\ ]+["']/, "checksum"],
- [/^ revision/, "revision"],
- [/^ version_scheme/, "version_scheme"],
- [/^ head ["'][\S\ ]+["']/, "head"],
- [/^ stable do/, "stable block"],
- [/^ bottle do/, "bottle block"],
- [/^ devel do/, "devel block"],
- [/^ head do/, "head block"],
- [/^ bottle (:unneeded|:disable)/, "bottle modifier"],
- [/^ keg_only/, "keg_only"],
- [/^ option/, "option"],
- [/^ depends_on/, "depends_on"],
- [/^ conflicts_with/, "conflicts_with"],
- [/^ (go_)?resource/, "resource"],
- [/^ def install/, "install method"],
- [/^ def caveats/, "caveats method"],
- [/^ (plist_options|def plist)/, "plist block"],
- [/^ test do/, "test block"],
- ]
- if previous_pair
- previous_before = previous_pair[0]
- previous_after = previous_pair[1]
- end
- offset = previous_after && previous_after[0] && previous_after[0] >= 1 ? previous_after[0] - 1 : 0
- present = component_list.map do |regex, name|
- lineno = if reverse
- text.reverse_line_number regex
- else
- text.line_number regex, offset
- end
- next unless lineno
- [lineno, name]
- end.compact
- no_problem = true
- present.each_cons(2) do |c1, c2|
- if reverse
- # scan in the forward direction from the offset
- audit_components(false, [c1, c2]) if c1[0] > c2[0] # at least one more offense
- elsif c1[0] > c2[0] && (offset.zero? || previous_pair.nil? || (c1[0] + offset) != previous_before[0] || (c2[0] + offset) != previous_after[0])
- component_problem c1, c2, offset
- no_problem = false
- end
- end
- if no_problem && previous_pair
- component_problem previous_before, previous_after
- end
- present
- end
-
def audit_file
# Under normal circumstances (umask 0022), we expect a file mode of 644. If
# the user's umask is more restrictive, respect that by masking out the
@@ -332,53 +291,60 @@ class FormulaAuditor
problem "File should end with a newline" unless text.trailing_newline?
if formula.versioned_formula?
- unversioned_formula = Pathname.new formula.path.to_s.gsub(/@.*\.rb$/, ".rb")
+ unversioned_formula = begin
+ # build this ourselves as we want e.g. homebrew/core to be present
+ full_name = if formula.tap
+ "#{formula.tap}/#{formula.name}"
+ else
+ formula.name
+ end
+ Formulary.factory(full_name.gsub(/@.*$/, "")).path
+ rescue FormulaUnavailableError, TapFormulaAmbiguityError,
+ TapFormulaWithOldnameAmbiguityError
+ Pathname.new formula.path.to_s.gsub(/@.*\.rb$/, ".rb")
+ end
unless unversioned_formula.exist?
unversioned_name = unversioned_formula.basename(".rb")
problem "#{formula} is versioned but no #{unversioned_name} formula exists"
end
- else
- versioned_formulae = Dir[formula.path.to_s.gsub(/\.rb$/, "@*.rb")]
- needs_versioned_alias = !versioned_formulae.empty? &&
- formula.tap &&
- formula.aliases.grep(/.@\d/).empty?
- if needs_versioned_alias
- _, last_alias_version = File.basename(versioned_formulae.sort.reverse.first)
- .gsub(/\.rb$/, "")
- .split("@")
- major, minor, = formula.version.to_s.split(".")
- alias_name = if last_alias_version.split(".").length == 1
- "#{formula.name}@#{major}"
- else
- "#{formula.name}@#{major}.#{minor}"
- end
- problem <<-EOS.undent
- Formula has other versions so create an alias:
- cd #{formula.tap.alias_dir}
- ln -s #{formula.path.to_s.gsub(formula.tap.path, "..")} #{alias_name}
- EOS
+ elsif ARGV.build_stable? &&
+ !(versioned_formulae = Dir[formula.path.to_s.gsub(/\.rb$/, "@*.rb")]).empty?
+ versioned_aliases = formula.aliases.grep(/.@\d/)
+ _, last_alias_version =
+ File.basename(versioned_formulae.sort.reverse.first)
+ .gsub(/\.rb$/, "").split("@")
+ major, minor, = formula.version.to_s.split(".")
+ alias_name_major = "#{formula.name}@#{major}"
+ alias_name_major_minor = "#{alias_name_major}.#{minor}"
+ alias_name = if last_alias_version.split(".").length == 1
+ alias_name_major
+ else
+ alias_name_major_minor
end
- end
-
- return unless @strict
+ valid_alias_names = [alias_name_major, alias_name_major_minor]
- present = audit_components
+ valid_versioned_aliases = versioned_aliases & valid_alias_names
+ invalid_versioned_aliases = versioned_aliases - valid_alias_names
- present.map!(&:last)
- if present.include?("stable block")
- %w[url checksum mirror].each do |component|
- if present.include?(component)
- problem "`#{component}` should be put inside `stable block`"
+ if valid_versioned_aliases.empty?
+ if formula.tap
+ problem <<-EOS.undent
+ Formula has other versions so create a versioned alias:
+ cd #{formula.tap.alias_dir}
+ ln -s #{formula.path.to_s.gsub(formula.tap.path, "..")} #{alias_name}
+ EOS
+ else
+ problem "Formula has other versions so create an alias named #{alias_name}."
end
end
- end
- if present.include?("head") && present.include?("head block")
- problem "Should not have both `head` and `head do`"
+ unless invalid_versioned_aliases.empty?
+ problem <<-EOS.undent
+ Formula has invalid versioned aliases:
+ #{invalid_versioned_aliases.join("\n ")}
+ EOS
+ end
end
-
- return unless present.include?("bottle modifier") && present.include?("bottle block")
- problem "Should not have `bottle :unneeded/:disable` and `bottle do`"
end
def audit_class
@@ -437,11 +403,11 @@ class FormulaAuditor
same_name_tap_formulae = @@local_official_taps_name_map[name] || []
if @online
- @@remote_official_taps ||= OFFICIAL_TAPS - Tap.select(&:official?).map(&:repo)
-
- same_name_tap_formulae += @@remote_official_taps.map do |tap|
- Thread.new { Homebrew.search_tap "homebrew", tap, name }
- end.flat_map(&:value)
+ 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)
@@ -558,6 +524,38 @@ class FormulaAuditor
EOS
end
+ def audit_keg_only_style
+ return unless @strict
+ return unless formula.keg_only?
+
+ whitelist = %w[
+ Apple
+ macOS
+ OS
+ Homebrew
+ Xcode
+ GPG
+ GNOME
+ BSD
+ Firefox
+ ].freeze
+
+ reason = formula.keg_only_reason.to_s
+ # Formulae names can legitimately be uppercase/lowercase/both.
+ name = Regexp.new(formula.name, Regexp::IGNORECASE)
+ reason.sub!(name, "")
+ first_word = reason.split[0]
+
+ if reason =~ /\A[A-Z]/ && !reason.start_with?(*whitelist)
+ problem <<-EOS.undent
+ '#{first_word}' from the keg_only reason should be '#{first_word.downcase}'.
+ EOS
+ end
+
+ return unless reason.end_with?(".")
+ problem "keg_only reason should not end with a period."
+ end
+
def audit_options
formula.options.each do |o|
if o.name == "32-bit"
@@ -590,78 +588,9 @@ class FormulaAuditor
homepage = formula.homepage
if homepage.nil? || homepage.empty?
- problem "Formula should have a homepage."
return
end
- unless homepage =~ %r{^https?://}
- problem "The homepage should start with http or https (URL is #{homepage})."
- end
-
- # Check for http:// GitHub homepage urls, https:// is preferred.
- # Note: only check homepages that are repo pages, not *.github.com hosts
- if homepage.start_with? "http://github.com/"
- problem "Please use https:// for #{homepage}"
- end
-
- # Savannah has full SSL/TLS support but no auto-redirect.
- # Doesn't apply to the download URLs, only the homepage.
- if homepage.start_with? "http://savannah.nongnu.org/"
- problem "Please use https:// for #{homepage}"
- end
-
- # Freedesktop is complicated to handle - It has SSL/TLS, but only on certain subdomains.
- # To enable https Freedesktop change the URL from http://project.freedesktop.org/wiki to
- # https://wiki.freedesktop.org/project_name.
- # "Software" is redirected to https://wiki.freedesktop.org/www/Software/project_name
- if homepage =~ %r{^http://((?:www|nice|libopenraw|liboil|telepathy|xorg)\.)?freedesktop\.org/(?:wiki/)?}
- if homepage =~ /Software/
- problem "#{homepage} should be styled `https://wiki.freedesktop.org/www/Software/project_name`"
- else
- problem "#{homepage} should be styled `https://wiki.freedesktop.org/project_name`"
- end
- end
-
- # Google Code homepages should end in a slash
- if homepage =~ %r{^https?://code\.google\.com/p/[^/]+[^/]$}
- problem "#{homepage} should end with a slash"
- end
-
- # People will run into mixed content sometimes, but we should enforce and then add
- # exemptions as they are discovered. Treat mixed content on homepages as a bug.
- # Justify each exemptions with a code comment so we can keep track here.
- case homepage
- when %r{^http://[^/]*\.github\.io/},
- %r{^http://[^/]*\.sourceforge\.io/}
- problem "Please use https:// for #{homepage}"
- end
-
- if homepage =~ %r{^http://([^/]*)\.(sf|sourceforge)\.net(/|$)}
- problem "#{homepage} should be `https://#{$1}.sourceforge.io/`"
- end
-
- # There's an auto-redirect here, but this mistake is incredibly common too.
- # Only applies to the homepage and subdomains for now, not the FTP URLs.
- if homepage =~ %r{^http://((?:build|cloud|developer|download|extensions|git|glade|help|library|live|nagios|news|people|projects|rt|static|wiki|www)\.)?gnome\.org}
- problem "Please use https:// for #{homepage}"
- end
-
- # Compact the above into this list as we're able to remove detailed notations, etc over time.
- case homepage
- when %r{^http://[^/]*\.apache\.org},
- %r{^http://packages\.debian\.org},
- %r{^http://wiki\.freedesktop\.org/},
- %r{^http://((?:www)\.)?gnupg\.org/},
- %r{^http://ietf\.org},
- %r{^http://[^/.]+\.ietf\.org},
- %r{^http://[^/.]+\.tools\.ietf\.org},
- %r{^http://www\.gnu\.org/},
- %r{^http://code\.google\.com/},
- %r{^http://bitbucket\.org/},
- %r{^http://(?:[^/]*\.)?archive\.org}
- problem "Please use https:// for #{homepage}"
- end
-
return unless @online
return unless DevelopmentTools.curl_handles_most_https_homepages?
@@ -728,7 +657,10 @@ class FormulaAuditor
}
end
- spec.patches.each { |p| audit_patch(p) if p.external? }
+ next if spec.patches.empty?
+ spec.patches.each { |p| patch_problems(p) if p.external? }
+ next unless @new_formula
+ problem "New formulae should not require patches to build. Patches should be submitted and accepted upstream first."
end
%w[Stable Devel].each do |name|
@@ -809,51 +741,67 @@ class FormulaAuditor
return unless formula.tap.git? # git log is required
return if @new_formula
- fv = FormulaVersions.new(formula, max_depth: 1)
+ fv = FormulaVersions.new(formula)
attributes = [:revision, :version_scheme]
-
attributes_map = fv.version_attributes_map(attributes, "origin/master")
- attributes.each do |attribute|
- stable_attribute_map = attributes_map[attribute][:stable]
- next if stable_attribute_map.nil? || stable_attribute_map.empty?
-
- attributes_for_version = stable_attribute_map[formula.version]
- next if attributes_for_version.nil? || attributes_for_version.empty?
-
- old_attribute = formula.send(attribute)
- max_attribute = attributes_for_version.max
- if max_attribute && old_attribute < max_attribute
- problem "#{attribute} should not decrease (from #{max_attribute} to #{old_attribute})"
- end
- end
-
+ current_version_scheme = formula.version_scheme
[:stable, :devel].each do |spec|
spec_version_scheme_map = attributes_map[:version_scheme][spec]
- next if spec_version_scheme_map.nil? || spec_version_scheme_map.empty?
+ next if spec_version_scheme_map.empty?
- max_version_scheme = spec_version_scheme_map.values.flatten.max
+ version_schemes = spec_version_scheme_map.values.flatten
+ max_version_scheme = version_schemes.max
max_version = spec_version_scheme_map.select do |_, version_scheme|
version_scheme.first == max_version_scheme
end.keys.max
- formula_spec = formula.send(spec)
- next if formula_spec.nil?
+ if max_version_scheme && current_version_scheme < max_version_scheme
+ problem "version_scheme should not decrease (from #{max_version_scheme} to #{current_version_scheme})"
+ end
- if max_version && formula_spec.version < max_version
- problem "#{spec} version should not decrease (from #{max_version} to #{formula_spec.version})"
+ if max_version_scheme && current_version_scheme >= max_version_scheme &&
+ current_version_scheme > 1 &&
+ !version_schemes.include?(current_version_scheme - 1)
+ problem "version_schemes should only increment by 1"
end
+
+ formula_spec = formula.send(spec)
+ next unless formula_spec
+
+ spec_version = formula_spec.version
+ next unless max_version
+ next if spec_version >= max_version
+
+ above_max_version_scheme = current_version_scheme > max_version_scheme
+ map_includes_version = spec_version_scheme_map.keys.include?(spec_version)
+ next if !current_version_scheme.zero? &&
+ (above_max_version_scheme || map_includes_version)
+ problem "#{spec} version should not decrease (from #{max_version} to #{spec_version})"
end
- return if formula.revision.zero?
- if formula.stable
- revision_map = attributes_map[:revision][:stable]
- stable_revisions = revision_map[formula.stable.version] if revision_map
- if !stable_revisions || stable_revisions.empty?
+ current_revision = formula.revision
+ revision_map = attributes_map[:revision][:stable]
+ if formula.stable && !revision_map.empty?
+ stable_revisions = revision_map[formula.stable.version]
+ stable_revisions ||= []
+ max_revision = stable_revisions.max || 0
+
+ if current_revision < max_revision
+ problem "revision should not decrease (from #{max_revision} to #{current_revision})"
+ end
+
+ stable_revisions -= [formula.revision]
+ if !current_revision.zero? && stable_revisions.empty? &&
+ revision_map.keys.length > 1
problem "'revision #{formula.revision}' should be removed"
+ elsif current_revision > 1 &&
+ current_revision != max_revision &&
+ !stable_revisions.include?(current_revision - 1)
+ problem "revisions should only increment by 1"
end
- else # head/devel-only formula
- problem "'revision #{formula.revision}' should be removed"
+ elsif !current_revision.zero? # head/devel-only formula
+ problem "'revision #{current_revision}' should be removed"
end
end
@@ -864,10 +812,10 @@ class FormulaAuditor
return if legacy_patches.empty?
problem "Use the patch DSL instead of defining a 'patches' method"
- legacy_patches.each { |p| audit_patch(p) }
+ legacy_patches.each { |p| patch_problems(p) }
end
- def audit_patch(patch)
+ def patch_problems(patch)
case patch.url
when /raw\.github\.com/, %r{gist\.github\.com/raw}, %r{gist\.github\.com/.+/raw},
%r{gist\.githubusercontent\.com/.+/raw}
@@ -935,11 +883,21 @@ class FormulaAuditor
problem "Formulae using virtualenvs do not need a `setuptools` resource."
end
+ if text =~ /system\s+['"]go['"],\s+['"]get['"]/
+ problem "Formulae should not use `go get`. If non-vendored resources are required use `go_resource`s."
+ end
+
return unless text.include?('require "language/go"') && !text.include?("go_resource")
problem "require \"language/go\" is unnecessary unless using `go_resource`s"
end
- def audit_line(line, _lineno)
+ def audit_lines
+ text.without_patch.split("\n").each_with_index do |line, lineno|
+ line_problems(line, lineno+1)
+ end
+ end
+
+ def line_problems(line, _lineno)
if line =~ /<(Formula|AmazonWebServicesFormula|ScriptFileFormula|GithubGistFormula)/
problem "Use a space in class inheritance: class Foo < #{$1}"
end
@@ -1018,7 +976,19 @@ class FormulaAuditor
end
if line =~ /depends_on :tex/
- problem ":tex is deprecated."
+ problem ":tex is deprecated"
+ end
+
+ if line =~ /depends_on\s+['"](.+)['"]\s+=>\s+:(lua|perl|python|ruby)(\d*)/
+ problem "#{$2} modules should be vendored rather than use deprecated `depends_on \"#{$1}\" => :#{$2}#{$3}`"
+ end
+
+ if line =~ /depends_on\s+['"](.+)['"]\s+=>\s+(.*)/
+ dep = $1
+ $2.split(" ").map do |o|
+ next unless o =~ /^\[?['"](.*)['"]/
+ problem "Dependency #{dep} should not use option #{$1}"
+ end
end
# Commented-out depends_on
@@ -1049,6 +1019,14 @@ class FormulaAuditor
problem "Use ENV instead of invoking '#{$1}' to modify the environment"
end
+ if formula.name != "wine" && line =~ /ENV\.universal_binary/
+ problem "macOS has been 64-bit only since 10.6 so ENV.universal_binary is deprecated."
+ end
+
+ if line =~ /build\.universal\?/
+ problem "macOS has been 64-bit only so build.universal? is deprecated."
+ end
+
if line =~ /version == ['"]HEAD['"]/
problem "Use 'build.head?' instead of inspecting 'version'"
end
@@ -1078,11 +1056,11 @@ class FormulaAuditor
end
if line =~ /(not\s|!)\s*build\.with?\?/
- problem "Don't negate 'build.without?': use 'build.with?'"
+ problem "Don't negate 'build.with?': use 'build.without?'"
end
if line =~ /(not\s|!)\s*build\.without?\?/
- problem "Don't negate 'build.with?': use 'build.without?'"
+ problem "Don't negate 'build.without?': use 'build.with?'"
end
if line =~ /ARGV\.(?!(debug\?|verbose\?|value[\(\s]))/
@@ -1130,11 +1108,11 @@ class FormulaAuditor
end
if line =~ /depends_on :(.+) (if.+|unless.+)$/
- audit_conditional_dep($1.to_sym, $2, $&)
+ conditional_dep_problems($1.to_sym, $2, $&)
end
if line =~ /depends_on ['"](.+)['"] (if.+|unless.+)$/
- audit_conditional_dep($1, $2, $&)
+ conditional_dep_problems($1, $2, $&)
end
if line =~ /(Dir\[("[^\*{},]+")\])/
@@ -1171,6 +1149,10 @@ class FormulaAuditor
end
end
+ if line =~ /((revision|version_scheme)\s+0)/
+ problem "'#{$1}' should be removed"
+ end
+
return unless @strict
problem "`#{$1}` in formulae is deprecated" if line =~ /(env :(std|userpaths))/
@@ -1222,7 +1204,7 @@ class FormulaAuditor
EOS
end
- def audit_conditional_dep(dep, condition, line)
+ def conditional_dep_problems(dep, condition, line)
quoted_dep = quote_dep(dep)
dep = Regexp.escape(dep.to_s)
@@ -1238,30 +1220,26 @@ class FormulaAuditor
dep.is_a?(Symbol) ? dep.inspect : "'#{dep}'"
end
- def audit_check_output(output)
+ def problem_if_output(output)
problem(output) if output
end
def audit
- audit_file
- audit_formula_name
- audit_class
- audit_specs
- audit_revision_and_version_scheme
- audit_homepage
- audit_bottle_spec
- audit_github_repository
- audit_deps
- audit_conflicts
- audit_options
- audit_legacy_patches
- audit_text
- audit_caveats
- text.without_patch.split("\n").each_with_index { |line, lineno| audit_line(line, lineno+1) }
- audit_installed
- audit_prefix_has_contents
- audit_reverse_migration
- audit_style
+ only_audits = ARGV.value("only").to_s.split(",")
+ except_audits = ARGV.value("except").to_s.split(",")
+ if !only_audits.empty? && !except_audits.empty?
+ odie "--only and --except cannot be used simultaneously!"
+ end
+
+ methods.map(&:to_s).grep(/^audit_/).each do |audit_method_name|
+ name = audit_method_name.gsub(/^audit_/, "")
+ if !only_audits.empty?
+ next unless only_audits.include?(name)
+ elsif !except_audits.empty?
+ next if except_audits.include?(name)
+ end
+ send(audit_method_name)
+ end
end
private
@@ -1392,8 +1370,8 @@ class ResourceAuditor
def audit_urls
# Check GNU urls; doesn't apply to mirrors
- if url =~ %r{^(?:https?|ftp)://(?!alpha).+/gnu/}
- problem "Please use \"https://ftpmirror.gnu.org\" instead of #{url}."
+ if url =~ %r{^(?:https?|ftp)://ftpmirror.gnu.org/(.*)}
+ problem "Please use \"https://ftp.gnu.org/gnu/#{$1}\" instead of #{url}."
end
if mirrors.include?(url)
diff --git a/Library/Homebrew/dev-cmd/create.rb b/Library/Homebrew/dev-cmd/create.rb
index 6855d6f37..908f65f8f 100644
--- a/Library/Homebrew/dev-cmd/create.rb
+++ b/Library/Homebrew/dev-cmd/create.rb
@@ -10,7 +10,8 @@
#: If `--meson` is passed, create a basic template for a Meson-style build.
#:
#: If `--no-fetch` is passed, Homebrew will not download <URL> to the cache and
-#: will thus not add the SHA256 to the formula for you.
+#: will thus not add the SHA256 to the formula for you. It will also not check
+#: the GitHub API for GitHub projects (to fill out the description and homepage).
#:
#: The options `--set-name` and `--set-version` each take an argument and allow
#: you to explicitly set the name and version of the package you are creating.
@@ -28,15 +29,6 @@ module Homebrew
# Create a formula from a tarball URL
def create
- # Allow searching MacPorts or Fink.
- if ARGV.include? "--macports"
- opoo "`brew create --macports` is deprecated; use `brew search --macports` instead"
- exec_browser "https://www.macports.org/ports.php?by=name&substr=#{ARGV.next}"
- elsif ARGV.include? "--fink"
- opoo "`brew create --fink` is deprecated; use `brew search --fink` instead"
- exec_browser "http://pdb.finkproject.org/pdb/browse.php?summary=#{ARGV.next}"
- end
-
raise UsageError if ARGV.named.empty?
# Ensure that the cache exists so we can fetch the tarball
@@ -100,7 +92,7 @@ module Homebrew
end
class FormulaCreator
- attr_reader :url, :sha256
+ attr_reader :url, :sha256, :desc, :homepage
attr_accessor :name, :version, :tap, :path, :mode
def url=(url)
@@ -108,11 +100,15 @@ class FormulaCreator
path = Pathname.new(url)
if @name.nil?
case url
- when %r{github\.com/\S+/(\S+)\.git}
- @name = $1
+ when %r{github\.com/(\S+)/(\S+)\.git}
+ @user = $1
+ @name = $2
@head = true
- when %r{github\.com/\S+/(\S+)/archive/}
- @name = $1
+ @github = true
+ when %r{github\.com/(\S+)/(\S+)/(archive|releases)/}
+ @user = $1
+ @name = $2
+ @github = true
else
@name = path.basename.to_s[/(.*?)[-_.]?#{Regexp.escape(path.version.to_s)}/, 1]
end
@@ -131,7 +127,7 @@ class FormulaCreator
end
def fetch?
- !head? && !ARGV.include?("--no-fetch")
+ !ARGV.include?("--no-fetch")
end
def head?
@@ -145,11 +141,25 @@ class FormulaCreator
opoo "Version cannot be determined from URL."
puts "You'll need to add an explicit 'version' to the formula."
elsif fetch?
- r = Resource.new
- r.url(url)
- r.version(version)
- r.owner = self
- @sha256 = r.fetch.sha256 if r.download_strategy == CurlDownloadStrategy
+ unless head?
+ r = Resource.new
+ r.url(url)
+ r.version(version)
+ r.owner = self
+ @sha256 = r.fetch.sha256 if r.download_strategy == CurlDownloadStrategy
+ end
+
+ if @user && @name
+ begin
+ metadata = GitHub.repository(@user, @name)
+ @desc = metadata["description"]
+ @homepage = metadata["homepage"]
+ rescue GitHub::HTTPNotFoundError
+ # If there was no repository found assume the network connection is at
+ # fault rather than the input URL.
+ nil
+ end
+ end
end
path.write ERB.new(template, nil, ">").result(binding)
@@ -161,8 +171,8 @@ class FormulaCreator
# PLEASE REMOVE ALL GENERATED COMMENTS BEFORE SUBMITTING YOUR PULL REQUEST!
class #{Formulary.class_s(name)} < Formula
- desc ""
- homepage ""
+ desc "#{desc}"
+ homepage "#{homepage}"
<% if head? %>
head "#{url}"
<% else %>
diff --git a/Library/Homebrew/dev-cmd/mirror.rb b/Library/Homebrew/dev-cmd/mirror.rb
index 10811493c..e2492203d 100644
--- a/Library/Homebrew/dev-cmd/mirror.rb
+++ b/Library/Homebrew/dev-cmd/mirror.rb
@@ -8,10 +8,10 @@ module Homebrew
def mirror
odie "This command requires at least formula argument!" if ARGV.named.empty?
- bintray_user = ENV["BINTRAY_USER"]
- bintray_key = ENV["BINTRAY_KEY"]
+ bintray_user = ENV["HOMEBREW_BINTRAY_USER"]
+ bintray_key = ENV["HOMEBREW_BINTRAY_KEY"]
if !bintray_user || !bintray_key
- raise "Missing BINTRAY_USER or BINTRAY_KEY variables!"
+ raise "Missing HOMEBREW_BINTRAY_USER or HOMEBREW_BINTRAY_KEY variables!"
end
ARGV.formulae.each do |f|
diff --git a/Library/Homebrew/dev-cmd/pull.rb b/Library/Homebrew/dev-cmd/pull.rb
index 36c9ac27c..9d08da95b 100644
--- a/Library/Homebrew/dev-cmd/pull.rb
+++ b/Library/Homebrew/dev-cmd/pull.rb
@@ -263,7 +263,7 @@ module Homebrew
end
published = []
- bintray_creds = { user: ENV["BINTRAY_USER"], key: ENV["BINTRAY_KEY"] }
+ bintray_creds = { user: ENV["HOMEBREW_BINTRAY_USER"], key: ENV["HOMEBREW_BINTRAY_KEY"] }
if bintray_creds[:user] && bintray_creds[:key]
changed_formulae_names.each do |name|
f = Formula[name]
@@ -272,7 +272,7 @@ module Homebrew
published << f.full_name
end
else
- opoo "You must set BINTRAY_USER and BINTRAY_KEY to add or update bottles on Bintray!"
+ opoo "You must set HOMEBREW_BINTRAY_USER and HOMEBREW_BINTRAY_KEY to add or update bottles on Bintray!"
end
published
end
@@ -608,7 +608,7 @@ module Homebrew
def check_bintray_mirror(name, url)
headers = curl_output("--connect-timeout", "15", "--head", url)[0]
status_code = headers.scan(%r{^HTTP\/.* (\d+)}).last.first
- return if status_code.start_with?("3")
+ return if status_code.start_with?("2")
opoo "The Bintray mirror #{url} is not reachable (HTTP status code #{status_code})."
opoo "Do you need to upload it with `brew mirror #{name}`?"
end
diff --git a/Library/Homebrew/dev-cmd/tap-new.rb b/Library/Homebrew/dev-cmd/tap-new.rb
index df295bf26..dcb41265c 100644
--- a/Library/Homebrew/dev-cmd/tap-new.rb
+++ b/Library/Homebrew/dev-cmd/tap-new.rb
@@ -47,8 +47,12 @@ module Homebrew
language: ruby
os: osx
env: OSX=10.12
- osx_image: xcode8.1
+ osx_image: xcode8.3
rvm: system
+ cache:
+ directories:
+ - $HOME/.gem/ruby
+ - Library/Homebrew/vendor/bundle
before_install:
- export TRAVIS_COMMIT="$(git rev-parse --verify -q HEAD)"
diff --git a/Library/Homebrew/dev-cmd/tests.rb b/Library/Homebrew/dev-cmd/tests.rb
index 91c7d880b..d90326768 100644
--- a/Library/Homebrew/dev-cmd/tests.rb
+++ b/Library/Homebrew/dev-cmd/tests.rb
@@ -33,7 +33,12 @@ module Homebrew
ENV["HOMEBREW_DEVELOPER"] = "1"
ENV["HOMEBREW_NO_COMPAT"] = "1" if ARGV.include? "--no-compat"
ENV["HOMEBREW_TEST_GENERIC_OS"] = "1" if ARGV.include? "--generic"
- ENV["HOMEBREW_NO_GITHUB_API"] = "1" unless ARGV.include? "--online"
+
+ if ARGV.include? "--online"
+ ENV["HOMEBREW_TEST_ONLINE"] = "1"
+ else
+ ENV["HOMEBREW_NO_GITHUB_API"] = "1"
+ end
if ARGV.include? "--official-cmd-taps"
ENV["HOMEBREW_TEST_OFFICIAL_CMD_TAPS"] = "1"
@@ -74,20 +79,24 @@ module Homebrew
Dir.glob("test/**/*_spec.rb").reject { |p| p =~ %r{^test/vendor/bundle/} }
end
- opts = []
-
- if ENV["CI"]
- opts << "--combine-stderr"
- opts << "--serialize-stdout"
+ opts = if ENV["CI"]
+ %w[
+ --combine-stderr
+ --serialize-stdout
+ ]
+ else
+ %w[
+ --nice
+ ]
end
- args = [
- "--color",
- "-I", HOMEBREW_LIBRARY_PATH/"test",
- "--require", "spec_helper",
- "--format", "progress",
- "--format", "ParallelTests::RSpec::RuntimeLogger",
- "--out", "tmp/parallel_runtime_rspec.log"
+ args = ["-I", HOMEBREW_LIBRARY_PATH/"test"]
+ args += %w[
+ --color
+ --require spec_helper
+ --format progress
+ --format ParallelTests::RSpec::RuntimeLogger
+ --out tmp/parallel_runtime_rspec.log
]
args << "--seed" << ARGV.next if ARGV.include? "--seed"
@@ -97,6 +106,10 @@ module Homebrew
files = files.reject { |p| p =~ %r{^test/(os/mac|cask)(/.*|_spec\.rb)$} }
end
+ unless OS.linux?
+ files = files.reject { |p| p =~ %r{^test/os/linux(/.*|_spec\.rb)$} }
+ end
+
if parallel
system "bundle", "exec", "parallel_rspec", *opts, "--", *args, "--", *files
else
diff --git a/Library/Homebrew/diagnostic.rb b/Library/Homebrew/diagnostic.rb
index 61cdf2f1a..6bb5c8b8e 100644
--- a/Library/Homebrew/diagnostic.rb
+++ b/Library/Homebrew/diagnostic.rb
@@ -100,8 +100,7 @@ module Homebrew
# See https://github.com/Homebrew/legacy-homebrew/pull/9986
def check_path_for_trailing_slashes
- all_paths = ENV["PATH"].split(File::PATH_SEPARATOR)
- bad_paths = all_paths.select { |p| p[-1..-1] == "/" }
+ bad_paths = PATH.new(ENV["HOMEBREW_PATH"]).select { |p| p.end_with?("/") }
return if bad_paths.empty?
inject_file_list bad_paths, <<-EOS.undent
@@ -439,7 +438,7 @@ module Homebrew
message = ""
- paths.each do |p|
+ paths(ENV["HOMEBREW_PATH"]).each do |p|
case p
when "/usr/bin"
unless $seen_prefix_bin
@@ -460,7 +459,7 @@ module Homebrew
Consider setting your PATH so that #{HOMEBREW_PREFIX}/bin
occurs before /usr/bin. Here is a one-liner:
- #{Utils::Shell.prepend_path_in_shell_profile("#{HOMEBREW_PREFIX}/bin")}
+ #{Utils::Shell.prepend_path_in_profile("#{HOMEBREW_PREFIX}/bin")}
EOS
end
end
@@ -480,7 +479,7 @@ module Homebrew
<<-EOS.undent
Homebrew's bin was not found in your PATH.
Consider setting the PATH for example like so
- #{Utils::Shell.prepend_path_in_shell_profile("#{HOMEBREW_PREFIX}/bin")}
+ #{Utils::Shell.prepend_path_in_profile("#{HOMEBREW_PREFIX}/bin")}
EOS
end
@@ -495,7 +494,7 @@ module Homebrew
Homebrew's sbin was not found in your PATH but you have installed
formulae that put executables in #{HOMEBREW_PREFIX}/sbin.
Consider setting the PATH for example like so
- #{Utils::Shell.prepend_path_in_shell_profile("#{HOMEBREW_PREFIX}/sbin")}
+ #{Utils::Shell.prepend_path_in_profile("#{HOMEBREW_PREFIX}/sbin")}
EOS
end
@@ -609,7 +608,7 @@ module Homebrew
/Applications/Server.app/Contents/ServerRoot/usr/sbin
].map(&:downcase)
- paths.each do |p|
+ paths(ENV["HOMEBREW_PATH"]).each do |p|
next if whitelist.include?(p.downcase) || !File.directory?(p)
realpath = Pathname.new(p).realpath.to_s
diff --git a/Library/Homebrew/download_strategy.rb b/Library/Homebrew/download_strategy.rb
index a0025cef3..d74efe0bb 100644
--- a/Library/Homebrew/download_strategy.rb
+++ b/Library/Homebrew/download_strategy.rb
@@ -520,6 +520,9 @@ class S3DownloadStrategy < CurlDownloadStrategy
bucket = $1
key = $2
+ ENV["AWS_ACCESS_KEY_ID"] = ENV["HOMEBREW_AWS_ACCESS_KEY_ID"]
+ ENV["AWS_SECRET_ACCESS_KEY"] = ENV["HOMEBREW_AWS_SECRET_ACCESS_KEY"]
+
obj = AWS::S3.new.buckets[bucket].objects[key]
begin
s3url = obj.url_for(:get)
diff --git a/Library/Homebrew/exceptions.rb b/Library/Homebrew/exceptions.rb
index cfdf5e12d..6751b2224 100644
--- a/Library/Homebrew/exceptions.rb
+++ b/Library/Homebrew/exceptions.rb
@@ -77,35 +77,11 @@ class FormulaUnavailableError < RuntimeError
end
end
-class TapFormulaUnavailableError < FormulaUnavailableError
- attr_reader :tap, :user, :repo
-
- def initialize(tap, name)
- @tap = tap
- @user = tap.user
- @repo = tap.repo
- super "#{tap}/#{name}"
- end
-
- def to_s
- s = super
- s += "\nPlease tap it and then try again: brew tap #{tap}" unless tap.installed?
- s
- end
-end
-
-class FormulaClassUnavailableError < FormulaUnavailableError
+module FormulaClassUnavailableErrorModule
attr_reader :path
attr_reader :class_name
attr_reader :class_list
- def initialize(name, path, class_name, class_list)
- @path = path
- @class_name = class_name
- @class_list = class_list
- super name
- end
-
def to_s
s = super
s += "\nIn formula file: #{path}"
@@ -131,16 +107,70 @@ class FormulaClassUnavailableError < FormulaUnavailableError
end
end
-class FormulaUnreadableError < FormulaUnavailableError
+class FormulaClassUnavailableError < FormulaUnavailableError
+ include FormulaClassUnavailableErrorModule
+
+ def initialize(name, path, class_name, class_list)
+ @path = path
+ @class_name = class_name
+ @class_list = class_list
+ super name
+ end
+end
+
+module FormulaUnreadableErrorModule
attr_reader :formula_error
+ def to_s
+ "#{name}: " + formula_error.to_s
+ end
+end
+
+class FormulaUnreadableError < FormulaUnavailableError
+ include FormulaUnreadableErrorModule
+
def initialize(name, error)
super(name)
@formula_error = error
end
+end
+
+class TapFormulaUnavailableError < FormulaUnavailableError
+ attr_reader :tap, :user, :repo
+
+ def initialize(tap, name)
+ @tap = tap
+ @user = tap.user
+ @repo = tap.repo
+ super "#{tap}/#{name}"
+ end
def to_s
- "#{name}: " + formula_error.to_s
+ s = super
+ s += "\nPlease tap it and then try again: brew tap #{tap}" unless tap.installed?
+ s
+ end
+end
+
+class TapFormulaClassUnavailableError < TapFormulaUnavailableError
+ include FormulaClassUnavailableErrorModule
+
+ attr_reader :tap
+
+ def initialize(tap, name, path, class_name, class_list)
+ @path = path
+ @class_name = class_name
+ @class_list = class_list
+ super tap, name
+ end
+end
+
+class TapFormulaUnreadableError < TapFormulaUnavailableError
+ include FormulaUnreadableErrorModule
+
+ def initialize(tap, name, error)
+ super(tap, name)
+ @formula_error = error
end
end
diff --git a/Library/Homebrew/extend/ENV.rb b/Library/Homebrew/extend/ENV.rb
index 729598e28..283e90b69 100644
--- a/Library/Homebrew/extend/ENV.rb
+++ b/Library/Homebrew/extend/ENV.rb
@@ -26,6 +26,13 @@ module EnvActivation
ensure
replace(old_env)
end
+
+ def clear_sensitive_environment!
+ ENV.keys.each do |key|
+ next unless /(cookie|key|token)/i =~ key
+ ENV.delete key
+ end
+ end
end
ENV.extend(EnvActivation)
diff --git a/Library/Homebrew/extend/ENV/shared.rb b/Library/Homebrew/extend/ENV/shared.rb
index 2cdc2f83a..b51ade48b 100644
--- a/Library/Homebrew/extend/ENV/shared.rb
+++ b/Library/Homebrew/extend/ENV/shared.rb
@@ -1,6 +1,7 @@
require "formula"
require "compilers"
require "development_tools"
+require "PATH"
# Homebrew extends Ruby's `ENV` to make our code more readable.
# Implemented in {SharedEnvExtension} and either {Superenv} or
@@ -80,7 +81,7 @@ module SharedEnvExtension
end
def append_path(key, path)
- append key, path, File::PATH_SEPARATOR if File.directory? path
+ self[key] = PATH.new(self[key]).append(path)
end
# Prepends a directory to `PATH`.
@@ -92,7 +93,7 @@ module SharedEnvExtension
# (e.g. <pre>ENV.prepend_path "PATH", which("emacs").dirname</pre>)
def prepend_path(key, path)
return if %w[/usr/bin /bin /usr/sbin /sbin].include? path.to_s
- prepend key, path, File::PATH_SEPARATOR if File.directory? path
+ self[key] = PATH.new(self[key]).prepend(path)
end
def prepend_create_path(key, path)
@@ -196,22 +197,23 @@ module SharedEnvExtension
# @private
def userpaths!
- paths = self["PATH"].split(File::PATH_SEPARATOR)
- # put Superenv.bin and opt path at the first
- new_paths = paths.select { |p| p.start_with?("#{HOMEBREW_REPOSITORY}/Library/ENV", "#{HOMEBREW_PREFIX}/opt") }
- # XXX hot fix to prefer brewed stuff (e.g. python) over /usr/bin.
- new_paths << "#{HOMEBREW_PREFIX}/bin"
- # reset of self["PATH"]
- new_paths += paths
- # user paths
- new_paths += ORIGINAL_PATHS.map do |p|
- begin
- p.realpath.to_s
- rescue
- nil
- end
- end - %w[/usr/X11/bin /opt/X11/bin]
- self["PATH"] = new_paths.uniq.join(File::PATH_SEPARATOR)
+ path = PATH.new(self["PATH"]).select do |p|
+ # put Superenv.bin and opt path at the first
+ p.start_with?("#{HOMEBREW_REPOSITORY}/Library/ENV", "#{HOMEBREW_PREFIX}/opt")
+ end
+ path.append(HOMEBREW_PREFIX/"bin") # XXX hot fix to prefer brewed stuff (e.g. python) over /usr/bin.
+ path.append(self["PATH"]) # reset of self["PATH"]
+ path.append(
+ # user paths
+ ORIGINAL_PATHS.map do |p|
+ begin
+ p.realpath.to_s
+ rescue
+ nil
+ end
+ end - %w[/usr/X11/bin /opt/X11/bin],
+ )
+ self["PATH"] = path
end
def fortran
@@ -244,7 +246,7 @@ module SharedEnvExtension
else
if (gfortran = which("gfortran", (HOMEBREW_PREFIX/"bin").to_s))
ohai "Using Homebrew-provided fortran compiler."
- elsif (gfortran = which("gfortran", ORIGINAL_PATHS.join(File::PATH_SEPARATOR)))
+ elsif (gfortran = which("gfortran", PATH.new(ORIGINAL_PATHS)))
ohai "Using a fortran compiler found at #{gfortran}."
end
if gfortran
diff --git a/Library/Homebrew/extend/ENV/std.rb b/Library/Homebrew/extend/ENV/std.rb
index 403ea1978..c4cc0985f 100644
--- a/Library/Homebrew/extend/ENV/std.rb
+++ b/Library/Homebrew/extend/ENV/std.rb
@@ -1,7 +1,6 @@
require "hardware"
require "extend/ENV/shared"
-# TODO: deprecate compiling related codes after it's only used by brew test.
# @private
module Stdenv
include SharedEnvExtension
@@ -58,12 +57,12 @@ module Stdenv
end
def determine_pkg_config_libdir
- paths = []
- paths << "#{HOMEBREW_PREFIX}/lib/pkgconfig"
- paths << "#{HOMEBREW_PREFIX}/share/pkgconfig"
- paths += homebrew_extra_pkg_config_paths
- paths << "/usr/lib/pkgconfig"
- paths.select { |d| File.directory? d }.join(File::PATH_SEPARATOR)
+ PATH.new(
+ HOMEBREW_PREFIX/"lib/pkgconfig",
+ HOMEBREW_PREFIX/"share/pkgconfig",
+ homebrew_extra_pkg_config_paths,
+ "/usr/lib/pkgconfig",
+ ).existing
end
# Removes the MAKEFLAGS environment variable, causing make to use a single job.
diff --git a/Library/Homebrew/extend/ENV/super.rb b/Library/Homebrew/extend/ENV/super.rb
index 0935647f5..ef41161af 100644
--- a/Library/Homebrew/extend/ENV/super.rb
+++ b/Library/Homebrew/extend/ENV/super.rb
@@ -101,29 +101,28 @@ module Superenv
end
def determine_path
- paths = [Superenv.bin]
+ path = PATH.new(Superenv.bin)
# Formula dependencies can override standard tools.
- paths += deps.map { |d| d.opt_bin.to_s }
-
- paths += homebrew_extra_paths
- paths += %w[/usr/bin /bin /usr/sbin /sbin]
+ path.append(deps.map(&:opt_bin))
+ path.append(homebrew_extra_paths)
+ path.append("/usr/bin", "/bin", "/usr/sbin", "/sbin")
# Homebrew's apple-gcc42 will be outside the PATH in superenv,
# so xcrun may not be able to find it
begin
case homebrew_cc
when "gcc-4.2"
- paths << Formulary.factory("apple-gcc42").opt_bin
+ path.append(Formulary.factory("apple-gcc42").opt_bin)
when GNU_GCC_REGEXP
- paths << gcc_version_formula($&).opt_bin
+ path.append(gcc_version_formula($&).opt_bin)
end
rescue FormulaUnavailableError
# Don't fail and don't add these formulae to the path if they don't exist.
nil
end
- paths.to_path_s
+ path.existing
end
def homebrew_extra_pkg_config_paths
@@ -131,15 +130,17 @@ module Superenv
end
def determine_pkg_config_path
- paths = deps.map { |d| "#{d.opt_lib}/pkgconfig" }
- paths += deps.map { |d| "#{d.opt_share}/pkgconfig" }
- paths.to_path_s
+ PATH.new(
+ deps.map { |d| d.opt_lib/"pkgconfig" },
+ deps.map { |d| d.opt_share/"pkgconfig" },
+ ).existing
end
def determine_pkg_config_libdir
- paths = %w[/usr/lib/pkgconfig]
- paths += homebrew_extra_pkg_config_paths
- paths.to_path_s
+ PATH.new(
+ "/usr/lib/pkgconfig",
+ homebrew_extra_pkg_config_paths,
+ ).existing
end
def homebrew_extra_aclocal_paths
@@ -147,10 +148,11 @@ module Superenv
end
def determine_aclocal_path
- paths = keg_only_deps.map { |d| "#{d.opt_share}/aclocal" }
- paths << "#{HOMEBREW_PREFIX}/share/aclocal"
- paths += homebrew_extra_aclocal_paths
- paths.to_path_s
+ PATH.new(
+ keg_only_deps.map { |d| d.opt_share/"aclocal" },
+ HOMEBREW_PREFIX/"share/aclocal",
+ homebrew_extra_aclocal_paths,
+ ).existing
end
def homebrew_extra_isystem_paths
@@ -158,13 +160,14 @@ module Superenv
end
def determine_isystem_paths
- paths = ["#{HOMEBREW_PREFIX}/include"]
- paths += homebrew_extra_isystem_paths
- paths.to_path_s
+ PATH.new(
+ HOMEBREW_PREFIX/"include",
+ homebrew_extra_isystem_paths,
+ ).existing
end
def determine_include_paths
- keg_only_deps.map { |d| d.opt_include.to_s }.to_path_s
+ PATH.new(keg_only_deps.map(&:opt_include)).existing
end
def homebrew_extra_library_paths
@@ -172,10 +175,11 @@ module Superenv
end
def determine_library_paths
- paths = keg_only_deps.map { |d| d.opt_lib.to_s }
- paths << "#{HOMEBREW_PREFIX}/lib"
- paths += homebrew_extra_library_paths
- paths.to_path_s
+ PATH.new(
+ keg_only_deps.map(&:opt_lib),
+ HOMEBREW_PREFIX/"lib",
+ homebrew_extra_library_paths,
+ ).existing
end
def determine_dependencies
@@ -183,9 +187,10 @@ module Superenv
end
def determine_cmake_prefix_path
- paths = keg_only_deps.map { |d| d.opt_prefix.to_s }
- paths << HOMEBREW_PREFIX.to_s
- paths.to_path_s
+ PATH.new(
+ keg_only_deps.map(&:opt_prefix),
+ HOMEBREW_PREFIX.to_s,
+ ).existing
end
def homebrew_extra_cmake_include_paths
@@ -193,9 +198,7 @@ module Superenv
end
def determine_cmake_include_path
- paths = []
- paths += homebrew_extra_cmake_include_paths
- paths.to_path_s
+ PATH.new(homebrew_extra_cmake_include_paths).existing
end
def homebrew_extra_cmake_library_paths
@@ -203,9 +206,7 @@ module Superenv
end
def determine_cmake_library_path
- paths = []
- paths += homebrew_extra_cmake_library_paths
- paths.to_path_s
+ PATH.new(homebrew_extra_cmake_library_paths).existing
end
def homebrew_extra_cmake_frameworks_paths
@@ -213,9 +214,10 @@ module Superenv
end
def determine_cmake_frameworks_path
- paths = deps.map { |d| d.opt_frameworks.to_s }
- paths += homebrew_extra_cmake_frameworks_paths
- paths.to_path_s
+ PATH.new(
+ deps.map(&:opt_frameworks),
+ homebrew_extra_cmake_frameworks_paths,
+ ).existing
end
def determine_make_jobs
@@ -326,15 +328,7 @@ module Superenv
def set_x11_env_if_installed
end
- # This method does nothing in superenv since there's no custom CFLAGS API
- # @private
- def set_cpu_flags(*_args)
- end
-end
-
-class Array
- def to_path_s
- map(&:to_s).uniq.select { |s| File.directory? s }.join(File::PATH_SEPARATOR).chuzzle
+ def set_cpu_flags(*)
end
end
diff --git a/Library/Homebrew/extend/io.rb b/Library/Homebrew/extend/io.rb
index 1357293cd..53bca196e 100644
--- a/Library/Homebrew/extend/io.rb
+++ b/Library/Homebrew/extend/io.rb
@@ -1,10 +1,17 @@
class IO
def readline_nonblock(sep = $INPUT_RECORD_SEPARATOR)
+ line = ""
buffer = ""
- buffer.concat(read_nonblock(1)) while buffer[-1] != sep
- buffer
+
+ loop do
+ break if buffer == sep
+ read_nonblock(1, buffer)
+ line.concat(buffer)
+ end
+
+ line
rescue IO::WaitReadable, EOFError => e
- raise e if buffer.empty?
- buffer
+ raise e if line.empty?
+ line
end
end
diff --git a/Library/Homebrew/extend/os/linux/requirements/osxfuse_requirement.rb b/Library/Homebrew/extend/os/linux/requirements/osxfuse_requirement.rb
new file mode 100644
index 000000000..3fd847bc4
--- /dev/null
+++ b/Library/Homebrew/extend/os/linux/requirements/osxfuse_requirement.rb
@@ -0,0 +1,39 @@
+require "requirement"
+
+class OsxfuseRequirement < Requirement
+ download "https://github.com/libfuse/libfuse"
+
+ satisfy(build_env: false) do
+ next true if libfuse_formula_exists? && Formula["libfuse"].installed?
+ includedirs = %w[
+ /usr/include
+ /usr/local/include
+ ]
+ next true if (includedirs.map do |dir|
+ File.exist? "#{dir}/fuse.h"
+ end).any?
+ false
+ end
+
+ def message
+ msg = "libfuse is required to install this formula.\n"
+ if libfuse_formula_exists?
+ msg + <<-EOS.undent
+ Run "brew install libfuse" to install it.
+ EOS
+ else
+ msg + super
+ end
+ end
+
+ private
+
+ def libfuse_formula_exists?
+ begin
+ Formula["libfuse"]
+ rescue FormulaUnavailableError
+ return false
+ end
+ true
+ end
+end
diff --git a/Library/Homebrew/extend/os/mac/diagnostic.rb b/Library/Homebrew/extend/os/mac/diagnostic.rb
index fb6b30836..ff936c75a 100644
--- a/Library/Homebrew/extend/os/mac/diagnostic.rb
+++ b/Library/Homebrew/extend/os/mac/diagnostic.rb
@@ -263,7 +263,7 @@ module Homebrew
SSL_CERT_DIR support was removed from Apple's curl.
If fetching formulae fails you should:
unset SSL_CERT_DIR
- and remove it from #{Utils::Shell.shell_profile} if present.
+ and remove it from #{Utils::Shell.profile} if present.
EOS
end
diff --git a/Library/Homebrew/extend/os/mac/formula_cellar_checks.rb b/Library/Homebrew/extend/os/mac/formula_cellar_checks.rb
index 5b1c648bf..10379c981 100644
--- a/Library/Homebrew/extend/os/mac/formula_cellar_checks.rb
+++ b/Library/Homebrew/extend/os/mac/formula_cellar_checks.rb
@@ -67,7 +67,7 @@ module FormulaCellarChecks
checker = LinkageChecker.new(keg, formula)
return unless checker.broken_dylibs?
- audit_check_output <<-EOS.undent
+ problem_if_output <<-EOS.undent
The installation was broken.
Broken dylib links found:
#{checker.broken_dylibs.to_a * "\n "}
@@ -76,9 +76,9 @@ module FormulaCellarChecks
def audit_installed
generic_audit_installed
- audit_check_output(check_shadowed_headers)
- audit_check_output(check_openssl_links)
- audit_check_output(check_python_framework_links(formula.lib))
+ problem_if_output(check_shadowed_headers)
+ problem_if_output(check_openssl_links)
+ problem_if_output(check_python_framework_links(formula.lib))
check_linkage
end
end
diff --git a/Library/Homebrew/extend/os/mac/hardware/cpu.rb b/Library/Homebrew/extend/os/mac/hardware/cpu.rb
index f180995fb..22d118e1a 100644
--- a/Library/Homebrew/extend/os/mac/hardware/cpu.rb
+++ b/Library/Homebrew/extend/os/mac/hardware/cpu.rb
@@ -107,6 +107,20 @@ module Hardware
end
end
+ # Determines whether the current CPU and macOS combination
+ # can run an executable of the specified architecture.
+ # `arch` is a symbol in the same format returned by
+ # Hardware::CPU.family
+ def can_run?(arch)
+ if Hardware::CPU.intel?
+ intel_can_run? arch
+ elsif Hardware::CPU.ppc?
+ ppc_can_run? arch
+ else
+ false
+ end
+ end
+
def features
@features ||= sysctl_n(
"machdep.cpu.features",
@@ -162,6 +176,35 @@ module Hardware
@properties[keys] = Utils.popen_read("/usr/sbin/sysctl", "-n", *keys)
end
end
+
+ def intel_can_run?(arch)
+ case arch
+ when :ppc
+ # Rosetta is still available
+ MacOS.version < :lion
+ when :ppc64
+ # Rosetta never supported PPC64
+ false
+ when :x86_64
+ Hardware::CPU.is_64_bit?
+ when :i386
+ true
+ else # dunno
+ false
+ end
+ end
+
+ def ppc_can_run?(arch)
+ case arch
+ when :ppc
+ true
+ when :ppc64
+ Hardware::CPU.is_64_bit?
+ else
+ # Intel is never supported
+ false
+ end
+ end
end
end
end
diff --git a/Library/Homebrew/extend/os/mac/requirements/osxfuse_requirement.rb b/Library/Homebrew/extend/os/mac/requirements/osxfuse_requirement.rb
new file mode 100644
index 000000000..8c898a272
--- /dev/null
+++ b/Library/Homebrew/extend/os/mac/requirements/osxfuse_requirement.rb
@@ -0,0 +1,34 @@
+require "requirement"
+
+class OsxfuseRequirement < Requirement
+ cask "osxfuse"
+ download "https://osxfuse.github.io/"
+
+ satisfy(build_env: false) { self.class.binary_osxfuse_installed? }
+
+ def self.binary_osxfuse_installed?
+ File.exist?("/usr/local/include/osxfuse/fuse.h") &&
+ !File.symlink?("/usr/local/include/osxfuse")
+ end
+
+ env do
+ ENV.append_path "PKG_CONFIG_PATH", HOMEBREW_LIBRARY/"Homebrew/os/mac/pkgconfig/fuse"
+
+ unless HOMEBREW_PREFIX.to_s == "/usr/local"
+ ENV.append_path "HOMEBREW_LIBRARY_PATHS", "/usr/local/lib"
+ ENV.append_path "HOMEBREW_INCLUDE_PATHS", "/usr/local/include/osxfuse"
+ end
+ end
+end
+
+class NonBinaryOsxfuseRequirement < Requirement
+ fatal true
+ satisfy(build_env: false) { HOMEBREW_PREFIX.to_s != "/usr/local" || !OsxfuseRequirement.binary_osxfuse_installed? }
+
+ def message
+ <<-EOS.undent
+ osxfuse is already installed from the binary distribution and
+ conflicts with this formula.
+ EOS
+ end
+end
diff --git a/Library/Homebrew/extend/os/requirements/osxfuse_requirement.rb b/Library/Homebrew/extend/os/requirements/osxfuse_requirement.rb
new file mode 100644
index 000000000..5f56d48c4
--- /dev/null
+++ b/Library/Homebrew/extend/os/requirements/osxfuse_requirement.rb
@@ -0,0 +1,7 @@
+require "requirements/osxfuse_requirement"
+
+if OS.mac?
+ require "extend/os/mac/requirements/osxfuse_requirement"
+elsif OS.linux?
+ require "extend/os/linux/requirements/osxfuse_requirement"
+end
diff --git a/Library/Homebrew/extend/pathname.rb b/Library/Homebrew/extend/pathname.rb
index eb254c624..c413e9e94 100644
--- a/Library/Homebrew/extend/pathname.rb
+++ b/Library/Homebrew/extend/pathname.rb
@@ -331,7 +331,6 @@ class Pathname
raise ChecksumMismatchError.new(self, expected, actual) unless expected == actual
end
- # FIXME: eliminate the places where we rely on this method
alias to_str to_s unless method_defined?(:to_str)
def cd
@@ -365,9 +364,8 @@ class Pathname
unless method_defined?(:/)
def /(other)
- unless other.respond_to?(:to_str) || other.respond_to?(:to_path)
- opoo "Pathname#/ called on #{inspect} with #{other.inspect} as an argument"
- puts "This behavior is deprecated, please pass either a String or a Pathname"
+ if !other.respond_to?(:to_str) && !other.respond_to?(:to_path)
+ odeprecated "Pathname#/ with #{other.class}", "a String or a Pathname"
end
self + other.to_s
end
diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb
index d544bd668..1230199bf 100644
--- a/Library/Homebrew/formula.rb
+++ b/Library/Homebrew/formula.rb
@@ -13,6 +13,7 @@ require "pkg_version"
require "tap"
require "keg"
require "migrator"
+require "extend/ENV"
# A formula provides instructions and metadata for Homebrew to install a piece
# of software. Every Homebrew formula is a {Formula}.
@@ -1004,19 +1005,26 @@ class Formula
def post_install; end
# @private
- def post_install_defined?
- method(:post_install).owner == self.class
- end
-
- # @private
def run_post_install
@prefix_returns_versioned_prefix = true
build = self.build
self.build = Tab.for_formula(self)
+
old_tmpdir = ENV["TMPDIR"]
old_temp = ENV["TEMP"]
old_tmp = ENV["TMP"]
+ old_path = ENV["HOMEBREW_PATH"]
+
ENV["TMPDIR"] = ENV["TEMP"] = ENV["TMP"] = HOMEBREW_TEMP
+ ENV["HOMEBREW_PATH"] = nil
+
+ ENV.clear_sensitive_environment!
+
+ Pathname.glob("#{bottle_prefix}/{etc,var}/**/*") do |path|
+ path.extend(InstallRenamed)
+ path.cp_path_sub(bottle_prefix, HOMEBREW_PREFIX)
+ end
+
with_logging("post_install") do
post_install
end
@@ -1025,6 +1033,7 @@ class Formula
ENV["TMPDIR"] = old_tmpdir
ENV["TEMP"] = old_temp
ENV["TMP"] = old_tmp
+ ENV["HOMEBREW_PATH"] = old_path
@prefix_returns_versioned_prefix = false
end
@@ -1664,9 +1673,15 @@ class Formula
old_temp = ENV["TEMP"]
old_tmp = ENV["TMP"]
old_term = ENV["TERM"]
+ old_path = ENV["HOMEBREW_PATH"]
+
ENV["CURL_HOME"] = old_curl_home || old_home
ENV["TMPDIR"] = ENV["TEMP"] = ENV["TMP"] = HOMEBREW_TEMP
ENV["TERM"] = "dumb"
+ ENV["HOMEBREW_PATH"] = nil
+
+ ENV.clear_sensitive_environment!
+
mktemp("#{name}-test") do |staging|
staging.retain! if ARGV.keep_tmp?
@testpath = staging.tmpdir
@@ -1689,6 +1704,7 @@ class Formula
ENV["TEMP"] = old_temp
ENV["TMP"] = old_tmp
ENV["TERM"] = old_term
+ ENV["HOMEBREW_PATH"] = old_path
@prefix_returns_versioned_prefix = false
end
@@ -1892,7 +1908,6 @@ class Formula
def exec_cmd(cmd, args, out, logfn)
ENV["HOMEBREW_CC_LOG_PATH"] = logfn
- # TODO: system "xcodebuild" is deprecated, this should be removed soon.
ENV.remove_cc_etc if cmd.to_s.start_with? "xcodebuild"
# Turn on argument filtering in the superenv compiler wrapper.
@@ -1925,17 +1940,28 @@ class Formula
mkdir_p env_home
old_home = ENV["HOME"]
- ENV["HOME"] = env_home
old_curl_home = ENV["CURL_HOME"]
- ENV["CURL_HOME"] = old_curl_home || old_home
+ old_path = ENV["HOMEBREW_PATH"]
+
+ unless ARGV.interactive?
+ ENV["HOME"] = env_home
+ ENV["CURL_HOME"] = old_curl_home || old_home
+ end
+ ENV["HOMEBREW_PATH"] = nil
+
setup_home env_home
+ ENV.clear_sensitive_environment!
+
begin
yield staging
ensure
@buildpath = nil
- ENV["HOME"] = old_home
- ENV["CURL_HOME"] = old_curl_home
+ unless ARGV.interactive?
+ ENV["HOME"] = old_home
+ ENV["CURL_HOME"] = old_curl_home
+ end
+ ENV["HOMEBREW_PATH"] = old_path
end
end
end
@@ -2396,7 +2422,6 @@ class Formula
# version '4.8.1'
# end</pre>
def fails_with(compiler, &block)
- # TODO: deprecate this in future.
# odeprecated "fails_with :llvm" if compiler == :llvm
specs.each { |spec| spec.fails_with(compiler, &block) }
end
diff --git a/Library/Homebrew/formula_cellar_checks.rb b/Library/Homebrew/formula_cellar_checks.rb
index 7db5e748b..7f7d77569 100644
--- a/Library/Homebrew/formula_cellar_checks.rb
+++ b/Library/Homebrew/formula_cellar_checks.rb
@@ -14,7 +14,7 @@ module FormulaCellarChecks
<<-EOS.undent
#{prefix_bin} is not in your PATH
- You can amend this by altering your #{Utils::Shell.shell_profile} file
+ You can amend this by altering your #{Utils::Shell.profile} file
EOS
end
@@ -154,17 +154,17 @@ module FormulaCellarChecks
end
def audit_installed
- audit_check_output(check_manpages)
- audit_check_output(check_infopages)
- audit_check_output(check_jars)
- audit_check_output(check_non_libraries)
- audit_check_output(check_non_executables(formula.bin))
- audit_check_output(check_generic_executables(formula.bin))
- audit_check_output(check_non_executables(formula.sbin))
- audit_check_output(check_generic_executables(formula.sbin))
- audit_check_output(check_easy_install_pth(formula.lib))
- audit_check_output(check_elisp_dirname(formula.share, formula.name))
- audit_check_output(check_elisp_root(formula.share, formula.name))
+ problem_if_output(check_manpages)
+ problem_if_output(check_infopages)
+ problem_if_output(check_jars)
+ problem_if_output(check_non_libraries)
+ problem_if_output(check_non_executables(formula.bin))
+ problem_if_output(check_generic_executables(formula.bin))
+ problem_if_output(check_non_executables(formula.sbin))
+ problem_if_output(check_generic_executables(formula.sbin))
+ problem_if_output(check_easy_install_pth(formula.lib))
+ problem_if_output(check_elisp_dirname(formula.share, formula.name))
+ problem_if_output(check_elisp_root(formula.share, formula.name))
end
alias generic_audit_installed audit_installed
diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb
index 017be51dc..f50d9ed9e 100644
--- a/Library/Homebrew/formula_installer.rb
+++ b/Library/Homebrew/formula_installer.rb
@@ -173,34 +173,22 @@ class FormulaInstaller
EOS
end
- if ENV["HOMEBREW_CHECK_RECURSIVE_VERSION_DEPENDENCIES"]
- version_hash = {}
- version_conflicts = Set.new
- recursive_formulae.each do |f|
- name = f.name
- unversioned_name, = name.split("@")
- version_hash[unversioned_name] ||= Set.new
- version_hash[unversioned_name] << name
- next if version_hash[unversioned_name].length < 2
- version_conflicts += version_hash[unversioned_name]
- end
- unless version_conflicts.empty?
- raise CannotInstallFormulaError, <<-EOS.undent
- #{formula.full_name} contains conflicting version recursive dependencies:
- #{version_conflicts.to_a.join ", "}
- View these with `brew deps --tree #{formula.full_name}`.
- EOS
- end
- end
-
- unless ENV["HOMEBREW_NO_CHECK_UNLINKED_DEPENDENCIES"]
- unlinked_deps = recursive_formulae.select do |dep|
- dep.installed? && !dep.keg_only? && !dep.linked_keg.directory?
- end
-
- unless unlinked_deps.empty?
- raise CannotInstallFormulaError, "You must `brew link #{unlinked_deps*" "}` before #{formula.full_name} can be installed"
- end
+ version_hash = {}
+ version_conflicts = Set.new
+ recursive_formulae.each do |f|
+ name = f.name
+ unversioned_name, = name.split("@")
+ version_hash[unversioned_name] ||= Set.new
+ version_hash[unversioned_name] << name
+ next if version_hash[unversioned_name].length < 2
+ version_conflicts += version_hash[unversioned_name]
+ end
+ unless version_conflicts.empty?
+ raise CannotInstallFormulaError, <<-EOS.undent
+ #{formula.full_name} contains conflicting version recursive dependencies:
+ #{version_conflicts.to_a.join ", "}
+ View these with `brew deps --tree #{formula.full_name}`.
+ EOS
end
pinned_unsatisfied_deps = recursive_deps.select do |dep|
@@ -229,11 +217,20 @@ class FormulaInstaller
# function but after instantiating this class so that it can avoid having to
# relink the active keg if possible (because it is slow).
if formula.linked_keg.directory?
- # some other version is already installed *and* linked
- raise CannotInstallFormulaError, <<-EOS.undent
- #{formula.name}-#{formula.linked_keg.resolved_path.basename} already installed
- To install this version, first `brew unlink #{formula.name}`
+ message = <<-EOS.undent
+ #{formula.name} #{formula.linked_keg.resolved_path.basename} is already installed
EOS
+ message += if formula.outdated? && !formula.head?
+ <<-EOS.undent
+ To upgrade to #{formula.version}, run `brew upgrade #{formula.name}`
+ EOS
+ else
+ # some other version is already installed *and* linked
+ <<-EOS.undent
+ To install #{formula.version}, first run `brew unlink #{formula.name}`
+ EOS
+ end
+ raise CannotInstallFormulaError, message
end
check_conflicts
@@ -567,13 +564,11 @@ class FormulaInstaller
fix_dynamic_linkage(keg)
end
- if formula.post_install_defined?
- if build_bottle?
- ohai "Not running post_install as we're building a bottle"
- puts "You can run it manually using `brew postinstall #{formula.full_name}`"
- else
- post_install
- end
+ if build_bottle?
+ ohai "Not running post_install as we're building a bottle"
+ puts "You can run it manually using `brew postinstall #{formula.full_name}`"
+ else
+ post_install
end
caveats
@@ -661,13 +656,15 @@ class FormulaInstaller
Sandbox.print_sandbox_message if Sandbox.formula?(formula)
Utils.safe_fork do
- # Invalidate the current sudo timestamp in case a build script calls sudo
- system "/usr/bin/sudo", "-k"
+ # 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.
+ system "/usr/bin/sudo", "-k" unless ENV["TRAVIS_SUDO"] == "false"
if Sandbox.formula?(formula)
sandbox = Sandbox.new
formula.logs.mkpath
sandbox.record_log(formula.logs/"build.sandbox.log")
+ sandbox.allow_write_path(ENV["HOME"]) if ARGV.interactive?
sandbox.allow_write_temp_and_cache
sandbox.allow_write_log(formula)
sandbox.allow_write_xcode
@@ -835,12 +832,6 @@ class FormulaInstaller
skip_linkage = formula.bottle_specification.skip_relocation?
keg.replace_placeholders_with_locations tab.changed_files, skip_linkage: skip_linkage
- Pathname.glob("#{formula.bottle_prefix}/{etc,var}/**/*") do |path|
- path.extend(InstallRenamed)
- path.cp_path_sub(formula.bottle_prefix, HOMEBREW_PREFIX)
- end
- FileUtils.rm_rf formula.bottle_prefix
-
tab = Tab.for_keg(keg)
CxxStdlib.check_compatibility(
@@ -858,15 +849,15 @@ class FormulaInstaller
tab.write
end
- def audit_check_output(output)
+ def problem_if_output(output)
return unless output
opoo output
@show_summary_heading = true
end
def audit_installed
- audit_check_output(check_env_path(formula.bin))
- audit_check_output(check_env_path(formula.sbin))
+ problem_if_output(check_env_path(formula.bin))
+ problem_if_output(check_env_path(formula.sbin))
super
end
@@ -899,6 +890,6 @@ class FormulaInstaller
def puts_requirement_messages
return unless @requirement_messages
return if @requirement_messages.empty?
- puts @requirement_messages
+ $stderr.puts @requirement_messages
end
end
diff --git a/Library/Homebrew/formula_support.rb b/Library/Homebrew/formula_support.rb
index b8476f5cc..4d963a55e 100644
--- a/Library/Homebrew/formula_support.rb
+++ b/Library/Homebrew/formula_support.rb
@@ -32,30 +32,30 @@ class KegOnlyReason
return @explanation unless @explanation.empty?
case @reason
when :versioned_formula then <<-EOS.undent
- This is an alternate version of another formula.
+ this is an alternate version of another formula
EOS
when :provided_by_macos, :provided_by_osx then <<-EOS.undent
macOS already provides this software and installing another version in
- parallel can cause all kinds of trouble.
+ parallel can cause all kinds of trouble
EOS
when :shadowed_by_macos, :shadowed_by_osx then <<-EOS.undent
macOS provides similar software and installing this software in
- parallel can cause all kinds of trouble.
+ parallel can cause all kinds of trouble
EOS
when :provided_pre_mountain_lion then <<-EOS.undent
- macOS already provides this software in versions before Mountain Lion.
+ macOS already provides this software in versions before Mountain Lion
EOS
when :provided_pre_mavericks then <<-EOS.undent
- macOS already provides this software in versions before Mavericks.
+ macOS already provides this software in versions before Mavericks
EOS
when :provided_pre_el_capitan then <<-EOS.undent
- macOS already provides this software in versions before El Capitan.
+ macOS already provides this software in versions before El Capitan
EOS
when :provided_until_xcode43 then <<-EOS.undent
- Xcode provides this software prior to version 4.3.
+ Xcode provides this software prior to version 4.3
EOS
when :provided_until_xcode5 then <<-EOS.undent
- Xcode provides this software prior to version 5.
+ Xcode provides this software prior to version 5
EOS
else
@reason
diff --git a/Library/Homebrew/formula_versions.rb b/Library/Homebrew/formula_versions.rb
index 28c2a3be8..70706a2f0 100644
--- a/Library/Homebrew/formula_versions.rb
+++ b/Library/Homebrew/formula_versions.rb
@@ -7,21 +7,22 @@ class FormulaVersions
ErrorDuringExecution, LoadError, MethodDeprecatedError
].freeze
+ MAX_VERSIONS_DEPTH = 2
+
attr_reader :name, :path, :repository, :entry_name
- def initialize(formula, options = {})
+ def initialize(formula)
@name = formula.name
@path = formula.path
@repository = formula.tap.path
@entry_name = @path.relative_path_from(repository).to_s
- @max_depth = options[:max_depth]
+ @current_formula = formula
end
def rev_list(branch)
repository.cd do
- depth = 0
Utils.popen_read("git", "rev-list", "--abbrev-commit", "--remove-empty", branch, "--", entry_name) do |io|
- yield io.readline.chomp until io.eof? || (@max_depth && (depth += 1) > @max_depth)
+ yield io.readline.chomp until io.eof?
end
end
end
@@ -49,11 +50,15 @@ class FormulaVersions
def bottle_version_map(branch)
map = Hash.new { |h, k| h[k] = [] }
+
+ versions_seen = 0
rev_list(branch) do |rev|
formula_at_revision(rev) do |f|
bottle = f.bottle_specification
map[f.pkg_version] << bottle.rebuild unless bottle.checksums.empty?
+ versions_seen = (map.keys + [f.pkg_version]).uniq.length
end
+ return map if versions_seen > MAX_VERSIONS_DEPTH
end
map
end
@@ -63,26 +68,38 @@ class FormulaVersions
return attributes_map if attributes.empty?
attributes.each do |attribute|
- attributes_map[attribute] ||= {}
+ attributes_map[attribute] ||= {
+ stable: {},
+ devel: {},
+ }
end
+ stable_versions_seen = 0
rev_list(branch) do |rev|
formula_at_revision(rev) do |f|
attributes.each do |attribute|
map = attributes_map[attribute]
- if f.stable
- map[:stable] ||= {}
- map[:stable][f.stable.version] ||= []
- map[:stable][f.stable.version] << f.send(attribute)
- end
- next unless f.devel
- map[:devel] ||= {}
- map[:devel][f.devel.version] ||= []
- map[:devel][f.devel.version] << f.send(attribute)
+ set_attribute_map(map, f, attribute)
+
+ stable_keys_length = (map[:stable].keys + [f.version]).uniq.length
+ stable_versions_seen = [stable_versions_seen, stable_keys_length].max
end
end
+ break if stable_versions_seen > MAX_VERSIONS_DEPTH
end
attributes_map
end
+
+ private
+
+ def set_attribute_map(map, f, attribute)
+ if f.stable
+ map[:stable][f.stable.version] ||= []
+ map[:stable][f.stable.version] << f.send(attribute)
+ end
+ return unless f.devel
+ map[:devel][f.devel.version] ||= []
+ map[:devel][f.devel.version] << f.send(attribute)
+ end
end
diff --git a/Library/Homebrew/formulary.rb b/Library/Homebrew/formulary.rb
index 4a65f8704..446d5dc10 100644
--- a/Library/Homebrew/formulary.rb
+++ b/Library/Homebrew/formulary.rb
@@ -105,7 +105,18 @@ module Formulary
# Loads formulae from bottles.
class BottleLoader < FormulaLoader
def initialize(bottle_name)
- @bottle_filename = Pathname(bottle_name).realpath
+ case bottle_name
+ when %r{(https?|ftp|file)://}
+ # The name of the formula is found between the last slash and the last hyphen.
+ resource = Resource.new bottle_name[%r{([^/]+)-}, 1] { url bottle_name }
+ downloader = CurlBottleDownloadStrategy.new resource.name, resource
+ @bottle_filename = downloader.cached_location
+ cached = @bottle_filename.exist?
+ downloader.fetch
+ ohai "Pouring the cached bottle" if cached
+ else
+ @bottle_filename = Pathname(bottle_name).realpath
+ end
name, full_name = Utils::Bottles.resolve_formula_names @bottle_filename
super name, Formulary.path(full_name)
end
@@ -210,6 +221,10 @@ module Formulary
def get_formula(spec, alias_path: nil)
super
+ rescue FormulaUnreadableError => e
+ raise TapFormulaUnreadableError.new(tap, name, e.formula_error), "", e.backtrace
+ rescue FormulaClassUnavailableError => e
+ raise TapFormulaClassUnavailableError.new(tap, name, e.path, e.class_name, e.class_list), "", e.backtrace
rescue FormulaUnavailableError => e
raise TapFormulaUnavailableError.new(tap, name), "", e.backtrace
end
@@ -331,10 +346,10 @@ module Formulary
def self.loader_for(ref, from: nil)
case ref
- when %r{(https?|ftp|file)://}
- return FromUrlLoader.new(ref)
when Pathname::BOTTLE_EXTNAME_RX
return BottleLoader.new(ref)
+ when %r{(https?|ftp|file)://}
+ return FromUrlLoader.new(ref)
when HOMEBREW_TAP_FORMULA_REGEX
return TapLoader.new(ref, from: from)
end
@@ -402,7 +417,7 @@ module Formulary
end
def self.tap_paths(name, taps = Dir["#{HOMEBREW_LIBRARY}/Taps/*/*/"])
- name = name.downcase
+ name = name.to_s.downcase
taps.map do |tap|
Pathname.glob([
"#{tap}Formula/#{name}.rb",
diff --git a/Library/Homebrew/global.rb b/Library/Homebrew/global.rb
index 391f5b012..877253072 100644
--- a/Library/Homebrew/global.rb
+++ b/Library/Homebrew/global.rb
@@ -3,6 +3,7 @@ require "extend/fileutils"
require "extend/pathname"
require "extend/git_repository"
require "extend/ARGV"
+require "PATH"
require "extend/string"
require "os"
require "utils"
@@ -10,6 +11,7 @@ require "exceptions"
require "set"
require "rbconfig"
require "official_taps"
+require "pp"
ARGV.extend(HomebrewArgvExtension)
@@ -53,7 +55,8 @@ HOMEBREW_PULL_OR_COMMIT_URL_REGEX = %r[https://github\.com/([\w-]+)/([\w-]+)?/(?
require "compat" unless ARGV.include?("--no-compat") || ENV["HOMEBREW_NO_COMPAT"]
-ORIGINAL_PATHS = ENV["PATH"].split(File::PATH_SEPARATOR).map do |p|
+ENV["HOMEBREW_PATH"] ||= ENV["PATH"]
+ORIGINAL_PATHS = PATH.new(ENV["HOMEBREW_PATH"]).map do |p|
begin
Pathname.new(p).expand_path
rescue
@@ -61,7 +64,6 @@ ORIGINAL_PATHS = ENV["PATH"].split(File::PATH_SEPARATOR).map do |p|
end
end.compact.freeze
-# TODO: remove this as soon as it's removed from commands.rb.
HOMEBREW_INTERNAL_COMMAND_ALIASES = {
"ls" => "list",
"homepage" => "home",
diff --git a/Library/Homebrew/gpg.rb b/Library/Homebrew/gpg.rb
index 777542055..cb9e367df 100644
--- a/Library/Homebrew/gpg.rb
+++ b/Library/Homebrew/gpg.rb
@@ -6,6 +6,7 @@ class Gpg
gpg_short_version = Utils.popen_read(gpg, "--version")[/\d\.\d/, 0]
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")
end
@@ -25,6 +26,10 @@ class Gpg
File.executable?(GPG_EXECUTABLE.to_s)
end
+ def self.version
+ @version if available?
+ end
+
def self.create_test_key(path)
odie "No GPG present to test against!" unless available?
diff --git a/Library/Homebrew/hardware.rb b/Library/Homebrew/hardware.rb
index fe07aee9d..997598def 100644
--- a/Library/Homebrew/hardware.rb
+++ b/Library/Homebrew/hardware.rb
@@ -80,6 +80,18 @@ module Hardware
def feature?(name)
features.include?(name)
end
+
+ def can_run?(arch)
+ if is_32_bit?
+ arch_32_bit == arch
+ elsif intel?
+ [:i386, :x86_64].include? arch
+ elsif ppc?
+ [:ppc, :ppc64].include? arch
+ else
+ false
+ end
+ end
end
end
diff --git a/Library/Homebrew/keg.rb b/Library/Homebrew/keg.rb
index d4b9c5d77..8733def27 100644
--- a/Library/Homebrew/keg.rb
+++ b/Library/Homebrew/keg.rb
@@ -468,7 +468,10 @@ class Keg
end
def aliases
- Formulary.from_rack(rack).aliases
+ formula = Formulary.from_rack(rack)
+ aliases = formula.aliases
+ return aliases if formula.stable?
+ aliases.reject { |a| a.include?("@") }
rescue FormulaUnavailableError
[]
end
diff --git a/Library/Homebrew/language/python.rb b/Library/Homebrew/language/python.rb
index 23c5246ba..0f8e3a4e6 100644
--- a/Library/Homebrew/language/python.rb
+++ b/Library/Homebrew/language/python.rb
@@ -53,29 +53,6 @@ module Language
quiet_system python, "-c", script
end
- # deprecated; use system "python", *setup_install_args(prefix) instead
- def self.setup_install(python, prefix, *args)
- opoo <<-EOS.undent
- Language::Python.setup_install is deprecated.
- If you are a formula author, please use
- system "python", *Language::Python.setup_install_args(prefix)
- instead.
- EOS
-
- # force-import setuptools, which monkey-patches distutils, to make
- # sure that we always call a setuptools setup.py. trick borrowed from pip:
- # https://github.com/pypa/pip/blob/043af83/pip/req/req_install.py#L743-L780
- shim = <<-EOS.undent
- import setuptools, tokenize
- __file__ = 'setup.py'
- exec(compile(getattr(tokenize, 'open', open)(__file__).read()
- .replace('\\r\\n', '\\n'), __file__, 'exec'))
- EOS
- args += %w[--single-version-externally-managed --record=installed.txt]
- args << "--prefix=#{prefix}"
- system python, "-c", shim, "install", *args
- end
-
def self.setup_install_args(prefix)
shim = <<-EOS.undent
import setuptools, tokenize
diff --git a/Library/Homebrew/manpages/brew.1.md.erb b/Library/Homebrew/manpages/brew.1.md.erb
index 5b0228e3f..29f8d0bec 100644
--- a/Library/Homebrew/manpages/brew.1.md.erb
+++ b/Library/Homebrew/manpages/brew.1.md.erb
@@ -98,8 +98,15 @@ can take several different forms:
The formula file will be cached for later use.
## ENVIRONMENT
+ * `HOMEBREW_ARTIFACT_DOMAIN`:
+ If set, instructs Homebrew to use the given URL as a download mirror for bottles and binaries.
+
+ * `HOMEBREW_AUTO_UPDATE_SECS`:
+ If set, Homebrew will only check for autoupdates once per this seconds interval.
+
+ *Default:* `60`.
- * `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`:
+ * `HOMEBREW_AWS_ACCESS_KEY_ID`, `HOMEBREW_AWS_SECRET_ACCESS_KEY`:
When using the `S3` download strategy, Homebrew will look in
these variables for access credentials (see
<https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html#cli-environment>
@@ -107,30 +114,9 @@ can take several different forms:
the `S3` download strategy will download with a public
(unsigned) URL.
- * `BROWSER`:
- If set, and `HOMEBREW_BROWSER` is not, use `BROWSER` as the web browser
- when opening project homepages.
-
- * `EDITOR`:
- If set, and `HOMEBREW_EDITOR` and `VISUAL` are not, use `EDITOR` as the text editor.
-
- * `GIT`:
- When using Git, Homebrew will use `GIT` if set,
- a Homebrew-built Git if installed, or the system-provided binary.
-
- Set this to force Homebrew to use a particular git binary.
-
* `HOMEBREW_BOTTLE_DOMAIN`:
If set, instructs Homebrew to use the given URL as a download mirror for bottles.
- * `HOMEBREW_ARTIFACT_DOMAIN`:
- If set, instructs Homebrew to use the given URL as a download mirror for bottles and binaries.
-
- * `HOMEBREW_AUTO_UPDATE_SECS`:
- If set, Homebrew will only check for autoupdates once per this seconds interval.
-
- *Default:* `60`.
-
* `HOMEBREW_BROWSER`:
If set, uses this setting as the browser when opening project homepages,
instead of the OS default browser.
@@ -178,6 +164,12 @@ can take several different forms:
If set, Homebrew will always use its vendored, relocatable Ruby 2.0 version
even if the system version of Ruby is >=2.0.
+ * `HOMEBREW_GIT`:
+ When using Git, Homebrew will use `GIT` if set,
+ a Homebrew-built Git if installed, or the system-provided binary.
+
+ Set this to force Homebrew to use a particular git binary.
+
* `HOMEBREW_GITHUB_API_TOKEN`:
A personal access token for the GitHub API, which you can create at
<https://github.com/settings/tokens>. If set, GitHub will allow you a
@@ -243,9 +235,6 @@ can take several different forms:
* `HOMEBREW_VERBOSE`:
If set, Homebrew always assumes `--verbose` when running commands.
- * `VISUAL`:
- If set, and `HOMEBREW_EDITOR` is not, use `VISUAL` as the text editor.
-
## USING HOMEBREW BEHIND A PROXY
Homebrew uses several commands for downloading files (e.g. `curl`, `git`, `svn`).
diff --git a/Library/Homebrew/missing_formula.rb b/Library/Homebrew/missing_formula.rb
index 5b903b899..eac3d7725 100644
--- a/Library/Homebrew/missing_formula.rb
+++ b/Library/Homebrew/missing_formula.rb
@@ -122,7 +122,7 @@ module Homebrew
path = Formulary.path name
return if File.exist? path
tap = Tap.from_path(path)
- return unless File.exist? tap.path
+ return if tap.nil? || !File.exist?(tap.path)
relative_path = path.relative_path_from tap.path
tap.path.cd do
diff --git a/Library/Homebrew/official_taps.rb b/Library/Homebrew/official_taps.rb
index a7bc4a1d6..dcb65d9f8 100644
--- a/Library/Homebrew/official_taps.rb
+++ b/Library/Homebrew/official_taps.rb
@@ -5,8 +5,29 @@ OFFICIAL_TAPS = %w[
science
].freeze
+OFFICIAL_CASK_TAPS = %w[
+ cask
+ versions
+].freeze
+
OFFICIAL_CMD_TAPS = {
"homebrew/bundle" => ["bundle"],
"homebrew/test-bot" => ["test-bot"],
"homebrew/services" => ["services"],
}.freeze
+
+DEPRECATED_OFFICIAL_TAPS = %w[
+ binary
+ completions
+ devel-only
+ dupes
+ emacs
+ fuse
+ games
+ gui
+ head-only
+ python
+ tex
+ versions
+ x11
+].freeze
diff --git a/Library/Homebrew/os/mac.rb b/Library/Homebrew/os/mac.rb
index 518936647..dba2480ef 100644
--- a/Library/Homebrew/os/mac.rb
+++ b/Library/Homebrew/os/mac.rb
@@ -205,6 +205,8 @@ module OS
"8.2" => { clang: "8.0", clang_build: 800 },
"8.2.1" => { clang: "8.0", clang_build: 800 },
"8.3" => { clang: "8.1", clang_build: 802 },
+ "8.3.1" => { clang: "8.1", clang_build: 802 },
+ "8.3.2" => { clang: "8.1", clang_build: 802 },
}.freeze
def compilers_standard?
diff --git a/Library/Homebrew/os/mac/xcode.rb b/Library/Homebrew/os/mac/xcode.rb
index 70fe3c14d..9ed95d3f2 100644
--- a/Library/Homebrew/os/mac/xcode.rb
+++ b/Library/Homebrew/os/mac/xcode.rb
@@ -17,12 +17,12 @@ module OS
when "10.9" then "6.2"
when "10.10" then "7.2.1"
when "10.11" then "8.2.1"
- when "10.12" then "8.3"
+ when "10.12" then "8.3.2"
else
raise "macOS '#{MacOS.version}' is invalid" unless OS::Mac.prerelease?
# Default to newest known version of Xcode for unreleased macOS versions.
- "8.3"
+ "8.3.2"
end
end
@@ -128,11 +128,10 @@ module OS
end
end
- # The remaining logic provides a fake Xcode version for CLT-only
- # systems. This behavior only exists because Homebrew used to assume
- # Xcode.version would always be non-nil. This is deprecated, and will
- # be removed in a future version. To remain compatible, guard usage of
- # Xcode.version with an Xcode.installed? check.
+ # The remaining logic provides a fake Xcode version based on the
+ # installed CLT version. This is useful as they are packaged
+ # simultaneously so workarounds need to apply to both based on their
+ # comparable version.
case (DevelopmentTools.clang_version.to_f * 10).to_i
when 0 then "dunno"
when 1..14 then "3.2.2"
@@ -214,7 +213,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.12" then "802.0.38"
+ when "10.12" then "802.0.42"
when "10.11" then "800.0.42.1"
when "10.10" then "700.1.81"
when "10.9" then "600.0.57"
diff --git a/Library/Homebrew/os/mac/xquartz.rb b/Library/Homebrew/os/mac/xquartz.rb
index b82772faf..2fdf0abea 100644
--- a/Library/Homebrew/os/mac/xquartz.rb
+++ b/Library/Homebrew/os/mac/xquartz.rb
@@ -5,7 +5,6 @@ module OS
module XQuartz
module_function
- # TODO: confirm this path when you have internet
DEFAULT_BUNDLE_PATH = Pathname.new("Applications/Utilities/XQuartz.app").freeze
FORGE_BUNDLE_ID = "org.macosforge.xquartz.X11".freeze
APPLE_BUNDLE_ID = "org.x.X11".freeze
diff --git a/Library/Homebrew/readall.rb b/Library/Homebrew/readall.rb
index 3dd7075ec..ddac58444 100644
--- a/Library/Homebrew/readall.rb
+++ b/Library/Homebrew/readall.rb
@@ -24,14 +24,21 @@ module Readall
!failed
end
- def valid_aliases?(alias_dirs)
+ def valid_aliases?(alias_dir, formula_dir)
+ return true unless alias_dir.directory?
+
failed = false
- alias_dirs.each do |alias_dir|
- next unless alias_dir.directory?
- alias_dir.children.each do |f|
- next unless f.symlink?
- next if f.file?
- onoe "Broken alias: #{f}"
+ alias_dir.each_child do |f|
+ if !f.symlink?
+ onoe "Non-symlink alias: #{f}"
+ failed = true
+ elsif !f.file?
+ onoe "Non-file alias: #{f}"
+ failed = true
+ end
+
+ if (formula_dir/"#{f.basename}.rb").exist?
+ onoe "Formula duplicating alias: #{f}"
failed = true
end
end
@@ -57,7 +64,7 @@ module Readall
def valid_tap?(tap, options = {})
failed = false
if options[:aliases]
- valid_aliases = valid_aliases?([tap.alias_dir])
+ valid_aliases = valid_aliases?(tap.alias_dir, tap.formula_dir)
failed = true unless valid_aliases
end
valid_formulae = valid_formulae?(tap.formula_files)
diff --git a/Library/Homebrew/requirement.rb b/Library/Homebrew/requirement.rb
index bd8cf20c8..6c20e7917 100644
--- a/Library/Homebrew/requirement.rb
+++ b/Library/Homebrew/requirement.rb
@@ -96,7 +96,7 @@ class Requirement
# PATH.
parent = satisfied_result_parent
return unless parent
- return if ENV["PATH"].split(File::PATH_SEPARATOR).include?(parent.to_s)
+ return if PATH.new(ENV["PATH"]).include?(parent.to_s)
ENV.append_path("PATH", parent)
end
@@ -151,21 +151,19 @@ class Requirement
end
def which(cmd)
- super(cmd, ORIGINAL_PATHS.join(File::PATH_SEPARATOR))
+ super(cmd, PATH.new(ORIGINAL_PATHS))
end
def which_all(cmd)
- super(cmd, ORIGINAL_PATHS.join(File::PATH_SEPARATOR))
+ super(cmd, PATH.new(ORIGINAL_PATHS))
end
class << self
include BuildEnvironmentDSL
- attr_reader :env_proc
+ attr_reader :env_proc, :build
attr_rw :fatal, :default_formula
attr_rw :cask, :download
- # build is deprecated, use `depends_on <requirement> => :build` instead
- attr_rw :build
def satisfy(options = {}, &block)
@satisfied ||= Requirement::Satisfier.new(options, &block)
diff --git a/Library/Homebrew/requirements/osxfuse_requirement.rb b/Library/Homebrew/requirements/osxfuse_requirement.rb
index d5a341567..9a07209d4 100644
--- a/Library/Homebrew/requirements/osxfuse_requirement.rb
+++ b/Library/Homebrew/requirements/osxfuse_requirement.rb
@@ -2,34 +2,10 @@ require "requirement"
class OsxfuseRequirement < Requirement
fatal true
- cask "osxfuse"
- download "https://osxfuse.github.io/"
-
- satisfy(build_env: false) { self.class.binary_osxfuse_installed? }
-
- def self.binary_osxfuse_installed?
- File.exist?("/usr/local/include/osxfuse/fuse.h") &&
- !File.symlink?("/usr/local/include/osxfuse")
- end
-
- env do
- ENV.append_path "PKG_CONFIG_PATH", HOMEBREW_LIBRARY/"Homebrew/os/mac/pkgconfig/fuse"
-
- unless HOMEBREW_PREFIX.to_s == "/usr/local"
- ENV.append_path "HOMEBREW_LIBRARY_PATHS", "/usr/local/lib"
- ENV.append_path "HOMEBREW_INCLUDE_PATHS", "/usr/local/include/osxfuse"
- end
- end
end
class NonBinaryOsxfuseRequirement < Requirement
- fatal true
- satisfy(build_env: false) { HOMEBREW_PREFIX.to_s != "/usr/local" || !OsxfuseRequirement.binary_osxfuse_installed? }
-
- def message
- <<-EOS.undent
- osxfuse is already installed from the binary distribution and
- conflicts with this formula.
- EOS
- end
+ fatal false
end
+
+require "extend/os/requirements/osxfuse_requirement"
diff --git a/Library/Homebrew/rubocops.rb b/Library/Homebrew/rubocops.rb
index 3625f2004..587bf4b20 100644
--- a/Library/Homebrew/rubocops.rb
+++ b/Library/Homebrew/rubocops.rb
@@ -1,2 +1,5 @@
require_relative "./rubocops/bottle_block_cop"
require_relative "./rubocops/formula_desc_cop"
+require_relative "./rubocops/components_order_cop"
+require_relative "./rubocops/components_redundancy_cop"
+require_relative "./rubocops/homepage_cop"
diff --git a/Library/Homebrew/rubocops/bottle_block_cop.rb b/Library/Homebrew/rubocops/bottle_block_cop.rb
index 4d7a94461..f0c7d59bb 100644
--- a/Library/Homebrew/rubocops/bottle_block_cop.rb
+++ b/Library/Homebrew/rubocops/bottle_block_cop.rb
@@ -2,18 +2,18 @@ require_relative "./extend/formula_cop"
module RuboCop
module Cop
- module Homebrew
+ module FormulaAuditStrict
# This cop audits `bottle` block in Formulae
#
# - `rebuild` should be used instead of `revision` in `bottle` block
- class CorrectBottleBlock < FormulaCop
+ class BottleBlock < FormulaCop
MSG = "Use rebuild instead of revision in bottle block".freeze
def audit_formula(_node, _class_node, _parent_class_node, formula_class_body_node)
bottle = find_block(formula_class_body_node, :bottle)
return if bottle.nil? || block_size(bottle).zero?
- problem "Use rebuild instead of revision in bottle block" if method_called?(bottle, :revision)
+ problem "Use rebuild instead of revision in bottle block" if method_called_in_block?(bottle, :revision)
end
private
diff --git a/Library/Homebrew/rubocops/components_order_cop.rb b/Library/Homebrew/rubocops/components_order_cop.rb
new file mode 100644
index 000000000..dfddbe145
--- /dev/null
+++ b/Library/Homebrew/rubocops/components_order_cop.rb
@@ -0,0 +1,114 @@
+require_relative "./extend/formula_cop"
+
+module RuboCop
+ module Cop
+ module FormulaAuditStrict
+ # This cop checks for correct order of components in a Formula
+ #
+ # - component_precedence_list has component hierarchy in a nested list
+ # where each sub array contains components' details which are at same precedence level
+ class ComponentsOrder < FormulaCop
+ def audit_formula(_node, _class_node, _parent_class_node, formula_class_body_node)
+ component_precedence_list = [
+ [{ name: :include, type: :method_call }],
+ [{ name: :desc, type: :method_call }],
+ [{ name: :homepage, type: :method_call }],
+ [{ name: :url, type: :method_call }],
+ [{ name: :mirror, type: :method_call }],
+ [{ name: :version, type: :method_call }],
+ [{ name: :sha256, type: :method_call }],
+ [{ name: :revision, type: :method_call }],
+ [{ name: :version_scheme, type: :method_call }],
+ [{ name: :head, type: :method_call }],
+ [{ name: :stable, type: :block_call }],
+ [{ name: :bottle, type: :block_call }],
+ [{ name: :devel, type: :block_call }],
+ [{ name: :head, type: :block_call }],
+ [{ name: :bottle, type: :method_call }],
+ [{ name: :keg_only, type: :method_call }],
+ [{ name: :option, type: :method_call }],
+ [{ name: :depends_on, type: :method_call }],
+ [{ name: :conflicts_with, type: :method_call }],
+ [{ name: :go_resource, type: :block_call }, { name: :resource, type: :block_call }],
+ [{ name: :install, type: :method_definition }],
+ [{ name: :caveats, type: :method_definition }],
+ [{ name: :plist_options, type: :method_call }, { name: :plist, type: :method_definition }],
+ [{ name: :test, type: :block_call }],
+ ]
+
+ @present_components = component_precedence_list.map do |components|
+ relevant_components = []
+ components.each do |component|
+ case component[:type]
+ when :method_call
+ relevant_components += find_method_calls_by_name(formula_class_body_node, component[:name]).to_a
+ when :block_call
+ relevant_components += find_blocks(formula_class_body_node, component[:name]).to_a
+ when :method_definition
+ relevant_components << find_method_def(formula_class_body_node, component[:name])
+ end
+ end
+ relevant_components.delete_if(&:nil?)
+ end
+
+ # Check if each present_components is above rest of the present_components
+ @present_components.take(@present_components.size-1).each_with_index do |preceding_component, p_idx|
+ next if preceding_component.empty?
+ @present_components.drop(p_idx+1).each do |succeeding_component|
+ next if succeeding_component.empty?
+ @offensive_nodes = check_precedence(preceding_component, succeeding_component)
+ component_problem @offensive_nodes[0], @offensive_nodes[1] if @offensive_nodes
+ end
+ end
+ end
+
+ private
+
+ # Method to format message for reporting component precedence violations
+ def component_problem(c1, c2)
+ problem "`#{format_component(c1)}` (line #{line_number(c1)}) should be put before `#{format_component(c2)}` (line #{line_number(c2)})"
+ end
+
+ # autocorrect method gets called just after component_problem method call
+ def autocorrect(_node)
+ succeeding_node = @offensive_nodes[0]
+ preceding_node = @offensive_nodes[1]
+ lambda do |corrector|
+ reorder_components(corrector, succeeding_node, preceding_node)
+ end
+ end
+
+ # Reorder two nodes in the source, using the corrector instance in autocorrect method
+ # Components of same type are grouped together when rewriting the source
+ # Linebreaks are introduced if components are of two different methods/blocks/multilines
+ def reorder_components(corrector, node1, node2)
+ # order_idx : node1's index in component_precedence_list
+ # curr_p_idx: node1's index in preceding_comp_arr
+ # 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
+ node2 = preceding_comp_arr[curr_p_idx-1]
+ indentation = " " * (start_column(node2) - line_start_column(node2))
+ line_breaks = node2.multiline? ? "\n\n" : "\n"
+ corrector.insert_after(node2.source_range, line_breaks+indentation+node1.source)
+ else
+ indentation = " " * (start_column(node2) - line_start_column(node2))
+ # No line breaks upto version_scheme, order_idx == 8
+ line_breaks = order_idx>8 ? "\n\n" : "\n"
+ corrector.insert_before(node2.source_range, node1.source+line_breaks+indentation)
+ end
+ corrector.remove(range_with_surrounding_space(node1.source_range, :left))
+ end
+
+ # Returns precedence index and component's index to properly reorder and group during autocorrect
+ def get_state(node1)
+ @present_components.each_with_index do |comp, idx|
+ return [idx, comp.index(node1), comp] if comp.member?(node1)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/Library/Homebrew/rubocops/components_redundancy_cop.rb b/Library/Homebrew/rubocops/components_redundancy_cop.rb
new file mode 100644
index 000000000..52dba4718
--- /dev/null
+++ b/Library/Homebrew/rubocops/components_redundancy_cop.rb
@@ -0,0 +1,33 @@
+require_relative "./extend/formula_cop"
+
+module RuboCop
+ module Cop
+ module FormulaAuditStrict
+ # This cop checks if redundant components are present and other component errors
+ #
+ # - `url|checksum|mirror` should be inside `stable` block
+ # - `head` and `head do` should not be simultaneously present
+ # - `bottle :unneeded/:disable` and `bottle do` should not be simultaneously present
+
+ class ComponentsRedundancy < FormulaCop
+ HEAD_MSG = "`head` and `head do` should not be simultaneously present".freeze
+ BOTTLE_MSG = "`bottle :modifier` and `bottle do` should not be simultaneously present".freeze
+
+ def audit_formula(_node, _class_node, _parent_class_node, formula_class_body_node)
+ stable_block = find_block(formula_class_body_node, :stable)
+ if stable_block
+ [:url, :sha256, :mirror].each do |method_name|
+ problem "`#{method_name}` should be put inside `stable` block" if method_called?(formula_class_body_node, method_name)
+ end
+ end
+
+ problem HEAD_MSG if method_called?(formula_class_body_node, :head) &&
+ find_block(formula_class_body_node, :head)
+
+ problem BOTTLE_MSG if method_called?(formula_class_body_node, :bottle) &&
+ find_block(formula_class_body_node, :bottle)
+ end
+ end
+ end
+ end
+end
diff --git a/Library/Homebrew/rubocops/extend/formula_cop.rb b/Library/Homebrew/rubocops/extend/formula_cop.rb
index 49108bd48..3f70086b3 100644
--- a/Library/Homebrew/rubocops/extend/formula_cop.rb
+++ b/Library/Homebrew/rubocops/extend/formula_cop.rb
@@ -1,143 +1,212 @@
module RuboCop
module Cop
- module Homebrew
- class FormulaCop < Cop
- @registry = Cop.registry
-
- def on_class(node)
- # This method is called by RuboCop and is the main entry point
- file_path = processed_source.buffer.name
- return unless file_path_allowed?(file_path)
- class_node, parent_class_node, body = *node
- return unless formula_class?(parent_class_node)
- return unless respond_to?(:audit_formula)
- @formula_name = class_name(class_node)
- audit_formula(node, class_node, parent_class_node, body)
- end
+ class FormulaCop < Cop
+ @registry = Cop.registry
+
+ # This method is called by RuboCop and is the main entry point
+ def on_class(node)
+ file_path = processed_source.buffer.name
+ return unless file_path_allowed?(file_path)
+ class_node, parent_class_node, body = *node
+ return unless formula_class?(parent_class_node)
+ return unless respond_to?(:audit_formula)
+ @formula_name = class_name(class_node)
+ audit_formula(node, class_node, parent_class_node, body)
+ end
- def regex_match_group(node, pattern)
- # Checks for regex match of pattern in the node and
- # Sets the appropriate instance variables to report the match
- string_repr = string_content(node)
- match_object = string_repr.match(pattern)
- return unless match_object
- node_begin_pos = start_column(node)
- line_begin_pos = line_start_column(node)
- @column = node_begin_pos + match_object.begin(0) - line_begin_pos + 1
- @length = match_object.to_s.length
- @line_no = line_number(node)
- @source_buf = source_buffer(node)
- @offense_source_range = source_range(@source_buf, @line_no, @column, @length)
- @offensive_node = node
- match_object
- end
+ # Checks for regex match of pattern in the node and
+ # Sets the appropriate instance variables to report the match
+ def regex_match_group(node, pattern)
+ string_repr = string_content(node)
+ match_object = string_repr.match(pattern)
+ return unless match_object
+ node_begin_pos = start_column(node)
+ line_begin_pos = line_start_column(node)
+ @column = node_begin_pos + match_object.begin(0) - line_begin_pos + 1
+ @length = match_object.to_s.length
+ @line_no = line_number(node)
+ @source_buf = source_buffer(node)
+ @offense_source_range = source_range(@source_buf, @line_no, @column, @length)
+ @offensive_node = node
+ match_object
+ end
- def find_node_method_by_name(node, method_name)
- # Returns method_node matching method_name
- return if node.nil?
- node.each_child_node(:send) do |method_node|
- next unless method_node.method_name == method_name
- @offensive_node = method_node
- @offense_source_range = method_node.source_range
- return method_node
- end
- # If not found then, parent node becomes the offensive node
- @offensive_node = node.parent
- @offense_source_range = node.parent.source_range
- nil
+ # Returns method_node matching method_name
+ def find_node_method_by_name(node, method_name)
+ return if node.nil?
+ node.each_child_node(:send) do |method_node|
+ next unless method_node.method_name == method_name
+ @offensive_node = method_node
+ @offense_source_range = method_node.source_range
+ return method_node
+ end
+ # If not found then, parent node becomes the offensive node
+ @offensive_node = node.parent
+ @offense_source_range = node.parent.source_range
+ nil
+ end
+
+ # Returns an array of method call nodes matching method_name inside node
+ def find_method_calls_by_name(node, method_name)
+ return if node.nil?
+ node.each_child_node(:send).select { |method_node| method_name == method_node.method_name }
+ end
+
+ # Returns a block named block_name inside node
+ def find_block(node, block_name)
+ return if node.nil?
+ node.each_child_node(:block) do |block_node|
+ next if block_node.method_name != block_name
+ @offensive_node = block_node
+ @offense_source_range = block_node.source_range
+ return block_node
+ end
+ # If not found then, parent node becomes the offensive node
+ @offensive_node = node.parent
+ @offense_source_range = node.parent.source_range
+ nil
+ end
+
+ # Returns an array of block nodes named block_name inside node
+ def find_blocks(node, block_name)
+ return if node.nil?
+ node.each_child_node(:block).select { |block_node| block_name == block_node.method_name }
+ end
+
+ # Returns a method definition node with method_name
+ def find_method_def(node, method_name)
+ return if node.nil?
+ node.each_child_node(:def) do |def_node|
+ def_method_name = method_name(def_node)
+ next unless method_name == def_method_name
+ @offensive_node = def_node
+ @offense_source_range = def_node.source_range
+ return def_node
+ end
+ # If not found then, parent node becomes the offensive node
+ @offensive_node = node.parent
+ @offense_source_range = node.parent.source_range
+ nil
+ end
+
+ # Check if a method is called inside a block
+ def method_called_in_block?(node, method_name)
+ block_body = node.children[2]
+ block_body.each_child_node(:send) do |call_node|
+ next unless call_node.method_name == method_name
+ @offensive_node = call_node
+ @offense_source_range = call_node.source_range
+ return true
end
+ false
+ end
- def find_block(node, block_name)
- # Returns a block named block_name inside node
- return if node.nil?
- node.each_child_node(:block) do |block_node|
- next if block_node.method_name != block_name
- @offensive_node = block_node
- @offense_source_range = block_node.source_range
- return block_node
- end
- # If not found then, parent node becomes the offensive node
- @offensive_node = node.parent
- @offense_source_range = node.parent.source_range
- nil
+ # Check if method_name is called among the direct children nodes in the given node
+ def method_called?(node, method_name)
+ node.each_child_node(:send) do |call_node|
+ next unless call_node.method_name == method_name
+ @offensive_node = call_node
+ @offense_source_range = call_node.source_range
+ return true
end
+ false
+ end
- def method_called?(node, method_name)
- # Check if a method is called inside a block
- block_body = node.children[2]
- block_body.each_child_node(:send) do |call_node|
- next unless call_node.method_name == method_name
- @offensive_node = call_node
- @offense_source_range = call_node.source_range
- return true
+ # Checks for precedence, returns the first pair of precedence violating nodes
+ def check_precedence(first_nodes, next_nodes)
+ next_nodes.each do |each_next_node|
+ first_nodes.each do |each_first_node|
+ if component_precedes?(each_first_node, each_next_node)
+ return [each_first_node, each_next_node]
+ end
end
- false
end
+ nil
+ end
- def parameters(method_node)
- # Returns the array of arguments of the method_node
- return unless method_node.send_type?
- method_node.method_args
- end
+ # If first node does not precede next_node, sets appropriate instance variables for reporting
+ def component_precedes?(first_node, next_node)
+ return false if line_number(first_node) < line_number(next_node)
+ @offense_source_range = first_node.source_range
+ @offensive_node = first_node
+ true
+ end
- def line_start_column(node)
- # Returns the begin position of the node's line in source code
- node.source_range.source_buffer.line_range(node.loc.line).begin_pos
- end
+ # Returns the array of arguments of the method_node
+ def parameters(method_node)
+ return unless method_node.send_type?
+ method_node.method_args
+ end
- def start_column(node)
- # Returns the begin position of the node in source code
- node.source_range.begin_pos
- end
+ # Returns the begin position of the node's line in source code
+ def line_start_column(node)
+ node.source_range.source_buffer.line_range(node.loc.line).begin_pos
+ end
- def line_number(node)
- # Returns the line number of the node
- node.loc.line
- end
+ # Returns the begin position of the node in source code
+ def start_column(node)
+ node.source_range.begin_pos
+ end
- def class_name(node)
- # Returns the class node's name, nil if not a class node
- @offensive_node = node
- @offense_source_range = node.source_range
- node.const_name
- end
+ # Returns the line number of the node
+ def line_number(node)
+ node.loc.line
+ end
- def size(node)
- # Returns the node size in the source code
- node.source_range.size
- end
+ # Returns the class node's name, nil if not a class node
+ def class_name(node)
+ @offensive_node = node
+ @offense_source_range = node.source_range
+ node.const_name
+ end
- def block_size(block)
- # Returns the block length of the block node
- block_length(block)
- end
+ # Returns the method name for a def node
+ def method_name(node)
+ node.children[0] if node.def_type?
+ end
- def source_buffer(node)
- # Source buffer is required as an argument to report style violations
- node.source_range.source_buffer
- end
+ # Returns the node size in the source code
+ def size(node)
+ node.source_range.size
+ end
- def string_content(node)
- # Returns the string representation if node is of type str
- node.str_content if node.type == :str
- end
+ # Returns the block length of the block node
+ def block_size(block)
+ block_length(block)
+ end
- def problem(msg)
- add_offense(@offensive_node, @offense_source_range, msg)
- end
+ # Source buffer is required as an argument to report style violations
+ def source_buffer(node)
+ node.source_range.source_buffer
+ end
- private
+ # Returns the string representation if node is of type str(plain) or dstr(interpolated)
+ def string_content(node)
+ return node.str_content if node.type == :str
+ node.each_child_node(:str).map(&:str_content).join("") if node.type == :dstr
+ end
- def formula_class?(parent_class_node)
- parent_class_node && parent_class_node.const_name == "Formula"
- end
+ # Returns printable component name
+ def format_component(component_node)
+ return component_node.method_name if component_node.send_type? || component_node.block_type?
+ method_name(component_node) if component_node.def_type?
+ end
- def file_path_allowed?(file_path)
- paths_to_exclude = [%r{/Library/Homebrew/compat/},
- %r{/Library/Homebrew/test/}]
- return true if file_path.nil? # file_path is nil when source is directly passed to the cop eg., in specs
- file_path !~ Regexp.union(paths_to_exclude)
- end
+ def problem(msg)
+ add_offense(@offensive_node, @offense_source_range, msg)
+ end
+
+ private
+
+ def formula_class?(parent_class_node)
+ parent_class_node && parent_class_node.const_name == "Formula"
+ end
+
+ def file_path_allowed?(file_path)
+ paths_to_exclude = [%r{/Library/Homebrew/compat/},
+ %r{/Library/Homebrew/test/}]
+ return true if file_path.nil? # file_path is nil when source is directly passed to the cop eg., in specs
+ file_path !~ Regexp.union(paths_to_exclude)
end
end
end
diff --git a/Library/Homebrew/rubocops/formula_desc_cop.rb b/Library/Homebrew/rubocops/formula_desc_cop.rb
index 7d69a48e7..1fbf1ddbf 100644
--- a/Library/Homebrew/rubocops/formula_desc_cop.rb
+++ b/Library/Homebrew/rubocops/formula_desc_cop.rb
@@ -3,7 +3,7 @@ require_relative "../extend/string"
module RuboCop
module Cop
- module Homebrew
+ module FormulaAuditStrict
# This cop audits `desc` in Formulae
#
# - Checks for existence of `desc`
@@ -11,7 +11,7 @@ module RuboCop
# - Checks if `desc` begins with an article
# - Checks for correct usage of `command-line` in `desc`
# - Checks if `desc` contains the formula name
- class FormulaDesc < FormulaCop
+ class Desc < FormulaCop
def audit_formula(_node, _class_node, _parent_class_node, body)
desc_call = find_node_method_by_name(body, :desc)
diff --git a/Library/Homebrew/rubocops/homepage_cop.rb b/Library/Homebrew/rubocops/homepage_cop.rb
new file mode 100644
index 000000000..a40c7b049
--- /dev/null
+++ b/Library/Homebrew/rubocops/homepage_cop.rb
@@ -0,0 +1,82 @@
+require_relative "./extend/formula_cop"
+
+module RuboCop
+ module Cop
+ module FormulaAudit
+ # This cop audits `homepage` url in Formulae
+ class Homepage < FormulaCop
+ def audit_formula(_node, _class_node, _parent_class_node, formula_class_body_node)
+ homepage_node = find_node_method_by_name(formula_class_body_node, :homepage)
+ homepage = if homepage_node
+ string_content(parameters(homepage_node).first)
+ else
+ ""
+ end
+
+ problem "Formula should have a homepage." if homepage_node.nil? || homepage.empty?
+
+ unless homepage =~ %r{^https?://}
+ problem "The homepage should start with http or https (URL is #{homepage})."
+ end
+
+ case homepage
+ # Check for http:// GitHub homepage urls, https:// is preferred.
+ # Note: only check homepages that are repo pages, not *.github.com hosts
+ when %r{^http://github.com/}
+ problem "Please use https:// for #{homepage}"
+
+ # Savannah has full SSL/TLS support but no auto-redirect.
+ # Doesn't apply to the download URLs, only the homepage.
+ when %r{^http://savannah.nongnu.org/}
+ problem "Please use https:// for #{homepage}"
+
+ # Freedesktop is complicated to handle - It has SSL/TLS, but only on certain subdomains.
+ # To enable https Freedesktop change the URL from http://project.freedesktop.org/wiki to
+ # https://wiki.freedesktop.org/project_name.
+ # "Software" is redirected to https://wiki.freedesktop.org/www/Software/project_name
+ when %r{^http://((?:www|nice|libopenraw|liboil|telepathy|xorg)\.)?freedesktop\.org/(?:wiki/)?}
+ if homepage =~ /Software/
+ problem "#{homepage} should be styled `https://wiki.freedesktop.org/www/Software/project_name`"
+ else
+ problem "#{homepage} should be styled `https://wiki.freedesktop.org/project_name`"
+ end
+
+ # Google Code homepages should end in a slash
+ when %r{^https?://code\.google\.com/p/[^/]+[^/]$}
+ problem "#{homepage} should end with a slash"
+
+ # People will run into mixed content sometimes, but we should enforce and then add
+ # exemptions as they are discovered. Treat mixed content on homepages as a bug.
+ # Justify each exemptions with a code comment so we can keep track here.
+
+ when %r{^http://[^/]*\.github\.io/},
+ %r{^http://[^/]*\.sourceforge\.io/}
+ problem "Please use https:// for #{homepage}"
+
+ when %r{^http://([^/]*)\.(sf|sourceforge)\.net(/|$)}
+ problem "#{homepage} should be `https://#{$1}.sourceforge.io/`"
+
+ # There's an auto-redirect here, but this mistake is incredibly common too.
+ # Only applies to the homepage and subdomains for now, not the FTP URLs.
+ when %r{^http://((?:build|cloud|developer|download|extensions|git|glade|help|library|live|nagios|news|people|projects|rt|static|wiki|www)\.)?gnome\.org}
+ problem "Please use https:// for #{homepage}"
+
+ # Compact the above into this list as we're able to remove detailed notations, etc over time.
+ when %r{^http://[^/]*\.apache\.org},
+ %r{^http://packages\.debian\.org},
+ %r{^http://wiki\.freedesktop\.org/},
+ %r{^http://((?:www)\.)?gnupg\.org/},
+ %r{^http://ietf\.org},
+ %r{^http://[^/.]+\.ietf\.org},
+ %r{^http://[^/.]+\.tools\.ietf\.org},
+ %r{^http://www\.gnu\.org/},
+ %r{^http://code\.google\.com/},
+ %r{^http://bitbucket\.org/},
+ %r{^http://(?:[^/]*\.)?archive\.org}
+ problem "Please use https:// for #{homepage}"
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/Library/Homebrew/sandbox.rb b/Library/Homebrew/sandbox.rb
index 9597dafa8..b16bbde1a 100644
--- a/Library/Homebrew/sandbox.rb
+++ b/Library/Homebrew/sandbox.rb
@@ -5,10 +5,6 @@ class Sandbox
SANDBOX_EXEC = "/usr/bin/sandbox-exec".freeze
SANDBOXED_TAPS = %w[
homebrew/core
- homebrew/dupes
- homebrew/fuse
- homebrew/devel-only
- homebrew/tex
].freeze
def self.available?
diff --git a/Library/Homebrew/shims/scm/git b/Library/Homebrew/shims/scm/git
index 82bb47c25..bfb779c25 100755
--- a/Library/Homebrew/shims/scm/git
+++ b/Library/Homebrew/shims/scm/git
@@ -86,7 +86,6 @@ fi
case "$(lowercase "$SCM_FILE")" in
git)
[[ -n "$HOMEBREW_GIT" ]] && safe_exec "$(which "$HOMEBREW_GIT")" "$@"
- [[ -n "$GIT" ]] && safe_exec "$(which "$GIT")" "$@"
;;
svn)
[[ -n "$HOMEBREW_SVN" ]] && safe_exec "$(which "$HOMEBREW_SVN")" "$@"
diff --git a/Library/Homebrew/software_spec.rb b/Library/Homebrew/software_spec.rb
index fb07f6c55..be851ca16 100644
--- a/Library/Homebrew/software_spec.rb
+++ b/Library/Homebrew/software_spec.rb
@@ -8,6 +8,7 @@ require "dependency_collector"
require "utils/bottles"
require "patch"
require "compilers"
+require "os/mac/version"
class SoftwareSpec
extend Forwardable
@@ -117,8 +118,7 @@ class SoftwareSpec
def option(name, description = "")
opt = PREDEFINED_OPTIONS.fetch(name) do
if name.is_a?(Symbol)
- opoo "Passing arbitrary symbols to `option` is deprecated: #{name.inspect}"
- puts "Symbols are reserved for future use, please pass a string instead"
+ odeprecated "passing arbitrary symbols (i.e. #{name.inspect}) to `option`"
name = name.to_s
end
unless name.is_a?(String)
@@ -172,7 +172,6 @@ class SoftwareSpec
end
def fails_with(compiler, &block)
- # TODO: deprecate this in future.
# odeprecated "fails_with :llvm" if compiler == :llvm
compiler_failures << CompilerFailure.create(compiler, &block)
end
@@ -340,8 +339,8 @@ class BottleSpecification
tags = collector.keys.sort_by do |tag|
# Sort non-MacOS tags below MacOS tags.
begin
- MacOS::Version.from_symbol tag
- rescue
+ OS::Mac::Version.from_symbol tag
+ rescue ArgumentError
"0.#{tag}"
end
end
diff --git a/Library/Homebrew/tap.rb b/Library/Homebrew/tap.rb
index 99138330b..66aa10158 100644
--- a/Library/Homebrew/tap.rb
+++ b/Library/Homebrew/tap.rb
@@ -201,6 +201,10 @@ class Tap
quiet = options.fetch(:quiet, false)
requested_remote = options[:clone_target] || default_remote
+ if official? && DEPRECATED_OFFICIAL_TAPS.include?(repo)
+ opoo "#{name} was deprecated. This tap is now empty as all its formulae were migrated."
+ end
+
if installed?
raise TapAlreadyTappedError, name unless full_clone
raise TapAlreadyUnshallowError, name unless shallow?
@@ -522,13 +526,11 @@ end
# A specialized {Tap} class for the core formulae
class CoreTap < Tap
- if OS.mac?
- def default_remote
- "https://github.com/Homebrew/homebrew-core"
- end
- else
- def default_remote
- "https://github.com/Linuxbrew/homebrew-core"
+ def default_remote
+ if OS.mac? || ENV["HOMEBREW_FORCE_HOMEBREW_ORG"]
+ "https://github.com/Homebrew/homebrew-core".freeze
+ else
+ "https://github.com/Linuxbrew/homebrew-core".freeze
end
end
diff --git a/Library/Homebrew/test/.bundle/config b/Library/Homebrew/test/.bundle/config
index e451829e9..20549341c 100644
--- a/Library/Homebrew/test/.bundle/config
+++ b/Library/Homebrew/test/.bundle/config
@@ -1,3 +1,4 @@
---
BUNDLE_PATH: "../vendor/bundle"
BUNDLE_DISABLE_SHARED_GEMS: "true"
+BUNDLE_BIN: "../bin"
diff --git a/Library/Homebrew/test/Gemfile.lock b/Library/Homebrew/test/Gemfile.lock
index 4d4eefd7d..1f6adae93 100644
--- a/Library/Homebrew/test/Gemfile.lock
+++ b/Library/Homebrew/test/Gemfile.lock
@@ -2,51 +2,53 @@ GEM
remote: https://rubygems.org/
specs:
ast (2.3.0)
- codecov (0.1.9)
+ codecov (0.1.10)
json
simplecov
url
diff-lcs (1.3)
docile (1.1.5)
- json (2.0.3)
- parallel (1.10.0)
- parallel_tests (2.13.0)
+ json (2.1.0)
+ parallel (1.11.2)
+ parallel_tests (2.14.1)
parallel
parser (2.4.0.0)
ast (~> 2.2)
powerpack (0.1.1)
- rainbow (2.2.1)
- rspec (3.5.0)
- rspec-core (~> 3.5.0)
- rspec-expectations (~> 3.5.0)
- rspec-mocks (~> 3.5.0)
- rspec-core (3.5.4)
- rspec-support (~> 3.5.0)
- rspec-expectations (3.5.0)
+ rainbow (2.2.2)
+ rake
+ rake (12.0.0)
+ rspec (3.6.0)
+ rspec-core (~> 3.6.0)
+ rspec-expectations (~> 3.6.0)
+ rspec-mocks (~> 3.6.0)
+ rspec-core (3.6.0)
+ rspec-support (~> 3.6.0)
+ rspec-expectations (3.6.0)
diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.5.0)
+ rspec-support (~> 3.6.0)
rspec-its (1.2.0)
rspec-core (>= 3.0.0)
rspec-expectations (>= 3.0.0)
- rspec-mocks (3.5.0)
+ rspec-mocks (3.6.0)
diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.5.0)
- rspec-support (3.5.0)
+ rspec-support (~> 3.6.0)
+ rspec-support (3.6.0)
rspec-wait (0.0.9)
rspec (>= 3, < 4)
- rubocop (0.47.1)
+ rubocop (0.48.1)
parser (>= 2.3.3.1, < 3.0)
powerpack (~> 0.1)
rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.7)
unicode-display_width (~> 1.0, >= 1.0.1)
ruby-progressbar (1.8.1)
- simplecov (0.13.0)
+ simplecov (0.14.1)
docile (~> 1.1.0)
json (>= 1.8, < 3)
simplecov-html (~> 0.10.0)
simplecov-html (0.10.0)
- unicode-display_width (1.1.3)
+ unicode-display_width (1.2.1)
url (0.3.2)
PLATFORMS
@@ -62,4 +64,4 @@ DEPENDENCIES
simplecov
BUNDLED WITH
- 1.14.5
+ 1.14.6
diff --git a/Library/Homebrew/test/PATH_spec.rb b/Library/Homebrew/test/PATH_spec.rb
new file mode 100644
index 000000000..68233c23c
--- /dev/null
+++ b/Library/Homebrew/test/PATH_spec.rb
@@ -0,0 +1,115 @@
+require "PATH"
+
+describe PATH do
+ describe "#initialize" do
+ it "can take multiple arguments" do
+ expect(described_class.new("/path1", "/path2")).to eq("/path1:/path2")
+ end
+
+ it "can parse a mix of arrays and arguments" do
+ expect(described_class.new(["/path1", "/path2"], "/path3")).to eq("/path1:/path2:/path3")
+ end
+
+ it "splits an existing PATH" do
+ expect(described_class.new("/path1:/path2")).to eq(["/path1", "/path2"])
+ end
+
+ it "removes duplicates" do
+ expect(described_class.new("/path1", "/path1")).to eq("/path1")
+ end
+ end
+
+ describe "#to_ary" do
+ it "returns a PATH array" do
+ expect(described_class.new("/path1", "/path2").to_ary).to eq(["/path1", "/path2"])
+ end
+ end
+
+ describe "#to_str" do
+ it "returns a PATH string" do
+ expect(described_class.new("/path1", "/path2").to_str).to eq("/path1:/path2")
+ end
+ end
+
+ describe "#prepend" do
+ it "prepends a path to a PATH" do
+ expect(described_class.new("/path1").prepend("/path2").to_str).to eq("/path2:/path1")
+ end
+
+ it "removes duplicates" do
+ expect(described_class.new("/path1").prepend("/path1").to_str).to eq("/path1")
+ end
+ end
+
+ describe "#append" do
+ it "prepends a path to a PATH" do
+ expect(described_class.new("/path1").append("/path2").to_str).to eq("/path1:/path2")
+ end
+
+ it "removes duplicates" do
+ expect(described_class.new("/path1").append("/path1").to_str).to eq("/path1")
+ end
+ end
+
+ describe "#insert" do
+ it "inserts a path at a given index" do
+ expect(described_class.new("/path1").insert(0, "/path2").to_str).to eq("/path2:/path1")
+ end
+
+ it "can insert multiple paths" do
+ expect(described_class.new("/path1").insert(0, "/path2", "/path3")).to eq("/path2:/path3:/path1")
+ end
+ end
+
+ describe "#include?" do
+ it "returns true if a path is included" do
+ path = described_class.new("/path1", "/path2")
+ expect(path).to include("/path1")
+ expect(path).to include("/path2")
+ end
+
+ it "returns false if a path is not included" do
+ expect(described_class.new("/path1")).not_to include("/path2")
+ end
+
+ it "returns false if the given string contains a separator" do
+ expect(described_class.new("/path1", "/path2")).not_to include("/path1:")
+ end
+ end
+
+ describe "#each" do
+ it "loops through each path" do
+ enum = described_class.new("/path1", "/path2").each
+
+ expect(enum.next).to eq("/path1")
+ expect(enum.next).to eq("/path2")
+ end
+ end
+
+ describe "#select" do
+ it "returns an object of the same class instead of an Array" do
+ expect(described_class.new.select { true }).to be_a(described_class)
+ end
+ end
+
+ describe "#reject" do
+ it "returns an object of the same class instead of an Array" do
+ expect(described_class.new.reject { true }).to be_a(described_class)
+ end
+ end
+
+ describe "#existing" do
+ it "returns a new PATH without non-existent paths" do
+ allow(File).to receive(:directory?).with("/path1").and_return(true)
+ allow(File).to receive(:directory?).with("/path2").and_return(false)
+
+ path = described_class.new("/path1", "/path2")
+ expect(path.existing.to_ary).to eq(["/path1"])
+ expect(path.to_ary).to eq(["/path1", "/path2"])
+ end
+
+ it "returns nil instead of an empty #{described_class}" do
+ expect(described_class.new.existing).to be nil
+ end
+ end
+end
diff --git a/Library/Homebrew/test/cask/artifact/binary_spec.rb b/Library/Homebrew/test/cask/artifact/binary_spec.rb
index 69bde3438..ee62e6439 100644
--- a/Library/Homebrew/test/cask/artifact/binary_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/binary_spec.rb
@@ -6,9 +6,7 @@ describe Hbc::Artifact::Binary, :cask do
end
end
}
- let(:expected_path) {
- Hbc.binarydir.join("binary")
- }
+ let(:expected_path) { Hbc.binarydir.join("binary") }
before(:each) do
Hbc.binarydir.mkpath
@@ -26,15 +24,28 @@ describe Hbc::Artifact::Binary, :cask do
expect(expected_path.readlink).to exist
end
- it "makes the binary executable" do
- expect(FileUtils).to receive(:chmod).with("+x", cask.staged_path.join("binary"))
+ 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|
+ shutup do
+ InstallHelper.install_without_artifacts(cask)
+ end
+ end
+ }
- shutup do
- Hbc::Artifact::Binary.new(cask).install_phase
- end
+ let(:expected_path) { Hbc.binarydir.join("naked_non_executable") }
- expect(expected_path).to be_a_symlink
- expect(expected_path.readlink).to be_executable
+ it "makes the binary executable" do
+ expect(FileUtils).to receive(:chmod)
+ .with("+x", cask.staged_path.join("naked_non_executable")).and_call_original
+
+ shutup do
+ Hbc::Artifact::Binary.new(cask).install_phase
+ end
+
+ expect(expected_path).to be_a_symlink
+ expect(expected_path.readlink).to be_executable
+ end
end
it "avoids clobbering an existing binary by linking over it" do
diff --git a/Library/Homebrew/test/cask/cask_spec.rb b/Library/Homebrew/test/cask/cask_spec.rb
index 2ab966f82..3736f3c01 100644
--- a/Library/Homebrew/test/cask/cask_spec.rb
+++ b/Library/Homebrew/test/cask/cask_spec.rb
@@ -85,8 +85,8 @@ describe Hbc::Cask, :cask do
it "proposes a versioned metadata directory name for each instance" do
cask_token = "local-caffeine"
c = Hbc::CaskLoader.load(cask_token)
- metadata_path = Hbc.caskroom.join(cask_token, ".metadata", c.version)
- expect(c.metadata_versioned_container_path.to_s).to eq(metadata_path.to_s)
+ metadata_timestamped_path = Hbc.caskroom.join(cask_token, ".metadata", c.version)
+ expect(c.metadata_versioned_path.to_s).to eq(metadata_timestamped_path.to_s)
end
end
diff --git a/Library/Homebrew/test/cask/cli/install_spec.rb b/Library/Homebrew/test/cask/cli/install_spec.rb
index 5a40017e8..219b9522e 100644
--- a/Library/Homebrew/test/cask/cli/install_spec.rb
+++ b/Library/Homebrew/test/cask/cli/install_spec.rb
@@ -1,4 +1,18 @@
describe Hbc::CLI::Install, :cask do
+ it "displays the installation progress" do
+ output = Regexp.new <<-EOS.undent
+ ==> Downloading file:.*caffeine.zip
+ ==> Verifying checksum for Cask local-caffeine
+ ==> Installing Cask local-caffeine
+ ==> Moving App 'Caffeine.app' to '.*Caffeine.app'.
+ .*local-caffeine was successfully installed!
+ EOS
+
+ expect {
+ Hbc::CLI::Install.run("local-caffeine")
+ }.to output(output).to_stdout
+ end
+
it "allows staging and activation of multiple Casks at once" do
shutup do
Hbc::CLI::Install.run("local-transmission", "local-caffeine")
diff --git a/Library/Homebrew/test/cask/cli/reinstall_spec.rb b/Library/Homebrew/test/cask/cli/reinstall_spec.rb
index e573a3470..8885fa199 100644
--- a/Library/Homebrew/test/cask/cli/reinstall_spec.rb
+++ b/Library/Homebrew/test/cask/cli/reinstall_spec.rb
@@ -1,4 +1,27 @@
describe Hbc::CLI::Reinstall, :cask do
+ it "displays the reinstallation progress" do
+ caffeine = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb")
+
+ shutup do
+ Hbc::Installer.new(caffeine).install
+ end
+
+ output = Regexp.new <<-EOS.undent
+ ==> Downloading file:.*caffeine.zip
+ Already downloaded: .*local-caffeine--1.2.3.zip
+ ==> Verifying checksum for Cask local-caffeine
+ ==> Uninstalling Cask local-caffeine
+ ==> Removing App '.*Caffeine.app'.
+ ==> Installing Cask local-caffeine
+ ==> Moving App 'Caffeine.app' to '.*Caffeine.app'.
+ .*local-caffeine was successfully installed!
+ EOS
+
+ expect {
+ Hbc::CLI::Reinstall.run("local-caffeine")
+ }.to output(output).to_stdout
+ end
+
it "allows reinstalling a Cask" do
shutup do
Hbc::CLI::Install.run("local-transmission")
diff --git a/Library/Homebrew/test/cask/cli/search_spec.rb b/Library/Homebrew/test/cask/cli/search_spec.rb
index 9843a6de6..00fcf7382 100644
--- a/Library/Homebrew/test/cask/cli/search_spec.rb
+++ b/Library/Homebrew/test/cask/cli/search_spec.rb
@@ -3,7 +3,7 @@ describe Hbc::CLI::Search, :cask do
expect {
Hbc::CLI::Search.run("local")
}.to output(<<-EOS.undent).to_stdout
- ==> Partial matches
+ ==> Partial Matches
local-caffeine
local-transmission
EOS
@@ -42,13 +42,13 @@ 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
+ }.to output("==> Regexp Matches\nlocal-caffeine\n").to_stdout
end
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
+ }.to output(/^==> Exact Match\ntest-opera\n==> Partial Matches\ntest-opera-mail/).to_stdout
end
it "does not search the Tap name" do
diff --git a/Library/Homebrew/test/cask/cli/style_spec.rb b/Library/Homebrew/test/cask/cli/style_spec.rb
index ca17c5e46..d41636beb 100644
--- a/Library/Homebrew/test/cask/cli/style_spec.rb
+++ b/Library/Homebrew/test/cask/cli/style_spec.rb
@@ -81,7 +81,7 @@ describe Hbc::CLI::Style, :cask do
end
context "version" do
- it "matches `HOMEBREW_RUBOCOP_VERSION`" do
+ it "matches `HOMEBREW_RUBOCOP_VERSION`", :needs_network do
stdout, status = Open3.capture2("gem", "dependency", "rubocop-cask", "--version", HOMEBREW_RUBOCOP_CASK_VERSION, "--pipe", "--remote")
expect(status).to be_a_success
diff --git a/Library/Homebrew/test/cask/cli/uninstall_spec.rb b/Library/Homebrew/test/cask/cli/uninstall_spec.rb
index fb196ee72..4089c47b4 100644
--- a/Library/Homebrew/test/cask/cli/uninstall_spec.rb
+++ b/Library/Homebrew/test/cask/cli/uninstall_spec.rb
@@ -1,4 +1,21 @@
describe Hbc::CLI::Uninstall, :cask do
+ it "displays the uninstallation progress" do
+ caffeine = Hbc::CaskLoader.load_from_file(TEST_FIXTURE_DIR/"cask/Casks/local-caffeine.rb")
+
+ shutup do
+ Hbc::Installer.new(caffeine).install
+ end
+
+ output = Regexp.new <<-EOS.undent
+ ==> Uninstalling Cask local-caffeine
+ ==> Removing App '.*Caffeine.app'.
+ EOS
+
+ expect {
+ Hbc::CLI::Uninstall.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")
@@ -13,7 +30,9 @@ describe Hbc::CLI::Uninstall, :cask do
it "tries anyway on a non-present Cask when --force is given" do
expect {
- Hbc::CLI::Uninstall.run("local-caffeine", "--force")
+ shutup do
+ Hbc::CLI::Uninstall.run("local-caffeine", "--force")
+ end
}.not_to raise_error
end
diff --git a/Library/Homebrew/test/cask/installer_spec.rb b/Library/Homebrew/test/cask/installer_spec.rb
index 7dd5b2bda..59d61bbdd 100644
--- a/Library/Homebrew/test/cask/installer_spec.rb
+++ b/Library/Homebrew/test/cask/installer_spec.rb
@@ -336,9 +336,8 @@ describe Hbc::Installer, :cask do
Hbc::Installer.new(caffeine).install
end
- m_path = caffeine.metadata_path(:now, true)
- expect(caffeine.metadata_path(:now, false)).to eq(m_path)
- expect(caffeine.metadata_path(:latest)).to eq(m_path)
+ m_path = caffeine.metadata_timestamped_path(timestamp: :now, create: true)
+ expect(caffeine.metadata_timestamped_path(timestamp: :latest)).to eq(m_path)
end
it "generates and finds a metadata subdirectory for an installed Cask" do
@@ -349,9 +348,8 @@ describe Hbc::Installer, :cask do
end
subdir_name = "Casks"
- m_subdir = caffeine.metadata_subdir(subdir_name, :now, true)
- expect(caffeine.metadata_subdir(subdir_name, :now, false)).to eq(m_subdir)
- expect(caffeine.metadata_subdir(subdir_name, :latest)).to eq(m_subdir)
+ m_subdir = caffeine.metadata_subdir(subdir_name, timestamp: :now, create: true)
+ expect(caffeine.metadata_subdir(subdir_name, timestamp: :latest)).to eq(m_subdir)
end
end
diff --git a/Library/Homebrew/test/cask/pkg_spec.rb b/Library/Homebrew/test/cask/pkg_spec.rb
index 9930cd00f..e507ceda0 100644
--- a/Library/Homebrew/test/cask/pkg_spec.rb
+++ b/Library/Homebrew/test/cask/pkg_spec.rb
@@ -36,7 +36,12 @@ describe Hbc::Pkg, :cask do
it "forgets the pkg" do
allow(fake_system_command).to receive(:run!).with(
"/usr/sbin/pkgutil",
- args: ["--export-plist", "my.fake.pkg"],
+ args: ["--pkg-info-plist", "my.fake.pkg"],
+ ).and_return(empty_response)
+
+ expect(fake_system_command).to receive(:run!).with(
+ "/usr/sbin/pkgutil",
+ args: ["--files", "my.fake.pkg"],
).and_return(empty_response)
expect(fake_system_command).to receive(:run!).with(
@@ -139,7 +144,7 @@ describe Hbc::Pkg, :cask do
expect(fake_system_command).to receive(:run!).with(
"/usr/sbin/pkgutil",
- args: ["--export-plist", pkg_id],
+ args: ["--pkg-info-plist", pkg_id],
).and_return(
Hbc::SystemCommand::Result.new(nil, pkg_info_plist, nil, 0),
)
diff --git a/Library/Homebrew/test/cmd/bundle_spec.rb b/Library/Homebrew/test/cmd/bundle_spec.rb
index 13f13485c..286ddba97 100644
--- a/Library/Homebrew/test/cmd/bundle_spec.rb
+++ b/Library/Homebrew/test/cmd/bundle_spec.rb
@@ -1,6 +1,6 @@
describe "brew bundle", :integration_test, :needs_test_cmd_taps do
describe "check" do
- it "checks if a Brewfile's dependencies are satisfied" do
+ it "checks if a Brewfile's dependencies are satisfied", :needs_network do
setup_remote_tap "homebrew/bundle"
HOMEBREW_REPOSITORY.cd do
diff --git a/Library/Homebrew/test/cmd/install_spec.rb b/Library/Homebrew/test/cmd/install_spec.rb
index c1240a30e..b819c17be 100644
--- a/Library/Homebrew/test/cmd/install_spec.rb
+++ b/Library/Homebrew/test/cmd/install_spec.rb
@@ -77,7 +77,7 @@ describe "brew install", :integration_test do
EOS
expect { brew "install", "testball1" }
- .to output(/first `brew unlink testball1`/).to_stderr
+ .to output(/`brew upgrade testball1`/).to_stderr
.and not_to_output.to_stdout
.and be_a_failure
@@ -217,10 +217,9 @@ describe "brew install", :integration_test do
depends_on NonFatalRequirement
EOS
- # FIXME: This should output to STDERR.
expect { brew "install", "testball1" }
- .to output(/NonFatalRequirement unsatisfied!/).to_stdout
- .and not_to_output.to_stderr
+ .to output(/NonFatalRequirement unsatisfied!/).to_stderr
+ .and output(/built in/).to_stdout
.and be_a_success
end
@@ -234,10 +233,9 @@ describe "brew install", :integration_test do
depends_on FatalRequirement
EOS
- # FIXME: This should output to STDERR.
expect { brew "install", "testball1" }
- .to output(/FatalRequirement unsatisfied!/).to_stdout
- .and output(/An unsatisfied requirement failed this build./).to_stderr
+ .to output(/FatalRequirement unsatisfied!/).to_stderr
+ .and not_to_output.to_stdout
.and be_a_failure
end
end
diff --git a/Library/Homebrew/test/cmd/search_remote_tap_spec.rb b/Library/Homebrew/test/cmd/search_remote_tap_spec.rb
index 99c2cc20b..b0beb122c 100644
--- a/Library/Homebrew/test/cmd/search_remote_tap_spec.rb
+++ b/Library/Homebrew/test/cmd/search_remote_tap_spec.rb
@@ -1,19 +1,21 @@
require "cmd/search"
describe Homebrew do
- specify "#search_tap" do
+ specify "#search_taps" do
json_response = {
- "tree" => [
+ "items" => [
{
- "path" => "Formula/not-a-formula.rb",
- "type" => "blob",
+ "path" => "Formula/some-formula.rb",
+ "repository" => {
+ "full_name" => "Homebrew/homebrew-foo",
+ },
},
],
}
allow(GitHub).to receive(:open).and_yield(json_response)
- expect(described_class.search_tap("homebrew", "not-a-tap", "not-a-formula"))
- .to eq(["homebrew/not-a-tap/not-a-formula"])
+ expect(described_class.search_taps("some-formula"))
+ .to match(["homebrew/foo/some-formula"])
end
end
diff --git a/Library/Homebrew/test/compiler_selector_spec.rb b/Library/Homebrew/test/compiler_selector_spec.rb
index 0f6f6b5f2..18efbfd42 100644
--- a/Library/Homebrew/test/compiler_selector_spec.rb
+++ b/Library/Homebrew/test/compiler_selector_spec.rb
@@ -3,7 +3,7 @@ require "software_spec"
describe CompilerSelector do
subject { described_class.new(software_spec, versions, compilers) }
- let(:compilers) { [:clang, :gcc, :llvm, :gnu] }
+ let(:compilers) { [:clang, :gcc, :gnu] }
let(:software_spec) { SoftwareSpec.new }
let(:cc) { :clang }
let(:versions) do
@@ -28,7 +28,6 @@ describe CompilerSelector do
describe "#compiler" do
it "raises an error if no matching compiler can be found" do
software_spec.fails_with(:clang)
- software_spec.fails_with(:llvm)
software_spec.fails_with(:gcc)
software_spec.fails_with(gcc: "4.8")
software_spec.fails_with(gcc: "4.7")
@@ -45,11 +44,6 @@ describe CompilerSelector do
expect(subject.compiler).to eq(:gcc)
end
- it "returns clang if it fails with llvm" do
- software_spec.fails_with(:llvm)
- expect(subject.compiler).to eq(:clang)
- end
-
it "returns clang if it fails with gcc" do
software_spec.fails_with(:gcc)
expect(subject.compiler).to eq(:clang)
@@ -68,13 +62,11 @@ describe CompilerSelector do
it "returns gcc if it fails with clang and llvm" do
software_spec.fails_with(:clang)
- software_spec.fails_with(:llvm)
expect(subject.compiler).to eq(:gcc)
end
it "returns clang if it fails with gcc and llvm" do
software_spec.fails_with(:gcc)
- software_spec.fails_with(:llvm)
expect(subject.compiler).to eq(:clang)
end
@@ -87,7 +79,6 @@ describe CompilerSelector do
example "returns a lower version of gcc if it fails with the highest version" do
software_spec.fails_with(:clang)
software_spec.fails_with(:gcc)
- software_spec.fails_with(:llvm)
software_spec.fails_with(gcc: "4.8")
expect(subject.compiler).to eq("gcc-4.7")
end
@@ -102,7 +93,6 @@ describe CompilerSelector do
allow(versions).to receive(:gcc_build_version).and_return(Version::NULL)
software_spec.fails_with(:clang)
- software_spec.fails_with(:llvm)
software_spec.fails_with(gcc: "4.8")
software_spec.fails_with(gcc: "4.7")
diff --git a/Library/Homebrew/test/dev-cmd/audit_spec.rb b/Library/Homebrew/test/dev-cmd/audit_spec.rb
index a6bb22837..b07ffaadc 100644
--- a/Library/Homebrew/test/dev-cmd/audit_spec.rb
+++ b/Library/Homebrew/test/dev-cmd/audit_spec.rb
@@ -5,6 +5,13 @@ RSpec::Matchers.alias_matcher :have_data, :be_data
RSpec::Matchers.alias_matcher :have_end, :be_end
RSpec::Matchers.alias_matcher :have_trailing_newline, :be_trailing_newline
+module Count
+ def self.increment
+ @count ||= 0
+ @count += 1
+ end
+end
+
describe FormulaText do
let(:dir) { mktmpdir }
@@ -141,100 +148,6 @@ describe FormulaAuditor do
fa.audit_file
expect(fa.problems).to eq([])
end
-
- specify "strict: ordering issue" do
- fa = formula_auditor "foo", <<-EOS.undent, strict: true
- class Foo < Formula
- url "http://example.com/foo-1.0.tgz"
- homepage "http://example.com"
- end
- EOS
-
- fa.audit_file
- expect(fa.problems)
- .to eq(["`homepage` (line 3) should be put before `url` (line 2)"])
- end
-
- specify "strict: resource placement" do
- fa = formula_auditor "foo", <<-EOS.undent, strict: true
- class Foo < Formula
- url "https://example.com/foo-1.0.tgz"
-
- resource "foo2" do
- url "https://example.com/foo-2.0.tgz"
- end
-
- depends_on "openssl"
- end
- EOS
-
- fa.audit_file
- expect(fa.problems)
- .to eq(["`depends_on` (line 8) should be put before `resource` (line 4)"])
- end
-
- specify "strict: plist placement" do
- fa = formula_auditor "foo", <<-EOS.undent, strict: true
- class Foo < Formula
- url "https://example.com/foo-1.0.tgz"
-
- test do
- expect(shell_output("./dogs")).to match("Dogs are terrific")
- end
-
- def plist
- end
- end
- EOS
-
- fa.audit_file
- expect(fa.problems)
- .to eq(["`plist block` (line 8) should be put before `test block` (line 4)"])
- end
-
- specify "strict: url outside of stable block" do
- fa = formula_auditor "foo", <<-EOS.undent, strict: true
- class Foo < Formula
- url "http://example.com/foo-1.0.tgz"
- stable do
- # stuff
- end
- end
- EOS
-
- fa.audit_file
- expect(fa.problems).to eq(["`url` should be put inside `stable block`"])
- end
-
- specify "strict: head and head do" do
- fa = formula_auditor "foo", <<-EOS.undent, strict: true
- class Foo < Formula
- head "http://example.com/foo.git"
- head do
- # stuff
- end
- end
- EOS
-
- fa.audit_file
- expect(fa.problems).to eq(["Should not have both `head` and `head do`"])
- end
-
- specify "strict: bottle and bottle do" do
- fa = formula_auditor "foo", <<-EOS.undent, strict: true
- class Foo < Formula
- url "http://example.com/foo-1.0.tgz"
- bottle do
- # bottles go here
- end
- bottle :unneeded
- end
- EOS
-
- fa.audit_file
- expect(fa.problems)
- .to eq(["Should not have `bottle :unneeded/:disable` and `bottle do`"])
- end
end
describe "#audit_class" do
@@ -303,7 +216,7 @@ describe FormulaAuditor do
end
end
- describe "#audit_line" do
+ describe "#line_problems" do
specify "pkgshare" do
fa = formula_auditor "foo", <<-EOS.undent, strict: true
class Foo < Formula
@@ -311,25 +224,25 @@ describe FormulaAuditor do
end
EOS
- fa.audit_line 'ohai "#{share}/foo"', 3
+ fa.line_problems 'ohai "#{share}/foo"', 3
expect(fa.problems.shift).to eq("Use \#{pkgshare} instead of \#{share}/foo")
- fa.audit_line 'ohai "#{share}/foo/bar"', 3
+ fa.line_problems 'ohai "#{share}/foo/bar"', 3
expect(fa.problems.shift).to eq("Use \#{pkgshare} instead of \#{share}/foo")
- fa.audit_line 'ohai share/"foo"', 3
+ fa.line_problems 'ohai share/"foo"', 3
expect(fa.problems.shift).to eq('Use pkgshare instead of (share/"foo")')
- fa.audit_line 'ohai share/"foo/bar"', 3
+ fa.line_problems 'ohai share/"foo/bar"', 3
expect(fa.problems.shift).to eq('Use pkgshare instead of (share/"foo")')
- fa.audit_line 'ohai "#{share}/foo-bar"', 3
+ fa.line_problems 'ohai "#{share}/foo-bar"', 3
expect(fa.problems).to eq([])
- fa.audit_line 'ohai share/"foo-bar"', 3
+ fa.line_problems 'ohai share/"foo-bar"', 3
expect(fa.problems).to eq([])
- fa.audit_line 'ohai share/"bar"', 3
+ fa.line_problems 'ohai share/"bar"', 3
expect(fa.problems).to eq([])
end
@@ -344,11 +257,11 @@ describe FormulaAuditor do
end
EOS
- fa.audit_line 'ohai "#{share}/foolibc++"', 3
+ fa.line_problems 'ohai "#{share}/foolibc++"', 3
expect(fa.problems.shift)
.to eq("Use \#{pkgshare} instead of \#{share}/foolibc++")
- fa.audit_line 'ohai share/"foolibc++"', 3
+ fa.line_problems 'ohai share/"foolibc++"', 3
expect(fa.problems.shift)
.to eq('Use pkgshare instead of (share/"foolibc++")')
end
@@ -360,7 +273,7 @@ describe FormulaAuditor do
end
EOS
- fa.audit_line "class Foo<Formula", 1
+ fa.line_problems "class Foo<Formula", 1
expect(fa.problems.shift)
.to eq("Use a space in class inheritance: class Foo < Formula")
end
@@ -368,10 +281,10 @@ describe FormulaAuditor do
specify "default template" do
fa = formula_auditor "foo", "class Foo < Formula; url '/foo-1.0.tgz'; end"
- fa.audit_line '# system "cmake", ".", *std_cmake_args', 3
+ fa.line_problems '# system "cmake", ".", *std_cmake_args', 3
expect(fa.problems.shift).to eq("Commented cmake call found")
- fa.audit_line "# PLEASE REMOVE", 3
+ fa.line_problems "# PLEASE REMOVE", 3
expect(fa.problems.shift).to eq("Please remove default template comments")
end
end
@@ -409,77 +322,66 @@ describe FormulaAuditor do
.to eq(["Don't recommend setuid in the caveats, suggest sudo instead."])
end
- describe "#audit_homepage" do
- specify "homepage URLs" do
- fa = formula_auditor "foo", <<-EOS.undent, online: true
+ describe "#audit_keg_only_style" do
+ specify "keg_only_needs_downcasing" do
+ fa = formula_auditor "foo", <<-EOS.undent, strict: true
class Foo < Formula
- homepage "ftp://example.com/foo"
url "http://example.com/foo-1.0.tgz"
+
+ keg_only "Because why not"
end
EOS
- fa.audit_homepage
+ fa.audit_keg_only_style
expect(fa.problems)
- .to eq(["The homepage should start with http or https (URL is #{fa.formula.homepage})."])
-
- formula_homepages = {
- "bar" => "http://www.freedesktop.org/wiki/bar",
- "baz" => "http://www.freedesktop.org/wiki/Software/baz",
- "qux" => "https://code.google.com/p/qux",
- "quux" => "http://github.com/quux",
- "corge" => "http://savannah.nongnu.org/corge",
- "grault" => "http://grault.github.io/",
- "garply" => "http://www.gnome.org/garply",
- "sf1" => "http://foo.sourceforge.net/",
- "sf2" => "http://foo.sourceforge.net",
- "sf3" => "http://foo.sf.net/",
- "sf4" => "http://foo.sourceforge.io/",
- "waldo" => "http://www.gnu.org/waldo",
- }
-
- formula_homepages.each do |name, homepage|
- fa = formula_auditor name, <<-EOS.undent
- class #{Formulary.class_s(name)} < Formula
- homepage "#{homepage}"
- url "http://example.com/#{name}-1.0.tgz"
- end
- EOS
+ .to eq(["'Because' from the keg_only reason should be 'because'.\n"])
+ end
- fa.audit_homepage
- if homepage =~ %r{http:\/\/www\.freedesktop\.org}
- if homepage =~ /Software/
- expect(fa.problems.first).to match(
- "#{homepage} should be styled " \
- "`https://wiki.freedesktop.org/www/Software/project_name`",
- )
- else
- expect(fa.problems.first).to match(
- "#{homepage} should be styled " \
- "`https://wiki.freedesktop.org/project_name`",
- )
- end
- elsif homepage =~ %r{https:\/\/code\.google\.com}
- expect(fa.problems.first)
- .to match("#{homepage} should end with a slash")
- elsif homepage =~ /foo\.(sf|sourceforge)\.net/
- expect(fa.problems.first)
- .to match("#{homepage} should be `https://foo.sourceforge.io/`")
- else
- expect(fa.problems.first)
- .to match("Please use https:// for #{homepage}")
+ specify "keg_only_redundant_period" do
+ fa = formula_auditor "foo", <<-EOS.undent, strict: true
+ class Foo < Formula
+ url "http://example.com/foo-1.0.tgz"
+
+ keg_only "because this line ends in a period."
end
- end
+ EOS
+
+ fa.audit_keg_only_style
+ expect(fa.problems)
+ .to eq(["keg_only reason should not end with a period."])
+ end
+
+ specify "keg_only_handles_block_correctly" do
+ fa = formula_auditor "foo", <<-EOS.undent, strict: true
+ class Foo < Formula
+ url "http://example.com/foo-1.0.tgz"
+
+ keg_only <<-EOF.undent
+ this line starts with a lowercase word.
+
+ This line does not but that shouldn't be a
+ problem
+ EOF
+ end
+ EOS
+
+ fa.audit_keg_only_style
+ expect(fa.problems)
+ .to eq([])
end
- specify "missing homepage" do
- fa = formula_auditor "foo", <<-EOS.undent, online: true
+ specify "keg_only_handles_whitelist_correctly" do
+ fa = formula_auditor "foo", <<-EOS.undent, strict: true
class Foo < Formula
url "http://example.com/foo-1.0.tgz"
+
+ keg_only "Apple ships foo in the CLT package"
end
EOS
- fa.audit_homepage
- expect(fa.problems.first).to match("Formula should have a homepage.")
+ fa.audit_keg_only_style
+ expect(fa.problems)
+ .to eq([])
end
end
@@ -517,5 +419,203 @@ describe FormulaAuditor do
expect(fa.problems.first)
.to match('xcodebuild should be passed an explicit "SYMROOT"')
end
+
+ specify "disallow go get usage" do
+ fa = formula_auditor "foo", <<-EOS.undent
+ class Foo <Formula
+ url "http://example.com/foo-1.0.tgz"
+
+ def install
+ system "go", "get", "bar"
+ end
+ end
+ EOS
+ fa.audit_text
+ expect(fa.problems.first)
+ .to match("Formulae should not use `go get`. If non-vendored resources are required use `go_resource`s.")
+ end
+ end
+
+ describe "#audit_revision_and_version_scheme" do
+ let(:origin_tap_path) { Tap::TAP_DIRECTORY/"homebrew/homebrew-foo" }
+ let(:formula_subpath) { "Formula/foo#{@foo_version}.rb" }
+ let(:origin_formula_path) { origin_tap_path/formula_subpath }
+ let(:tap_path) { Tap::TAP_DIRECTORY/"homebrew/homebrew-bar" }
+ let(:formula_path) { tap_path/formula_subpath }
+
+ before(:each) do
+ @foo_version = Count.increment
+
+ origin_formula_path.write <<-EOS.undent
+ class Foo#{@foo_version} < Formula
+ url "https://example.com/foo-1.0.tar.gz"
+ revision 2
+ version_scheme 1
+ end
+ EOS
+
+ origin_tap_path.mkpath
+ origin_tap_path.cd do
+ shutup do
+ system "git", "init"
+ system "git", "add", "--all"
+ system "git", "commit", "-m", "init"
+ end
+ end
+
+ tap_path.mkpath
+ tap_path.cd do
+ shutup do
+ system "git", "clone", origin_tap_path, "."
+ end
+ end
+ end
+
+ subject do
+ fa = described_class.new(Formulary.factory(formula_path))
+ fa.audit_revision_and_version_scheme
+ fa.problems.first
+ end
+
+ def formula_gsub(before, after = "")
+ text = formula_path.read
+ text.gsub! before, after
+ formula_path.unlink
+ formula_path.write text
+ end
+
+ def formula_gsub_commit(before, after = "")
+ text = origin_formula_path.read
+ text.gsub!(before, after)
+ origin_formula_path.unlink
+ origin_formula_path.write text
+
+ origin_tap_path.cd do
+ shutup do
+ system "git", "commit", "-am", "commit"
+ end
+ end
+
+ tap_path.cd do
+ shutup do
+ system "git", "fetch"
+ system "git", "reset", "--hard", "origin/master"
+ end
+ end
+ end
+
+ context "revisions" do
+ context "should not be removed when first committed above 0" do
+ it { is_expected.to be_nil }
+ end
+
+ context "should not decrease with the same version" do
+ before { formula_gsub_commit "revision 2", "revision 1" }
+
+ it { is_expected.to match("revision should not decrease (from 2 to 1)") }
+ end
+
+ context "should not be removed with the same version" do
+ before { formula_gsub_commit "revision 2" }
+
+ it { is_expected.to match("revision should not decrease (from 2 to 0)") }
+ end
+
+ context "should not decrease with the same, uncommitted version" do
+ before { formula_gsub "revision 2", "revision 1" }
+
+ it { is_expected.to match("revision should not decrease (from 2 to 1)") }
+ end
+
+ context "should be removed with a newer version" do
+ before { formula_gsub_commit "foo-1.0.tar.gz", "foo-1.1.tar.gz" }
+
+ it { is_expected.to match("'revision 2' should be removed") }
+ end
+
+ context "should not warn on an newer version revision removal" do
+ before do
+ formula_gsub_commit "revision 2", ""
+ formula_gsub_commit "foo-1.0.tar.gz", "foo-1.1.tar.gz"
+ end
+
+ it { is_expected.to be_nil }
+ end
+
+ context "should only increment by 1 with an uncommitted version" do
+ before do
+ formula_gsub "foo-1.0.tar.gz", "foo-1.1.tar.gz"
+ formula_gsub "revision 2", "revision 4"
+ end
+
+ it { is_expected.to match("revisions should only increment by 1") }
+ end
+
+ context "should not warn on past increment by more than 1" do
+ before do
+ formula_gsub_commit "revision 2", "# no revision"
+ formula_gsub_commit "foo-1.0.tar.gz", "foo-1.1.tar.gz"
+ formula_gsub_commit "# no revision", "revision 3"
+ end
+
+ it { is_expected.to be_nil }
+ end
+ end
+
+ context "version_schemes" do
+ context "should not decrease with the same version" do
+ before { formula_gsub_commit "version_scheme 1" }
+
+ it { is_expected.to match("version_scheme should not decrease (from 1 to 0)") }
+ end
+
+ context "should not decrease with a new version" do
+ before do
+ formula_gsub_commit "foo-1.0.tar.gz", "foo-1.1.tar.gz"
+ formula_gsub_commit "version_scheme 1", ""
+ formula_gsub_commit "revision 2", ""
+ end
+
+ it { is_expected.to match("version_scheme should not decrease (from 1 to 0)") }
+ end
+
+ context "should only increment by 1" do
+ before do
+ formula_gsub_commit "version_scheme 1", "# no version_scheme"
+ formula_gsub_commit "foo-1.0.tar.gz", "foo-1.1.tar.gz"
+ formula_gsub_commit "revision 2", ""
+ formula_gsub_commit "# no version_scheme", "version_scheme 3"
+ end
+
+ it { is_expected.to match("version_schemes should only increment by 1") }
+ end
+ end
+
+ context "versions" do
+ context "uncommitted should not decrease" do
+ before { formula_gsub "foo-1.0.tar.gz", "foo-0.9.tar.gz" }
+
+ it { is_expected.to match("stable version should not decrease (from 1.0 to 0.9)") }
+ end
+
+ context "committed can decrease" do
+ before do
+ formula_gsub_commit "revision 2"
+ formula_gsub_commit "foo-1.0.tar.gz", "foo-0.9.tar.gz"
+ end
+
+ it { is_expected.to be_nil }
+ end
+
+ context "can decrease with version_scheme increased" do
+ before do
+ formula_gsub "revision 2"
+ formula_gsub "foo-1.0.tar.gz", "foo-0.9.tar.gz"
+ formula_gsub "version_scheme 1", "version_scheme 2"
+ end
+
+ it { is_expected.to be_nil }
+ end
+ end
end
end
diff --git a/Library/Homebrew/test/dev-cmd/pull_spec.rb b/Library/Homebrew/test/dev-cmd/pull_spec.rb
index 3c0108df2..2ebe144bb 100644
--- a/Library/Homebrew/test/dev-cmd/pull_spec.rb
+++ b/Library/Homebrew/test/dev-cmd/pull_spec.rb
@@ -6,9 +6,7 @@ describe "brew pull", :integration_test do
.and be_a_failure
end
- it "fetches a patch from a GitHub commit or pull request and applies it" do
- skip "Requires network connection." if ENV["HOMEBREW_NO_GITHUB_API"]
-
+ it "fetches a patch from a GitHub commit or pull request and applies it", :needs_network do
CoreTap.instance.path.cd do
shutup do
system "git", "init"
diff --git a/Library/Homebrew/test/diagnostic_spec.rb b/Library/Homebrew/test/diagnostic_spec.rb
index 59560127c..c4373671e 100644
--- a/Library/Homebrew/test/diagnostic_spec.rb
+++ b/Library/Homebrew/test/diagnostic_spec.rb
@@ -7,7 +7,7 @@ describe Homebrew::Diagnostic::Checks do
end
specify "#check_path_for_trailing_slashes" do
- ENV["PATH"] += File::PATH_SEPARATOR + "/foo/bar/"
+ ENV["HOMEBREW_PATH"] += File::PATH_SEPARATOR + "/foo/bar/"
expect(subject.check_path_for_trailing_slashes)
.to match("Some directories in your path end in a slash")
end
@@ -41,6 +41,20 @@ describe Homebrew::Diagnostic::Checks do
end
end
+ specify "#check_access_lock_dir" do
+ begin
+ prev_mode = HOMEBREW_LOCK_DIR.stat.mode
+ mode = HOMEBREW_LOCK_DIR.stat.mode & 0777
+ HOMEBREW_LOCK_DIR.chmod 0555
+ expect(HOMEBREW_LOCK_DIR.stat.mode).not_to eq(prev_mode)
+
+ expect(subject.check_access_lock_dir)
+ .to match("#{HOMEBREW_LOCK_DIR} isn't writable.")
+ ensure
+ HOMEBREW_LOCK_DIR.chmod mode
+ end
+ end
+
specify "#check_access_logs" do
begin
mode = HOMEBREW_LOGS.stat.mode & 0777
@@ -110,8 +124,9 @@ describe Homebrew::Diagnostic::Checks do
specify "#check_user_path_3" do
begin
sbin = HOMEBREW_PREFIX/"sbin"
- ENV["PATH"] = "#{HOMEBREW_PREFIX}/bin#{File::PATH_SEPARATOR}" +
- ENV["PATH"].gsub(/(?:^|#{Regexp.escape(File::PATH_SEPARATOR)})#{Regexp.escape(sbin)}/, "")
+ ENV["HOMEBREW_PATH"] =
+ "#{HOMEBREW_PREFIX}/bin#{File::PATH_SEPARATOR}" +
+ ENV["HOMEBREW_PATH"].gsub(/(?:^|#{Regexp.escape(File::PATH_SEPARATOR)})#{Regexp.escape(sbin)}/, "")
(sbin/"something").mkpath
expect(subject.check_user_path_1).to be nil
@@ -137,7 +152,9 @@ describe Homebrew::Diagnostic::Checks do
file = "#{path}/foo-config"
FileUtils.touch file
FileUtils.chmod 0755, file
- ENV["PATH"] = "#{path}#{File::PATH_SEPARATOR}#{ENV["PATH"]}"
+ ENV["HOMEBREW_PATH"] =
+ ENV["PATH"] =
+ "#{path}#{File::PATH_SEPARATOR}#{ENV["PATH"]}"
expect(subject.check_for_config_scripts)
.to match('"config" scripts exist')
diff --git a/Library/Homebrew/test/formula_spec.rb b/Library/Homebrew/test/formula_spec.rb
index 2309c36fb..1f98ca525 100644
--- a/Library/Homebrew/test/formula_spec.rb
+++ b/Library/Homebrew/test/formula_spec.rb
@@ -10,7 +10,6 @@ RSpec::Matchers.alias_matcher :supersede_an_installed_formula, :be_supersedes_an
RSpec::Matchers.alias_matcher :have_changed_alias, :be_alias_changed
RSpec::Matchers.alias_matcher :have_option_defined, :be_option_defined
-RSpec::Matchers.alias_matcher :have_post_install_defined, :be_post_install_defined
RSpec::Matchers.alias_matcher :have_test_defined, :be_test_defined
RSpec::Matchers.alias_matcher :pour_bottle, :be_pour_bottle
@@ -624,23 +623,6 @@ describe Formula do
expect(f.desc).to eq("a formula")
end
- specify "#post_install_defined?" do
- f1 = formula do
- url "foo-1.0"
-
- def post_install
- # do nothing
- end
- end
-
- f2 = formula do
- url "foo-1.0"
- end
-
- expect(f1).to have_post_install_defined
- expect(f2).not_to have_post_install_defined
- end
-
specify "#test_defined?" do
f1 = formula do
url "foo-1.0"
diff --git a/Library/Homebrew/test/gpg2_requirement_spec.rb b/Library/Homebrew/test/gpg2_requirement_spec.rb
index d7767abd3..a5501c84e 100644
--- a/Library/Homebrew/test/gpg2_requirement_spec.rb
+++ b/Library/Homebrew/test/gpg2_requirement_spec.rb
@@ -9,7 +9,7 @@ describe GPG2Requirement do
ENV["PATH"] = dir/"bin"
(dir/"bin/gpg").write <<-EOS.undent
#!/bin/bash
- echo 2.0.30
+ echo 2.1.20
EOS
FileUtils.chmod 0755, dir/"bin/gpg"
diff --git a/Library/Homebrew/test/gpg_spec.rb b/Library/Homebrew/test/gpg_spec.rb
index aa00d79f5..160e55379 100644
--- a/Library/Homebrew/test/gpg_spec.rb
+++ b/Library/Homebrew/test/gpg_spec.rb
@@ -13,7 +13,12 @@ describe Gpg do
shutup do
subject.create_test_key(dir)
end
- expect(dir/".gnupg/secring.gpg").to exist
+
+ if subject.version == Version.create("2.0")
+ expect(dir/".gnupg/secring.gpg").to be_a_file
+ else
+ expect(dir/".gnupg/pubring.kbx").to be_a_file
+ end
end
end
end
diff --git a/Library/Homebrew/test/hardware_spec.rb b/Library/Homebrew/test/hardware_spec.rb
index c5f8daf4e..de8d77e68 100644
--- a/Library/Homebrew/test/hardware_spec.rb
+++ b/Library/Homebrew/test/hardware_spec.rb
@@ -36,5 +36,52 @@ module Hardware
).to include(described_class.family)
end
end
+
+ describe "::can_run?" do
+ it "reports that Intel machines can run Intel executables" do
+ allow(Hardware::CPU).to receive(:type).and_return :intel
+ allow(Hardware::CPU).to receive(:bits).and_return 64
+ expect(Hardware::CPU.can_run?(:i386)).to be true
+ expect(Hardware::CPU.can_run?(:x86_64)).to be true
+ end
+
+ it "reports that PowerPC machines can run PowerPC executables" do
+ allow(Hardware::CPU).to receive(:type).and_return :ppc
+ allow(Hardware::CPU).to receive(:bits).and_return 64
+ expect(Hardware::CPU.can_run?(:ppc)).to be true
+ expect(Hardware::CPU.can_run?(:ppc64)).to be true
+ end
+
+ it "reports that 32-bit Intel machines can't run x86_64 executables" do
+ allow(Hardware::CPU).to receive(:type).and_return :intel
+ allow(Hardware::CPU).to receive(:bits).and_return 32
+ expect(Hardware::CPU.can_run?(:x86_64)).to be false
+ end
+
+ it "reports that 32-bit PowerPC machines can't run ppc64 executables" do
+ allow(Hardware::CPU).to receive(:type).and_return :ppc
+ allow(Hardware::CPU).to receive(:bits).and_return 32
+ expect(Hardware::CPU.can_run?(:ppc64)).to be false
+ end
+
+ it "identifies that Intel and PowerPC machines can't run each others' executables" do
+ allow(Hardware::CPU).to receive(:type).and_return :ppc
+ expect(Hardware::CPU.can_run?(:i386)).to be false
+ expect(Hardware::CPU.can_run?(:x86_64)).to be false
+
+ allow(Hardware::CPU).to receive(:type).and_return :intel
+ expect(Hardware::CPU.can_run?(:ppc)).to be false
+ expect(Hardware::CPU.can_run?(:ppc64)).to be false
+ end
+
+ it "returns false for unknown CPU types" do
+ allow(Hardware::CPU).to receive(:type).and_return :dunno
+ expect(Hardware::CPU.can_run?(:i386)).to be false
+ end
+
+ it "returns false for unknown arches" do
+ expect(Hardware::CPU.can_run?(:blah)).to be false
+ end
+ end
end
end
diff --git a/Library/Homebrew/test/missing_formula_spec.rb b/Library/Homebrew/test/missing_formula_spec.rb
index 215cf17f7..69bb3e70d 100644
--- a/Library/Homebrew/test/missing_formula_spec.rb
+++ b/Library/Homebrew/test/missing_formula_spec.rb
@@ -139,7 +139,7 @@ describe Homebrew::MissingFormula do
end
context "::deleted_reason" do
- subject { described_class.deleted_reason(formula) }
+ subject { described_class.deleted_reason(formula, silent: true) }
before do
Tap.clear_cache
diff --git a/Library/Homebrew/test/os/linux/osxfuse_requirement_spec.rb b/Library/Homebrew/test/os/linux/osxfuse_requirement_spec.rb
new file mode 100644
index 000000000..c45af2fa7
--- /dev/null
+++ b/Library/Homebrew/test/os/linux/osxfuse_requirement_spec.rb
@@ -0,0 +1,9 @@
+require "requirements/osxfuse_requirement"
+
+describe OsxfuseRequirement do
+ subject { described_class.new([]) }
+
+ describe "#message" do
+ its(:message) { is_expected.to match("libfuse is required to install this formula") }
+ end
+end
diff --git a/Library/Homebrew/test/os/mac/hardware_spec.rb b/Library/Homebrew/test/os/mac/hardware_spec.rb
new file mode 100644
index 000000000..fa577ba7d
--- /dev/null
+++ b/Library/Homebrew/test/os/mac/hardware_spec.rb
@@ -0,0 +1,56 @@
+require "hardware"
+require "extend/os/mac/hardware/cpu"
+
+describe Hardware::CPU do
+ describe "::can_run?" do
+ it "reports that Intel Macs can run Intel executables" do
+ allow(Hardware::CPU).to receive(:type).and_return :intel
+ allow(Hardware::CPU).to receive(:bits).and_return 64
+ expect(Hardware::CPU.can_run?(:i386)).to be true
+ expect(Hardware::CPU.can_run?(:x86_64)).to be true
+ end
+
+ it "reports that PowerPC Macs can run PowerPC executables" do
+ allow(Hardware::CPU).to receive(:type).and_return :ppc
+ allow(Hardware::CPU).to receive(:bits).and_return 64
+ expect(Hardware::CPU.can_run?(:ppc)).to be true
+ expect(Hardware::CPU.can_run?(:ppc64)).to be true
+ end
+
+ it "reports that 32-bit Intel Macs can't run x86_64 executables" do
+ allow(Hardware::CPU).to receive(:type).and_return :intel
+ allow(Hardware::CPU).to receive(:bits).and_return 32
+ expect(Hardware::CPU.can_run?(:x86_64)).to be false
+ end
+
+ it "reports that 32-bit PowerPC Macs can't run ppc64 executables" do
+ allow(Hardware::CPU).to receive(:type).and_return :ppc
+ allow(Hardware::CPU).to receive(:bits).and_return 32
+ expect(Hardware::CPU.can_run?(:ppc64)).to be false
+ end
+
+ it "reports that Intel Macs can only run 32-bit PowerPC executables on 10.6 and older" do
+ allow(Hardware::CPU).to receive(:type).and_return :intel
+ allow(OS::Mac).to receive(:version).and_return OS::Mac::Version.new "10.6"
+ expect(Hardware::CPU.can_run?(:ppc)).to be true
+
+ allow(OS::Mac).to receive(:version).and_return OS::Mac::Version.new "10.7"
+ expect(Hardware::CPU.can_run?(:ppc)).to be false
+ end
+
+ it "reports that PowerPC Macs can't run Intel executables" do
+ allow(Hardware::CPU).to receive(:type).and_return :ppc
+ expect(Hardware::CPU.can_run?(:i386)).to be false
+ expect(Hardware::CPU.can_run?(:x86_64)).to be false
+ end
+
+ it "returns false for unknown CPU types" do
+ allow(Hardware::CPU).to receive(:type).and_return :dunno
+ expect(Hardware::CPU.can_run?(:i386)).to be false
+ end
+
+ it "returns false for unknown arches" do
+ expect(Hardware::CPU.can_run?(:blah)).to be false
+ end
+ end
+end
diff --git a/Library/Homebrew/test/os/mac/osxfuse_requirement_spec.rb b/Library/Homebrew/test/os/mac/osxfuse_requirement_spec.rb
new file mode 100644
index 000000000..06d3d885e
--- /dev/null
+++ b/Library/Homebrew/test/os/mac/osxfuse_requirement_spec.rb
@@ -0,0 +1,36 @@
+require "requirements/osxfuse_requirement"
+
+describe OsxfuseRequirement do
+ subject { described_class.new([]) }
+
+ describe "::binary_osxfuse_installed?" do
+ it "returns false if fuse.h does not exist" do
+ allow(File).to receive(:exist?).and_return(false)
+ expect(described_class).not_to be_binary_osxfuse_installed
+ end
+
+ it "returns false if osxfuse include directory is a symlink" do
+ allow(File).to receive(:exist?).and_return(true)
+ allow(File).to receive(:symlink?).and_return(true)
+ expect(described_class).not_to be_binary_osxfuse_installed
+ end
+ end
+
+ describe "environment" do
+ it "adds the fuse directories to the appropriate paths" do
+ expect(ENV).to receive(:append_path).with("PKG_CONFIG_PATH", any_args)
+ expect(ENV).to receive(:append_path).with("HOMEBREW_LIBRARY_PATHS", any_args)
+ expect(ENV).to receive(:append_path).with("HOMEBREW_INCLUDE_PATHS", any_args)
+ subject.modify_build_environment
+ end
+ end
+end
+
+describe NonBinaryOsxfuseRequirement do
+ subject { described_class.new([]) }
+
+ describe "#message" do
+ msg = /osxfuse is already installed from the binary distribution/
+ its(:message) { is_expected.to match(msg) }
+ end
+end
diff --git a/Library/Homebrew/test/requirement_spec.rb b/Library/Homebrew/test/requirement_spec.rb
index 110a7ac4f..959041cf4 100644
--- a/Library/Homebrew/test/requirement_spec.rb
+++ b/Library/Homebrew/test/requirement_spec.rb
@@ -146,17 +146,13 @@ describe Requirement do
end
describe "#build?" do
- context "#build true is specified" do
- let(:klass) do
- Class.new(described_class) do
- build true
- end
- end
+ context ":build tag is specified" do
+ subject { described_class.new([:build]) }
it { is_expected.to be_a_build_requirement }
end
- context "#build ommitted" do
+ context "#build omitted" do
it { is_expected.not_to be_a_build_requirement }
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 5be2d6cf5..a775b0b17 100644
--- a/Library/Homebrew/test/rubocops/bottle_block_cop_spec.rb
+++ b/Library/Homebrew/test/rubocops/bottle_block_cop_spec.rb
@@ -3,7 +3,7 @@ require "rubocop/rspec/support"
require_relative "../../extend/string"
require_relative "../../rubocops/bottle_block_cop"
-describe RuboCop::Cop::Homebrew::CorrectBottleBlock do
+describe RuboCop::Cop::FormulaAuditStrict::BottleBlock do
subject(:cop) { described_class.new }
context "When auditing Bottle Block" do
diff --git a/Library/Homebrew/test/rubocops/components_order_cop_spec.rb b/Library/Homebrew/test/rubocops/components_order_cop_spec.rb
new file mode 100644
index 000000000..25467c635
--- /dev/null
+++ b/Library/Homebrew/test/rubocops/components_order_cop_spec.rb
@@ -0,0 +1,163 @@
+require "rubocop"
+require "rubocop/rspec/support"
+require_relative "../../extend/string"
+require_relative "../../rubocops/components_order_cop"
+
+describe RuboCop::Cop::FormulaAuditStrict::ComponentsOrder do
+ subject(:cop) { described_class.new }
+
+ context "When auditing formula components order" do
+ it "When url precedes homepage" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ url "http://example.com/foo-1.0.tgz"
+ homepage "http://example.com"
+ end
+ EOS
+
+ expected_offenses = [{ message: "`homepage` (line 3) should be put before `url` (line 2)",
+ severity: :convention,
+ line: 3,
+ column: 2,
+ source: source }]
+
+ inspect_source(cop, source)
+
+ expected_offenses.zip(cop.offenses).each do |expected, actual|
+ expect_offense(expected, actual)
+ end
+ end
+
+ it "When `resource` precedes `depends_on`" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ url "https://example.com/foo-1.0.tgz"
+
+ resource "foo2" do
+ url "https://example.com/foo-2.0.tgz"
+ end
+
+ depends_on "openssl"
+ end
+ EOS
+
+ expected_offenses = [{ message: "`depends_on` (line 8) should be put before `resource` (line 4)",
+ severity: :convention,
+ line: 8,
+ column: 2,
+ source: source }]
+
+ inspect_source(cop, source)
+
+ expected_offenses.zip(cop.offenses).each do |expected, actual|
+ expect_offense(expected, actual)
+ end
+ end
+
+ it "When `test` precedes `plist`" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ url "https://example.com/foo-1.0.tgz"
+
+ test do
+ expect(shell_output("./dogs")).to match("Dogs are terrific")
+ end
+
+ def plist
+ end
+ end
+ EOS
+
+ expected_offenses = [{ message: "`plist` (line 8) should be put before `test` (line 4)",
+ severity: :convention,
+ line: 8,
+ column: 2,
+ source: source }]
+
+ inspect_source(cop, source)
+
+ expected_offenses.zip(cop.offenses).each do |expected, actual|
+ expect_offense(expected, actual)
+ end
+ end
+
+ it "When only one of many `depends_on` precedes `conflicts_with`" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ depends_on "autoconf" => :build
+ conflicts_with "visionmedia-watch"
+ depends_on "automake" => :build
+ depends_on "libtool" => :build
+ depends_on "pkg-config" => :build
+ depends_on "gettext"
+ end
+ EOS
+
+ expected_offenses = [{ message: "`depends_on` (line 4) should be put before `conflicts_with` (line 3)",
+ severity: :convention,
+ line: 4,
+ column: 2,
+ source: source }]
+
+ inspect_source(cop, source)
+
+ expected_offenses.zip(cop.offenses).each do |expected, actual|
+ expect_offense(expected, actual)
+ end
+ end
+
+ 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
+
+ context "When auditing formula components order with autocorrect" do
+ it "When url precedes homepage" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ url "http://example.com/foo-1.0.tgz"
+ homepage "http://example.com"
+ end
+ EOS
+ correct_source = <<-EOS.undent
+ class Foo < Formula
+ homepage "http://example.com"
+ url "http://example.com/foo-1.0.tgz"
+ end
+ EOS
+
+ corrected_source = autocorrect_source(cop, source)
+ expect(corrected_source).to eq(correct_source)
+ end
+
+ it "When `resource` precedes `depends_on`" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ url "https://example.com/foo-1.0.tgz"
+
+ resource "foo2" do
+ url "https://example.com/foo-2.0.tgz"
+ end
+
+ depends_on "openssl"
+ end
+ EOS
+ correct_source = <<-EOS.undent
+ class Foo < Formula
+ url "https://example.com/foo-1.0.tgz"
+
+ depends_on "openssl"
+
+ resource "foo2" do
+ url "https://example.com/foo-2.0.tgz"
+ end
+ end
+ EOS
+ corrected_source = autocorrect_source(cop, source)
+ expect(corrected_source).to eq(correct_source)
+ end
+ end
+end
diff --git a/Library/Homebrew/test/rubocops/components_redundancy_cop_spec.rb b/Library/Homebrew/test/rubocops/components_redundancy_cop_spec.rb
new file mode 100644
index 000000000..fd635a126
--- /dev/null
+++ b/Library/Homebrew/test/rubocops/components_redundancy_cop_spec.rb
@@ -0,0 +1,87 @@
+require "rubocop"
+require "rubocop/rspec/support"
+require_relative "../../extend/string"
+require_relative "../../rubocops/components_redundancy_cop"
+
+describe RuboCop::Cop::FormulaAuditStrict::ComponentsRedundancy do
+ subject(:cop) { described_class.new }
+
+ context "When auditing formula components common errors" do
+ it "When url outside stable block" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ url "http://example.com/foo-1.0.tgz"
+ stable do
+ # stuff
+ end
+ end
+ EOS
+
+ expected_offenses = [{ message: "`url` should be put inside `stable` block",
+ severity: :convention,
+ line: 2,
+ column: 2,
+ source: source }]
+
+ inspect_source(cop, source)
+
+ expected_offenses.zip(cop.offenses).each do |expected, actual|
+ expect_offense(expected, actual)
+ end
+ end
+
+ it "When both `head` and `head do` are present" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ head "http://example.com/foo.git"
+ head do
+ # stuff
+ end
+ end
+ EOS
+
+ expected_offenses = [{ message: "`head` and `head do` should not be simultaneously present",
+ severity: :convention,
+ line: 3,
+ column: 2,
+ source: source }]
+
+ inspect_source(cop, source)
+
+ expected_offenses.zip(cop.offenses).each do |expected, actual|
+ expect_offense(expected, actual)
+ end
+ end
+
+ it "When both `bottle :modifier` and `bottle do` are present" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ url "http://example.com/foo-1.0.tgz"
+ bottle do
+ # bottles go here
+ end
+ bottle :unneeded
+ end
+ EOS
+
+ expected_offenses = [{ message: "`bottle :modifier` and `bottle do` should not be simultaneously present",
+ severity: :convention,
+ line: 3,
+ column: 2,
+ source: source }]
+
+ inspect_source(cop, source)
+
+ expected_offenses.zip(cop.offenses).each do |expected, actual|
+ expect_offense(expected, actual)
+ 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
+end
diff --git a/Library/Homebrew/test/rubocops/formula_desc_cop_spec.rb b/Library/Homebrew/test/rubocops/formula_desc_cop_spec.rb
index 04c4c27da..432b15e3c 100644
--- a/Library/Homebrew/test/rubocops/formula_desc_cop_spec.rb
+++ b/Library/Homebrew/test/rubocops/formula_desc_cop_spec.rb
@@ -3,7 +3,7 @@ require "rubocop/rspec/support"
require_relative "../../extend/string"
require_relative "../../rubocops/formula_desc_cop"
-describe RuboCop::Cop::Homebrew::FormulaDesc do
+describe RuboCop::Cop::FormulaAuditStrict::Desc do
subject(:cop) { described_class.new }
context "When auditing formula desc" do
@@ -51,6 +51,31 @@ describe RuboCop::Cop::Homebrew::FormulaDesc do
end
end
+ it "When desc is multiline string" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ url 'http://example.com/foo-1.0.tgz'
+ desc '#{"bar"*10}'\
+ '#{"foo"*21}'
+ end
+ EOS
+
+ msg = <<-EOS.undent
+ Description is too long. "name: desc" should be less than 80 characters.
+ Length is calculated as Foo + desc. (currently 98)
+ EOS
+ expected_offenses = [{ message: msg,
+ severity: :convention,
+ line: 3,
+ column: 2,
+ source: source }]
+
+ inspect_source(cop, source)
+ expected_offenses.zip(cop.offenses).each do |expected, actual|
+ expect_offense(expected, actual)
+ end
+ end
+
it "When wrong \"command-line\" usage in desc" do
source = <<-EOS.undent
class Foo < Formula
diff --git a/Library/Homebrew/test/rubocops/homepage_cop_spec.rb b/Library/Homebrew/test/rubocops/homepage_cop_spec.rb
new file mode 100644
index 000000000..c03efd825
--- /dev/null
+++ b/Library/Homebrew/test/rubocops/homepage_cop_spec.rb
@@ -0,0 +1,124 @@
+require "rubocop"
+require "rubocop/rspec/support"
+require_relative "../../extend/string"
+require_relative "../../rubocops/homepage_cop"
+
+describe RuboCop::Cop::FormulaAudit::Homepage do
+ subject(:cop) { described_class.new }
+
+ context "When auditing homepage" do
+ it "When there is no homepage" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ url 'http://example.com/foo-1.0.tgz'
+ end
+ EOS
+
+ expected_offenses = [{ message: "Formula should have a homepage.",
+ severity: :convention,
+ line: 1,
+ column: 0,
+ source: source }]
+
+ inspect_source(cop, source)
+
+ expected_offenses.zip(cop.offenses).each do |expected, actual|
+ expect_offense(expected, actual)
+ end
+ end
+
+ it "Homepage with ftp" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ homepage "ftp://example.com/foo"
+ url "http://example.com/foo-1.0.tgz"
+ end
+ EOS
+
+ expected_offenses = [{ message: "The homepage should start with http or https (URL is ftp://example.com/foo).",
+ severity: :convention,
+ line: 2,
+ column: 2,
+ source: source }]
+
+ inspect_source(cop, source)
+
+ expected_offenses.zip(cop.offenses).each do |expected, actual|
+ expect_offense(expected, actual)
+ end
+ end
+
+ it "Homepage URLs" do
+ formula_homepages = {
+ "bar" => "http://www.freedesktop.org/wiki/bar",
+ "baz" => "http://www.freedesktop.org/wiki/Software/baz",
+ "qux" => "https://code.google.com/p/qux",
+ "quux" => "http://github.com/quux",
+ "corge" => "http://savannah.nongnu.org/corge",
+ "grault" => "http://grault.github.io/",
+ "garply" => "http://www.gnome.org/garply",
+ "sf1" => "http://foo.sourceforge.net/",
+ "sf2" => "http://foo.sourceforge.net",
+ "sf3" => "http://foo.sf.net/",
+ "sf4" => "http://foo.sourceforge.io/",
+ "waldo" => "http://www.gnu.org/waldo",
+ }
+
+ formula_homepages.each do |name, homepage|
+ source = <<-EOS.undent
+ class #{name.capitalize} < Formula
+ homepage "#{homepage}"
+ url "http://example.com/#{name}-1.0.tgz"
+ end
+ EOS
+
+ inspect_source(cop, source)
+ if homepage =~ %r{http:\/\/www\.freedesktop\.org}
+ if homepage =~ /Software/
+ expected_offenses = [{ message: "#{homepage} should be styled " \
+ "`https://wiki.freedesktop.org/www/Software/project_name`",
+ severity: :convention,
+ line: 2,
+ column: 2,
+ source: source }]
+ else
+ expected_offenses = [{ message: "#{homepage} should be styled " \
+ "`https://wiki.freedesktop.org/project_name`",
+ severity: :convention,
+ line: 2,
+ column: 2,
+ source: source }]
+ end
+ elsif homepage =~ %r{https:\/\/code\.google\.com}
+ expected_offenses = [{ message: "#{homepage} should end with a slash",
+ severity: :convention,
+ line: 2,
+ column: 2,
+ source: source }]
+ elsif homepage =~ /foo\.(sf|sourceforge)\.net/
+ expected_offenses = [{ message: "#{homepage} should be `https://foo.sourceforge.io/`",
+ severity: :convention,
+ line: 2,
+ column: 2,
+ source: source }]
+ else
+ expected_offenses = [{ message: "Please use https:// for #{homepage}",
+ severity: :convention,
+ line: 2,
+ column: 2,
+ source: source }]
+ end
+ expected_offenses.zip([cop.offenses.last]).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
+end
diff --git a/Library/Homebrew/test/spec_helper.rb b/Library/Homebrew/test/spec_helper.rb
index 2f6274fd1..e193b91a0 100644
--- a/Library/Homebrew/test/spec_helper.rb
+++ b/Library/Homebrew/test/spec_helper.rb
@@ -61,6 +61,10 @@ RSpec.configure do |config|
skip "Python not installed." unless which("python")
end
+ config.before(:each, :needs_network) do
+ skip "Requires network connection." unless ENV["HOMEBREW_TEST_ONLINE"]
+ end
+
config.around(:each) do |example|
begin
TEST_DIRECTORIES.each(&:mkpath)
@@ -89,6 +93,7 @@ RSpec.configure do |config|
HOMEBREW_PREFIX/"opt",
HOMEBREW_PREFIX/"Caskroom",
HOMEBREW_LIBRARY/"Taps/caskroom",
+ HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-bar",
HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-bundle",
HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-foo",
HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-services",
diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/with-non-executable-binary.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-non-executable-binary.rb
new file mode 100644
index 000000000..4bd2f0882
--- /dev/null
+++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-non-executable-binary.rb
@@ -0,0 +1,9 @@
+cask 'with-non-executable-binary' do
+ version '1.2.3'
+ sha256 'd5b2dfbef7ea28c25f7a77cd7fa14d013d82b626db1d82e00e25822464ba19e2'
+
+ url "file://#{TEST_FIXTURE_DIR}/cask/naked_non_executable"
+ homepage 'http://example.com/with-binary'
+
+ binary "naked_non_executable"
+end
diff --git a/Library/Homebrew/test/support/fixtures/cask/naked_non_executable b/Library/Homebrew/test/support/fixtures/cask/naked_non_executable
new file mode 100644
index 000000000..039e4d006
--- /dev/null
+++ b/Library/Homebrew/test/support/fixtures/cask/naked_non_executable
@@ -0,0 +1,2 @@
+#!/bin/sh
+exit 0
diff --git a/Library/Homebrew/test/support/helper/spec/shared_context/integration_test.rb b/Library/Homebrew/test/support/helper/spec/shared_context/integration_test.rb
index b037068d2..ae1854f58 100644
--- a/Library/Homebrew/test/support/helper/spec/shared_context/integration_test.rb
+++ b/Library/Homebrew/test/support/helper/spec/shared_context/integration_test.rb
@@ -72,6 +72,7 @@ RSpec.shared_context "integration test" do
env.merge!(
"PATH" => path,
+ "HOMEBREW_PATH" => path,
"HOMEBREW_BREW_FILE" => HOMEBREW_PREFIX/"bin/brew",
"HOMEBREW_INTEGRATION_TEST" => command_id_from_args(args),
"HOMEBREW_TEST_TMPDIR" => TEST_TMPDIR,
diff --git a/Library/Homebrew/test/utils/github_spec.rb b/Library/Homebrew/test/utils/github_spec.rb
new file mode 100644
index 000000000..9b539262f
--- /dev/null
+++ b/Library/Homebrew/test/utils/github_spec.rb
@@ -0,0 +1,13 @@
+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")
+
+ expect(results.count).to eq(1)
+ expect(results.first["name"]).to eq("README.md")
+ expect(results.first["path"]).to eq("README.md")
+ end
+ end
+end
diff --git a/Library/Homebrew/test/utils/shell_spec.rb b/Library/Homebrew/test/utils/shell_spec.rb
index c44bd8253..d32f9928f 100644
--- a/Library/Homebrew/test/utils/shell_spec.rb
+++ b/Library/Homebrew/test/utils/shell_spec.rb
@@ -1,92 +1,92 @@
require "utils/shell"
describe Utils::Shell do
- describe "::shell_profile" do
+ describe "::profile" do
it "returns ~/.bash_profile by default" do
ENV["SHELL"] = "/bin/another_shell"
- expect(subject.shell_profile).to eq("~/.bash_profile")
+ expect(subject.profile).to eq("~/.bash_profile")
end
it "returns ~/.bash_profile for Sh" do
ENV["SHELL"] = "/bin/another_shell"
- expect(subject.shell_profile).to eq("~/.bash_profile")
+ expect(subject.profile).to eq("~/.bash_profile")
end
it "returns ~/.bash_profile for Bash" do
ENV["SHELL"] = "/bin/bash"
- expect(subject.shell_profile).to eq("~/.bash_profile")
+ expect(subject.profile).to eq("~/.bash_profile")
end
it "returns ~/.zshrc for Zsh" do
ENV["SHELL"] = "/bin/zsh"
- expect(subject.shell_profile).to eq("~/.zshrc")
+ expect(subject.profile).to eq("~/.zshrc")
end
it "returns ~/.kshrc for Ksh" do
ENV["SHELL"] = "/bin/ksh"
- expect(subject.shell_profile).to eq("~/.kshrc")
+ expect(subject.profile).to eq("~/.kshrc")
end
end
- describe "::path_to_shell" do
+ describe "::from_path" do
it "supports a raw command name" do
- expect(subject.path_to_shell("bash")).to eq(:bash)
+ expect(subject.from_path("bash")).to eq(:bash)
end
it "supports full paths" do
- expect(subject.path_to_shell("/bin/bash")).to eq(:bash)
+ expect(subject.from_path("/bin/bash")).to eq(:bash)
end
it "supports versions" do
- expect(subject.path_to_shell("zsh-5.2")).to eq(:zsh)
+ expect(subject.from_path("zsh-5.2")).to eq(:zsh)
end
it "strips newlines" do
- expect(subject.path_to_shell("zsh-5.2\n")).to eq(:zsh)
+ expect(subject.from_path("zsh-5.2\n")).to eq(:zsh)
end
it "returns nil when input is invalid" do
- expect(subject.path_to_shell("")).to be nil
- expect(subject.path_to_shell("@@@@@@")).to be nil
- expect(subject.path_to_shell("invalid_shell-4.2")).to be nil
+ expect(subject.from_path("")).to be nil
+ expect(subject.from_path("@@@@@@")).to be nil
+ expect(subject.from_path("invalid_shell-4.2")).to be nil
end
end
specify "::sh_quote" do
- expect(subject.sh_quote("")).to eq("''")
- expect(subject.sh_quote("\\")).to eq("\\\\")
- expect(subject.sh_quote("\n")).to eq("'\n'")
- expect(subject.sh_quote("$")).to eq("\\$")
- expect(subject.sh_quote("word")).to eq("word")
+ expect(subject.send(:sh_quote, "")).to eq("''")
+ expect(subject.send(:sh_quote, "\\")).to eq("\\\\")
+ expect(subject.send(:sh_quote, "\n")).to eq("'\n'")
+ expect(subject.send(:sh_quote, "$")).to eq("\\$")
+ expect(subject.send(:sh_quote, "word")).to eq("word")
end
specify "::csh_quote" do
- expect(subject.csh_quote("")).to eq("''")
- expect(subject.csh_quote("\\")).to eq("\\\\")
+ expect(subject.send(:csh_quote, "")).to eq("''")
+ expect(subject.send(:csh_quote, "\\")).to eq("\\\\")
# note this test is different than for sh
- expect(subject.csh_quote("\n")).to eq("'\\\n'")
- expect(subject.csh_quote("$")).to eq("\\$")
- expect(subject.csh_quote("word")).to eq("word")
+ expect(subject.send(:csh_quote, "\n")).to eq("'\\\n'")
+ expect(subject.send(:csh_quote, "$")).to eq("\\$")
+ expect(subject.send(:csh_quote, "word")).to eq("word")
end
- describe "::prepend_path_in_shell_profile" do
+ describe "::prepend_path_in_profile" do
let(:path) { "/my/path" }
it "supports Tcsh" do
ENV["SHELL"] = "/bin/tcsh"
- expect(subject.prepend_path_in_shell_profile(path))
+ expect(subject.prepend_path_in_profile(path))
.to start_with("echo 'setenv PATH #{path}:$")
end
it "supports Bash" do
ENV["SHELL"] = "/bin/bash"
- expect(subject.prepend_path_in_shell_profile(path))
+ expect(subject.prepend_path_in_profile(path))
.to start_with("echo 'export PATH=\"#{path}:$")
end
it "supports Fish" do
ENV["SHELL"] = "/usr/local/bin/fish"
- expect(subject.prepend_path_in_shell_profile(path))
+ expect(subject.prepend_path_in_profile(path))
.to start_with("echo 'set -g fish_user_paths \"#{path}\" $fish_user_paths' >>")
end
end
diff --git a/Library/Homebrew/test/utils_spec.rb b/Library/Homebrew/test/utils_spec.rb
index 314c299a8..be224990a 100644
--- a/Library/Homebrew/test/utils_spec.rb
+++ b/Library/Homebrew/test/utils_spec.rb
@@ -189,7 +189,13 @@ describe "globally-scoped helper methods" do
specify "#which_editor" do
ENV["HOMEBREW_EDITOR"] = "vemate"
- expect(which_editor).to eq("vemate")
+ ENV["HOMEBREW_PATH"] = dir
+
+ editor = "#{dir}/vemate"
+ FileUtils.touch editor
+ FileUtils.chmod 0755, editor
+
+ expect(which_editor).to eql editor
end
specify "#gzip" do
diff --git a/Library/Homebrew/test/version_spec.rb b/Library/Homebrew/test/version_spec.rb
index d3d63a25c..41e05019c 100644
--- a/Library/Homebrew/test/version_spec.rb
+++ b/Library/Homebrew/test/version_spec.rb
@@ -433,6 +433,11 @@ describe Version do
.to be_detected_from("https://homebrew.bintray.com/bottles/imagemagick-6.7.5-7.lion.bottle.1.tar.gz")
end
+ specify "date-based version style" do
+ expect(Version.create("2017-04-17"))
+ .to be_detected_from("https://example.com/dada-v2017-04-17.tar.gz")
+ end
+
specify "dash version style" do
expect(Version.create("3.4"))
.to be_detected_from("http://www.antlr.org/download/antlr-3.4-complete.jar")
diff --git a/Library/Homebrew/utils.rb b/Library/Homebrew/utils.rb
index 46a8cc68e..28d7fc283 100644
--- a/Library/Homebrew/utils.rb
+++ b/Library/Homebrew/utils.rb
@@ -190,10 +190,10 @@ module Homebrew
Gem::Specification.reset
# Add Gem binary directory and (if missing) Ruby binary directory to PATH.
- path = ENV["PATH"].split(File::PATH_SEPARATOR)
- path.unshift(RUBY_BIN) if which("ruby") != RUBY_PATH
- path.unshift(Gem.bindir)
- ENV["PATH"] = path.join(File::PATH_SEPARATOR)
+ path = PATH.new(ENV["PATH"])
+ path.prepend(RUBY_BIN) if which("ruby") != RUBY_PATH
+ path.prepend(Gem.bindir)
+ ENV["PATH"] = path
if Gem::Specification.find_all_by_name(name, version).empty?
ohai "Installing or updating '#{name}' gem"
@@ -293,7 +293,7 @@ def quiet_system(cmd, *args)
end
def which(cmd, path = ENV["PATH"])
- path.split(File::PATH_SEPARATOR).each do |p|
+ PATH.new(path).each do |p|
begin
pcmd = File.expand_path(cmd, p)
rescue ArgumentError
@@ -307,7 +307,7 @@ def which(cmd, path = ENV["PATH"])
end
def which_all(cmd, path = ENV["PATH"])
- path.to_s.split(File::PATH_SEPARATOR).map do |p|
+ PATH.new(path).map do |p|
begin
pcmd = File.expand_path(cmd, p)
rescue ArgumentError
@@ -320,25 +320,34 @@ def which_all(cmd, path = ENV["PATH"])
end
def which_editor
- editor = ENV.values_at("HOMEBREW_EDITOR", "VISUAL", "EDITOR").compact.first
- return editor unless editor.nil?
+ editor = ENV.values_at("HOMEBREW_EDITOR", "HOMEBREW_VISUAL").compact.reject(&:empty?).first
+ if editor
+ editor_name, _, editor_args = editor.partition " "
+ editor_path = which(editor_name, ENV["HOMEBREW_PATH"])
+ editor = if editor_args.to_s.empty?
+ editor_path.to_s
+ else
+ "#{editor_path} #{editor_args}"
+ end
+ return editor
+ end
# Find Textmate
- editor = "mate" if which "mate"
+ editor = which("mate", ENV["HOMEBREW_PATH"])
# Find BBEdit / TextWrangler
- editor ||= "edit" if which "edit"
+ editor ||= which("edit", ENV["HOMEBREW_PATH"])
# Find vim
- editor ||= "vim" if which "vim"
+ editor ||= which("vim", ENV["HOMEBREW_PATH"])
# Default to standard vim
editor ||= "/usr/bin/vim"
opoo <<-EOS.undent
Using #{editor} because no editor was set in the environment.
- This may change in the future, so we recommend setting EDITOR, VISUAL,
+ This may change in the future, so we recommend setting EDITOR,
or HOMEBREW_EDITOR to your preferred text editor.
EOS
- editor
+ editor.to_s
end
def exec_editor(*args)
@@ -347,7 +356,7 @@ def exec_editor(*args)
end
def exec_browser(*args)
- browser = ENV["HOMEBREW_BROWSER"] || ENV["BROWSER"]
+ browser = ENV["HOMEBREW_BROWSER"]
browser ||= OS::PATH_OPEN if defined?(OS::PATH_OPEN)
return unless browser
safe_exec(browser, *args)
@@ -406,8 +415,8 @@ def nostdout
end
end
-def paths
- @paths ||= ENV["PATH"].split(File::PATH_SEPARATOR).collect do |p|
+def paths(env_path = ENV["PATH"])
+ @paths ||= PATH.new(env_path).collect do |p|
begin
File.expand_path(p).chomp("/")
rescue ArgumentError
diff --git a/Library/Homebrew/utils/analytics.sh b/Library/Homebrew/utils/analytics.sh
index 35f91eabc..8d5cf2ff7 100644
--- a/Library/Homebrew/utils/analytics.sh
+++ b/Library/Homebrew/utils/analytics.sh
@@ -85,8 +85,6 @@ report-analytics-screenview-command() {
fi
# Don't report commands used mostly by our scripts and not users.
- # TODO: list more e.g. shell completion things here perhaps using a single
- # script as a shell-completion entry point.
case "$HOMEBREW_COMMAND" in
--prefix|analytics|command|commands)
return
diff --git a/Library/Homebrew/utils/github.rb b/Library/Homebrew/utils/github.rb
index a5ed5394a..88c5199c2 100644
--- a/Library/Homebrew/utils/github.rb
+++ b/Library/Homebrew/utils/github.rb
@@ -4,7 +4,7 @@ require "tempfile"
module GitHub
module_function
- ISSUES_URI = URI.parse("https://api.github.com/search/issues")
+ API_URL = "https://api.github.com".freeze
CREATE_GIST_SCOPES = ["gist"].freeze
CREATE_ISSUE_SCOPES = ["public_repo"].freeze
@@ -228,13 +228,19 @@ module GitHub
end
def issues_matching(query, qualifiers = {})
- uri = ISSUES_URI.dup
+ uri = URI.parse("#{API_URL}/search/issues")
uri.query = build_query_string(query, qualifiers)
open(uri) { |json| json["items"] }
end
def repository(user, repo)
- open(URI.parse("https://api.github.com/repos/#{user}/#{repo}")) { |j| j }
+ 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"] }
end
def build_query_string(query, qualifiers)
@@ -286,7 +292,7 @@ module GitHub
end
def private_repo?(user, repo)
- uri = URI.parse("https://api.github.com/repos/#{user}/#{repo}")
+ uri = URI.parse("#{API_URL}/repos/#{user}/#{repo}")
open(uri) { |json| json["private"] }
end
end
diff --git a/Library/Homebrew/utils/shell.rb b/Library/Homebrew/utils/shell.rb
index 302167d47..5327f6ecf 100644
--- a/Library/Homebrew/utils/shell.rb
+++ b/Library/Homebrew/utils/shell.rb
@@ -1,62 +1,24 @@
module Utils
- SHELL_PROFILE_MAP = {
- bash: "~/.bash_profile",
- csh: "~/.cshrc",
- fish: "~/.config/fish/config.fish",
- ksh: "~/.kshrc",
- sh: "~/.bash_profile",
- tcsh: "~/.tcshrc",
- zsh: "~/.zshrc",
- }.freeze
-
module Shell
- UNSAFE_SHELL_CHAR = %r{([^A-Za-z0-9_\-.,:/@\n])}
+ module_function
# take a path and heuristically convert it
# to a shell name, return nil if there's no match
- def path_to_shell(path)
+ def from_path(path)
# we only care about the basename
shell_name = File.basename(path)
# handle possible version suffix like `zsh-5.2`
shell_name.sub!(/-.*\z/m, "")
shell_name.to_sym if %w[bash csh fish ksh sh tcsh zsh].include?(shell_name)
end
- module_function :path_to_shell
-
- def preferred_shell
- path_to_shell(ENV.fetch("SHELL", ""))
- end
- module_function :preferred_shell
- def parent_shell
- path_to_shell(`ps -p #{Process.ppid} -o ucomm=`.strip)
+ def preferred
+ from_path(ENV.fetch("SHELL", ""))
end
- module_function :parent_shell
- def csh_quote(str)
- # ruby's implementation of shell_escape
- str = str.to_s
- return "''" if str.empty?
- str = str.dup
- # anything that isn't a known safe character is padded
- str.gsub!(UNSAFE_SHELL_CHAR, "\\\\" + "\\1")
- # newlines have to be specially quoted in csh
- str.gsub!(/\n/, "'\\\n'")
- str
+ def parent
+ from_path(`ps -p #{Process.ppid} -o ucomm=`.strip)
end
- module_function :csh_quote
-
- def sh_quote(str)
- # ruby's implementation of shell_escape
- str = str.to_s
- return "''" if str.empty?
- str = str.dup
- # anything that isn't a known safe character is padded
- str.gsub!(UNSAFE_SHELL_CHAR, "\\\\" + "\\1")
- str.gsub!(/\n/, "'\n'")
- str
- end
- module_function :sh_quote
# quote values. quoting keys is overkill
def export_value(shell, key, value)
@@ -72,24 +34,60 @@ module Utils
"setenv #{key} #{csh_quote(value)};"
end
end
- module_function :export_value
# return the shell profile file based on users' preferred shell
- def shell_profile
- SHELL_PROFILE_MAP.fetch(preferred_shell, "~/.bash_profile")
+ def profile
+ SHELL_PROFILE_MAP.fetch(preferred, "~/.bash_profile")
end
- module_function :shell_profile
- def prepend_path_in_shell_profile(path)
- case preferred_shell
+ def prepend_path_in_profile(path)
+ case preferred
when :bash, :ksh, :sh, :zsh, nil
- "echo 'export PATH=\"#{sh_quote(path)}:$PATH\"' >> #{shell_profile}"
+ "echo 'export PATH=\"#{sh_quote(path)}:$PATH\"' >> #{profile}"
when :csh, :tcsh
- "echo 'setenv PATH #{csh_quote(path)}:$PATH' >> #{shell_profile}"
+ "echo 'setenv PATH #{csh_quote(path)}:$PATH' >> #{profile}"
when :fish
- "echo 'set -g fish_user_paths \"#{sh_quote(path)}\" $fish_user_paths' >> #{shell_profile}"
+ "echo 'set -g fish_user_paths \"#{sh_quote(path)}\" $fish_user_paths' >> #{profile}"
end
end
- module_function :prepend_path_in_shell_profile
+
+ private
+
+ SHELL_PROFILE_MAP = {
+ bash: "~/.bash_profile",
+ csh: "~/.cshrc",
+ fish: "~/.config/fish/config.fish",
+ ksh: "~/.kshrc",
+ sh: "~/.bash_profile",
+ tcsh: "~/.tcshrc",
+ zsh: "~/.zshrc",
+ }.freeze
+
+ 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
+ return "''" if str.empty?
+ str = str.dup
+ # anything that isn't a known safe character is padded
+ str.gsub!(UNSAFE_SHELL_CHAR, "\\\\" + "\\1")
+ # newlines have to be specially quoted in csh
+ str.gsub!(/\n/, "'\\\n'")
+ str
+ end
+
+ def sh_quote(str)
+ # ruby's implementation of shell_escape
+ str = str.to_s
+ return "''" if str.empty?
+ str = str.dup
+ # anything that isn't a known safe character is padded
+ str.gsub!(UNSAFE_SHELL_CHAR, "\\\\" + "\\1")
+ str.gsub!(/\n/, "'\n'")
+ str
+ end
end
end
diff --git a/Library/Homebrew/vendor/README.md b/Library/Homebrew/vendor/README.md
index 906d42918..b408631c7 100644
--- a/Library/Homebrew/vendor/README.md
+++ b/Library/Homebrew/vendor/README.md
@@ -1,7 +1,7 @@
Vendored Dependencies
=====================
-* [plist](https://github.com/bleything/plist), version 3.1.0
+* [plist](https://github.com/patsplat/plist), version 3.3.0
* [ruby-macho](https://github.com/Homebrew/ruby-macho), version 1.1.0
diff --git a/Library/Homebrew/vendor/plist/plist.rb b/Library/Homebrew/vendor/plist/plist.rb
index 0b828afc6..82ecb27d2 100755
--- a/Library/Homebrew/vendor/plist/plist.rb
+++ b/Library/Homebrew/vendor/plist/plist.rb
@@ -1,5 +1,5 @@
-#!/usr/bin/env ruby
-#
+# encoding: utf-8
+
# = plist
#
# This is the main file for plist. Everything interesting happens in
@@ -15,7 +15,7 @@ require 'stringio'
require_relative 'plist/generator'
require_relative 'plist/parser'
+require_relative 'plist/version'
module Plist
- VERSION = '3.1.0'
end
diff --git a/Library/Homebrew/vendor/plist/plist/generator.rb b/Library/Homebrew/vendor/plist/plist/generator.rb
index 3b84c301f..84bef3aaf 100644..100755
--- a/Library/Homebrew/vendor/plist/plist/generator.rb
+++ b/Library/Homebrew/vendor/plist/plist/generator.rb
@@ -1,12 +1,12 @@
-#!/usr/bin/env ruby
-#
+# encoding: utf-8
+
# = plist
#
# Copyright 2006-2010 Ben Bleything and Patrick May
# Distributed under the MIT License
#
-module Plist ; end
+module Plist; end
# === Create a plist
# You can dump an object to a plist in one of two ways:
@@ -94,7 +94,7 @@ module Plist::Emit
output << tag('date', element.utc.strftime('%Y-%m-%dT%H:%M:%SZ'))
when Date # also catches DateTime
output << tag('date', element.strftime('%Y-%m-%dT%H:%M:%SZ'))
- when String, Symbol, Fixnum, Bignum, Integer, Float
+ when String, Symbol, Integer, Float
output << tag(element_type(element), CGI::escapeHTML(element.to_s))
when IO, StringIO
element.rewind
@@ -159,7 +159,7 @@ module Plist::Emit
when String, Symbol
'string'
- when Fixnum, Bignum, Integer
+ when Integer
'integer'
when Float
diff --git a/Library/Homebrew/vendor/plist/plist/parser.rb b/Library/Homebrew/vendor/plist/plist/parser.rb
index de441fcc5..4de13f881 100644..100755
--- a/Library/Homebrew/vendor/plist/plist/parser.rb
+++ b/Library/Homebrew/vendor/plist/plist/parser.rb
@@ -1,5 +1,5 @@
-#!/usr/bin/env ruby
-#
+# encoding: utf-8
+
# = plist
#
# Copyright 2006-2010 Ben Bleything and Patrick May
@@ -73,10 +73,10 @@ module Plist
end
TEXT = /([^<]+)/
- XMLDECL_PATTERN = /<\?xml\s+(.*?)\?>*/um
- DOCTYPE_PATTERN = /\s*<!DOCTYPE\s+(.*?)(\[|>)/um
- COMMENT_START = /\A<!--/u
- COMMENT_END = /.*?-->/um
+ XMLDECL_PATTERN = /<\?xml\s+(.*?)\?>*/m
+ DOCTYPE_PATTERN = /\s*<!DOCTYPE\s+(.*?)(\[|>)/m
+ COMMENT_START = /\A<!--/
+ COMMENT_END = /.*?-->/m
def parse
@@ -91,7 +91,14 @@ module Plist
if @scanner.scan(COMMENT_START)
@scanner.scan(COMMENT_END)
elsif @scanner.scan(XMLDECL_PATTERN)
+ encoding = parse_encoding_from_xml_declaration(@scanner[1])
+ next if encoding.nil?
+
+ # use the specified encoding for the rest of the file
+ next unless String.method_defined?(:force_encoding)
+ @scanner.string = @scanner.rest.force_encoding(encoding)
elsif @scanner.scan(DOCTYPE_PATTERN)
+ next
elsif @scanner.scan(start_tag)
@listener.tag_start(@scanner[1], nil)
if (@scanner[2] =~ /\/$/)
@@ -106,6 +113,22 @@ module Plist
end
end
end
+
+ private
+
+ def parse_encoding_from_xml_declaration(xml_declaration)
+ return unless defined?(Encoding)
+
+ xml_encoding = xml_declaration.match(/(?:\A|\s)encoding=(?:"(.*?)"|'(.*?)')(?:\s|\Z)/)
+
+ return if xml_encoding.nil?
+
+ begin
+ Encoding.find(xml_encoding[1])
+ rescue ArgumentError
+ nil
+ end
+ end
end
class PTag
@@ -213,7 +236,7 @@ module Plist
data = Base64.decode64(text.gsub(/\s+/, '')) unless text.nil?
begin
return Marshal.load(data)
- rescue Exception => e
+ rescue Exception
io = StringIO.new
io.write data
io.rewind
diff --git a/Library/Homebrew/vendor/plist/plist/version.rb b/Library/Homebrew/vendor/plist/plist/version.rb
new file mode 100755
index 000000000..80b1f73dd
--- /dev/null
+++ b/Library/Homebrew/vendor/plist/plist/version.rb
@@ -0,0 +1,5 @@
+# encoding: utf-8
+
+module Plist
+ VERSION = '3.3.0'.freeze
+end
diff --git a/Library/Homebrew/version.rb b/Library/Homebrew/version.rb
index b9f512a50..da239f788 100644
--- a/Library/Homebrew/version.rb
+++ b/Library/Homebrew/version.rb
@@ -316,6 +316,11 @@ class Version
spec.stem
end
+ # date-based versioning
+ # e.g. ltopers-v2017-04-14.tar.gz
+ m = /-v?(\d{4}-\d{2}-\d{2})/.match(stem)
+ return m.captures.first unless m.nil?
+
# GitHub tarballs
# e.g. https://github.com/foo/bar/tarball/v1.2.3
# e.g. https://github.com/sam-github/libnet/tarball/libnet-1.1.4
diff --git a/README.md b/README.md
index 47aa217cf..76434beae 100644
--- a/README.md
+++ b/README.md
@@ -32,22 +32,17 @@ We'd love you to contribute to Homebrew. First, please read our [Contribution Gu
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.
-A good starting point for contributing is running `brew audit --strict`with some of the packages you use (e.g. `brew audit --strict wget` if you use `wget`) and then read through the warnings, try to fix them until `brew audit --strict` shows no results and [submit a pull request](http://docs.brew.sh/How-To-Open-a-Homebrew-Pull-Request.html). If no formulae you use have warnings you can run `brew audit --strict` without arguments to have it run on all packages and pick one. Good luck!
+A good starting point for contributing is running `brew audit --strict` with some of the packages you use (e.g. `brew audit --strict wget` if you use `wget`) and then read through the warnings, try to fix them until `brew audit --strict` shows no results and [submit a pull request](http://docs.brew.sh/How-To-Open-a-Homebrew-Pull-Request.html). If no formulae you use have warnings you can run `brew audit --strict` without arguments to have it run on all packages and pick one. Good luck!
## Security
-Please report security issues to security@brew.sh.
-
-This is our PGP key which is valid until May 24, 2017.
-* Key ID: `0xE33A3D3CCE59E297`
-* Fingerprint: `C657 8F76 2E23 441E C879 EC5C E33A 3D3C CE59 E297`
-* Full key: https://keybase.io/homebrew/key.asc
+Please report security issues to our [HackerOne](https://hackerone.com/homebrew/).
## Who Are You?
Homebrew's lead maintainer is [Mike McQuaid](https://github.com/mikemcquaid).
Homebrew's current maintainers are [Alyssa Ross](https://github.com/alyssais), [Andrew Janke](https://github.com/apjanke), [Baptiste Fontaine](https://github.com/bfontaine), [Alex Dunn](https://github.com/dunn), [FX Coudert](https://github.com/fxcoudert), [ilovezfs](https://github.com/ilovezfs), [Josh Hagins](https://github.com/jawshooah), [JCount](https://github.com/jcount), [Misty De Meo](https://github.com/mistydemeo), [neutric](https://github.com/neutric), [Tomasz Pajor](https://github.com/nijikon), [Markus Reiter](https://github.com/reitermarkus), [Tim Smith](https://github.com/tdsmith), [Tom Schoonjans](https://github.com/tschoonj), [Uladzislau Shablinski](https://github.com/vladshablinsky) and [William Woodruff](https://github.com/woodruffw).
-Former maintainers with significant contributions include [Xu Cheng](https://github.com/xu-cheng), [Martin Afanasjew](https://github.com/UniqMartin), [Dominyk Tiller](https://github.com/DomT4), [Brett Koonce](https://github.com/asparagui), [Jack Nagel](https://github.com/jacknagel), [Adam Vandenberg](https://github.com/adamv) and Homebrew's creator: [Max Howell](https://github.com/mxcl).
+Former maintainers with significant contributions include [Xu Cheng](https://github.com/xu-cheng), [Martin Afanasjew](https://github.com/UniqMartin), [Dominyk Tiller](https://github.com/DomT4), [Brett Koonce](https://github.com/asparagui), [Charlie Sharpsteen](https://github.com/Sharpie), [Jack Nagel](https://github.com/jacknagel), [Adam Vandenberg](https://github.com/adamv) and Homebrew's creator: [Max Howell](https://github.com/mxcl).
## Community
- [discourse.brew.sh (forum)](https://discourse.brew.sh)
@@ -70,9 +65,7 @@ Our Xserve ESXi boxes for CI are hosted by [MacStadium](https://www.macstadium.c
[![Powered by MacStadium](https://cloud.githubusercontent.com/assets/125011/22776032/097557ac-eea6-11e6-8ba8-eff22dfd58f1.png)](https://www.macstadium.com)
-Our Mac Minis for CI were paid for by [our Kickstarter supporters](http://docs.brew.sh/Kickstarter-Supporters.html).
-
-Our Mac Minis for CI are hosted by [The Positive Internet Company](http://www.positive-internet.com).
+Our Jenkins CI installation is hosted by [DigitalOcean](https://m.do.co/c/7e39c35d5581).
Our bottles (binary packages) are hosted by [Bintray](https://bintray.com/homebrew).
diff --git a/bin/brew b/bin/brew
index 43a807c7b..90e0cf3e9 100755
--- a/bin/brew
+++ b/bin/brew
@@ -44,6 +44,20 @@ fi
HOMEBREW_LIBRARY="$HOMEBREW_REPOSITORY/Library"
+# Whitelist and copy to HOMEBREW_* all variables previously mentioned in
+# manpage or used elsewhere by Homebrew.
+for VAR in AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY BINTRAY_USER BINTRAY_KEY \
+ BROWSER EDITOR GIT PATH VISUAL
+do
+ # Skip if variable value is empty.
+ [[ -z "${!VAR}" ]] && continue
+
+ VAR_NEW="HOMEBREW_${VAR}"
+ # Skip if existing HOMEBREW_* variable is set.
+ [[ -n "${!VAR_NEW}" ]] && continue
+ export "$VAR_NEW"="${!VAR}"
+done
+
if [[ -n "$HOMEBREW_ENV_FILTERING" ]]
then
PATH="/usr/bin:/bin:/usr/sbin:/sbin"
diff --git a/docs/.well-known/acme-challenge/CgQNmjNTd6fUriinp4XpuRI5PBGp7zEXbEEsQceSD0k b/docs/.well-known/acme-challenge/CgQNmjNTd6fUriinp4XpuRI5PBGp7zEXbEEsQceSD0k
new file mode 100644
index 000000000..d3ba42ff4
--- /dev/null
+++ b/docs/.well-known/acme-challenge/CgQNmjNTd6fUriinp4XpuRI5PBGp7zEXbEEsQceSD0k
@@ -0,0 +1 @@
+CgQNmjNTd6fUriinp4XpuRI5PBGp7zEXbEEsQceSD0k.unNjkXuFqjKx4BO8gem4nzeMm1tSZxPPeBjNqQhFCqQ
diff --git a/docs/Acceptable-Formulae.md b/docs/Acceptable-Formulae.md
index d600a31a0..d59129ecc 100644
--- a/docs/Acceptable-Formulae.md
+++ b/docs/Acceptable-Formulae.md
@@ -80,12 +80,12 @@ useful to people. Just install the stuff! Having to faff around with
foo-ruby, foo-perl etc. sucks.
### Niche (or self-submitted) stuff
-The software in question must be:
+The software in question must:
-* maintained (e.g. upstream is still making new releases)
-* known
-* stable (e.g. not declared "unstable" or "beta" by upstream)
-* used
+* be maintained (e.g. upstream is still making new releases)
+* be known
+* be stable (e.g. not declared "unstable" or "beta" by upstream)
+* be used
* have a homepage
We will reject formulae that seem too obscure, partly because they won’t
@@ -93,7 +93,8 @@ get maintained and partly because we have to draw the line somewhere.
We frown on authors submitting their own work unless it is very popular.
-Don’t forget Homebrew is all Git underneath! Maintain your own tap if you have to!
+Don’t forget Homebrew is all Git underneath!
+[Maintain your own tap](How-to-Create-and-Maintain-a-Tap.md) if you have to!
There may be exceptions to these rules in the main repository; we may
include things that don't meet these criteria or reject things that do.
diff --git a/docs/Interesting-Taps-&-Forks.md b/docs/Interesting-Taps-&-Forks.md
index 54f6de25e..6b70fadec 100644
--- a/docs/Interesting-Taps-&-Forks.md
+++ b/docs/Interesting-Taps-&-Forks.md
@@ -15,7 +15,7 @@ Homebrew has the capability to add (and remove) multiple taps to your local inst
`brew search` looks in these taps as well as in [homebrew/core](https://github.com/Homebrew/homebrew-core) so don't worry about missing stuff.
-You can be added as a maintainer for one of the Homebrew organization taps and aid the project! If you are interested write to our list: homebrew-discuss@googlegroups.com. We want your help!
+You can be added as a maintainer for one of the Homebrew organization taps and aid the project! If you are interested please feel free to ask in an issue or pull request after submitting multiple high-quality pull requests. We want your help!
## Other interesting taps
diff --git a/docs/Manpage.md b/docs/Manpage.md
index 23e338213..2dac89443 100644
--- a/docs/Manpage.md
+++ b/docs/Manpage.md
@@ -402,7 +402,7 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note
If `--env=std` is passed, use the standard `PATH` instead of superenv's.
- * `style` [`--fix`] [`--display-cop-names`] [`files`|`taps`|`formulae`]:
+ * `style` [`--fix`] [`--display-cop-names`] [`--only-cops=`[COP1,COP2..]|`--except-cops=`[COP1,COP2..]] [`files`|`taps`|`formulae`]:
Check formulae or files for conformance to Homebrew style guidelines.
`formulae` and `files` may not be combined. If both are omitted, style will run
@@ -415,6 +415,10 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note
If `--display-cop-names` is passed, the RuboCop cop name for each violation
is included in the output.
+ If `--only-cops` is passed, only the given Rubocop cop(s)' violations would be checked.
+
+ If `--except-cops` is passed, the given Rubocop cop(s)' checks would be skipped.
+
Exits with a non-zero status if any style violations are found.
* `switch` `name` `version`:
@@ -606,7 +610,7 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note
## DEVELOPER COMMANDS
- * `audit` [`--strict`] [`--fix`] [`--online`] [`--new-formula`] [`--display-cop-names`] [`--display-filename`] [`formulae`]:
+ * `audit` [`--strict`] [`--fix`] [`--online`] [`--new-formula`] [`--display-cop-names`] [`--display-filename`] [`--only=``method`|`--except=``method`] [`--only-cops=`[COP1,COP2..]|`--except-cops=`[COP1,COP2..]] [`formulae`]:
Check `formulae` for Homebrew coding style violations. This should be
run before submitting a new formula.
@@ -631,6 +635,14 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note
If `--display-filename` is passed, every line of output is prefixed with the
name of the file or formula being audited, to make the output easy to grep.
+ If `--only` is passed, only the methods named `audit_`method`` will be run.
+
+ If `--except` is passed, the methods named `audit_`method`` will not be run.
+
+ If `--only-cops` is passed, only the given Rubocop cop(s)' violations would be checked.
+
+ If `--except-cops` is passed, the given Rubocop cop(s)' checks would be skipped.
+
`audit` exits with a non-zero status if any errors are found. This is useful,
for instance, for implementing pre-commit hooks.
@@ -709,7 +721,8 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note
If `--meson` is passed, create a basic template for a Meson-style build.
If `--no-fetch` is passed, Homebrew will not download `URL` to the cache and
- will thus not add the SHA256 to the formula for you.
+ will thus not add the SHA256 to the formula for you. It will also not check
+ the GitHub API for GitHub projects (to fill out the description and homepage).
The options `--set-name` and `--set-version` each take an argument and allow
you to explicitly set the name and version of the package you are creating.
@@ -897,8 +910,15 @@ can take several different forms:
The formula file will be cached for later use.
## ENVIRONMENT
+ * `HOMEBREW_ARTIFACT_DOMAIN`:
+ If set, instructs Homebrew to use the given URL as a download mirror for bottles and binaries.
- * `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`:
+ * `HOMEBREW_AUTO_UPDATE_SECS`:
+ If set, Homebrew will only check for autoupdates once per this seconds interval.
+
+ *Default:* `60`.
+
+ * `HOMEBREW_AWS_ACCESS_KEY_ID`, `HOMEBREW_AWS_SECRET_ACCESS_KEY`:
When using the `S3` download strategy, Homebrew will look in
these variables for access credentials (see
<https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html#cli-environment>
@@ -906,30 +926,9 @@ can take several different forms:
the `S3` download strategy will download with a public
(unsigned) URL.
- * `BROWSER`:
- If set, and `HOMEBREW_BROWSER` is not, use `BROWSER` as the web browser
- when opening project homepages.
-
- * `EDITOR`:
- If set, and `HOMEBREW_EDITOR` and `VISUAL` are not, use `EDITOR` as the text editor.
-
- * `GIT`:
- When using Git, Homebrew will use `GIT` if set,
- a Homebrew-built Git if installed, or the system-provided binary.
-
- Set this to force Homebrew to use a particular git binary.
-
* `HOMEBREW_BOTTLE_DOMAIN`:
If set, instructs Homebrew to use the given URL as a download mirror for bottles.
- * `HOMEBREW_ARTIFACT_DOMAIN`:
- If set, instructs Homebrew to use the given URL as a download mirror for bottles and binaries.
-
- * `HOMEBREW_AUTO_UPDATE_SECS`:
- If set, Homebrew will only check for autoupdates once per this seconds interval.
-
- *Default:* `60`.
-
* `HOMEBREW_BROWSER`:
If set, uses this setting as the browser when opening project homepages,
instead of the OS default browser.
@@ -977,6 +976,12 @@ can take several different forms:
If set, Homebrew will always use its vendored, relocatable Ruby 2.0 version
even if the system version of Ruby is >=2.0.
+ * `HOMEBREW_GIT`:
+ When using Git, Homebrew will use `GIT` if set,
+ a Homebrew-built Git if installed, or the system-provided binary.
+
+ Set this to force Homebrew to use a particular git binary.
+
* `HOMEBREW_GITHUB_API_TOKEN`:
A personal access token for the GitHub API, which you can create at
<https://github.com/settings/tokens>. If set, GitHub will allow you a
@@ -1042,9 +1047,6 @@ can take several different forms:
* `HOMEBREW_VERBOSE`:
If set, Homebrew always assumes `--verbose` when running commands.
- * `VISUAL`:
- If set, and `HOMEBREW_EDITOR` is not, use `VISUAL` as the text editor.
-
## USING HOMEBREW BEHIND A PROXY
Homebrew uses several commands for downloading files (e.g. `curl`, `git`, `svn`).
@@ -1072,7 +1074,7 @@ Homebrew's lead maintainer is Mike McQuaid.
Homebrew's current maintainers are Alyssa Ross, Andrew Janke, Baptiste Fontaine, Alex Dunn, FX Coudert, ilovezfs, Josh Hagins, JCount, Misty De Meo, neutric, Tomasz Pajor, Markus Reiter, Tim Smith, Tom Schoonjans, Uladzislau Shablinski and William Woodruff.
-Former maintainers with significant contributions include Xu Cheng, Martin Afanasjew, Dominyk Tiller, Brett Koonce, Jack Nagel, Adam Vandenberg and Homebrew's creator: Max Howell.
+Former maintainers with significant contributions include Xu Cheng, Martin Afanasjew, Dominyk Tiller, Brett Koonce, Charlie Sharpsteen, Jack Nagel, Adam Vandenberg and Homebrew's creator: Max Howell.
## BUGS
diff --git a/docs/Python-for-Formula-Authors.md b/docs/Python-for-Formula-Authors.md
index d3e7543db..ea86cf84c 100644
--- a/docs/Python-for-Formula-Authors.md
+++ b/docs/Python-for-Formula-Authors.md
@@ -143,7 +143,7 @@ def install
%w[six parsedatetime].each do |r|
venv.pip_install resource(r)
end
- venv.link_scripts(bin) { venv.pip_install buildpath }
+ venv.pip_install_and_link buildpath
end
```
diff --git a/docs/Troubleshooting.md b/docs/Troubleshooting.md
index 180dac1fd..2ffa256d1 100644
--- a/docs/Troubleshooting.md
+++ b/docs/Troubleshooting.md
@@ -13,12 +13,11 @@ Follow these steps to fix common problems:
* Check that **Command Line Tools for Xcode (CLT)** and **Xcode** are up to date.
* If commands fail with permissions errors, check the permissions of `/usr/local`'s subdirectories. If you’re unsure what to do, you can run `cd /usr/local && sudo chown -R $(whoami) bin etc include lib sbin share var Frameworks`.
* Read through the [Common Issues](Common-Issues.md).
-* If you’re installing something Java-related, make sure you have installed Java (you can run `brew cask install java`).
## Check to see if the issue has been reported
* Search the [issue tracker](https://github.com/Homebrew/homebrew-core/issues) to see if someone else has already reported the same issue.
-* Make sure you search issues on the correct repository. If a formula that has failed to build is part of a tap like [homebrew/science](https://github.com/Homebrew/homebrew-science/issues) or [homebrew/dupes](https://github.com/Homebrew/homebrew-dupes/issues) check those issue trackers instead.
+* Make sure you search issues on the correct repository. If a formula that has failed to build is part of a tap like [homebrew/science](https://github.com/Homebrew/homebrew-science/issues) or a cask is part of [caskroom/cask](https://github.com/caskroom/homebrew-cask/issues) check those issue trackers instead.
## Create an issue
diff --git a/docs/Xcode.md b/docs/Xcode.md
index 759bf63c4..7c2cca5c8 100644
--- a/docs/Xcode.md
+++ b/docs/Xcode.md
@@ -12,7 +12,7 @@ Tools available for your platform:
| 10.9 | 6.2 | 6.2 |
| 10.10 | 7.2.1 | 7.2 |
| 10.11 | 8.2.1 | 8.2 |
-| 10.12 | 8.3 | 8.3 |
+| 10.12 | 8.3.2 | 8.3 |
## Compiler version database
@@ -70,6 +70,8 @@ Tools available for your platform:
| 8.2 | β€” | β€” | β€” | β€” | 8.0 (800.0.42.1)| β€” |
| 8.2.1 | β€” | β€” | β€” | β€” | 8.0 (800.0.42.1)| β€” |
| 8.3 | β€” | β€” | β€” | β€” | 8.1 (802.0.38) | β€” |
+| 8.3.1 | β€” | β€” | β€” | β€” | 8.1 (802.0.41) | β€” |
+| 8.3.2 | β€” | β€” | β€” | β€” | 8.1 (802.0.42) | β€” |
## References to Xcode and compiler versions in code
When a new Xcode release is made, the following things need to be
diff --git a/docs/_config.yml b/docs/_config.yml
index dce1f3bd3..2bdba509e 100644
--- a/docs/_config.yml
+++ b/docs/_config.yml
@@ -1,3 +1,4 @@
+include: [.well-known]
exclude: [bin, vendor, CNAME, Gemfile, Gemfile.lock]
gems:
diff --git a/docs/_layouts/index.html b/docs/_layouts/index.html
index 570718287..daf4fb6c0 100644
--- a/docs/_layouts/index.html
+++ b/docs/_layouts/index.html
@@ -1,7 +1,7 @@
---
layout: base
---
-<div id="informations">
+<div id="information">
<ul>
<li>
<div class="group row">
diff --git a/docs/css/reset.css b/docs/css/reset.css
deleted file mode 100644
index 1c85489d6..000000000
--- a/docs/css/reset.css
+++ /dev/null
@@ -1,53 +0,0 @@
-/* http://meyerweb.com/eric/tools/css/reset/ */
-/* v1.0 | 20080212 */
-
-html, body, div, span, applet, object, iframe,
-h1, h2, h3, h4, h5, h6, p, blockquote, pre,
-a, abbr, acronym, address, big, cite, code,
-del, dfn, em, font, img, ins, kbd, q, s, samp,
-small, strike, strong, sub, sup, tt, var,
-b, u, i, center,
-dl, dt, dd, ol, ul, li,
-fieldset, form, label, legend,
-table, caption, tbody, tfoot, thead, tr, th, td {
- margin: 0;
- padding: 0;
- border: 0;
- outline: 0;
- font-size: 100%;
- vertical-align: baseline;
- background: transparent;
-}
-body {
- line-height: 1;
-}
-ol, ul {
- list-style: none;
-}
-blockquote, q {
- quotes: none;
-}
-blockquote:before, blockquote:after,
-q:before, q:after {
- content: '';
- content: none;
-}
-
-/* remember to define focus styles! */
-:focus {
- outline: 0;
-}
-
-/* remember to highlight inserts somehow! */
-ins {
- text-decoration: none;
-}
-del {
- text-decoration: line-through;
-}
-
-/* tables still need 'cellspacing="0"' in the markup */
-table {
- border-collapse: collapse;
- border-spacing: 0;
-}
diff --git a/docs/css/screen.css b/docs/css/screen.css
deleted file mode 100644
index 2f1e84ce1..000000000
--- a/docs/css/screen.css
+++ /dev/null
@@ -1,362 +0,0 @@
-/* ****************************************************
-
- @file screen.css
- @description Screen stylesheet
- vim: set noet ts=4 fdm=marker fenc=utf-8:
-
-***************************************************** */
-
-@import url("./reset.css");
-
-/* @section Basic {{{
-******************************************************************************/
-
-html {
- font-size: 62.5%;
- font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "Roboto", sans-serif;
-}
-
-html, body { height: 100%; }
-
-body {
- font-size: 150%;
- line-height: 1.4;
- color: #F9D094;
- background: #2E2A24;
- position: relative;
- behavior: url("/js/ie6/csshover.htc");
- padding: 0 30px;
-}
-
-p,ul,ol,dl,table,pre { margin-bottom: 1em; }
-ul { margin-left: 20px; }
-a { text-decoration: none; cursor: pointer; color: #ba832c; font-weight: bold; }
-a:focus { outline: 1px dotted; }
-a:visited { }
-a:hover, a:focus { color: #d3a459; text-decoration: none; }
-a *, button * { cursor: pointer; }
-hr { display: none; }
-small { font-size: 90%; }
-input, select, button, textarea, option { font-size: 100%; }
-button, label, select, option, input[type=submit] { cursor: pointer; }
-.group:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } .group {display: inline-block;}
-/* Hides from IE-mac \*/ * html .group {height: 1%;} .group {display: block;} /* End hide from IE-mac */
-sup { font-size: 80%; line-height: 1; vertical-align: super; }
-button::-moz-focus-inner { border: 0; padding: 1px; }
-span.amp { font-weight: normal; font-style: italic; font-size: 1.2em; line-height: 0.8; }
-h1,h2,h3,h4,h5,h6 { line-height: 1.1; }
-
-::selection { background: #745626; }
-::-moz-selection { background: #745626; }
-
-h1, h2, h3 {
- font-size: 420%;
- margin: 0 0 0.1em;
- font-weight: 900;
- text-shadow: 1px 1px 10px rgba(0,0,0,0.25);
-}
-
-h2 {
- font-size: 300%;
- text-align: center;
- font-weight: 800;
- color: #F9D094;
- margin-top: 0.5em;
- margin-bottom: 0.1em;
-}
-
-h3 {
- font-size: 125%;
- text-align: center;
- font-weight: 800;
- color: #F9D094;
- margin-top: 0.5em;
- margin-bottom: 0.1em;
-}
-
-#forkme {
- width: 149px;
- height: 149px;
- position: absolute;
- top: 0;
- right: 0;
- border: 0
-}
-
-h1 a,
-h1 a:hover {
- color: #F9D094;
- font-weight: 900;
- text-decoration: none;
-}
-
-#wrap {
- width: 57em;
- /*width: 760px;*/
- max-width: 100%;
- margin: 0 auto;
- padding: 15px 0 0;
-}
-
-#header {
- text-align: center;
- margin-bottom: 1em;
-}
-
-#language {
- margin-bottom: 2em;
-}
-
-pre {
- background: rgba(0,0,0,0.3);
- color: #fff;
- padding: 8px 10px;
- border-radius: 0.4em;
- -moz-border-radius: 0.4em;
- -webkit-border-radius: 0.4em;
- overflow-x: auto;
-}
-
-pre code {
- font-family: "Monaco", "Menlo", monospace;
- font-size: 11px;
- line-height: 1.6;
-}
-
-#selectable {
- font-size: 13px;
-}
-
-.avatar {
- border-radius: 0.4em;
- overflow: hidden;
- margin-right: 0.5em;
- vertical-align: middle;
-}
-
-#home, #page, .postcontent {
- font-size: 1.2em;
- min-width: 25em;
- max-width: 35em;
- margin: 0 auto;
- margin-top: 1em;
- padding-top: 1em;
- padding-bottom: 1em;
-}
-
-#home img, #page img, .postcontent img {
- min-width: 25em;
- max-width: 35em;
-}
-
-#home th, #page th, .postcontent th, #home td, #page td, .postcontent td {
- padding: 0.25em 0.5em;
-}
-
-#post, #home, #page, .singlepostcontent, .posts li {
- border-top: 1px solid rgba(255,255,255,0.08);
- box-shadow: 0 -1px 0 rgba(0,0,0,0.5);
-}
-
-#home ol, #page ol, .postcontent ol {
- list-style: decimal;
-}
-
-#home ul, #page ul, .postcontent ul {
- list-style: disc;
-}
-
-#home h1, #page h1 {
- font-size: 250%;
- font-weight: 800;
- text-align: center;
- padding-bottom: 0.5em;
-}
-
-#home h2, #page h2 {
- font-size: 175%;
- font-weight: 700;
- text-align: left;
- padding-bottom: 0.3em;
-}
-
-#home h3, #page h3 {
- font-size: 150%;
- font-weight: 700;
- text-align: left;
- padding-bottom: 0.3em;
-}
-
-#home code, #page code {
- font-size: 100%;
-}
-
-#home pre code, #page pre code {
- font-size: 80%;
-}
-
-/*}}}*/
-
-/* @section Informations {{{
-******************************************************************************/
-
-#informations {
- border-top: 1px solid rgba(0,0,0,0.5);
-}
-
-#informations ul {
- margin: 0;
-}
-
-#informations .row, #border-bottom {
- border-bottom: 1px solid rgba(0,0,0,0.5);
- border-top: 1px solid rgba(255,255,255,0.08);
- padding: 2em 20px 0;
-}
-
-#informations .row .col-1 {
- width: 49%;
- float: left;
- padding: 0 0 1em;
-}
-
-#informations .row .col-2 {
- width: 49%;
- float: right;
- padding: 0 0 1em;
-}
-
-@media screen and (min-width: 700px) {
- #informations .highlight {
- margin-inline-end: 0;
- -moz-margin-end: 0;
- -webkit-margin-end: 0;
- }
-}
-
-.button {
- text-align: center;
- margin: 1em 0 2em;
-}
-
-#informations .button a {
- background: rgba(162,107,20,0.3);
- padding: 8px 10px 6px;
- border-radius: 0.4em;
- -moz-border-radius: 0.4em;
- -webkit-border-radius: 0.4em;
- box-shadow: 0 0 5px rgba(0,0,0,0.4);
- -moz-box-shadow: 0 0 5px rgba(0,0,0,0.4);
- -webkit-box-shadow: 0 0 5px rgba(0,0,0,0.4);
- text-decoration: none;
- font-size: larger;
-}
-
-#informations .button a:hover {
- background: rgba(162,107,20,0.25);
-}
-
-#informations .button-large {
- padding: 2em 0 1em;
- font-size: 120%;
-}
-
-#informations .quote {
- text-align: center;
- color: #816f51;
- padding-bottom: 2em;
-}
-
-#informations .quote blockquote {
- font-size: 140%;
- padding: 0 15%;
-}
-
-#informations .quote blockquote span {
- font-size: 140%;
- line-height: 0.5;
- vertical-align: sub;
-}
-
-#informations .quote cite {
- font-style: normal;
-}
-
-#informations .quote cite a {
- font-weight: normal;
-}
-
-#informations .credits, #border-no-bottom {
- border-bottom: none;
- font-size: 70%;
- text-align: center;
- padding-top: 1.8em;
- opacity: 0.5;
-}
-
-#informations .credits p {
- margin: 0;
- padding: 0 0 0.7em;
-}
-
-/*}}}*/
-
-/* @section Mobile {{{
-******************************************************************************/
-@media screen and (max-width: 700px) {
- body {
- padding: 0px;
- }
-
- h1 {
- font-size: 350%;
- }
-
- h2 {
- font-size: 250%;
- }
-
- #forkme {
- width: 100px;
- height: 100px;
- }
-
- #informations .row .col-1 {
- width: 100%;
- padding: 0;
- margin: 0;
- }
-
- #informations .row .col-2 {
- width: 100%;
- float: left;
- }
- pre code#selectable {
- width: 90%;
- margin: 0 auto;
- }
-}
-/*}}}*/
-
-/* @section RTL {{{
-******************************************************************************/
-[dir="rtl"] ul { margin-left: 0; margin-right: 20px; }
-
-[dir="rtl"] pre {
- direction: ltr;
- text-align: left;
-}
-
-[dir="rtl"] #informations .row .col-1 {
- float: right;
-}
-
-[dir="rtl"] #informations .row .col-2 {
- float: left;
-}
-
-@media screen and (max-width: 700px) {
- [dir="rtl"] #informations .row .col-2 {
- float: right;
- }
-}
diff --git a/docs/css/screen.scss b/docs/css/screen.scss
new file mode 100644
index 000000000..5acdf4657
--- /dev/null
+++ b/docs/css/screen.scss
@@ -0,0 +1,488 @@
+---
+---
+
+$color_peach_orange_approx: #f9d094;
+$color_rangitoto_approx: #2e2a24;
+$color_marigold_approx: #ba832c;
+$color_di_serria_approx: #d3a459;
+$color_dallas_approx: #745626;
+$black_25: rgba(0, 0, 0, 0.25);
+$black_30: rgba(0, 0, 0, 0.3);
+$white: #fff;
+$white_8: rgba(255, 255, 255, 0.08);
+$black_50: rgba(0, 0, 0, 0.5);
+$black_40: rgba(0, 0, 0, 0.4);
+$black_20: rgba(0, 0, 0, 0.2);
+$color_reno_sand_30_approx: rgba(162, 107, 20, 0.3);
+$color_reno_sand_25_approx: rgba(162, 107, 20, 0.25);
+$color_shadow_approx: #816f51;
+
+@mixin border-radius($radius) {
+ border-radius: $radius;
+ -moz-border-radius: $radius;
+ -webkit-border-radius: $radius;
+}
+
+@mixin box-shadow($x, $y, $blur, $color) {
+ box-shadow: $x $y $blur $color;
+ -moz-box-shadow: $x $y $blur $color;
+ -webkit-box-shadow: $x $y $blur $color;
+}
+
+@mixin margin-inline-end($margin) {
+ margin-inline-end: $margin;
+ -moz-margin-end: $margin;
+ -webkit-margin-end: $margin;
+}
+
+h1, h2, h3 {
+ font-size: 420%;
+ color: $color_peach_orange_approx;
+ margin: 0 0 0.1em;
+ text-align: center;
+ text-shadow: 1px 1px 10px $black_25;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ line-height: 1.1;
+}
+
+h1 {
+ font-weight: 900;
+ a, a:hover {
+ font-weight: 900;
+ color: $color_peach_orange_approx;
+ }
+}
+
+h2, h3 {
+ font-weight: 800;
+ margin-top: 0.5em;
+ margin-bottom: 0.1em;
+}
+
+h2 {
+ font-size: 300%;
+}
+
+h3 {
+ font-size: 125%;
+}
+
+#home, #page {
+ h1 {
+ font-size: 250%;
+ font-weight: 800;
+ padding-bottom: 0.5em;
+ }
+
+ h2, h3 {
+ font-weight: 700;
+ text-align: left;
+ padding-bottom: 0.3em;
+ }
+
+ h2 {
+ font-size: 175%;
+ }
+
+ h3 {
+ font-size: 150%;
+ }
+}
+
+#home, #page, .postcontent {
+ font-size: 1.2em;
+ min-width: 25em;
+ max-width: 35em;
+ margin: 0 auto;
+ margin-top: 1em;
+ padding-top: 1em;
+ padding-bottom: 1em;
+}
+
+#information .row, #border-bottom {
+ border-bottom: 1px solid $black_50;
+ border-top: 1px solid $white_8;
+ padding: 2em 20px 0;
+}
+
+html {
+ margin: 0;
+ padding: 0;
+ font-size: 62.5%;
+ font-family: "-apple-system", "BlinkMacSystemFont", "Helvetica Neue", "Roboto", "sans-serif";
+ height: 100%;
+}
+
+body {
+ height: 100%;
+ font-size: 150%;
+ line-height: 1.4;
+ color: $color_peach_orange_approx;
+ background: $color_rangitoto_approx;
+ position: relative;
+ margin: 0;
+ padding: 0 30px;
+}
+
+p {
+ margin: 0 0 1em 0;
+}
+
+ul, ol, dl {
+ margin-bottom: 1em;
+}
+
+ul {
+ margin-left: 20px;
+}
+
+table {
+ margin-bottom: 1em;
+ border-collapse: separate;
+ border-spacing: 0;
+ border: solid $black_40 1px;
+ @include border-radius(0.4em);
+ margin-top: 1em;
+ td {
+ padding: 0.1em 1em;
+ }
+
+ code {
+ font-size: 130%;
+ }
+
+ tr {
+ &:nth-child(odd) {
+ background: $black_20;
+ }
+
+ th {
+ background: $black_40;
+ }
+
+ &:nth-child(even) {
+ background: $black_40;
+ }
+ }
+}
+
+pre {
+ margin: 0 0 1em 0;
+ background: $black_30;
+ color: $white;
+ padding: 8px 10px;
+ @include border-radius(0.4em);
+ overflow-x: auto;
+ code {
+ font-family: "Monaco", "Menlo", "monospace";
+ font-size: 11px;
+ line-height: 1.6;
+ }
+}
+
+a {
+ text-decoration: none;
+ color: $color_marigold_approx;
+ font-weight: bold;
+ &:focus {
+ outline: 1px dotted;
+ color: $color_di_serria_approx;
+ text-decoration: underline;
+ }
+
+ &:hover {
+ color: $color_di_serria_approx;
+ text-decoration: underline;
+ }
+}
+
+button, input, select, textarea, option {
+ font-size: 100%;
+}
+
+a, a *, button, button *, select, option, label, input[type=submit] {
+ cursor: pointer;
+}
+
+hr {
+ display: none;
+}
+
+small {
+ font-size: 90%;
+}
+
+.group {
+ display: block;
+ &:after {
+ content: ".";
+ display: block;
+ height: 0;
+ clear: both;
+ visibility: hidden;
+ }
+}
+
+sup {
+ font-size: 80%;
+ line-height: 1;
+ vertical-align: super;
+}
+
+button::-moz-focus-inner {
+ border: 0;
+ padding: 1px;
+}
+
+::selection, ::-moz-selection {
+ background: $color_dallas_approx;
+}
+
+#forkme {
+ width: 149px;
+ height: 149px;
+ position: absolute;
+ top: 0;
+ right: 0;
+ border: 0;
+}
+
+#wrap {
+ width: 57em;
+ max-width: 100%;
+ margin: 0 auto;
+ padding: 15px 0 0;
+}
+
+#header {
+ text-align: center;
+ margin-bottom: 1em;
+}
+
+#language {
+ margin-bottom: 2em;
+}
+
+#selectable {
+ font-size: 13px;
+}
+
+.avatar {
+ @include border-radius(0.4em);
+ overflow: hidden;
+ margin-right: 0.5em;
+ vertical-align: middle;
+}
+
+#home, #page, #post, .singlepostcontent {
+ border-top: 1px solid $white_8;
+ @include box-shadow(0, -1px, 0, $black_50);
+}
+
+#home, #page {
+ code {
+ font-size: 100%;
+ }
+
+ pre code {
+ font-size: 80%;
+ }
+}
+
+#home, #page, .postcontent {
+ img {
+ min-width: 25em;
+ max-width: 35em;
+ }
+
+ th, td {
+ padding: 0.25em 0.5em;
+ }
+}
+
+.full-width {
+ width: 100%;
+}
+
+th {
+ padding: 0.1em 1em;
+}
+
+.number-data {
+ text-align: right;
+}
+
+#information ul, .posts {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+#information {
+ border-top: 1px solid $black_50;
+ .row {
+ .col-1 {
+ width: 49%;
+ float: left;
+ padding: 0 0 1em;
+ }
+
+ .col-2 {
+ width: 49%;
+ float: right;
+ padding: 0 0 1em;
+ }
+ }
+
+ .button-large {
+ padding: 2em 0 1em;
+ font-size: 120%;
+ }
+
+ .quote {
+ text-align: center;
+ color: $color_shadow_approx;
+ padding-bottom: 2em;
+ blockquote {
+ font-size: 140%;
+ padding: 0 15%;
+ span {
+ font-size: 140%;
+ line-height: 0.5;
+ vertical-align: sub;
+ }
+ }
+
+ cite {
+ font-style: normal;
+ a {
+ font-weight: normal;
+ }
+ }
+ }
+
+ .credits {
+ border-bottom: none;
+ font-size: 70%;
+ text-align: center;
+ padding-top: 1.8em;
+ opacity: 0.5;
+ p {
+ margin: 0;
+ padding: 0 0 0.7em;
+ }
+ }
+ .button a {
+ background: $color_reno_sand_30_approx;
+ padding: 8px 10px 6px;
+ @include border-radius(0.4em);
+ @include box-shadow(0, 0, 5px, $black_40);
+ font-size: larger;
+ &:hover {
+ background: $color_reno_sand_25_approx;
+ }
+ }
+}
+
+.button {
+ text-align: center;
+ margin: 1em 0 2em;
+}
+
+#border-no-bottom {
+ border-bottom: none;
+ font-size: 70%;
+ text-align: center;
+ padding-top: 1.8em;
+ opacity: 0.5;
+}
+
+* html .group {
+ height: 1%;
+}
+
+span .amp {
+ font-weight: normal;
+ font-style: italic;
+ font-size: 1.2em;
+ line-height: 0.8;
+}
+
+.posts li {
+ border-top: 1px solid $white_8;
+ @include box-shadow(0, -1px, 0, $black_50);
+}
+
+[dir="rtl"] {
+ ul {
+ margin-left: 0;
+ margin-right: 20px;
+ }
+
+ pre {
+ direction: ltr;
+ text-align: left;
+ }
+
+ #information .row {
+ .col-1 {
+ float: right;
+ }
+ .col-2 {
+ float: left;
+ }
+ }
+}
+
+@media screen and(min-width: 700px) {
+ #information .highlight {
+ @include margin-inline-end(0);
+ }
+}
+
+@media screen and(max-width: 700px) {
+ body {
+ padding: 0;
+ }
+
+ #post, #page, .posts {
+ margin: 0 1em;
+ }
+
+ h1 {
+ font-size: 350%;
+ }
+
+ h2 {
+ font-size: 250%;
+ }
+
+ #forkme {
+ width: 100px;
+ height: 100px;
+ }
+
+ #information .row {
+ .col-1 {
+ width: 100%;
+ padding: 0;
+ margin: 0;
+ }
+
+ .col-2 {
+ width: 100%;
+ float: left;
+ }
+ }
+
+ pre code#selectable {
+ width: 90%;
+ margin: 0 auto;
+ }
+
+ [dir="rtl"] #information .row .col-2 {
+ float: right;
+ }
+}
diff --git a/manpages/brew-cask.1 b/manpages/brew-cask.1
index e45824927..bde8ff3c2 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" "April 2017" "Homebrew" "brew-cask"
+.TH "BREW\-CASK" "1" "May 2017" "Homebrew" "brew-cask"
.
.SH "NAME"
\fBbrew\-cask\fR \- a friendly binary installer for macOS
diff --git a/manpages/brew.1 b/manpages/brew.1
index 6c30b60cf..ca11439a6 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" "April 2017" "Homebrew" "brew"
+.TH "BREW" "1" "May 2017" "Homebrew" "brew"
.
.SH "NAME"
\fBbrew\fR \- The missing package manager for macOS
@@ -415,7 +415,7 @@ Start a Homebrew build environment shell\. Uses our years\-battle\-hardened Home
If \fB\-\-env=std\fR is passed, use the standard \fBPATH\fR instead of superenv\'s\.
.
.TP
-\fBstyle\fR [\fB\-\-fix\fR] [\fB\-\-display\-cop\-names\fR] [\fIfiles\fR|\fItaps\fR|\fIformulae\fR]
+\fBstyle\fR [\fB\-\-fix\fR] [\fB\-\-display\-cop\-names\fR] [\fB\-\-only\-cops=\fR[COP1,COP2\.\.]|\fB\-\-except\-cops=\fR[COP1,COP2\.\.]] [\fIfiles\fR|\fItaps\fR|\fIformulae\fR]
Check formulae or files for conformance to Homebrew style guidelines\.
.
.IP
@@ -428,6 +428,12 @@ If \fB\-\-fix\fR is passed, style violations will be automatically fixed using R
If \fB\-\-display\-cop\-names\fR is passed, the RuboCop cop name for each violation is included in the output\.
.
.IP
+If \fB\-\-only\-cops\fR is passed, only the given Rubocop cop(s)\' violations would be checked\.
+.
+.IP
+If \fB\-\-except\-cops\fR is passed, the given Rubocop cop(s)\' checks would be skipped\.
+.
+.IP
Exits with a non\-zero status if any style violations are found\.
.
.TP
@@ -631,7 +637,7 @@ Print the version number of Homebrew to standard output and exit\.
.SH "DEVELOPER COMMANDS"
.
.TP
-\fBaudit\fR [\fB\-\-strict\fR] [\fB\-\-fix\fR] [\fB\-\-online\fR] [\fB\-\-new\-formula\fR] [\fB\-\-display\-cop\-names\fR] [\fB\-\-display\-filename\fR] [\fIformulae\fR]
+\fBaudit\fR [\fB\-\-strict\fR] [\fB\-\-fix\fR] [\fB\-\-online\fR] [\fB\-\-new\-formula\fR] [\fB\-\-display\-cop\-names\fR] [\fB\-\-display\-filename\fR] [\fB\-\-only=\fR\fImethod\fR|\fB\-\-except=\fR\fImethod\fR] [\fB\-\-only\-cops=\fR[COP1,COP2\.\.]|\fB\-\-except\-cops=\fR[COP1,COP2\.\.]] [\fIformulae\fR]
Check \fIformulae\fR for Homebrew coding style violations\. This should be run before submitting a new formula\.
.
.IP
@@ -656,6 +662,18 @@ If \fB\-\-display\-cop\-names\fR is passed, the RuboCop cop name for each violat
If \fB\-\-display\-filename\fR is passed, every line of output is prefixed with the name of the file or formula being audited, to make the output easy to grep\.
.
.IP
+If \fB\-\-only\fR is passed, only the methods named \fBaudit_<method>\fR will be run\.
+.
+.IP
+If \fB\-\-except\fR is passed, the methods named \fBaudit_<method>\fR will not be run\.
+.
+.IP
+If \fB\-\-only\-cops\fR is passed, only the given Rubocop cop(s)\' violations would be checked\.
+.
+.IP
+If \fB\-\-except\-cops\fR is passed, the given Rubocop cop(s)\' checks would be skipped\.
+.
+.IP
\fBaudit\fR exits with a non\-zero status if any errors are found\. This is useful, for instance, for implementing pre\-commit hooks\.
.
.TP
@@ -729,7 +747,7 @@ Generate a formula for the downloadable file at \fIURL\fR and open it in the edi
If \fB\-\-autotools\fR is passed, create a basic template for an Autotools\-style build\. If \fB\-\-cmake\fR is passed, create a basic template for a CMake\-style build\. If \fB\-\-meson\fR is passed, create a basic template for a Meson\-style build\.
.
.IP
-If \fB\-\-no\-fetch\fR is passed, Homebrew will not download \fIURL\fR to the cache and will thus not add the SHA256 to the formula for you\.
+If \fB\-\-no\-fetch\fR is passed, Homebrew will not download \fIURL\fR to the cache and will thus not add the SHA256 to the formula for you\. It will also not check the GitHub API for GitHub projects (to fill out the description and homepage)\.
.
.IP
The options \fB\-\-set\-name\fR and \fB\-\-set\-version\fR each take an argument and allow you to explicitly set the name and version of the package you are creating\.
@@ -923,29 +941,6 @@ Homebrew can install formulae via URL, e\.g\. \fBhttps://raw\.github\.com/Homebr
.SH "ENVIRONMENT"
.
.TP
-\fBAWS_ACCESS_KEY_ID\fR, \fBAWS_SECRET_ACCESS_KEY\fR
-When using the \fBS3\fR download strategy, Homebrew will look in these variables for access credentials (see \fIhttps://docs\.aws\.amazon\.com/cli/latest/userguide/cli\-chap\-getting\-started\.html#cli\-environment\fR to retrieve these access credentials from AWS)\. If they are not set, the \fBS3\fR download strategy will download with a public (unsigned) URL\.
-.
-.TP
-\fBBROWSER\fR
-If set, and \fBHOMEBREW_BROWSER\fR is not, use \fBBROWSER\fR as the web browser when opening project homepages\.
-.
-.TP
-\fBEDITOR\fR
-If set, and \fBHOMEBREW_EDITOR\fR and \fBVISUAL\fR are not, use \fBEDITOR\fR as the text editor\.
-.
-.TP
-\fBGIT\fR
-When using Git, Homebrew will use \fBGIT\fR if set, a Homebrew\-built Git if installed, or the system\-provided binary\.
-.
-.IP
-Set this to force Homebrew to use a particular git binary\.
-.
-.TP
-\fBHOMEBREW_BOTTLE_DOMAIN\fR
-If set, instructs Homebrew to use the given URL as a download mirror for bottles\.
-.
-.TP
\fBHOMEBREW_ARTIFACT_DOMAIN\fR
If set, instructs Homebrew to use the given URL as a download mirror for bottles and binaries\.
.
@@ -957,6 +952,14 @@ If set, Homebrew will only check for autoupdates once per this seconds interval\
\fIDefault:\fR \fB60\fR\.
.
.TP
+\fBHOMEBREW_AWS_ACCESS_KEY_ID\fR, \fBHOMEBREW_AWS_SECRET_ACCESS_KEY\fR
+When using the \fBS3\fR download strategy, Homebrew will look in these variables for access credentials (see \fIhttps://docs\.aws\.amazon\.com/cli/latest/userguide/cli\-chap\-getting\-started\.html#cli\-environment\fR to retrieve these access credentials from AWS)\. If they are not set, the \fBS3\fR download strategy will download with a public (unsigned) URL\.
+.
+.TP
+\fBHOMEBREW_BOTTLE_DOMAIN\fR
+If set, instructs Homebrew to use the given URL as a download mirror for bottles\.
+.
+.TP
\fBHOMEBREW_BROWSER\fR
If set, uses this setting as the browser when opening project homepages, instead of the OS default browser\.
.
@@ -1003,6 +1006,13 @@ If set, Homebrew will use this editor when editing a single formula, or several
If set, Homebrew will always use its vendored, relocatable Ruby 2\.0 version even if the system version of Ruby is >=2\.0\.
.
.TP
+\fBHOMEBREW_GIT\fR
+When using Git, Homebrew will use \fBGIT\fR if set, a Homebrew\-built Git if installed, or the system\-provided binary\.
+.
+.IP
+Set this to force Homebrew to use a particular git binary\.
+.
+.TP
\fBHOMEBREW_GITHUB_API_TOKEN\fR
A personal access token for the GitHub API, which you can create at \fIhttps://github\.com/settings/tokens\fR\. If set, GitHub will allow you a greater number of API requests\. See \fIhttps://developer\.github\.com/v3/#rate\-limiting\fR for more information\. Homebrew uses the GitHub API for features such as \fBbrew search\fR\.
.
@@ -1068,10 +1078,6 @@ This issue typically occurs when using FileVault or custom SSD configurations\.
\fBHOMEBREW_VERBOSE\fR
If set, Homebrew always assumes \fB\-\-verbose\fR when running commands\.
.
-.TP
-\fBVISUAL\fR
-If set, and \fBHOMEBREW_EDITOR\fR is not, use \fBVISUAL\fR as the text editor\.
-.
.SH "USING HOMEBREW BEHIND A PROXY"
Homebrew uses several commands for downloading files (e\.g\. \fBcurl\fR, \fBgit\fR, \fBsvn\fR)\. Many of these tools can download via a proxy\. It\'s common for these tools to read proxy parameters from environment variables\.
.
@@ -1114,7 +1120,7 @@ Homebrew\'s lead maintainer is Mike McQuaid\.
Homebrew\'s current maintainers are Alyssa Ross, Andrew Janke, Baptiste Fontaine, Alex Dunn, FX Coudert, ilovezfs, Josh Hagins, JCount, Misty De Meo, neutric, Tomasz Pajor, Markus Reiter, Tim Smith, Tom Schoonjans, Uladzislau Shablinski and William Woodruff\.
.
.P
-Former maintainers with significant contributions include Xu Cheng, Martin Afanasjew, Dominyk Tiller, Brett Koonce, Jack Nagel, Adam Vandenberg and Homebrew\'s creator: Max Howell\.
+Former maintainers with significant contributions include Xu Cheng, Martin Afanasjew, Dominyk Tiller, Brett Koonce, Charlie Sharpsteen, Jack Nagel, Adam Vandenberg and Homebrew\'s creator: Max Howell\.
.
.SH "BUGS"
See our issues on GitHub: