aboutsummaryrefslogtreecommitdiffstats
path: root/Library
diff options
context:
space:
mode:
Diffstat (limited to 'Library')
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/search.rb21
-rw-r--r--Library/Homebrew/cleanup.rb8
-rw-r--r--Library/Homebrew/cmd/search.rb8
-rw-r--r--Library/Homebrew/cmd/update-report.rb1
-rw-r--r--Library/Homebrew/compat/ENV/shared.rb4
-rw-r--r--Library/Homebrew/dev-cmd/audit.rb78
-rw-r--r--Library/Homebrew/dev-cmd/pull.rb2
-rw-r--r--Library/Homebrew/download_strategy.rb2
-rw-r--r--Library/Homebrew/extend/ENV/shared.rb4
-rw-r--r--Library/Homebrew/extend/fileutils.rb2
-rw-r--r--Library/Homebrew/extend/pathname.rb2
-rw-r--r--Library/Homebrew/formula.rb6
-rw-r--r--Library/Homebrew/formula_installer.rb3
-rw-r--r--Library/Homebrew/gpg.rb23
-rw-r--r--Library/Homebrew/manpages/brew-cask.1.md13
-rw-r--r--Library/Homebrew/missing_formula.rb13
-rw-r--r--Library/Homebrew/requirements/gpg2_requirement.rb6
-rw-r--r--Library/Homebrew/rubocops/extend/formula_cop.rb32
-rw-r--r--Library/Homebrew/rubocops/lines_cop.rb54
-rw-r--r--Library/Homebrew/rubocops/patches_cop.rb12
-rw-r--r--Library/Homebrew/test/cask/cli/search_spec.rb48
-rw-r--r--Library/Homebrew/test/cleanup_spec.rb132
-rw-r--r--Library/Homebrew/test/cmd/search_remote_tap_spec.rb3
-rw-r--r--Library/Homebrew/test/cmd/search_spec.rb2
-rw-r--r--Library/Homebrew/test/dev-cmd/audit_spec.rb22
-rw-r--r--Library/Homebrew/test/download_strategies_spec.rb11
-rw-r--r--Library/Homebrew/test/missing_formula_spec.rb6
-rw-r--r--Library/Homebrew/test/rubocops/lines_cop_spec.rb151
-rw-r--r--Library/Homebrew/test/rubocops/patches_cop_spec.rb222
-rw-r--r--Library/Homebrew/test/utils/analytics_spec.rb88
-rw-r--r--Library/Homebrew/test/utils/git_spec.rb150
-rw-r--r--Library/Homebrew/test/utils/svn_spec.rb39
-rw-r--r--Library/Homebrew/utils/analytics.rb5
-rw-r--r--Library/Homebrew/utils/curl.rb7
-rw-r--r--Library/Homebrew/utils/fork.rb2
-rw-r--r--Library/Homebrew/utils/git.rb3
-rw-r--r--Library/Homebrew/utils/github.rb2
-rw-r--r--Library/Homebrew/utils/svn.rb4
38 files changed, 943 insertions, 248 deletions
diff --git a/Library/Homebrew/cask/lib/hbc/cli/search.rb b/Library/Homebrew/cask/lib/hbc/cli/search.rb
index e89dced92..d56d0c81f 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/search.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/search.rb
@@ -2,8 +2,12 @@ module Hbc
class CLI
class Search < AbstractCommand
def run
- results = self.class.search(*args)
- self.class.render_results(*results)
+ if args.empty?
+ puts Formatter.columns(CLI.nice_listing(Hbc.all_tokens))
+ else
+ results = self.class.search(*args)
+ self.class.render_results(*results)
+ end
end
def self.extract_regexp(string)
@@ -15,8 +19,17 @@ module Hbc
end
def self.search_remote(query)
- matches = GitHub.search_code(user: "caskroom", path: "Casks",
- filename: query, extension: "rb")
+ matches = begin
+ GitHub.search_code(
+ user: "caskroom",
+ path: "Casks",
+ filename: query,
+ extension: "rb",
+ )
+ rescue GitHub::Error => error
+ opoo "Error searching on GitHub: #{error}\n"
+ []
+ end
matches.map do |match|
tap = Tap.fetch(match["repository"]["full_name"])
next if tap.installed?
diff --git a/Library/Homebrew/cleanup.rb b/Library/Homebrew/cleanup.rb
index d1f0b2516..340161204 100644
--- a/Library/Homebrew/cleanup.rb
+++ b/Library/Homebrew/cleanup.rb
@@ -6,6 +6,10 @@ module Homebrew
module Cleanup
@disk_cleanup_size = 0
+ class << self
+ attr_reader :disk_cleanup_size
+ end
+
module_function
def cleanup
@@ -21,10 +25,6 @@ module Homebrew
@disk_cleanup_size += path_size
end
- def disk_cleanup_size
- @disk_cleanup_size
- end
-
def unremovable_kegs
@unremovable_kegs ||= []
end
diff --git a/Library/Homebrew/cmd/search.rb b/Library/Homebrew/cmd/search.rb
index 0718a3af4..acee9817f 100644
--- a/Library/Homebrew/cmd/search.rb
+++ b/Library/Homebrew/cmd/search.rb
@@ -36,7 +36,7 @@ module Homebrew
elsif ARGV.include? "--fedora"
exec_browser "https://apps.fedoraproject.org/packages/s/#{ARGV.next}"
elsif ARGV.include? "--ubuntu"
- exec_browser "http://packages.ubuntu.com/search?keywords=#{ARGV.next}&searchon=names&suite=all&section=all"
+ exec_browser "https://packages.ubuntu.com/search?keywords=#{ARGV.next}&searchon=names&suite=all&section=all"
elsif ARGV.include? "--desc"
query = ARGV.next
regex = query_regexp(query)
@@ -102,11 +102,13 @@ module Homebrew
odie "#{query} is not a valid regex"
end
- def search_taps(query)
+ def search_taps(query, silent: false)
return [] if ENV["HOMEBREW_NO_GITHUB_API"]
# Use stderr to avoid breaking parsed output
- $stderr.puts Formatter.headline("Searching taps on GitHub...", color: :blue)
+ unless silent
+ $stderr.puts Formatter.headline("Searching taps on GitHub...", color: :blue)
+ end
valid_dirnames = ["Formula", "HomebrewFormula", "Casks", "."].freeze
matches = GitHub.search_code(user: ["Homebrew", "caskroom"], filename: query, extension: "rb")
diff --git a/Library/Homebrew/cmd/update-report.rb b/Library/Homebrew/cmd/update-report.rb
index ea915f99c..164413cd1 100644
--- a/Library/Homebrew/cmd/update-report.rb
+++ b/Library/Homebrew/cmd/update-report.rb
@@ -203,6 +203,7 @@ module Homebrew
end
new_homebrew_repository = Pathname.new "/usr/local/Homebrew"
+ new_homebrew_repository.rmdir_if_possible
if new_homebrew_repository.exist?
ofail <<-EOS.undent
#{new_homebrew_repository} already exists.
diff --git a/Library/Homebrew/compat/ENV/shared.rb b/Library/Homebrew/compat/ENV/shared.rb
index 200e7b132..c700b1e00 100644
--- a/Library/Homebrew/compat/ENV/shared.rb
+++ b/Library/Homebrew/compat/ENV/shared.rb
@@ -3,4 +3,8 @@ module SharedEnvExtension
odeprecated "ENV.j1", "ENV.deparallelize"
deparallelize
end
+
+ def java_cache
+ # odeprecated "ENV.java_cache"
+ end
end
diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb
index 170fb6d5f..d089f308d 100644
--- a/Library/Homebrew/dev-cmd/audit.rb
+++ b/Library/Homebrew/dev-cmd/audit.rb
@@ -201,7 +201,7 @@ class FormulaAuditor
@specs = %w[stable devel head].map { |s| formula.send(s) }.compact
end
- def self.check_http_content(url, name, user_agents: [:default])
+ def self.check_http_content(url, name, user_agents: [:default], check_content: false, strict: false)
return unless url.start_with? "http"
details = nil
@@ -236,8 +236,32 @@ class FormulaAuditor
details[:content_length] == secure_details[:content_length]
file_match = details[:file_hash] == secure_details[:file_hash]
- return if !etag_match && !content_length_match && !file_match
- "The URL #{url} could use HTTPS rather than HTTP"
+ if etag_match || content_length_match || file_match
+ return "The URL #{url} should use HTTPS rather than HTTP"
+ end
+
+ return unless check_content
+
+ no_protocol_file_contents = %r{https?:\\?/\\?/}
+ details[:file] = details[:file].gsub(no_protocol_file_contents, "/")
+ secure_details[:file] = secure_details[:file].gsub(no_protocol_file_contents, "/")
+
+ # Check for the same content after removing all protocols
+ if details[:file] == secure_details[:file]
+ return "The URL #{url} should use HTTPS rather than HTTP"
+ end
+
+ return unless strict
+
+ # Same size, different content after normalization
+ # (typical causes: Generated ID, Timestamp, Unix time)
+ if details[:file].length == secure_details[:file].length
+ return "The URL #{url} may be able to use HTTPS rather than HTTP. Please verify it in a browser."
+ end
+
+ lenratio = (100 * secure_details[:file].length / details[:file].length).to_i
+ return unless (90..110).cover?(lenratio)
+ "The URL #{url} may be able to use HTTPS rather than HTTP. Please verify it in a browser."
end
def self.http_content_headers_and_checksum(url, hash_needed: false, user_agent: :default)
@@ -260,6 +284,7 @@ class FormulaAuditor
etag: headers[%r{ETag: ([wW]\/)?"(([^"]|\\")*)"}, 2],
content_length: headers[/Content-Length: (\d+)/, 1],
file_hash: output_hash,
+ file: output,
}
end
@@ -412,7 +437,7 @@ class FormulaAuditor
same_name_tap_formulae = @@local_official_taps_name_map[name] || []
if @online
- Homebrew.search_taps(name).each do |tap_formula_full_name|
+ Homebrew.search_taps(name, silent: true).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
@@ -566,7 +591,9 @@ class FormulaAuditor
return unless DevelopmentTools.curl_handles_most_https_homepages?
if http_content_problem = FormulaAuditor.check_http_content(homepage,
formula.name,
- user_agents: [:browser, :default])
+ user_agents: [:browser, :default],
+ check_content: true,
+ strict: @strict)
problem http_content_problem
end
end
@@ -808,39 +835,6 @@ class FormulaAuditor
end
def line_problems(line, _lineno)
- if line =~ /<(Formula|AmazonWebServicesFormula|ScriptFileFormula|GithubGistFormula)/
- problem "Use a space in class inheritance: class Foo < #{Regexp.last_match(1)}"
- end
-
- # Commented-out cmake support from default template
- problem "Commented cmake call found" if line.include?('# system "cmake')
-
- # Comments from default template
- [
- "# PLEASE REMOVE",
- "# Documentation:",
- "# if this fails, try separate make/make install steps",
- "# The URL of the archive",
- "## Naming --",
- "# if your formula requires any X11/XQuartz components",
- "# if your formula fails when building in parallel",
- "# Remove unrecognized options if warned by configure",
- ].each do |comment|
- next unless line.include?(comment)
- problem "Please remove default template comments"
- end
-
- # FileUtils is included in Formula
- # encfs modifies a file with this name, so check for some leading characters
- if line =~ %r{[^'"/]FileUtils\.(\w+)}
- problem "Don't need 'FileUtils.' before #{Regexp.last_match(1)}."
- end
-
- # Check for long inreplace block vars
- if line =~ /inreplace .* do \|(.{2,})\|/
- problem "\"inreplace <filenames> do |s|\" is preferred over \"|#{Regexp.last_match(1)}|\"."
- end
-
# Check for string interpolation of single values.
if line =~ /(system|inreplace|gsub!|change_make_var!).*[ ,]"#\{([\w.]+)\}"/
problem "Don't need to interpolate \"#{Regexp.last_match(2)}\" with #{Regexp.last_match(1)}"
@@ -890,9 +884,6 @@ class FormulaAuditor
end
end
- # Commented-out depends_on
- problem "Commented-out dep #{Regexp.last_match(1)}" if line =~ /#\s*depends_on\s+(.+)\s*$/
-
if line =~ /if\s+ARGV\.include\?\s+'--(HEAD|devel)'/
problem "Use \"if build.#{Regexp.last_match(1).downcase}?\" instead"
end
@@ -905,6 +896,10 @@ class FormulaAuditor
problem "Use \"depends_on :x11\" instead of \"ENV.x11\""
end
+ if line.include?("ENV.java_cache")
+ problem "In-formula ENV.java_cache usage has been deprecated & should be removed."
+ end
+
# Avoid hard-coding compilers
if line =~ %r{(system|ENV\[.+\]\s?=)\s?['"](/usr/bin/)?(gcc|llvm-gcc|clang)['" ]}
problem "Use \"\#{ENV.cc}\" instead of hard-coding \"#{Regexp.last_match(3)}\""
@@ -1264,6 +1259,7 @@ class ResourceAuditor
end
elsif strategy <= SubversionDownloadStrategy
next unless DevelopmentTools.subversion_handles_most_https_certificates?
+ next unless Utils.svn_available?
unless Utils.svn_remote_exists url
problem "The URL #{url} is not a valid svn URL"
end
diff --git a/Library/Homebrew/dev-cmd/pull.rb b/Library/Homebrew/dev-cmd/pull.rb
index dd2bc6270..a8f35531f 100644
--- a/Library/Homebrew/dev-cmd/pull.rb
+++ b/Library/Homebrew/dev-cmd/pull.rb
@@ -587,7 +587,7 @@ module Homebrew
# We're in the cache; make sure to force re-download
loop do
begin
- curl_download url, to: filename
+ curl_download url, continue_at: 0, to: filename
break
rescue
if retry_count >= max_curl_retries
diff --git a/Library/Homebrew/download_strategy.rb b/Library/Homebrew/download_strategy.rb
index 2a8b6e585..adeb0a02a 100644
--- a/Library/Homebrew/download_strategy.rb
+++ b/Library/Homebrew/download_strategy.rb
@@ -381,7 +381,7 @@ class CurlDownloadStrategy < AbstractFileDownloadStrategy
# Curl options to be always passed to curl,
# with raw head calls (`curl --head`) or with actual `fetch`.
def _curl_opts
- return ["--user" << meta.fetch(:user)] if meta.key?(:user)
+ return ["--user", meta.fetch(:user)] if meta.key?(:user)
[]
end
diff --git a/Library/Homebrew/extend/ENV/shared.rb b/Library/Homebrew/extend/ENV/shared.rb
index b51ade48b..15488ee19 100644
--- a/Library/Homebrew/extend/ENV/shared.rb
+++ b/Library/Homebrew/extend/ENV/shared.rb
@@ -260,10 +260,6 @@ module SharedEnvExtension
set_cpu_flags(flags)
end
- def java_cache
- append "_JAVA_OPTIONS", "-Duser.home=#{HOMEBREW_CACHE}/java_cache"
- end
-
# ld64 is a newer linker provided for Xcode 2.5
# @private
def ld64
diff --git a/Library/Homebrew/extend/fileutils.rb b/Library/Homebrew/extend/fileutils.rb
index 52d4cbf51..ed5bfe6c3 100644
--- a/Library/Homebrew/extend/fileutils.rb
+++ b/Library/Homebrew/extend/fileutils.rb
@@ -3,7 +3,7 @@ require "tmpdir"
require "etc"
# Homebrew extends Ruby's `FileUtils` to make our code more readable.
-# @see http://ruby-doc.org/stdlib-2.0.0/libdoc/fileutils/rdoc/FileUtils.html Ruby's FileUtils API
+# @see https://ruby-doc.org/stdlib-2.0.0/libdoc/fileutils/rdoc/FileUtils.html Ruby's FileUtils API
module FileUtils
# Create a temporary directory then yield. When the block returns,
# recursively delete the temporary directory. Passing opts[:retain]
diff --git a/Library/Homebrew/extend/pathname.rb b/Library/Homebrew/extend/pathname.rb
index 767d83ff9..e1acd1f77 100644
--- a/Library/Homebrew/extend/pathname.rb
+++ b/Library/Homebrew/extend/pathname.rb
@@ -59,7 +59,7 @@ module DiskUsageExtension
end
# Homebrew extends Ruby's `Pathname` to make our code more readable.
-# @see http://ruby-doc.org/stdlib-1.8.7/libdoc/pathname/rdoc/Pathname.html Ruby's Pathname API
+# @see https://ruby-doc.org/stdlib-1.8.7/libdoc/pathname/rdoc/Pathname.html Ruby's Pathname API
class Pathname
include DiskUsageExtension
diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb
index 8cea85a99..2f0c913c2 100644
--- a/Library/Homebrew/formula.rb
+++ b/Library/Homebrew/formula.rb
@@ -1613,6 +1613,7 @@ class Formula
def run_test
@prefix_returns_versioned_prefix = true
old_home = ENV["HOME"]
+ old_java_opts = ENV["_JAVA_OPTIONS"]
old_curl_home = ENV["CURL_HOME"]
old_tmpdir = ENV["TMPDIR"]
old_temp = ENV["TEMP"]
@@ -1626,6 +1627,7 @@ class Formula
ENV["TERM"] = "dumb"
ENV["PATH"] = PATH.new(old_path).append(HOMEBREW_PREFIX/"bin")
ENV["HOMEBREW_PATH"] = nil
+ ENV["_JAVA_OPTIONS"] = "#{old_java_opts} -Duser.home=#{HOMEBREW_CACHE}/java_cache"
ENV.clear_sensitive_environment!
@@ -1646,6 +1648,7 @@ class Formula
ensure
@testpath = nil
ENV["HOME"] = old_home
+ ENV["_JAVA_OPTIONS"] = old_java_opts
ENV["CURL_HOME"] = old_curl_home
ENV["TMPDIR"] = old_tmpdir
ENV["TEMP"] = old_temp
@@ -1888,11 +1891,13 @@ class Formula
mkdir_p env_home
old_home = ENV["HOME"]
+ old_java_opts = ENV["_JAVA_OPTIONS"]
old_curl_home = ENV["CURL_HOME"]
old_path = ENV["HOMEBREW_PATH"]
unless ARGV.interactive?
ENV["HOME"] = env_home
+ ENV["_JAVA_OPTIONS"] = "#{old_java_opts} -Duser.home=#{HOMEBREW_CACHE}/java_cache"
ENV["CURL_HOME"] = old_curl_home || old_home
end
ENV["HOMEBREW_PATH"] = nil
@@ -1907,6 +1912,7 @@ class Formula
@buildpath = nil
unless ARGV.interactive?
ENV["HOME"] = old_home
+ ENV["_JAVA_OPTIONS"] = old_java_opts
ENV["CURL_HOME"] = old_curl_home
end
ENV["HOMEBREW_PATH"] = old_path
diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb
index 6c5b8bdab..216a375ce 100644
--- a/Library/Homebrew/formula_installer.rb
+++ b/Library/Homebrew/formula_installer.rb
@@ -85,13 +85,12 @@ class FormulaInstaller
return false if @pour_failed
bottle = formula.bottle
- return false unless bottle
+ return false if !bottle && !formula.local_bottle_path
return true if force_bottle?
return false if build_from_source? || build_bottle? || interactive?
return false if ARGV.cc
return false unless options.empty?
return false if formula.bottle_disabled?
- return true if formula.local_bottle_path
unless formula.pour_bottle?
if install_bottle_options[:warn] && formula.pour_bottle_check_unsatisfied_reason
opoo <<-EOS.undent
diff --git a/Library/Homebrew/gpg.rb b/Library/Homebrew/gpg.rb
index f56473df3..de2089dda 100644
--- a/Library/Homebrew/gpg.rb
+++ b/Library/Homebrew/gpg.rb
@@ -7,8 +7,7 @@ class Gpg
next unless gpg_short_version
gpg_version = Version.create(gpg_short_version.to_s)
@version = gpg_version
- gpg_version == Version.create("2.1") ||
- gpg_version == Version.create("2.0")
+ gpg_version >= Version.create("2.0")
end
end
@@ -38,12 +37,30 @@ class Gpg
Key-Length: 2048
Subkey-Type: RSA
Subkey-Length: 2048
- Passphrase: ''
Name-Real: Testing
Name-Email: testing@foo.bar
Expire-Date: 1d
+ %no-protection
%commit
EOS
system GPG_EXECUTABLE, "--batch", "--gen-key", "batch.gpg"
end
+
+ def self.cleanup_test_processes!
+ odie "No GPG present to test against!" unless available?
+ gpgconf = Pathname.new(GPG_EXECUTABLE).parent/"gpgconf"
+
+ system gpgconf, "--kill", "gpg-agent"
+ system gpgconf, "--homedir", "keyrings/live", "--kill",
+ "gpg-agent"
+ end
+
+ def self.test(path)
+ create_test_key(path)
+ begin
+ yield
+ ensure
+ cleanup_test_processes!
+ end
+ end
end
diff --git a/Library/Homebrew/manpages/brew-cask.1.md b/Library/Homebrew/manpages/brew-cask.1.md
index bfb9cd7a5..715d8fd77 100644
--- a/Library/Homebrew/manpages/brew-cask.1.md
+++ b/Library/Homebrew/manpages/brew-cask.1.md
@@ -1,5 +1,5 @@
brew-cask(1) - a friendly binary installer for macOS
-========================================================
+====================================================
## SYNOPSIS
@@ -85,7 +85,7 @@ names, and other aspects of this manual are still subject to change.
If <token> is given, summarize the staged files associated with the
given Cask.
-
+
* `outdated` [--greedy] [--verbose|--quiet] [ <token> ...]:
Without token arguments, display all the installed Casks that have newer
versions available in the tap; otherwise check only the tokens given
@@ -101,9 +101,10 @@ names, and other aspects of this manual are still subject to change.
Reinstall the given Cask.
* `search` or `-S` [<text> | /<regexp>/]:
- Without an argument, display all Casks available for install; otherwise
- perform a substring search of known Cask tokens for <text> or, if the
- text is delimited by slashes (/<regexp>/), it is interpreted as a
+ Without an argument, display all locally available Casks for install; no
+ online search is performed.
+ Otherwise perform a substring search of known Cask tokens for <text> or,
+ if the text is delimited by slashes (/<regexp>/), it is interpreted as a
Ruby regular expression.
* `style` [--fix] [ <token> ... ]:
@@ -255,7 +256,7 @@ Environment variables specific to Homebrew-Cask:
export HOMEBREW_CASK_OPTS='--appdir=~/Applications --fontdir=/Library/Fonts'
Other environment variables:
-
+
* `SUDO_ASKPASS`:
When this variable is set, Homebrew-Cask will call `sudo`(8) with the `-A` option.
diff --git a/Library/Homebrew/missing_formula.rb b/Library/Homebrew/missing_formula.rb
index 4d90ddb61..a3d182a2b 100644
--- a/Library/Homebrew/missing_formula.rb
+++ b/Library/Homebrew/missing_formula.rb
@@ -31,7 +31,7 @@ module Homebrew
#{Formatter.url("https://pip.readthedocs.io/en/stable/installing/")}
EOS
when "pil" then <<-EOS.undent
- Instead of PIL, consider `pip install pillow` or `brew install Homebrew/science/pillow`.
+ Instead of PIL, consider `pip2 install pillow`.
EOS
when "macruby" then <<-EOS.undent
MacRuby is not packaged and is on an indefinite development hiatus.
@@ -53,16 +53,7 @@ module Homebrew
ruin SSH's security.
EOS
when "gsutil" then <<-EOS.undent
- Install gsutil with `pip install gsutil`
- EOS
- when "clojure" then <<-EOS.undent
- Clojure isn't really a program but a library managed as part of a
- project and Leiningen is the user interface to that library.
-
- To install Clojure you should install Leiningen:
- brew install leiningen
- and then follow the tutorial:
- #{Formatter.url("https://github.com/technomancy/leiningen/blob/stable/doc/TUTORIAL.md")}
+ Install gsutil with `pip2 install gsutil`
EOS
when "gfortran" then <<-EOS.undent
GNU Fortran is now provided as part of GCC, and can be installed with:
diff --git a/Library/Homebrew/requirements/gpg2_requirement.rb b/Library/Homebrew/requirements/gpg2_requirement.rb
index d570983eb..ebdd71f6e 100644
--- a/Library/Homebrew/requirements/gpg2_requirement.rb
+++ b/Library/Homebrew/requirements/gpg2_requirement.rb
@@ -5,8 +5,8 @@ class GPG2Requirement < Requirement
fatal true
default_formula "gnupg"
- # GPGTools installs GnuPG 2.0.x as a vanilla `gpg` symlink
- # pointing to `gpg2`. Homebrew install 2.1.x as a non-symlink `gpg`.
- # We support both the 2.0.x "stable" and 2.1.x "modern" series here.
+ # GPGTools installs GnuPG 2.0.x as a `gpg` symlink pointing
+ # to `gpg2`. Our `gnupg` installs only a non-symlink `gpg`.
+ # The aim is to retain support for any version above 2.0.
satisfy(build_env: false) { Gpg.gpg || Gpg.gpg2 }
end
diff --git a/Library/Homebrew/rubocops/extend/formula_cop.rb b/Library/Homebrew/rubocops/extend/formula_cop.rb
index 862664010..7844f7bf2 100644
--- a/Library/Homebrew/rubocops/extend/formula_cop.rb
+++ b/Library/Homebrew/rubocops/extend/formula_cop.rb
@@ -86,9 +86,13 @@ module RuboCop
end
# Returns an array of method call nodes matching method_name in every descendant of node
- def find_every_method_call_by_name(node, method_name)
+ # Returns every method call if no method_name is passed
+ def find_every_method_call_by_name(node, method_name = nil)
return if node.nil?
- node.each_descendant(:send).select { |method_node| method_name == method_node.method_name }
+ node.each_descendant(:send).select do |method_node|
+ method_name.nil? ||
+ method_name == method_node.method_name
+ end
end
# Given a method_name and arguments, yields to a block with
@@ -108,7 +112,7 @@ module RuboCop
def find_instance_method_call(node, instance, method_name)
methods = find_every_method_call_by_name(node, method_name)
methods.each do |method|
- next unless method.receiver.const_name == instance
+ next unless method.receiver && method.receiver.const_name == instance
@offense_source_range = method.source_range
@offensive_node = method
yield method
@@ -202,9 +206,15 @@ module RuboCop
end
# Returns an array of block nodes of any depth below node in AST
+ # If a block is given then yields matching block node to the block!
def find_all_blocks(node, block_name)
return if node.nil?
- node.each_descendant(:block).select { |block_node| block_name == block_node.method_name }
+ blocks = node.each_descendant(:block).select { |block_node| block_name == block_node.method_name }
+ return blocks unless block_given?
+ blocks.each do |block_node|
+ offending_node(block_node)
+ yield block_node
+ end
end
# Returns a method definition node with method_name
@@ -316,6 +326,15 @@ module RuboCop
end
end
+ # Yields to a block with comment text as parameter
+ def audit_comments
+ @processed_source.comments.each do |comment_node|
+ @offensive_node = comment_node
+ @offense_source_range = :expression
+ yield comment_node.text
+ end
+ 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
@@ -326,6 +345,11 @@ module RuboCop
node.source_range.begin_pos
end
+ # Returns the ending position of the node in source code
+ def end_column(node)
+ node.source_range.end_pos
+ end
+
# Returns the line number of the node
def line_number(node)
node.loc.line
diff --git a/Library/Homebrew/rubocops/lines_cop.rb b/Library/Homebrew/rubocops/lines_cop.rb
index 22039869b..ed50ba49c 100644
--- a/Library/Homebrew/rubocops/lines_cop.rb
+++ b/Library/Homebrew/rubocops/lines_cop.rb
@@ -15,6 +15,60 @@ module RuboCop
problem ":tex is deprecated" if depends_on?(:tex)
end
end
+
+ class ClassInheritance < FormulaCop
+ def audit_formula(_node, class_node, parent_class_node, _body_node)
+ begin_pos = start_column(parent_class_node)
+ end_pos = end_column(class_node)
+ return unless begin_pos-end_pos != 3
+ problem "Use a space in class inheritance: class #{@formula_name} < #{class_name(parent_class_node)}"
+ end
+ end
+
+ class Comments < FormulaCop
+ def audit_formula(_node, _class_node, _parent_class_node, _body_node)
+ audit_comments do |comment|
+ [
+ "# PLEASE REMOVE",
+ "# Documentation:",
+ "# if this fails, try separate make/make install steps",
+ "# The URL of the archive",
+ "## Naming --",
+ "# if your formula requires any X11/XQuartz components",
+ "# if your formula fails when building in parallel",
+ "# Remove unrecognized options if warned by configure",
+ '# system "cmake',
+ ].each do |template_comment|
+ next unless comment.include?(template_comment)
+ problem "Please remove default template comments"
+ break
+ end
+ end
+
+ audit_comments do |comment|
+ # Commented-out depends_on
+ next unless comment =~ /#\s*depends_on\s+(.+)\s*$/
+ problem "Commented-out dependency #{Regexp.last_match(1)}"
+ end
+ end
+ end
+
+ class Miscellaneous < FormulaCop
+ def audit_formula(_node, _class_node, _parent_class_node, body_node)
+ # FileUtils is included in Formula
+ # encfs modifies a file with this name, so check for some leading characters
+ find_instance_method_call(body_node, "FileUtils", nil) do |method_node|
+ problem "Don't need 'FileUtils.' before #{method_node.method_name}"
+ end
+
+ # Check for long inreplace block vars
+ find_all_blocks(body_node, :inreplace) do |node|
+ block_arg = node.arguments.children.first
+ next unless block_arg.source.size>1
+ problem "\"inreplace <filenames> do |s|\" is preferred over \"|#{block_arg.source}|\"."
+ end
+ end
+ end
end
end
end
diff --git a/Library/Homebrew/rubocops/patches_cop.rb b/Library/Homebrew/rubocops/patches_cop.rb
index b27283382..7ee1a127a 100644
--- a/Library/Homebrew/rubocops/patches_cop.rb
+++ b/Library/Homebrew/rubocops/patches_cop.rb
@@ -25,12 +25,22 @@ module RuboCop
def patch_problems(patch)
patch_url = string_content(patch)
+ gh_patch_param_pattern = %r{https?://github\.com/.+/.+/(?:commit|pull)/[a-fA-F0-9]*.(?:patch|diff)}
+ if regex_match_group(patch, gh_patch_param_pattern)
+ if patch_url !~ /\?full_index=\w+$/
+ problem <<-EOS.undent
+ GitHub patches should use the full_index parameter:
+ #{patch_url}?full_index=1
+ EOS
+ end
+ end
+
gh_patch_patterns = Regexp.union([%r{/raw\.github\.com/},
%r{gist\.github\.com/raw},
%r{gist\.github\.com/.+/raw},
%r{gist\.githubusercontent\.com/.+/raw}])
if regex_match_group(patch, gh_patch_patterns)
- unless patch_url =~ /[a-fA-F0-9]{40}/
+ if patch_url !~ /[a-fA-F0-9]{40}/
problem <<-EOS.undent.chomp
GitHub/Gist patches should specify a revision:
#{patch_url}
diff --git a/Library/Homebrew/test/cask/cli/search_spec.rb b/Library/Homebrew/test/cask/cli/search_spec.rb
index e237ad464..6dc980590 100644
--- a/Library/Homebrew/test/cask/cli/search_spec.rb
+++ b/Library/Homebrew/test/cask/cli/search_spec.rb
@@ -22,16 +22,36 @@ describe Hbc::CLI::Search, :cask do
EOS
end
+ it "returns matches even when online search failed" do
+ allow(GitHub).to receive(:search_code).and_raise(GitHub::Error.new("reason"))
+ expect {
+ Hbc::CLI::Search.run("local")
+ }.to output(<<-EOS.undent).to_stdout
+ local-caffeine
+ local-transmission
+ EOS
+ .and output(/^Warning: Error searching on GitHub: reason/).to_stderr
+ end
+
it "shows that there are no Casks matching a search term that did not result in anything" do
expect {
Hbc::CLI::Search.run("foo-bar-baz")
- }.to output("No Cask found for \"foo-bar-baz\".\n").to_stdout.as_tty
+ }.to output(<<-EOS.undent).to_stdout.as_tty
+ No Cask found for "foo-bar-baz".
+ EOS
end
- it "lists all available Casks with no search term" do
- expect {
- Hbc::CLI::Search.run
- }.to output(/local-caffeine/).to_stdout.as_tty
+ it "doesn't output anything to non-TTY stdout when there are no matches" do
+ expect { Hbc::CLI::Search.run("foo-bar-baz") }
+ .to not_to_output.to_stdout
+ .and not_to_output.to_stderr
+ end
+
+ it "lists all Casks available offline with no search term" do
+ allow(GitHub).to receive(:search_code).and_raise(GitHub::Error.new("reason"))
+ expect { Hbc::CLI::Search.run }
+ .to output(/local-caffeine/).to_stdout.as_tty
+ .and not_to_output.to_stderr
end
it "ignores hyphens in search terms" do
@@ -55,19 +75,29 @@ describe Hbc::CLI::Search, :cask do
it "accepts a regexp argument" do
expect {
Hbc::CLI::Search.run("/^local-c[a-z]ffeine$/")
- }.to output("==> Regexp Matches\nlocal-caffeine\n").to_stdout.as_tty
+ }.to output(<<-EOS.undent).to_stdout.as_tty
+ ==> Regexp Matches
+ local-caffeine
+ EOS
end
- it "Returns both exact and partial matches" do
+ it "returns both exact and partial matches" do
expect {
Hbc::CLI::Search.run("test-opera")
- }.to output(/^==> Exact Match\ntest-opera\n==> Partial Matches\ntest-opera-mail/).to_stdout.as_tty
+ }.to output(<<-EOS.undent).to_stdout.as_tty
+ ==> Exact Match
+ test-opera
+ ==> Partial Matches
+ test-opera-mail
+ EOS
end
it "does not search the Tap name" do
expect {
Hbc::CLI::Search.run("caskroom")
- }.to output(/^No Cask found for "caskroom"\.\n/).to_stdout.as_tty
+ }.to output(<<-EOS.undent).to_stdout.as_tty
+ No Cask found for "caskroom".
+ EOS
end
it "doesn't highlight packages that aren't installed" do
diff --git a/Library/Homebrew/test/cleanup_spec.rb b/Library/Homebrew/test/cleanup_spec.rb
index 4e5e42efa..da262c5ca 100644
--- a/Library/Homebrew/test/cleanup_spec.rb
+++ b/Library/Homebrew/test/cleanup_spec.rb
@@ -5,6 +5,7 @@ require "pathname"
describe Homebrew::Cleanup do
let(:ds_store) { Pathname.new("#{HOMEBREW_PREFIX}/Library/.DS_Store") }
+ let(:sec_in_a_day) { 60 * 60 * 24 }
around(:each) do |example|
begin
@@ -104,14 +105,30 @@ describe Homebrew::Cleanup do
expect(f4).to be_installed
end
- specify "::cleanup_logs" do
- path = (HOMEBREW_LOGS/"delete_me")
- path.mkpath
- ARGV << "--prune=all"
+ describe "::cleanup_logs" do
+ let(:path) { (HOMEBREW_LOGS/"delete_me") }
- described_class.cleanup_logs
+ before do
+ path.mkpath
+ end
+
+ it "cleans all logs if prune all" do
+ ARGV << "--prune=all"
+ described_class.cleanup_logs
+ expect(path).not_to exist
+ end
- expect(path).not_to exist
+ it "cleans up logs if older than 14 days" do
+ allow_any_instance_of(Pathname).to receive(:mtime).and_return(Time.now - sec_in_a_day * 15)
+ described_class.cleanup_logs
+ expect(path).not_to exist
+ end
+
+ it "does not clean up logs less than 14 days old" do
+ allow_any_instance_of(Pathname).to receive(:mtime).and_return(Time.now - sec_in_a_day * 2)
+ described_class.cleanup_logs
+ expect(path).to exist
+ end
end
describe "::cleanup_cache" do
@@ -124,6 +141,15 @@ describe Homebrew::Cleanup do
expect(incomplete).not_to exist
end
+ it "cleans up 'glide_home'" do
+ glide_home = (HOMEBREW_CACHE/"glide_home")
+ glide_home.mkpath
+
+ described_class.cleanup_cache
+
+ expect(glide_home).not_to exist
+ end
+
it "cleans up 'java_cache'" do
java_cache = (HOMEBREW_CACHE/"java_cache")
java_cache.mkpath
@@ -141,5 +167,99 @@ describe Homebrew::Cleanup do
expect(npm_cache).not_to exist
end
+
+ it "cleans up all files and directories" do
+ git = (HOMEBREW_CACHE/"gist--git")
+ gist = (HOMEBREW_CACHE/"gist")
+ svn = (HOMEBREW_CACHE/"gist--svn")
+
+ git.mkpath
+ gist.mkpath
+ FileUtils.touch svn
+
+ allow(ARGV).to receive(:value).with("prune").and_return("all")
+
+ described_class.cleanup_cache
+
+ expect(git).not_to exist
+ expect(gist).to exist
+ expect(svn).not_to exist
+ end
+
+ it "does not clean up directories that are not VCS checkouts" do
+ git = (HOMEBREW_CACHE/"git")
+ git.mkpath
+ allow(ARGV).to receive(:value).with("prune").and_return("all")
+
+ described_class.cleanup_cache
+
+ expect(git).to exist
+ end
+
+ it "cleans up VCS checkout directories with modified time < prune time" do
+ foo = (HOMEBREW_CACHE/"--foo")
+ foo.mkpath
+ allow(ARGV).to receive(:value).with("prune").and_return("1")
+ allow_any_instance_of(Pathname).to receive(:mtime).and_return(Time.now - sec_in_a_day * 2)
+ described_class.cleanup_cache
+ expect(foo).not_to exist
+ end
+
+ it "does not clean up VCS checkout directories with modified time >= prune time" do
+ foo = (HOMEBREW_CACHE/"--foo")
+ foo.mkpath
+ allow(ARGV).to receive(:value).with("prune").and_return("1")
+ described_class.cleanup_cache
+ expect(foo).to exist
+ end
+
+ context "cleans old files in HOMEBREW_CACHE" do
+ let(:bottle) { (HOMEBREW_CACHE/"testball-0.0.1.bottle.tar.gz") }
+ let(:testball) { (HOMEBREW_CACHE/"testball-0.0.1") }
+
+ before(:each) do
+ FileUtils.touch(bottle)
+ FileUtils.touch(testball)
+ (HOMEBREW_CELLAR/"testball"/"0.0.1").mkpath
+ FileUtils.touch(CoreTap.instance.formula_dir/"testball.rb")
+ end
+
+ it "cleans up file if outdated" do
+ allow(Utils::Bottles).to receive(:file_outdated?).with(any_args).and_return(true)
+ described_class.cleanup_cache
+ expect(bottle).not_to exist
+ expect(testball).not_to exist
+ end
+
+ it "cleans up file if ARGV has -s and formula not installed" do
+ ARGV << "-s"
+ described_class.cleanup_cache
+ expect(bottle).not_to exist
+ expect(testball).not_to exist
+ end
+
+ it "cleans up file if stale" do
+ described_class.cleanup_cache
+ expect(bottle).not_to exist
+ expect(testball).not_to exist
+ end
+ end
+ end
+
+ describe "::prune?" do
+ before do
+ foo.mkpath
+ end
+
+ let(:foo) { HOMEBREW_CACHE/"foo" }
+
+ it "returns true when path_modified_time < days_default" do
+ allow_any_instance_of(Pathname).to receive(:mtime).and_return(Time.now - sec_in_a_day * 2)
+ expect(described_class.prune?(foo, days_default: "1")).to be_truthy
+ end
+
+ it "returns false when path_modified_time >= days_default" do
+ expect(described_class.prune?(foo, days_default: "2")).to be_falsey
+ end
end
end
diff --git a/Library/Homebrew/test/cmd/search_remote_tap_spec.rb b/Library/Homebrew/test/cmd/search_remote_tap_spec.rb
index b0beb122c..eb256b924 100644
--- a/Library/Homebrew/test/cmd/search_remote_tap_spec.rb
+++ b/Library/Homebrew/test/cmd/search_remote_tap_spec.rb
@@ -2,6 +2,9 @@ require "cmd/search"
describe Homebrew do
specify "#search_taps" do
+ # Otherwise the tested method returns [], regardless of our stub
+ ENV.delete("HOMEBREW_NO_GITHUB_API")
+
json_response = {
"items" => [
{
diff --git a/Library/Homebrew/test/cmd/search_spec.rb b/Library/Homebrew/test/cmd/search_spec.rb
index 77c2c6352..36ddde3e1 100644
--- a/Library/Homebrew/test/cmd/search_spec.rb
+++ b/Library/Homebrew/test/cmd/search_spec.rb
@@ -53,7 +53,7 @@ describe "brew search", :integration_test do
"debian" => "https://packages.debian.org/search?keywords=testball&searchon=names&suite=all&section=all",
"opensuse" => "https://software.opensuse.org/search?q=testball",
"fedora" => "https://apps.fedoraproject.org/packages/s/testball",
- "ubuntu" => "http://packages.ubuntu.com/search?keywords=testball&searchon=names&suite=all&section=all",
+ "ubuntu" => "https://packages.ubuntu.com/search?keywords=testball&searchon=names&suite=all&section=all",
}.each do |flag, url|
specify "--#{flag}" do
expect { brew "search", "--#{flag}", "testball", "HOMEBREW_BROWSER" => "echo" }
diff --git a/Library/Homebrew/test/dev-cmd/audit_spec.rb b/Library/Homebrew/test/dev-cmd/audit_spec.rb
index f2d8a8e7c..037865fdf 100644
--- a/Library/Homebrew/test/dev-cmd/audit_spec.rb
+++ b/Library/Homebrew/test/dev-cmd/audit_spec.rb
@@ -263,28 +263,6 @@ describe FormulaAuditor do
expect(fa.problems.shift)
.to eq('Use pkgshare instead of (share/"foolibc++")')
end
-
- specify "no space in class inheritance" do
- fa = formula_auditor "foo", <<-EOS.undent
- class Foo<Formula
- url '/foo-1.0.tgz'
- end
- EOS
-
- fa.line_problems "class Foo<Formula", 1
- expect(fa.problems.shift)
- .to eq("Use a space in class inheritance: class Foo < Formula")
- end
-
- specify "default template" do
- fa = formula_auditor "foo", "class Foo < Formula; url '/foo-1.0.tgz'; end"
-
- fa.line_problems '# system "cmake", ".", *std_cmake_args', 3
- expect(fa.problems.shift).to eq("Commented cmake call found")
-
- fa.line_problems "# PLEASE REMOVE", 3
- expect(fa.problems.shift).to eq("Please remove default template comments")
- end
end
describe "#audit_github_repository" do
diff --git a/Library/Homebrew/test/download_strategies_spec.rb b/Library/Homebrew/test/download_strategies_spec.rb
index 8c376a649..06d6fa855 100644
--- a/Library/Homebrew/test/download_strategies_spec.rb
+++ b/Library/Homebrew/test/download_strategies_spec.rb
@@ -200,6 +200,17 @@ describe GitDownloadStrategy do
end
end
+describe CurlDownloadStrategy do
+ subject { described_class.new(name, resource) }
+ let(:name) { "foo" }
+ let(:url) { "http://example.com/foo.tar.gz" }
+ let(:resource) { double(Resource, url: url, mirrors: [], specs: { user: "download:123456" }, version: nil) }
+
+ it "parses the opts and sets the corresponding args" do
+ expect(subject.send(:_curl_opts)).to eq(["--user", "download:123456"])
+ end
+end
+
describe DownloadStrategyDetector do
describe "::detect" do
subject { described_class.detect(url) }
diff --git a/Library/Homebrew/test/missing_formula_spec.rb b/Library/Homebrew/test/missing_formula_spec.rb
index a48f12ecd..0a905004b 100644
--- a/Library/Homebrew/test/missing_formula_spec.rb
+++ b/Library/Homebrew/test/missing_formula_spec.rb
@@ -82,12 +82,6 @@ describe Homebrew::MissingFormula do
it { is_expected.to be_blacklisted }
end
- context "clojure" do
- subject { "clojure" }
-
- it { is_expected.to be_blacklisted }
- end
-
context "gfortran" do
subject { "gfortran" }
diff --git a/Library/Homebrew/test/rubocops/lines_cop_spec.rb b/Library/Homebrew/test/rubocops/lines_cop_spec.rb
index c865e1480..b0ed8f4d1 100644
--- a/Library/Homebrew/test/rubocops/lines_cop_spec.rb
+++ b/Library/Homebrew/test/rubocops/lines_cop_spec.rb
@@ -51,3 +51,154 @@ describe RuboCop::Cop::FormulaAudit::Lines do
end
end
end
+
+describe RuboCop::Cop::FormulaAudit::ClassInheritance do
+ subject(:cop) { described_class.new }
+
+ context "When auditing lines" do
+ it "with no space in class inheritance" do
+ source = <<-EOS.undent
+ class Foo<Formula
+ desc "foo"
+ url 'http://example.com/foo-1.0.tgz'
+ end
+ EOS
+
+ expected_offenses = [{ message: "Use a space in class inheritance: class Foo < Formula",
+ severity: :convention,
+ line: 1,
+ column: 10,
+ source: source }]
+
+ inspect_source(cop, source)
+
+ expected_offenses.zip(cop.offenses).each do |expected, actual|
+ expect_offense(expected, actual)
+ end
+ end
+ end
+end
+
+describe RuboCop::Cop::FormulaAudit::Comments do
+ subject(:cop) { described_class.new }
+
+ context "When auditing formula" do
+ it "with commented cmake call" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ desc "foo"
+ url 'http://example.com/foo-1.0.tgz'
+ # system "cmake", ".", *std_cmake_args
+ end
+ EOS
+
+ expected_offenses = [{ message: "Please remove default template comments",
+ severity: :convention,
+ line: 4,
+ column: 2,
+ source: source }]
+
+ inspect_source(cop, source)
+
+ expected_offenses.zip(cop.offenses).each do |expected, actual|
+ expect_offense(expected, actual)
+ end
+ end
+
+ it "with default template comments" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ # PLEASE REMOVE
+ desc "foo"
+ url 'http://example.com/foo-1.0.tgz'
+ end
+ EOS
+
+ expected_offenses = [{ message: "Please remove default template comments",
+ 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 "with commented out depends_on" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ desc "foo"
+ url 'http://example.com/foo-1.0.tgz'
+ # depends_on "foo"
+ end
+ EOS
+
+ expected_offenses = [{ message: 'Commented-out dependency "foo"',
+ 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
+ end
+end
+
+describe RuboCop::Cop::FormulaAudit::Miscellaneous do
+ subject(:cop) { described_class.new }
+
+ context "When auditing formula" do
+ it "with FileUtils" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ desc "foo"
+ url 'http://example.com/foo-1.0.tgz'
+ FileUtils.mv "hello"
+ end
+ EOS
+
+ expected_offenses = [{ message: "Don't need 'FileUtils.' before mv",
+ severity: :convention,
+ line: 4,
+ column: 2,
+ source: source }]
+
+ inspect_source(cop, source)
+
+ expected_offenses.zip(cop.offenses).each do |expected, actual|
+ expect_offense(expected, actual)
+ end
+ end
+
+ it "with long inreplace block vars" do
+ source = <<-EOS.undent
+ class Foo < Formula
+ desc "foo"
+ url 'http://example.com/foo-1.0.tgz'
+ inreplace "foo" do |longvar|
+ somerandomCall(longvar)
+ end
+ end
+ EOS
+
+ expected_offenses = [{ message: "\"inreplace <filenames> do |s|\" is preferred over \"|longvar|\".",
+ 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
+ end
+end
diff --git a/Library/Homebrew/test/rubocops/patches_cop_spec.rb b/Library/Homebrew/test/rubocops/patches_cop_spec.rb
index 092782bfb..28915a1ec 100644
--- a/Library/Homebrew/test/rubocops/patches_cop_spec.rb
+++ b/Library/Homebrew/test/rubocops/patches_cop_spec.rb
@@ -28,11 +28,11 @@ describe RuboCop::Cop::FormulaAudit::Patches do
end
EOS
- expected_offenses = [{ message: "Use the patch DSL instead of defining a 'patches' method",
- severity: :convention,
- line: 4,
- column: 2,
- source: source }]
+ expected_offenses = [{ message: "Use the patch DSL instead of defining a 'patches' method",
+ severity: :convention,
+ line: 4,
+ column: 2,
+ source: source }]
inspect_source(cop, source)
@@ -48,6 +48,7 @@ describe RuboCop::Cop::FormulaAudit::Patches do
"http://trac.macports.org/export/102865/trunk/dports/mail/uudeview/files/inews.c.patch",
"http://bugs.debian.org/cgi-bin/bugreport.cgi?msg=5;filename=patch-libunac1.txt;att=1;bug=623340",
"https://patch-diff.githubusercontent.com/raw/foo/foo-bar/pull/100.patch",
+ "https://github.com/dlang/dub/pull/1221.patch",
]
patch_urls.each do |patch_url|
source = <<-EOS.undent
@@ -61,55 +62,64 @@ describe RuboCop::Cop::FormulaAudit::Patches do
EOS
inspect_source(cop, source)
- if patch_url =~ %r{/raw\.github\.com/}
- expected_offenses = [{ message: <<-EOS.undent.chomp,
- GitHub/Gist patches should specify a revision:
- #{patch_url}
- EOS
- severity: :convention,
- line: 5,
- column: 12,
- source: source }]
+ expected_offense = if patch_url =~ %r{/raw\.github\.com/}
+ [{ message: <<-EOS.undent.chomp,
+ GitHub/Gist patches should specify a revision:
+ #{patch_url}
+ EOS
+ severity: :convention,
+ line: 5,
+ column: 12,
+ source: source }]
elsif patch_url =~ %r{macports/trunk}
- expected_offenses = [{ message: <<-EOS.undent.chomp,
- MacPorts patches should specify a revision instead of trunk:
- #{patch_url}
- EOS
- severity: :convention,
- line: 5,
- column: 33,
- source: source }]
+ [{ message: <<-EOS.undent.chomp,
+ MacPorts patches should specify a revision instead of trunk:
+ #{patch_url}
+ EOS
+ severity: :convention,
+ line: 5,
+ column: 33,
+ source: source }]
elsif patch_url =~ %r{^http://trac\.macports\.org}
- expected_offenses = [{ message: <<-EOS.undent.chomp,
- Patches from MacPorts Trac should be https://, not http:
- #{patch_url}
- EOS
- severity: :convention,
- line: 5,
- column: 5,
- source: source }]
+ [{ message: <<-EOS.undent.chomp,
+ Patches from MacPorts Trac should be https://, not http:
+ #{patch_url}
+ EOS
+ severity: :convention,
+ line: 5,
+ column: 5,
+ source: source }]
elsif patch_url =~ %r{^http://bugs\.debian\.org}
- expected_offenses = [{ message: <<-EOS.undent.chomp,
- Patches from Debian should be https://, not http:
- #{patch_url}
- EOS
- severity: :convention,
- line: 5,
- column: 5,
- source: source }]
+ [{ message: <<-EOS.undent.chomp,
+ Patches from Debian should be https://, not http:
+ #{patch_url}
+ EOS
+ severity: :convention,
+ line: 5,
+ column: 5,
+ source: source }]
elsif patch_url =~ %r{https?://patch-diff\.githubusercontent\.com/raw/(.+)/(.+)/pull/(.+)\.(?:diff|patch)}
- expected_offenses = [{ message: <<-EOS.undent,
- use GitHub pull request URLs:
- https://github.com/foo/foo-bar/pull/100.patch
- Rather than patch-diff:
- https://patch-diff.githubusercontent.com/raw/foo/foo-bar/pull/100.patch
- EOS
- severity: :convention,
- line: 5,
- column: 5,
- source: source }]
+ [{ message: <<-EOS.undent,
+ use GitHub pull request URLs:
+ https://github.com/foo/foo-bar/pull/100.patch
+ Rather than patch-diff:
+ https://patch-diff.githubusercontent.com/raw/foo/foo-bar/pull/100.patch
+ EOS
+ severity: :convention,
+ line: 5,
+ column: 5,
+ source: source }]
+ elsif patch_url =~ %r{https?://github\.com/.+/.+/(?:commit|pull)/[a-fA-F0-9]*.(?:patch|diff)}
+ [{ message: <<-EOS.undent,
+ GitHub patches should use the full_index parameter:
+ #{patch_url}?full_index=1
+ EOS
+ severity: :convention,
+ line: 5,
+ column: 5,
+ source: source }]
end
- expected_offenses.zip([cop.offenses.last]).each do |expected, actual|
+ expected_offense.zip([cop.offenses.last]).each do |expected, actual|
expect_offense(expected, actual)
end
end
@@ -130,19 +140,19 @@ describe RuboCop::Cop::FormulaAudit::Patches do
end
EOS
- expected_offenses = [{ message: "Use the patch DSL instead of defining a 'patches' method",
- severity: :convention,
- line: 4,
- column: 2,
- source: source },
- { message: <<-EOS.undent.chomp,
- Patches from MacPorts Trac should be https://, not http:
- http://trac.macports.org/export/68507/trunk/dports/net/trafshow/files/
- EOS
- severity: :convention,
- line: 8,
- column: 26,
- source: source }]
+ expected_offenses = [{ message: "Use the patch DSL instead of defining a 'patches' method",
+ severity: :convention,
+ line: 4,
+ column: 2,
+ source: source },
+ { message: <<-EOS.undent.chomp,
+ Patches from MacPorts Trac should be https://, not http:
+ http://trac.macports.org/export/68507/trunk/dports/net/trafshow/files/
+ EOS
+ severity: :convention,
+ line: 8,
+ column: 26,
+ source: source }]
inspect_source(cop, source)
@@ -174,55 +184,55 @@ describe RuboCop::Cop::FormulaAudit::Patches do
EOS
inspect_source(cop, source)
- if patch_url =~ %r{/raw\.github\.com/}
- expected_offenses = [{ message: <<-EOS.undent.chomp,
- GitHub/Gist patches should specify a revision:
- #{patch_url}
- EOS
- severity: :convention,
- line: 5,
- column: 16,
- source: source }]
+ expected_offense = if patch_url =~ %r{/raw\.github\.com/}
+ [{ message: <<-EOS.undent.chomp,
+ GitHub/Gist patches should specify a revision:
+ #{patch_url}
+ EOS
+ severity: :convention,
+ line: 5,
+ column: 16,
+ source: source }]
elsif patch_url =~ %r{macports/trunk}
- expected_offenses = [{ message: <<-EOS.undent.chomp,
- MacPorts patches should specify a revision instead of trunk:
- #{patch_url}
- EOS
- severity: :convention,
- line: 5,
- column: 37,
- source: source }]
+ [{ message: <<-EOS.undent.chomp,
+ MacPorts patches should specify a revision instead of trunk:
+ #{patch_url}
+ EOS
+ severity: :convention,
+ line: 5,
+ column: 37,
+ source: source }]
elsif patch_url =~ %r{^http://trac\.macports\.org}
- expected_offenses = [{ message: <<-EOS.undent.chomp,
- Patches from MacPorts Trac should be https://, not http:
- #{patch_url}
- EOS
- severity: :convention,
- line: 5,
- column: 9,
- source: source }]
+ [{ message: <<-EOS.undent.chomp,
+ Patches from MacPorts Trac should be https://, not http:
+ #{patch_url}
+ EOS
+ severity: :convention,
+ line: 5,
+ column: 9,
+ source: source }]
elsif patch_url =~ %r{^http://bugs\.debian\.org}
- expected_offenses = [{ message: <<-EOS.undent.chomp,
- Patches from Debian should be https://, not http:
- #{patch_url}
- EOS
- severity: :convention,
- line: 5,
- column: 9,
- source: source }]
+ [{ message: <<-EOS.undent.chomp,
+ Patches from Debian should be https://, not http:
+ #{patch_url}
+ EOS
+ severity: :convention,
+ line: 5,
+ column: 9,
+ source: source }]
elsif patch_url =~ %r{https?://patch-diff\.githubusercontent\.com/raw/(.+)/(.+)/pull/(.+)\.(?:diff|patch)}
- expected_offenses = [{ message: <<-EOS.undent,
- use GitHub pull request URLs:
- https://github.com/foo/foo-bar/pull/100.patch
- Rather than patch-diff:
- https://patch-diff.githubusercontent.com/raw/foo/foo-bar/pull/100.patch
- EOS
- severity: :convention,
- line: 5,
- column: 9,
- source: source }]
+ [{ message: <<-EOS.undent,
+ use GitHub pull request URLs:
+ https://github.com/foo/foo-bar/pull/100.patch
+ Rather than patch-diff:
+ https://patch-diff.githubusercontent.com/raw/foo/foo-bar/pull/100.patch
+ EOS
+ severity: :convention,
+ line: 5,
+ column: 9,
+ source: source }]
end
- expected_offenses.zip([cop.offenses.last]).each do |expected, actual|
+ expected_offense.zip([cop.offenses.last]).each do |expected, actual|
expect_offense(expected, actual)
end
end
diff --git a/Library/Homebrew/test/utils/analytics_spec.rb b/Library/Homebrew/test/utils/analytics_spec.rb
new file mode 100644
index 000000000..bb6cda0b1
--- /dev/null
+++ b/Library/Homebrew/test/utils/analytics_spec.rb
@@ -0,0 +1,88 @@
+require "utils/analytics"
+require "formula_installer"
+
+describe Utils::Analytics do
+ describe "::os_prefix_ci" do
+ context "when anonymous_os_prefix_ci is not set" do
+ before(:each) do
+ described_class.clear_anonymous_os_prefix_ci_cache
+ end
+
+ it "returns OS_VERSION and prefix when HOMEBREW_PREFIX is not /usr/local" do
+ stub_const("HOMEBREW_PREFIX", "blah")
+ expect(described_class.os_prefix_ci).to include("#{OS_VERSION}, non-/usr/local")
+ end
+
+ it "includes CI when ENV['CI'] is set" do
+ ENV["CI"] = "true"
+ expect(described_class.os_prefix_ci).to include("CI")
+ end
+
+ it "does not include prefix when HOMEBREW_PREFIX is /usr/local" do
+ stub_const("HOMEBREW_PREFIX", "/usr/local")
+ expect(described_class.os_prefix_ci).not_to include("non-/usr/local")
+ end
+ end
+ end
+
+ describe "::report_event" do
+ let(:f) { formula { url "foo-1.0" } }
+ let(:options) { FormulaInstaller.new(f).display_options(f) }
+ let(:action) { "#{f.full_name} #{options}".strip }
+
+ context "when ENV vars is set" do
+ it "returns nil when HOMEBREW_NO_ANALYTICS is true" do
+ ENV["HOMEBREW_NO_ANALYTICS"] = "true"
+ expect(described_class.report_event("install", action)).to be_nil
+ end
+
+ it "returns nil when HOMEBREW_NO_ANALYTICS_THIS_RUN is true" do
+ ENV["HOMEBREW_NO_ANALYTICS_THIS_RUN"] = "true"
+ expect(described_class.report_event("install", action)).to be_nil
+ end
+
+ it "returns nil when HOMEBREW_ANALYTICS_DEBUG is true" do
+ ENV.delete("HOMEBREW_NO_ANALYTICS_THIS_RUN")
+ ENV.delete("HOMEBREW_NO_ANALYTICS")
+ ENV["HOMEBREW_ANALYTICS_DEBUG"] = "true"
+ expect(described_class.report_event("install", action)).to be_nil
+ end
+ end
+ end
+
+ describe "::report_build_error" do
+ context "when tap is installed" do
+ let(:err) { BuildError.new(f, "badprg", %w[arg1 arg2], {}) }
+ let(:f) { formula { url "foo-1.0" } }
+
+ it "reports event if BuildError raised for a formula with a public remote repository" do
+ allow_any_instance_of(Tap).to receive(:custom_remote?).and_return(false)
+ expect(described_class).to respond_to(:report_event)
+ described_class.report_build_error(err)
+ end
+
+ it "does not report event if BuildError raised for a formula with a private remote repository" do
+ expect(described_class.report_build_error(err)).to be_nil
+ end
+ end
+
+ context "when formula does not have a tap" do
+ let(:err) { BuildError.new(f, "badprg", %w[arg1 arg2], {}) }
+ let(:f) { double(Formula, name: "foo", path: "blah", tap: nil) }
+
+ it "does not report event if BuildError is raised" do
+ expect(described_class.report_build_error(err)).to be_nil
+ end
+ end
+
+ context "when tap for a formula is not installed" do
+ let(:err) { BuildError.new(f, "badprg", %w[arg1 arg2], {}) }
+ let(:f) { double(Formula, name: "foo", path: "blah", tap: CoreTap.instance) }
+
+ it "does not report event if BuildError is raised" do
+ allow_any_instance_of(Pathname).to receive(:directory?).and_return(false)
+ expect(described_class.report_build_error(err)).to be_nil
+ end
+ end
+ end
+end
diff --git a/Library/Homebrew/test/utils/git_spec.rb b/Library/Homebrew/test/utils/git_spec.rb
new file mode 100644
index 000000000..e511212f4
--- /dev/null
+++ b/Library/Homebrew/test/utils/git_spec.rb
@@ -0,0 +1,150 @@
+require "utils/git"
+
+describe Git do
+ before(:each) do
+ git = HOMEBREW_SHIMS_PATH/"scm/git"
+
+ HOMEBREW_CACHE.cd do
+ system git, "init"
+
+ File.open(file, "w") { |f| f.write("blah") }
+ system git, "add", HOMEBREW_CACHE/file
+ system git, "commit", "-m", "'File added'"
+ @h1 = `git rev-parse HEAD`
+
+ File.open(file, "w") { |f| f.write("brew") }
+ system git, "add", HOMEBREW_CACHE/file
+ system git, "commit", "-m", "'written to File'"
+ @h2 = `git rev-parse HEAD`
+ end
+ end
+
+ let(:file) { "blah.rb" }
+ let(:hash1) { @h1[0..6] }
+ let(:hash2) { @h2[0..6] }
+
+ describe "#last_revision_commit_of_file" do
+ it "gives last revision commit when before_commit is nil" do
+ expect(
+ described_class.last_revision_commit_of_file(HOMEBREW_CACHE, file),
+ ).to eq(hash1)
+ end
+
+ it "gives revision commit based on before_commit when it is not nil" do
+ expect(
+ described_class.last_revision_commit_of_file(HOMEBREW_CACHE,
+ file,
+ before_commit: hash2),
+ ).to eq(hash2)
+ end
+ end
+
+ describe "#last_revision_of_file" do
+ it "returns last revision of file" do
+ expect(
+ described_class.last_revision_of_file(HOMEBREW_CACHE,
+ HOMEBREW_CACHE/file),
+ ).to eq("blah")
+ end
+
+ it "returns last revision of file based on before_commit" do
+ expect(
+ described_class.last_revision_of_file(HOMEBREW_CACHE, HOMEBREW_CACHE/file,
+ before_commit: "0..3"),
+ ).to eq("brew")
+ end
+ end
+end
+
+describe Utils do
+ before(:each) do
+ described_class.clear_git_available_cache
+ end
+
+ describe "::git_available?" do
+ it "returns true if git --version command succeeds" do
+ expect(described_class.git_available?).to be_truthy
+ end
+
+ it "returns false if git --version command does not succeed" do
+ stub_const("HOMEBREW_SHIMS_PATH", HOMEBREW_PREFIX/"bin/shim")
+ expect(described_class.git_available?).to be_falsey
+ end
+ end
+
+ describe "::git_path" do
+ it "returns nil when git is not available" do
+ stub_const("HOMEBREW_SHIMS_PATH", HOMEBREW_PREFIX/"bin/shim")
+ expect(described_class.git_path).to eq(nil)
+ end
+
+ it "returns path of git when git is available" do
+ expect(described_class.git_path).to end_with("git")
+ end
+ end
+
+ describe "::git_version" do
+ it "returns nil when git is not available" do
+ stub_const("HOMEBREW_SHIMS_PATH", HOMEBREW_PREFIX/"bin/shim")
+ expect(described_class.git_path).to eq(nil)
+ end
+
+ it "returns version of git when git is available" do
+ expect(described_class.git_version).not_to be_nil
+ end
+ end
+
+ describe "::ensure_git_installed!" do
+ it "returns nil if git already available" do
+ expect(described_class.ensure_git_installed!).to be_nil
+ end
+
+ context "when git is not already available" do
+ before do
+ stub_const("HOMEBREW_SHIMS_PATH", HOMEBREW_PREFIX/"bin/shim")
+ end
+
+ it "can't install brewed git if homebrew/core is unavailable" do
+ allow_any_instance_of(Pathname).to receive(:directory?).and_return(false)
+ expect { described_class.ensure_git_installed! }.to raise_error("Git is unavailable")
+ end
+
+ it "raises error if can't install git" do
+ stub_const("HOMEBREW_BREW_FILE", HOMEBREW_PREFIX/"bin/brew")
+ expect { described_class.ensure_git_installed! }.to raise_error("Git is unavailable")
+ end
+
+ it "installs git" do
+ allow(Homebrew).to receive(:_system).with(any_args).and_return(true)
+ described_class.ensure_git_installed!
+ end
+ end
+ end
+
+ describe "::git_remote_exists" do
+ it "returns true when git is not available" do
+ stub_const("HOMEBREW_SHIMS_PATH", HOMEBREW_PREFIX/"bin/shim")
+ expect(described_class.git_remote_exists("blah")).to be_truthy
+ end
+
+ context "when git is available" do
+ it "returns true when git remote exists", :needs_network do
+ git = HOMEBREW_SHIMS_PATH/"scm/git"
+ url = "http://github.com/Homebrew/homebrew.github.io"
+ repo = HOMEBREW_CACHE/"hey"
+ repo.mkpath
+
+ repo.cd do
+ system git, "init"
+ system git, "remote", "add", "origin", url
+ end
+
+ expect(described_class.git_remote_exists(url)).to be_truthy
+ end
+
+ it "returns false when git remote does not exist" do
+ expect(described_class.git_remote_exists("blah")).to be_falsey
+ end
+ end
+ end
+end
diff --git a/Library/Homebrew/test/utils/svn_spec.rb b/Library/Homebrew/test/utils/svn_spec.rb
new file mode 100644
index 000000000..4edb365a0
--- /dev/null
+++ b/Library/Homebrew/test/utils/svn_spec.rb
@@ -0,0 +1,39 @@
+require "utils/svn"
+
+describe Utils do
+ describe "#self.svn_available?" do
+ before(:each) do
+ described_class.clear_svn_version_cache
+ end
+
+ it "returns svn version if svn available" do
+ expect(described_class.svn_available?).to be_truthy
+ end
+ end
+
+ describe "#self.svn_remote_exists" do
+ it "returns true when svn is not available" do
+ allow(Utils).to receive(:svn_available?).and_return(false)
+ expect(described_class.svn_remote_exists("blah")).to be_truthy
+ end
+
+ context "when svn is available" do
+ before do
+ allow(Utils).to receive(:svn_available?).and_return(true)
+ end
+
+ it "returns false when remote does not exist" do
+ expect(described_class.svn_remote_exists(HOMEBREW_CACHE/"install")).to be_falsey
+ end
+
+ it "returns true when remote exists", :needs_network do
+ remote = "http://github.com/Homebrew/install"
+ svn = HOMEBREW_SHIMS_PATH/"scm/svn"
+
+ HOMEBREW_CACHE.cd { system svn, "checkout", remote }
+
+ expect(described_class.svn_remote_exists(HOMEBREW_CACHE/"install")).to be_truthy
+ end
+ end
+ end
+end
diff --git a/Library/Homebrew/utils/analytics.rb b/Library/Homebrew/utils/analytics.rb
index a89995ba9..9766c14db 100644
--- a/Library/Homebrew/utils/analytics.rb
+++ b/Library/Homebrew/utils/analytics.rb
@@ -3,6 +3,11 @@ require "erb"
module Utils
module Analytics
class << self
+ def clear_anonymous_os_prefix_ci_cache
+ return unless instance_variable_defined?(:@anonymous_os_prefix_ci)
+ remove_instance_variable(:@anonymous_os_prefix_ci)
+ end
+
def os_prefix_ci
@anonymous_os_prefix_ci ||= begin
os = OS_VERSION
diff --git a/Library/Homebrew/utils/curl.rb b/Library/Homebrew/utils/curl.rb
index 52d03c93e..bc7055c0c 100644
--- a/Library/Homebrew/utils/curl.rb
+++ b/Library/Homebrew/utils/curl.rb
@@ -37,13 +37,12 @@ def curl(*args)
safe_system(*curl_args(*args))
end
-def curl_download(*args, to: nil, **options)
- continue_at ||= "-"
- curl("--location", "--remote-time", "--continue-at", continue_at, "--output", to, *args, **options)
+def curl_download(*args, to: nil, continue_at: "-", **options)
+ curl("--location", "--remote-time", "--continue-at", continue_at.to_s, "--output", to, *args, **options)
rescue ErrorDuringExecution
# `curl` error 33: HTTP server doesn't seem to support byte ranges. Cannot resume.
if $CHILD_STATUS.exitstatus == 33 && continue_at == "-"
- continue_at = "0"
+ continue_at = 0
retry
end
diff --git a/Library/Homebrew/utils/fork.rb b/Library/Homebrew/utils/fork.rb
index 92f5bf899..2f2a403e2 100644
--- a/Library/Homebrew/utils/fork.rb
+++ b/Library/Homebrew/utils/fork.rb
@@ -38,7 +38,7 @@ module Utils
Process.wait(pid) unless socket.nil?
raise Marshal.load(data) unless data.nil? || data.empty?
raise Interrupt if $CHILD_STATUS.exitstatus == 130
- raise "Suspicious failure" unless $CHILD_STATUS.success?
+ raise "Forked child process failed: #{$CHILD_STATUS}" unless $CHILD_STATUS.success?
end
end
end
diff --git a/Library/Homebrew/utils/git.rb b/Library/Homebrew/utils/git.rb
index 43d93b64e..1fc01188c 100644
--- a/Library/Homebrew/utils/git.rb
+++ b/Library/Homebrew/utils/git.rb
@@ -16,8 +16,7 @@ module Git
def last_revision_of_file(repo, file, before_commit: nil)
relative_file = Pathname(file).relative_path_from(repo)
- commit_hash = last_revision_commit_of_file(repo, file, before_commit: before_commit)
-
+ commit_hash = last_revision_commit_of_file(repo, relative_file, before_commit: before_commit)
out, = Open3.capture3(
HOMEBREW_SHIMS_PATH/"scm/git", "-C", repo,
"show", "#{commit_hash}:#{relative_file}"
diff --git a/Library/Homebrew/utils/github.rb b/Library/Homebrew/utils/github.rb
index a1cf5fbba..a50d6d8e5 100644
--- a/Library/Homebrew/utils/github.rb
+++ b/Library/Homebrew/utils/github.rb
@@ -245,7 +245,7 @@ module GitHub
end
def print_pull_requests_matching(query)
- open_or_closed_prs = search_issues(query, type: "pr")
+ open_or_closed_prs = search_issues(query, type: "pr", user: "Homebrew")
open_prs = open_or_closed_prs.select { |i| i["state"] == "open" }
prs = if !open_prs.empty?
diff --git a/Library/Homebrew/utils/svn.rb b/Library/Homebrew/utils/svn.rb
index fb49ac2e9..150b7eee7 100644
--- a/Library/Homebrew/utils/svn.rb
+++ b/Library/Homebrew/utils/svn.rb
@@ -1,4 +1,8 @@
module Utils
+ def self.clear_svn_version_cache
+ remove_instance_variable(:@svn) if instance_variable_defined?(:@svn)
+ end
+
def self.svn_available?
return @svn if instance_variable_defined?(:@svn)
@svn = quiet_system HOMEBREW_SHIMS_PATH/"scm/svn", "--version"