Merge branch 'master' into appcast-configuration-match

This commit is contained in:
Vítor Galvão 2020-06-06 03:04:57 +01:00 committed by GitHub
commit 446ef2c85f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
204 changed files with 2282 additions and 1386 deletions

View File

@ -4,6 +4,8 @@ about: Request our thoughts on your suggestion for a new feature for Homebrew.
---
# Please note we will close your issue without comment if you delete, do not read or do not fill out the issue checklist below and provide ALL the requested information. If you repeatedly fail to use the issue template, we will block you from ever submitting issues to Homebrew again.
<!-- Please fill these sections with the relevant information: -->
# A detailed description of the proposed feature

View File

@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
version: ["18.04", "20.04"]
version: ["16.04", "18.04", "20.04"]
steps:
- name: Checkout
uses: actions/checkout@master
@ -33,9 +33,24 @@ jobs:
docker login docker.pkg.github.com -u BrewTestBot -p ${{secrets.GITHUB_TOKEN}}
docker tag brew "docker.pkg.github.com/homebrew/brew/ubuntu${{matrix.version}}:$brew_version"
docker push "docker.pkg.github.com/homebrew/brew/ubuntu${{matrix.version}}:$brew_version"
docker tag brew "docker.pkg.github.com/homebrew/brew/ubuntu${{matrix.version}}:latest"
docker push "docker.pkg.github.com/homebrew/brew/ubuntu${{matrix.version}}:latest"
- name: Deploy the tagged Docker image to Docker Hub
if: startsWith(github.ref, 'refs/tags/')
run: |
docker login -u brewtestbot -p ${{secrets.DOCKER_TOKEN}}
docker tag brew "homebrew/ubuntu${{matrix.version}}:$brew_version"
docker push "homebrew/ubuntu${{matrix.version}}:$brew_version"
docker tag brew "homebrew/ubuntu${{matrix.version}}:latest"
docker push "homebrew/ubuntu${{matrix.version}}:latest"
- name: Deploy the homebrew/brew Docker image to GitHub and Docker Hub
if: startsWith(github.ref, 'refs/tags/') && matrix.version == '20.04'
run: |
docker tag brew "docker.pkg.github.com/homebrew/brew/brew:$brew_version"
docker push "docker.pkg.github.com/homebrew/brew/brew:$brew_version"
docker tag brew "docker.pkg.github.com/homebrew/brew/brew:latest"
docker push "docker.pkg.github.com/homebrew/brew/brew:latest"
docker tag brew "homebrew/brew:$brew_version"
docker push "homebrew/brew:$brew_version"
docker tag brew "homebrew/brew:latest"
docker push "homebrew/brew:latest"

View File

@ -3,9 +3,6 @@ on:
push:
branches: master
pull_request: []
release:
types:
- published
env:
HOMEBREW_GITHUB_ACTIONS: 1
HOMEBREW_NO_AUTO_UPDATE: 1
@ -71,6 +68,9 @@ jobs:
else
# Link old gettext (otherwise `brew doctor` is sad)
brew link gettext
# remove deleted formula
brew uninstall --force python@2
fi
brew doctor
@ -173,7 +173,7 @@ jobs:
- name: Build Docker image
if: matrix.os == 'ubuntu-latest'
run: docker build -t brew .
run: docker build -t brew --build-arg=version=16.04 .
- name: Run brew test-bot
run: |
@ -184,16 +184,11 @@ jobs:
fi
- name: Deploy the Docker image to GitHub and Docker Hub
if: matrix.os == 'ubuntu-latest' && (github.ref == 'refs/heads/master' || github.event_name == 'release')
if: matrix.os == 'ubuntu-latest' && github.ref == 'refs/heads/master'
run: |
case $GITHUB_REF in
refs/heads/master) v=latest ;;
refs/tags/*) v=${GITHUB_REF:10} ;;
*) echo Error: unexpected GITHUB_REF: $GITHUB_REF; exit 1 ;;
esac
docker login docker.pkg.github.com -u BrewTestBot -p ${{secrets.GITHUB_TOKEN}}
docker tag brew "docker.pkg.github.com/homebrew/brew/brew:$v"
docker push "docker.pkg.github.com/homebrew/brew/brew:$v"
docker tag brew "docker.pkg.github.com/homebrew/brew/ubuntu16.04:master"
docker push "docker.pkg.github.com/homebrew/brew/ubuntu16.04:master"
docker login -u brewtestbot -p ${{secrets.DOCKER_TOKEN}}
docker tag brew "homebrew/brew:$v"
docker push "homebrew/brew:$v"
docker tag brew "homebrew/ubuntu16.04:master"
docker push "homebrew/ubuntu16.04:master"

2
.gitignore vendored
View File

@ -110,6 +110,7 @@
**/vendor/bundle/ruby/*/gems/pry-*/
**/vendor/bundle/ruby/*/gems/rainbow-*/
**/vendor/bundle/ruby/*/gems/rdiscount-*/
**/vendor/bundle/ruby/*/gems/regexp_parser-*/
**/vendor/bundle/ruby/*/gems/ronn-*/
**/vendor/bundle/ruby/*/gems/rspec-*/
**/vendor/bundle/ruby/*/gems/rspec-core-*/
@ -120,6 +121,7 @@
**/vendor/bundle/ruby/*/gems/rspec-support-*/
**/vendor/bundle/ruby/*/gems/rspec-wait-*/
**/vendor/bundle/ruby/*/gems/rubocop-0*/
**/vendor/bundle/ruby/*/gems/rubocop-ast-*/
**/vendor/bundle/ruby/*/gems/ruby-prof-*/
**/vendor/bundle/ruby/*/gems/ruby-progressbar-*/
**/vendor/bundle/ruby/*/gems/simplecov-*/

View File

@ -1,4 +1,4 @@
ARG version=16.04
ARG version=20.04
FROM ubuntu:$version
ARG DEBIAN_FRONTEND=noninteractive
@ -42,6 +42,8 @@ RUN cd /home/linuxbrew/.linuxbrew \
&& HOMEBREW_NO_ANALYTICS=1 HOMEBREW_NO_AUTO_UPDATE=1 brew tap homebrew/core \
&& brew install-bundler-gems \
&& brew cleanup \
&& { git -C /home/linuxbrew/.linuxbrew/Homebrew config --unset gc.auto; true; } \
&& { git -C /home/linuxbrew/.linuxbrew/Homebrew config --unset homebrew.devcmdrun; true; } \
&& rm -rf ~/.cache \
&& chown -R linuxbrew: /home/linuxbrew/.linuxbrew \
&& chmod -R g+w,o-w /home/linuxbrew/.linuxbrew

View File

@ -8,7 +8,7 @@ AllCops:
# Use `<<~` for heredocs.
Layout/HeredocIndentation:
EnforcedStyle: squiggly
Enabled: true
# Not useful in casks and formulae.
Metrics/BlockLength:

View File

@ -10,7 +10,7 @@ GEM
ast (2.4.0)
byebug (11.1.3)
concurrent-ruby (1.1.6)
connection_pool (2.2.2)
connection_pool (2.2.3)
coveralls (0.8.23)
json (>= 1.8, < 3)
simplecov (~> 0.16.1)
@ -24,7 +24,7 @@ GEM
hpricot (0.8.6)
http-cookie (1.0.3)
domain_name (~> 0.5)
i18n (1.8.2)
i18n (1.8.3)
concurrent-ruby (~> 1.0)
json (2.3.0)
mechanize (2.7.6)
@ -51,11 +51,12 @@ GEM
parallel (1.19.1)
parallel_tests (2.32.0)
parallel
parser (2.7.1.2)
parser (2.7.1.3)
ast (~> 2.4.0)
plist (3.5.0)
rainbow (3.0.0)
rdiscount (2.2.0.1)
regexp_parser (1.7.0)
rexml (3.2.4)
ronn (0.7.3)
hpricot (>= 0.8.2)
@ -81,14 +82,18 @@ GEM
rspec-support (3.9.3)
rspec-wait (0.0.9)
rspec (>= 3, < 4)
rubocop (0.83.0)
rubocop (0.85.0)
parallel (~> 1.10)
parser (>= 2.7.0.1)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.7)
rexml
rubocop-ast (>= 0.0.3)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 2.0)
rubocop-performance (1.5.2)
rubocop-ast (0.0.3)
parser (>= 2.7.0.1)
rubocop-performance (1.6.1)
rubocop (>= 0.71.0)
rubocop-rspec (1.39.0)
rubocop (>= 0.68.1)

View File

@ -50,7 +50,7 @@ begin
help_flag = !ENV["HOMEBREW_HELP"].nil?
cmd = nil
ARGV.dup.each_with_index do |arg, i|
ARGV.each_with_index do |arg, i|
break if help_flag && cmd
if arg == "help" && !cmd
@ -139,8 +139,8 @@ rescue UsageError => e
require "help"
Homebrew::Help.help cmd, usage_error: e.message
rescue SystemExit => e
onoe "Kernel.exit" if ARGV.debug? && !e.success?
$stderr.puts e.backtrace if ARGV.debug?
onoe "Kernel.exit" if Homebrew.args.debug? && !e.success?
$stderr.puts e.backtrace if Homebrew.args.debug?
raise
rescue Interrupt
$stderr.puts # seemingly a newline is typical
@ -156,7 +156,7 @@ rescue RuntimeError, SystemCallError => e
raise if e.message.empty?
onoe e
$stderr.puts e.backtrace if ARGV.debug?
$stderr.puts e.backtrace if Homebrew.args.debug?
output_unsupported_error if Homebrew.args.HEAD?
@ -167,7 +167,7 @@ rescue MethodDeprecatedError => e
$stderr.puts "If reporting this issue please do so at (not Homebrew/brew or Homebrew/core):"
$stderr.puts " #{Formatter.url(e.issues_url)}"
end
$stderr.puts e.backtrace if ARGV.debug?
$stderr.puts e.backtrace if Homebrew.args.debug?
exit 1
rescue Exception => e # rubocop:disable Lint/RescueException
onoe e

View File

@ -52,6 +52,8 @@ class Build
Requirement.prune
elsif req.prune_if_build_and_not_dependent?(dependent, formula)
Requirement.prune
elsif req.test?
Requirement.prune
end
end
end
@ -65,6 +67,8 @@ class Build
Dependency.prune
elsif dep.build?
Dependency.keep_but_prune_recursive_deps
elsif dep.test?
Dependency.prune
end
end
end
@ -112,7 +116,7 @@ class Build
}
with_env(new_env) do
formula.extend(Debrew::Formula) if ARGV.debug?
formula.extend(Debrew::Formula) if Homebrew.args.debug?
formula.update_head_version

View File

@ -89,7 +89,7 @@ module Cask
args: ["list", service],
sudo: with_sudo, print_stderr: false
).stdout
if plist_status.match?(/^\{/)
if plist_status.start_with?("{")
command.run!("/bin/launchctl", args: ["remove", service], sudo: with_sudo)
sleep 1
end
@ -326,7 +326,14 @@ module Cask
next
end
begin
yield path, Pathname.glob(resolved_path)
rescue Errno::EPERM
raise if File.readable?(File.expand_path("~/Library/Application Support/com.apple.TCC"))
odie "Unable to remove some files. Please enable Full Disk Access for your terminal under " \
"System Preferences → Security & Privacy → Privacy → Full Disk Access."
end
end
end

View File

@ -6,6 +6,7 @@ require "cask/download"
require "digest"
require "utils/curl"
require "utils/git"
require "utils/notability"
module Cask
class Audit
@ -14,22 +15,22 @@ module Cask
attr_reader :cask, :commit_range, :download
attr_predicate :check_appcast?
attr_predicate :appcast?
def initialize(cask, check_appcast: false, download: false, check_token_conflicts: false,
commit_range: nil, command: SystemCommand)
def initialize(cask, appcast: false, download: false,
token_conflicts: false, online: false, strict: false,
new_cask: false, commit_range: nil, command: SystemCommand)
@cask = cask
@check_appcast = check_appcast
@appcast = appcast
@download = download
@online = online
@strict = strict
@new_cask = new_cask
@commit_range = commit_range
@check_token_conflicts = check_token_conflicts
@token_conflicts = token_conflicts
@command = command
end
def check_token_conflicts?
@check_token_conflicts
end
def run!
check_blacklist
check_required_stanzas
@ -48,6 +49,9 @@ module Cask
check_latest_with_auto_updates
check_stanza_requires_uninstall
check_appcast_contains_version
check_github_repository
check_gitlab_repository
check_bitbucket_repository
self
rescue => e
odebug "#{e.message}\n#{e.backtrace.join("\n")}"
@ -255,7 +259,7 @@ module Cask
bad_url_format?(/sourceforge/,
[
%r{\Ahttps://sourceforge\.net/projects/[^/]+/files/latest/download\Z},
%r{\Ahttps://downloads\.sourceforge\.net/(?!(project|sourceforge)\/)},
%r{\Ahttps://downloads\.sourceforge\.net/(?!(project|sourceforge)/)},
])
end
@ -272,7 +276,7 @@ module Cask
end
def check_token_conflicts
return unless check_token_conflicts?
return unless @token_conflicts
return unless core_formula_names.include?(cask.token)
add_warning "possible duplicate, cask token conflicts with Homebrew core formula: #{core_formula_url}"
@ -301,7 +305,7 @@ module Cask
end
def check_appcast_contains_version
return unless check_appcast?
return unless appcast?
return if cask.appcast.to_s.empty?
return if cask.appcast.must_contain == :no_check
@ -309,8 +313,8 @@ module Cask
appcast_contents, = curl_output("--compressed", "--user-agent", HOMEBREW_USER_AGENT_FAKE_SAFARI, "--location",
"--globoff", "--max-time", "5", appcast_stanza)
version_stanza = cask.version.to_s
adjusted_version_stanza = if cask.appcast.must_contain.blank?
version_stanza.split(",")[0].split("-")[0].split("_")[0]
adjusted_version_stanza = if cask.appcast.configuration.blank?
version_stanza.match(/^[[:alnum:].]+/)[0]
else
cask.appcast.must_contain
end
@ -322,6 +326,50 @@ module Cask
add_error "appcast at URL '#{appcast_stanza}' offline or looping"
end
def check_github_repository
user, repo = get_repo_data(%r{https?://github\.com/([^/]+)/([^/]+)/?.*})
return if user.nil?
odebug "Auditing GitHub repo"
error = SharedAudits.github(user, repo)
add_error error if error
end
def check_gitlab_repository
user, repo = get_repo_data(%r{https?://gitlab\.com/([^/]+)/([^/]+)/?.*})
return if user.nil?
odebug "Auditing GitLab repo"
error = SharedAudits.gitlab(user, repo)
add_error error if error
end
def check_bitbucket_repository
user, repo = get_repo_data(%r{https?://bitbucket\.org/([^/]+)/([^/]+)/?.*})
return if user.nil?
odebug "Auditing Bitbucket repo"
error = SharedAudits.bitbucket(user, repo)
add_error error if error
end
def get_repo_data(regex)
return unless @online
return unless @new_cask
_, user, repo = *regex.match(cask.url.to_s)
_, user, repo = *regex.match(cask.homepage) unless user
_, user, repo = *regex.match(cask.appcast.to_s) unless user
return if !user || !repo
repo.gsub!(/.git$/, "")
[user, repo]
end
def check_blacklist
return if cask.tap&.user != "Homebrew"
return unless reason = Blacklist.blacklisted_reason(cask.token)

View File

@ -8,37 +8,40 @@ module Cask
extend Predicable
def self.audit(cask, audit_download: false, audit_appcast: false,
check_token_conflicts: false, quarantine: true, commit_range: nil)
audit_online: false, audit_strict: false,
audit_token_conflicts: false, audit_new_cask: false,
quarantine: true, commit_range: nil)
new(cask, audit_download: audit_download,
audit_appcast: audit_appcast,
check_token_conflicts: check_token_conflicts,
audit_online: audit_online,
audit_new_cask: audit_new_cask,
audit_strict: audit_strict,
audit_token_conflicts: audit_token_conflicts,
quarantine: quarantine, commit_range: commit_range).audit
end
attr_reader :cask, :commit_range
def initialize(cask, audit_download: false, audit_appcast: false,
check_token_conflicts: false, quarantine: true, commit_range: nil)
audit_online: false, audit_strict: false,
audit_token_conflicts: false, audit_new_cask: false,
quarantine: true, commit_range: nil)
@cask = cask
@audit_download = audit_download
@audit_appcast = audit_appcast
@audit_online = audit_online
@audit_strict = audit_strict
@audit_new_cask = audit_new_cask
@quarantine = quarantine
@commit_range = commit_range
@check_token_conflicts = check_token_conflicts
@audit_token_conflicts = audit_token_conflicts
end
def audit_download?
@audit_download
end
attr_predicate :audit_appcast?, :quarantine?
def check_token_conflicts?
@check_token_conflicts
end
attr_predicate :audit_appcast?, :audit_download?, :audit_online?,
:audit_strict?, :audit_new_cask?, :audit_token_conflicts?, :quarantine?
def audit
if !ARGV.value("language") && language_blocks
if !Homebrew.args.value("language") && language_blocks
audit_all_languages
else
audit_cask_instance(cask)
@ -64,9 +67,12 @@ module Cask
def audit_cask_instance(cask)
download = audit_download? && Download.new(cask, quarantine: quarantine?)
audit = Audit.new(cask, check_appcast: audit_appcast?,
audit = Audit.new(cask, appcast: audit_appcast?,
online: audit_online?,
strict: audit_strict?,
new_cask: audit_new_cask?,
token_conflicts: audit_token_conflicts?,
download: download,
check_token_conflicts: check_token_conflicts?,
commit_range: commit_range)
audit.run!
puts audit.summary

View File

@ -4,7 +4,7 @@ module Cask
module Blacklist
def self.blacklisted_reason(name)
case name
when /^adobe\-(after|illustrator|indesign|photoshop|premiere)/
when /^adobe-(after|illustrator|indesign|photoshop|premiere)/
"Adobe casks were removed because they are too difficult to maintain."
when /^audacity$/
"Audacity was removed because it is too difficult to download programmatically."

View File

@ -145,13 +145,13 @@ module Cask
command, args = detect_internal_command(*args) || detect_external_command(*args) || [NullCommand.new, args]
if help?
puts command.help
Help.new(command.command_name).run
else
command.run(*args)
end
rescue CaskError, MethodDeprecatedError, ArgumentError, OptionParser::InvalidOption => e
onoe e.message
$stderr.puts e.backtrace if ARGV.debug?
$stderr.puts e.backtrace if Homebrew.args.debug?
exit 1
rescue StandardError, ScriptError, NoMemoryError => e
onoe e.message
@ -180,7 +180,7 @@ module Cask
end
def process_options(*args)
exclude_regex = /^\-\-#{Regexp.union(*Config::DEFAULT_DIRS.keys.map(&Regexp.public_method(:escape)))}=/
exclude_regex = /^--#{Regexp.union(*Config::DEFAULT_DIRS.keys.map(&Regexp.public_method(:escape)))}=/
non_options = []

View File

@ -1,32 +1,66 @@
# frozen_string_literal: true
require "cli/parser"
module Cask
class Cmd
class Audit < AbstractCommand
option "--download", :download, false
option "--appcast", :appcast, false
option "--token-conflicts", :token_conflicts, false
option "--download", :download_arg, false
option "--appcast", :appcast_arg, false
option "--token-conflicts", :token_conflicts_arg, false
option "--strict", :strict_arg, false
option "--online", :online_arg, false
option "--new-cask", :new_cask_arg, false
def self.usage
<<~EOS
`cask audit` [<options>] [<cask>]
--strict - Run additional, stricter style checks.
--online - Run additional, slower style checks that require a network connection.
--new-cask - Run various additional style checks to determine if a new cask is eligible
for Homebrew. This should be used when creating new casks and implies
`--strict` and `--online`.
--download - Audit the downloaded file
--appcast - Audit the appcast
--token-conflicts - Audit for token conflicts
Check <cask> for Homebrew coding style violations. This should be run before
submitting a new cask. If no <casks> are provided, check all locally
available casks. Will exit with a non-zero status if any errors are
found, which can be useful for implementing pre-commit hooks.
EOS
end
def self.help
"verifies installability of Casks"
end
def run
Homebrew.auditing = true
strict = new_cask_arg? || strict_arg?
token_conflicts = strict || token_conflicts_arg?
online = new_cask_arg? || online_arg?
download = online || download_arg?
appcast = online || appcast_arg?
failed_casks = casks(alternative: -> { Cask.to_a })
.reject { |cask| audit(cask) }
.reject do |cask|
odebug "Auditing Cask #{cask}"
Auditor.audit(cask, audit_download: download,
audit_appcast: appcast,
audit_online: online,
audit_strict: strict,
audit_new_cask: new_cask_arg?,
audit_token_conflicts: token_conflicts,
quarantine: quarantine?)
end
return if failed_casks.empty?
raise CaskError, "audit failed for casks: #{failed_casks.join(" ")}"
end
def audit(cask)
odebug "Auditing Cask #{cask}"
Auditor.audit(cask, audit_download: download?,
audit_appcast: appcast?,
check_token_conflicts: token_conflicts?,
quarantine: quarantine?)
end
end
end
end

View File

@ -3,17 +3,26 @@
module Cask
class Cmd
class Help < AbstractCommand
def initialize(*)
super
return if args.empty?
raise ArgumentError, "#{self.class.command_name} does not take arguments."
end
def run
if args.empty?
puts self.class.purpose
puts
puts self.class.usage
elsif args.count == 1
command_name = args.first
unless command = self.class.commands[command_name]
raise "No help information found for command '#{command_name}'."
end
if command.respond_to?(:usage)
puts command.usage
else
puts command.help
end
else
raise ArgumentError, "#{self.class.command_name} only takes up to one argument."
end
end
def self.purpose
@ -23,6 +32,10 @@ module Cask
EOS
end
def self.commands
Cmd.command_classes.select(&:visible?).map { |klass| [klass.command_name, klass] }.to_h
end
def self.usage
max_command_len = Cmd.commands.map(&:length).max

View File

@ -46,6 +46,7 @@ module Cask
def self.info(cask)
puts get_info(cask)
::Utils::Analytics.cask_output(cask)
end
def self.title_info(cask)

View File

@ -46,7 +46,7 @@ module Cask
next if self.class.options.nil?
self.class.options.each do |option_name, option_method|
option_type = case option_name.split(/(\ |\=)/).last
option_type = case option_name.split(/(\ |=)/).last
when "PATH"
Pathname
when /\w+(,\w+)+/

View File

@ -86,7 +86,7 @@ module Cask
Shellwords.shellsplit(ENV.fetch("HOMEBREW_CASK_OPTS", ""))
.select { |arg| arg.include?("=") }
.map { |arg| arg.split("=", 2) }
.map { |(flag, value)| [flag.sub(/^\-\-/, ""), value] },
.map { |(flag, value)| [flag.sub(/^--/, ""), value] },
)
end

View File

@ -58,6 +58,19 @@ module Cask
EOS
end
caveat :unsigned_accessibility do |access = "Accessibility"|
# access: the category in System Preferences -> Security & Privacy -> Privacy the app requires.
<<~EOS
#{@cask} is not signed and requires Accessibility access,
so you will need to re-grant Accessibility access every time the app is updated.
Enable or re-enable it in:
System Preferences Security & Privacy Privacy -> #{access}
To re-enable untick and retick #{@cask}.app.
EOS
end
caveat :path_environment_variable do |path|
<<~EOS
To use #{@cask}, you may need to add the #{path} directory

View File

@ -11,9 +11,9 @@ module Cask
DIVIDER_REGEX = /(#{DIVIDERS.keys.map { |v| Regexp.quote(v) }.join('|')})/.freeze
MAJOR_MINOR_PATCH_REGEX = /^([^.,:]+)(?:\.([^.,:]+)(?:\.([^.,:]+))?)?/.freeze
MAJOR_MINOR_PATCH_REGEX = /^([^.,:]+)(?:.([^.,:]+)(?:.([^.,:]+))?)?/.freeze
INVALID_CHARACTERS = /[^0-9a-zA-Z\.\,\:\-\_]/.freeze
INVALID_CHARACTERS = /[^0-9a-zA-Z.,:\-_]/.freeze
class << self
private
@ -75,7 +75,7 @@ module Cask
s = downcase.delete(".").gsub(/[^a-z\d]+/, "-")
return true if s.match?(/(\d+|\b)(alpha|beta|preview|rc|dev|canary|snapshot)(\d+|\b)/i)
return true if s.match?(/\A[a-z\d]+(\-\d+)*\-?(a|b|pre)(\d+|\b)/i)
return true if s.match?(/\A[a-z\d]+(-\d+)*-?(a|b|pre)(\d+|\b)/i)
false
end

View File

@ -368,8 +368,8 @@ module Cask
fi.installed_on_request = false
fi.show_header = true
fi.verbose = verbose?
fi.fetch
fi.prelude
fi.fetch
fi.install
fi.finish
end

View File

@ -109,7 +109,7 @@ class Cleaner
else
0444
end
if ARGV.debug?
if Homebrew.args.debug?
old_perms = path.stat.mode & 0777
odebug "Fixing #{path} permissions from #{old_perms.to_s(8)} to #{perms.to_s(8)}" if perms != old_perms
end

View File

@ -56,14 +56,14 @@ module CleanupRefinement
end
end
version ||= basename.to_s[/\A.*(?:\-\-.*?)*\-\-(.*?)#{Regexp.escape(extname)}\Z/, 1]
version ||= basename.to_s[/\A.*\-\-?(.*?)#{Regexp.escape(extname)}\Z/, 1]
version ||= basename.to_s[/\A.*(?:--.*?)*--(.*?)#{Regexp.escape(extname)}\Z/, 1]
version ||= basename.to_s[/\A.*--?(.*?)#{Regexp.escape(extname)}\Z/, 1]
return false unless version
version = Version.new(version)
return false unless formula_name = basename.to_s[/\A(.*?)(?:\-\-.*?)*\-\-?(?:#{Regexp.escape(version)})/, 1]
return false unless formula_name = basename.to_s[/\A(.*?)(?:--.*?)*--?(?:#{Regexp.escape(version)})/, 1]
formula = begin
Formulary.from_rack(HOMEBREW_CELLAR/formula_name)
@ -71,7 +71,7 @@ module CleanupRefinement
return false
end
resource_name = basename.to_s[/\A.*?\-\-(.*?)\-\-?(?:#{Regexp.escape(version)})/, 1]
resource_name = basename.to_s[/\A.*?--(.*?)--?(?:#{Regexp.escape(version)})/, 1]
if resource_name == "patch"
patch_hashes = formula.stable&.patches&.select(&:external?)&.map(&:resource)&.map(&:version)
@ -84,7 +84,7 @@ module CleanupRefinement
return true
end
return true if scrub && !formula.installed?
return true if scrub && !formula.latest_version_installed?
return true if Utils::Bottles.file_outdated?(formula, self)
@ -92,7 +92,7 @@ module CleanupRefinement
end
def stale_cask?(scrub)
return false unless name = basename.to_s[/\A(.*?)\-\-/, 1]
return false unless name = basename.to_s[/\A(.*?)--/, 1]
cask = begin
Cask::CaskLoader.load(name)
@ -100,7 +100,7 @@ module CleanupRefinement
return false
end
return true unless basename.to_s.match?(/\A#{Regexp.escape(name)}\-\-#{Regexp.escape(cask.version)}\b/)
return true unless basename.to_s.match?(/\A#{Regexp.escape(name)}--#{Regexp.escape(cask.version)}\b/)
return true if scrub && !cask.versions.include?(cask.version)

View File

@ -10,7 +10,7 @@ module Homebrew
# undefine tap to allow --tap argument
undef tap
def initialize(argv = ARGV.dup.freeze, set_default_args: false)
def initialize(argv = ARGV.freeze, set_default_args: false)
super()
@processed_options = []
@ -84,11 +84,7 @@ module Homebrew
require "formula"
@formulae ||= (downcased_unique_named - casks).map do |name|
if name.include?("/") || File.exist?(name)
Formulary.factory(name, spec)
else
Formulary.find_with_priority(name, spec)
end
end.uniq(&:name).freeze
end
@ -175,6 +171,20 @@ module Homebrew
formulae.any? { |args_f| args_f.full_name == f.full_name }
end
def include_formula_test_deps?(f)
return false unless include_test?
formulae.any? { |args_f| args_f.full_name == f.full_name }
end
def value(name)
arg_prefix = "--#{name}="
flag_with_value = flags_only.find { |arg| arg.start_with?(arg_prefix) }
return unless flag_with_value
flag_with_value.delete_prefix(arg_prefix)
end
private
def option_to_name(option)

View File

@ -13,7 +13,7 @@ module Homebrew
class Parser
attr_reader :processed_options, :hide_from_man_page
def self.parse(argv = ARGV.dup.freeze, allow_no_named_args: false, &block)
def self.parse(argv = ARGV.freeze, allow_no_named_args: false, &block)
new(argv, &block).parse(allow_no_named_args: allow_no_named_args)
end
@ -38,7 +38,7 @@ module Homebrew
}
end
def initialize(argv = ARGV.dup.freeze, &block)
def initialize(argv = ARGV.freeze, &block)
@parser = OptionParser.new
@argv = argv
@args = Homebrew::CLI::Args.new(@argv)
@ -359,11 +359,7 @@ module Homebrew
named_args.map do |arg|
next if arg.match?(HOMEBREW_CASK_TAP_CASK_REGEX)
if arg.include?("/") || arg.end_with?(".tar.gz") || File.exist?(arg)
Formulary.factory(arg, spec)
else
Formulary.find_with_priority(arg.downcase, spec)
end
end.compact.uniq(&:name)
end
end

View File

@ -36,7 +36,6 @@ module Homebrew
shell = if args.plain?
nil
elsif args.shell.nil?
# legacy behavior
:bash unless $stdout.tty?
elsif args.shell == "auto"
Utils::Shell.parent || Utils::Shell.preferred

View File

@ -105,11 +105,7 @@ module Homebrew
args.named.each_with_index do |f, i|
puts unless i.zero?
begin
formula = if f.include?("/") || File.exist?(f)
Formulary.factory(f)
else
Formulary.find_with_priority(f)
end
formula = Formulary.factory(f)
if args.analytics?
Utils::Analytics.formula_output(formula)
else

View File

@ -325,8 +325,8 @@ module Homebrew
fi.build_bottle = args.build_bottle?
fi.interactive = args.interactive?
fi.git = args.git?
fi.fetch
fi.prelude
fi.fetch
fi.install
fi.finish
rescue FormulaInstallationAlreadyAttemptedError

View File

@ -20,8 +20,8 @@ homebrew-shellenv() {
echo "setenv HOMEBREW_CELLAR $HOMEBREW_CELLAR;"
echo "setenv HOMEBREW_REPOSITORY $HOMEBREW_REPOSITORY;"
echo "setenv PATH $HOMEBREW_PREFIX/bin:$HOMEBREW_PREFIX/sbin:\$PATH;"
echo "setenv MANPATH $HOMEBREW_PREFIX/share/man:\$MANPATH;"
echo "setenv INFOPATH $HOMEBREW_PREFIX/share/info:\$INFOPATH;"
echo "setenv MANPATH $HOMEBREW_PREFIX/share/man\`[ \${?MANPATH} == 1 ] && echo \":\${MANPATH}\"\`:;"
echo "setenv INFOPATH $HOMEBREW_PREFIX/share/info\`[ \${?INFOPATH} == 1 ] && echo \":\${INFOPATH}\"\`;"
;;
*)
echo "export HOMEBREW_PREFIX=\"$HOMEBREW_PREFIX\";"

View File

@ -1,18 +0,0 @@
# frozen_string_literal: true
require "cli/parser"
module Homebrew
module_function
def tap_pin_args
Homebrew::CLI::Parser.new do
hide_from_man_page!
end
end
def tap_pin
odisabled "the brew tap-pin command",
"fully-scoped user/tap/formula naming when installing and in dependency references"
end
end

View File

@ -1,18 +0,0 @@
# frozen_string_literal: true
require "cli/parser"
module Homebrew
module_function
def tap_unpin_args
Homebrew::CLI::Parser.new do
hide_from_man_page!
end
end
def tap_unpin
odisabled "the brew tap-unpin command",
"fully-scoped user/tap/formula naming when installing and in dependency references"
end
end

View File

@ -599,7 +599,6 @@ EOS
-d "$HOMEBREW_LIBRARY/LinkedKegs" ||
(-n "$HOMEBREW_DEVELOPER" && -z "$HOMEBREW_UPDATE_PREINSTALL") ]]
then
unset HOMEBREW_RUBY_PATH
brew update-report "$@"
return $?
elif [[ -z "$HOMEBREW_UPDATE_PREINSTALL" ]]

View File

@ -191,8 +191,8 @@ module Homebrew
end
oh1 "Upgrading #{Formatter.identifier(f.full_specified_name)} #{upgrade_version} #{fi.options.to_a.join(" ")}"
fi.fetch
fi.prelude
fi.fetch
# first we unlink the currently active keg for this formula otherwise it is
# possible for the existing build to interfere with the build we are about to
@ -216,7 +216,7 @@ module Homebrew
ensure
# restore previous installation state if build failed
begin
linked_kegs.each(&:link) unless f.installed?
linked_kegs.each(&:link) unless f.latest_version_installed?
rescue
nil
end

View File

@ -101,7 +101,7 @@ module Commands
end
def official_external_commands_paths
%w[bundle services].map do |cmd|
%w[bundle services test-bot].map do |cmd|
tap = Tap.fetch("Homebrew/#{cmd}")
tap.install unless tap.installed?
external_ruby_v2_cmd_path(cmd)

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true
require "compat/cask/dsl/version"
require "compat/language/python"
require "compat/requirements/macos_requirement"
require "compat/extend/nil"
require "compat/extend/string"
require "compat/formula"
require "compat/language/python"
require "compat/os/mac" if OS.mac?

View File

@ -1,23 +0,0 @@
# frozen_string_literal: true
module Cask
class DSL
class Version < ::String
module Compat
def dots_to_slashes
odisabled "#dots_to_slashes"
end
def hyphens_to_slashes
odisabled "#hyphens_to_slashes"
end
def underscores_to_slashes
odisabled "#underscores_to_slashes"
end
end
prepend Compat
end
end
end

View File

@ -0,0 +1,11 @@
# frozen_string_literal: true
class NilClass
module Compat
def chuzzle
odeprecated "chuzzle", "chomp.presence"
end
end
prepend Compat
end

View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
class String
module Compat
# String.chomp, but if result is empty: returns nil instead.
# Allows `chuzzle || foo` short-circuits.
def chuzzle
odeprecated "chuzzle", "chomp.presence"
s = chomp
s unless s.empty?
end
end
prepend Compat
end

View File

@ -3,10 +3,19 @@
class Formula
module Compat
def installed?
# odeprecated "Formula#installed?",
# "Formula#latest_version_installed? (or Formula#any_version_installed? )"
odeprecated "Formula#installed?",
"Formula#latest_version_installed? (or Formula#any_version_installed? )"
latest_version_installed?
end
def prepare_patches
if respond_to?(:patches)
active_spec.add_legacy_patches(patches)
odeprecated "patches", "patch do"
end
super
end
end
prepend Compat

View File

@ -5,7 +5,7 @@ module Language
module Cabal
module Compat
def cabal_sandbox(options = {})
# odeprecated "Language::Haskell::Cabal.cabal_sandbox"
odeprecated "Language::Haskell::Cabal.cabal_sandbox"
pwd = Pathname.pwd
home = options[:home] || pwd
@ -41,14 +41,14 @@ module Language
end
def cabal_sandbox_add_source(*args)
# odeprecated "Language::Haskell::Cabal.cabal_sandbox_add_source"
odeprecated "Language::Haskell::Cabal.cabal_sandbox_add_source"
system "cabal", "v1-sandbox", "add-source", *args
end
def cabal_install(*args)
# odeprecated "Language::Haskell::Cabal.cabal_install",
# "cabal v2-install directly with std_cabal_v2_args"
odeprecated "Language::Haskell::Cabal.cabal_install",
"cabal v2-install directly with std_cabal_v2_args"
# cabal hardcodes 64 as the maximum number of parallel jobs
# https://github.com/Homebrew/legacy-homebrew/issues/49509
@ -64,13 +64,13 @@ module Language
end
def cabal_configure(flags)
# odeprecated "Language::Haskell::Cabal.cabal_configure"
odeprecated "Language::Haskell::Cabal.cabal_configure"
system "cabal", "v1-configure", flags
end
def cabal_install_tools(*tools)
# odeprecated "Language::Haskell::Cabal.cabal_install_tools"
odeprecated "Language::Haskell::Cabal.cabal_install_tools"
# install tools sequentially, as some tools can depend on other tools
tools.each { |tool| cabal_install tool }
@ -81,8 +81,8 @@ module Language
end
def install_cabal_package(*args, **options)
# odeprecated "Language::Haskell::Cabal.install_cabal_package",
# "cabal v2-update directly followed by v2-install with std_cabal_v2_args"
odeprecated "Language::Haskell::Cabal.install_cabal_package",
"cabal v2-update directly followed by v2-install with std_cabal_v2_args"
cabal_sandbox do
cabal_install_tools(*options[:using]) if options[:using]

View File

@ -5,6 +5,8 @@ module Language
class << self
module Compat
def rewrite_python_shebang(python_path)
odeprecated "Language::Python.rewrite_python_shebang",
"Utils::Shebang.rewrite_shebang and Shebang.python_shebang_rewrite_info(python_path)"
Pathname.pwd.find do |f|
Utils::Shebang.rewrite_shebang(Shebang.python_shebang_rewrite_info(python_path), f)
end

View File

@ -5,7 +5,7 @@ module OS
class << self
module Compat
def preferred_arch
# odeprecated "MacOS.preferred_arch", "Hardware::CPU.arch (or ideally let the compiler handle it)"
odeprecated "MacOS.preferred_arch", "Hardware::CPU.arch (or ideally let the compiler handle it)"
if Hardware::CPU.is_64_bit?
Hardware::CPU.arch_64_bit
else
@ -14,12 +14,12 @@ module OS
end
def tcc_db
# odeprecated "MacOS.tcc_db"
odeprecated "MacOS.tcc_db"
@tcc_db ||= Pathname.new("/Library/Application Support/com.apple.TCC/TCC.db")
end
def pre_mavericks_accessibility_dotfile
# odeprecated "MacOS.pre_mavericks_accessibility_dotfile"
odeprecated "MacOS.pre_mavericks_accessibility_dotfile"
@pre_mavericks_accessibility_dotfile ||= Pathname.new("/private/var/db/.AccessibilityAPIEnabled")
end
end

View File

@ -1,35 +0,0 @@
# frozen_string_literal: true
class MacOSRequirement < Requirement
module Compat
def initialize(tags = [], comparator: ">=")
if tags.first.respond_to?(:map)
versions, *rest = tags
versions = versions.map do |v|
next v if v.is_a?(Symbol)
sym = MacOS::Version.new(v).to_sym
odisabled "depends_on macos: #{v.inspect}",
"depends_on macos: #{sym.inspect}"
sym
end
tags = [versions, *rest]
elsif !tags.empty? && !tags.first.is_a?(Symbol)
v, *rest = tags
sym = MacOS::Version.new(v).to_sym
odisabled "depends_on macos: #{v.inspect}",
"depends_on macos: #{sym.inspect}"
tags = [sym, *rest]
end
super(tags, comparator: comparator)
end
end
prepend Compat
end

View File

@ -100,16 +100,11 @@ module Homebrew
klass.prune if ignores.include?("recommended?") || dependent.build.without?(dep)
elsif dep.optional?
klass.prune if !includes.include?("optional?") && !dependent.build.with?(dep)
elsif dep.test?
if includes.include?("test?")
Dependency.keep_but_prune_recursive_deps if type == :dependencies
elsif dep.build?
klass.prune unless includes.include?("build?")
else
klass.prune
end
elsif dep.build?
klass.prune unless includes.include?("build?")
elsif dep.build? || dep.test?
keep = false
keep ||= dep.test? && includes.include?("test?") && dependent == formula
keep ||= dep.build? && includes.include?("build?")
klass.prune unless keep
end
# If a tap isn't installed, we can't find the dependencies of one of

View File

@ -89,9 +89,6 @@ class Dependency
deps.each do |dep|
next if dependent.name == dep.name
# we only care about one level of test dependencies.
next if dep.test? && @expand_stack.length > 1
case action(dependent, dep, &block)
when :prune
next

View File

@ -3,6 +3,7 @@
require "formula"
require "formula_versions"
require "utils/curl"
require "utils/notability"
require "extend/ENV"
require "formula_cellar_checks"
require "cmd/search"
@ -134,19 +135,8 @@ module Homebrew
end
end
created_pr_comment = false
if new_formula && !new_formula_problem_lines.empty?
begin
created_pr_comment = true if GitHub.create_issue_comment(new_formula_problem_lines.join("\n"))
rescue *GitHub.api_errors => e
opoo "Unable to create issue comment: #{e.message}"
end
end
unless created_pr_comment
new_formula_problem_count += new_formula_problem_lines.size
puts new_formula_problem_lines.map { |s| " #{s}" }
end
total_problems_count = problem_count + new_formula_problem_count
problem_plural = "#{total_problems_count} #{"problem".pluralize(total_problems_count)}"
@ -155,10 +145,7 @@ module Homebrew
errors_summary = "#{problem_plural} in #{formula_plural} detected"
errors_summary += ", #{corrected_problem_plural} corrected" if corrected_problem_count.positive?
if problem_count.positive? ||
(new_formula_problem_count.positive? && !created_pr_comment)
ofail errors_summary
end
ofail errors_summary if problem_count.positive? || new_formula_problem_count.positive?
end
def format_problem_lines(problems)
@ -458,9 +445,10 @@ module Homebrew
autoconf@2.13
bash-completion@2
gnupg@1.4
libsigc++@2
lua@5.1
numpy@1.16
libsigc++@2
python@3.8
].freeze
def audit_versioned_keg_only
@ -524,79 +512,30 @@ module Homebrew
user, repo = get_repo_data(%r{https?://github\.com/([^/]+)/([^/]+)/?.*})
return if user.nil?
begin
metadata = GitHub.repository(user, repo)
rescue GitHub::HTTPNotFoundError
return
end
warning = SharedAudits.github(user, repo)
return if warning.nil?
return if metadata.nil?
new_formula_problem "GitHub fork (not canonical repository)" if metadata["fork"]
if (metadata["forks_count"] < 30) && (metadata["subscribers_count"] < 30) &&
(metadata["stargazers_count"] < 75)
new_formula_problem "GitHub repository not notable enough (<30 forks, <30 watchers and <75 stars)"
end
return if Date.parse(metadata["created_at"]) <= (Date.today - 30)
new_formula_problem "GitHub repository too new (<30 days old)"
new_formula_problem warning
end
def audit_gitlab_repository
user, repo = get_repo_data(%r{https?://gitlab\.com/([^/]+)/([^/]+)/?.*})
return if user.nil?
out, _, status= curl_output("--request", "GET", "https://gitlab.com/api/v4/projects/#{user}%2F#{repo}")
return unless status.success?
warning = SharedAudits.gitlab(user, repo)
return if warning.nil?
metadata = JSON.parse(out)
return if metadata.nil?
new_formula_problem "GitLab fork (not canonical repository)" if metadata["fork"]
if (metadata["forks_count"] < 30) && (metadata["star_count"] < 75)
new_formula_problem "GitLab repository not notable enough (<30 forks and <75 stars)"
end
return if Date.parse(metadata["created_at"]) <= (Date.today - 30)
new_formula_problem "GitLab repository too new (<30 days old)"
new_formula_problem warning
end
def audit_bitbucket_repository
user, repo = get_repo_data(%r{https?://bitbucket\.org/([^/]+)/([^/]+)/?.*})
return if user.nil?
api_url = "https://api.bitbucket.org/2.0/repositories/#{user}/#{repo}"
out, _, status= curl_output("--request", "GET", api_url)
return unless status.success?
warning = SharedAudits.bitbucket(user, repo)
return if warning.nil?
metadata = JSON.parse(out)
return if metadata.nil?
new_formula_problem "Uses deprecated mercurial support in Bitbucket" if metadata["scm"] == "hg"
new_formula_problem "Bitbucket fork (not canonical repository)" unless metadata["parent"].nil?
if Date.parse(metadata["created_on"]) >= (Date.today - 30)
new_formula_problem "Bitbucket repository too new (<30 days old)"
end
forks_out, _, forks_status= curl_output("--request", "GET", "#{api_url}/forks")
return unless forks_status.success?
watcher_out, _, watcher_status= curl_output("--request", "GET", "#{api_url}/watchers")
return unless watcher_status.success?
forks_metadata = JSON.parse(forks_out)
return if forks_metadata.nil?
watcher_metadata = JSON.parse(watcher_out)
return if watcher_metadata.nil?
return if (forks_metadata["size"] < 30) && (watcher_metadata["size"] < 75)
new_formula_problem "Bitbucket repository not notable enough (<30 forks and <75 watchers)"
new_formula_problem warning
end
def get_repo_data(regex)
@ -608,7 +547,7 @@ module Homebrew
_, user, repo = *regex.match(formula.homepage) unless user
return if !user || !repo
repo.gsub!(/.git$/, "")
repo.delete_suffix!(".git")
[user, repo]
end
@ -730,7 +669,7 @@ module Homebrew
.map(&:to_i)
case (url = stable.url)
when /[\d\._-](alpha|beta|rc\d)/
when /[\d._-](alpha|beta|rc\d)/
matched = Regexp.last_match(1)
version_prefix = stable_version_string.sub(/\d+$/, "")
return if UNSTABLE_WHITELIST[formula.name] == version_prefix
@ -758,7 +697,7 @@ module Homebrew
.second
begin
if (release = GitHub.open_api("#{GitHub::API_URL}/repos/#{owner}/#{repo}/releases/tags/#{tag}"))
if @online && (release = GitHub.open_api("#{GitHub::API_URL}/repos/#{owner}/#{repo}/releases/tags/#{tag}"))
problem "#{tag} is a GitHub prerelease" if release["prerelease"]
problem "#{tag} is a GitHub draft" if release["draft"]
end
@ -864,7 +803,7 @@ module Homebrew
end
bin_names.each do |name|
["system", "shell_output", "pipe_output"].each do |cmd|
if text.to_s.match?(/test do.*#{cmd}[\(\s]+['"]#{Regexp.escape(name)}[\s'"]/m)
if text.to_s.match?(/test do.*#{cmd}[(\s]+['"]#{Regexp.escape(name)}[\s'"]/m)
problem %Q(fully scope test #{cmd} calls, e.g. #{cmd} "\#{bin}/#{name}")
end
end
@ -984,7 +923,7 @@ module Homebrew
except_audits = @except
methods.map(&:to_s).grep(/^audit_/).each do |audit_method_name|
name = audit_method_name.gsub(/^audit_/, "")
name = audit_method_name.delete_prefix("audit_")
if only_audits
next unless only_audits.include?(name)
elsif except_audits
@ -1052,15 +991,9 @@ module Homebrew
end
def audit_download_strategy
if url =~ %r{^(cvs|bzr|hg|fossil)://} || url =~ %r{^(svn)\+http://}
# TODO: check could be in RuboCop
problem "Use of the #{$&} scheme is deprecated, pass `:using => :#{Regexp.last_match(1)}` instead"
end
url_strategy = DownloadStrategyDetector.detect(url)
if using == :git || url_strategy == GitDownloadStrategy
# TODO: check could be in RuboCop
problem "Git should specify :revision when a :tag is specified." if specs[:tag] && !specs[:revision]
end

View File

@ -321,7 +321,7 @@ module Homebrew
if any_go_deps
go_regex =
Version.formula_optionally_versioned_regex(:go, full: false)
ignores << %r{#{Regexp.escape(HOMEBREW_CELLAR)}/#{go_regex}/[\d\.]+/libexec}
ignores << %r{#{Regexp.escape(HOMEBREW_CELLAR)}/#{go_regex}/[\d.]+/libexec}
end
relocatable = true

View File

@ -79,7 +79,7 @@ module Homebrew
origin_branch = "#{homebrew_core_remote}/#{homebrew_core_branch}"
previous_branch = Utils.popen_read("git -C \"#{formula.tap.path}\" symbolic-ref -q --short HEAD").chomp
previous_branch = "master" if previous_branch.empty?
formula_path = formula.path.to_s[%r{(Formula\/.*)}, 1]
formula_path = formula.path.to_s[%r{(Formula/.*)}, 1]
if args.dry_run?
ohai "git remote add #{homebrew_core_remote} #{homebrew_core_url}"
@ -89,7 +89,7 @@ module Homebrew
return tap_full_name, origin_branch, previous_branch
else
formula.path.parent.cd do
unless Utils.popen_read("git remote -v").match?(%r{^homebrew.*Homebrew\/homebrew-core.*$})
unless Utils.popen_read("git remote -v").match?(%r{^homebrew.*Homebrew/homebrew-core.*$})
ohai "Adding #{homebrew_core_remote} remote"
safe_system "git", "remote", "add", homebrew_core_remote, homebrew_core_url
end
@ -118,12 +118,6 @@ module Homebrew
formula = args.formulae.first
if formula
tap_full_name, origin_branch, previous_branch = use_correct_linux_tap(formula)
check_for_duplicate_pull_requests(formula, tap_full_name)
checked_for_duplicates = true
end
new_url = args.url
if new_url && !formula
# Split the new URL on / and find any formulae that have the same URL
@ -152,7 +146,8 @@ module Homebrew
end
raise FormulaUnspecifiedError unless formula
check_for_duplicate_pull_requests(formula, tap_full_name) unless checked_for_duplicates
tap_full_name, origin_branch, previous_branch = use_correct_linux_tap(formula)
check_for_duplicate_pull_requests(formula, tap_full_name)
requested_spec, formula_spec = if args.devel?
devel_message = " (devel)"
@ -230,7 +225,7 @@ module Homebrew
replacement_pairs += formula_spec.mirrors.map do |mirror|
[
/ +mirror \"#{Regexp.escape(mirror)}\"\n/m,
/ +mirror "#{Regexp.escape(mirror)}"\n/m,
"",
]
end
@ -263,7 +258,7 @@ module Homebrew
if new_mirrors
replacement_pairs << [
/^( +)(url \"#{Regexp.escape(new_url)}\"\n)/m,
/^( +)(url "#{Regexp.escape(new_url)}"\n)/m,
"\\1\\2\\1mirror \"#{new_mirrors.join("\"\n\\1mirror \"")}\"\n",
]
end
@ -288,30 +283,30 @@ module Homebrew
]
elsif new_mirrors
[
/^( +)(mirror \"#{Regexp.escape(new_mirrors.last)}\"\n)/m,
/^( +)(mirror "#{Regexp.escape(new_mirrors.last)}"\n)/m,
"\\1\\2\\1version \"#{forced_version}\"\n",
]
else
[
/^( +)(url \"#{Regexp.escape(new_url)}\"\n)/m,
/^( +)(url "#{Regexp.escape(new_url)}"\n)/m,
"\\1\\2\\1version \"#{forced_version}\"\n",
]
end
elsif requested_spec == :devel
replacement_pairs << [
/( devel do.+?version \")#{old_formula_version}(\"\n.+?end\n)/m,
/( devel do.+?version ")#{old_formula_version}("\n.+?end\n)/m,
"\\1#{forced_version}\\2",
]
end
elsif forced_version && forced_version == "0"
if requested_spec == :stable
replacement_pairs << [
/^ version \"[\w\.\-\+]+\"\n/m,
/^ version "[\w.\-+]+"\n/m,
"",
]
elsif requested_spec == :devel
replacement_pairs << [
/( devel do.+?)^ +version \"[^\n]+\"\n(.+?end\n)/m,
/( devel do.+?)^ +version "[^\n]+"\n(.+?end\n)/m,
"\\1\\2",
]
end

View File

@ -19,7 +19,7 @@ module Homebrew
def irb_args
# work around IRB modifying ARGV.
Homebrew::CLI::Parser.new(ARGV.dup) do
Homebrew::CLI::Parser.new(ARGV.dup.freeze) do
usage_banner <<~EOS
`irb` [<options>]
@ -38,7 +38,7 @@ module Homebrew
if args.examples?
puts "'v8'.f # => instance of the v8 formula"
puts ":hub.f.installed?"
puts ":hub.f.latest_version_installed?"
puts ":lua.f.methods - 1.methods"
puts ":mpd.f.recursive_dependencies.reject(&:installed?)"
return

View File

@ -60,7 +60,7 @@ module Homebrew
rescue FormulaUnavailableError
nil
else
if gnupg.installed?
if gnupg.any_version_installed?
path = PATH.new(ENV.fetch("PATH"))
path.prepend(gnupg.installed_prefix/"bin")
ENV["PATH"] = path

View File

@ -15,6 +15,7 @@ module Homebrew
def pull_args
Homebrew::CLI::Parser.new do
hide_from_man_page!
usage_banner <<~EOS
`pull` [<options>] <patch>
@ -43,6 +44,8 @@ module Homebrew
end
def pull
odeprecated "brew pull", "hub checkout"
odie "You meant `git pull --rebase`." if ARGV[0] == "--rebase"
pull_args.parse
@ -56,7 +59,7 @@ module Homebrew
gnupg = Formula["gnupg"]
rescue FormulaUnavailableError # rubocop:disable Lint/SuppressedException
else
if gnupg.installed?
if gnupg.any_version_installed?
path = PATH.new(ENV.fetch("PATH"))
path.prepend(gnupg.installed_prefix/"bin")
ENV["PATH"] = path
@ -333,7 +336,7 @@ module Homebrew
def check_bintray_mirror(name, url)
headers, = curl_output("--connect-timeout", "15", "--location", "--head", url)
status_code = headers.scan(%r{^HTTP\/.* (\d+)}).last.first
status_code = headers.scan(%r{^HTTP/.* (\d+)}).last.first
return if status_code.start_with?("2")
opoo "The Bintray mirror #{url} is not reachable (HTTP status code #{status_code})."

View File

@ -38,12 +38,6 @@ module Homebrew
Or `brew tap #{tap}` and then `brew install <formula>`.
Or install via URL (which will not receive updates):
```
brew install https://raw.githubusercontent.com/#{tap.user}/homebrew-#{tap.repo}/master/Formula/<formula>.rb
```
## Documentation
`brew help`, `man brew` or check [Homebrew's documentation](https://docs.brew.sh).
MARKDOWN

View File

@ -3,6 +3,7 @@
require "keg"
require "language/python"
require "formula"
require "formulary"
require "version"
require "development_tools"
require "utils/shell"
@ -832,6 +833,23 @@ module Homebrew
EOS
end
def check_deleted_formula
kegs = Keg.all
deleted_formulae = []
kegs.each do |keg|
keg_name = keg.name
deleted_formulae << keg_name if Formulary.tap_paths(keg_name).blank?
end
return if deleted_formulae.blank?
message = <<~EOS
Some installed formulae were deleted!
You should find replacements for the following formulae:
#{deleted_formulae.join("\n ")}
EOS
message
end
def all
methods.map(&:to_s).grep(/^check_/)
end

View File

@ -221,7 +221,7 @@ class AbstractFileDownloadStrategy < AbstractDownloadStrategy
end
def basename
cached_location.basename.sub(/^[\da-f]{64}\-\-/, "")
cached_location.basename.sub(/^[\da-f]{64}--/, "")
end
private
@ -390,7 +390,7 @@ class CurlDownloadStrategy < AbstractFileDownloadStrategy
filenames = lines.map(&parse_content_disposition).compact
time =
lines.map { |line| line[/^Last\-Modified:\s*(.+)/i, 1] }
lines.map { |line| line[/^Last-Modified:\s*(.+)/i, 1] }
.compact
.map { |t| t.match?(/^\d+$/) ? Time.at(t.to_i) : Time.parse(t) }
.last
@ -820,7 +820,7 @@ class GitHubGitDownloadStrategy < GitDownloadStrategy
return unless status.success?
commit = output[/^ETag: \"(\h+)\"/, 1]
commit = output[/^ETag: "(\h+)"/, 1]
version.update_commit(commit) if commit
commit
end

View File

@ -1,63 +0,0 @@
# frozen_string_literal: true
module HomebrewArgvExtension
def value(name)
arg_prefix = "--#{name}="
flag_with_value = find { |arg| arg.start_with?(arg_prefix) }
flag_with_value&.delete_prefix(arg_prefix)
end
def debug?
flag?("--debug") || !ENV["HOMEBREW_DEBUG"].nil?
end
def cc
value "cc"
end
def env
value "env"
end
private
def options_only
select { |arg| arg.start_with?("-") }
end
def flag?(flag)
options_only.include?(flag) || switch?(flag[2, 1])
end
# e.g. `foo -ns -i --bar` has three switches: `n`, `s` and `i`
def switch?(char)
return false if char.length > 1
options_only.any? { |arg| arg.scan("-").size == 1 && arg.include?(char) }
end
def spec(default = :stable)
if include?("--HEAD")
:head
elsif include?("--devel")
:devel
else
default
end
end
def named
self - options_only
end
def downcased_unique_named
# Only lowercase names, not paths, bottle filenames or URLs
named.map do |arg|
if arg.include?("/") || arg.end_with?(".tar.gz") || File.exist?(arg)
arg
else
arg.downcase
end
end.uniq
end
end

View File

@ -6,7 +6,7 @@ require "extend/ENV/std"
require "extend/ENV/super"
def superenv?
ARGV.env != "std" && Superenv.bin
Homebrew.args.env != "std" && Superenv.bin
end
module EnvActivation

View File

@ -162,7 +162,7 @@ module SharedEnvExtension
# ENV.append_to_cflags "-I ./missing/includes"
# end</pre>
def compiler
@compiler ||= if (cc = ARGV.cc)
@compiler ||= if (cc = Homebrew.args.cc)
warn_about_non_apple_gcc($&) if cc =~ GNU_GCC_REGEXP
fetch_compiler(cc, "--cc")
elsif (cc = homebrew_cc)

View File

@ -19,6 +19,8 @@ class Keg
return if !file.elf? || !file.dynamic_elf?
patchelf = DevelopmentTools.locate "patchelf"
odie "Could not locate patchelf, please: brew install patchelf." if patchelf.nil?
cmd_rpath = [patchelf, "--print-rpath", file]
old_rpath = Utils.popen_read(*cmd_rpath, err: :out).strip

View File

@ -347,12 +347,13 @@ module Homebrew
end
def check_deprecated_caskroom_taps
tapped_caskroom_taps = Tap.select { |t| t.user == "caskroom" }.map(&:repo)
tapped_caskroom_taps = Tap.select { |t| t.user == "caskroom" || t.name == "phinze/cask" }
.map(&:name)
return if tapped_caskroom_taps.empty?
<<~EOS
You have the following deprecated, cask taps tapped:
Caskroom/homebrew-#{tapped_caskroom_taps.join("\n Caskroom/homebrew-")}
#{tapped_caskroom_taps.join("\n ")}
Untap them with `brew untap`.
EOS
end

View File

@ -81,7 +81,7 @@ module Stdenv
prepend "LDFLAGS", "-L#{HOMEBREW_PREFIX}/lib"
sdk = formula ? MacOS.sdk_for_formula(formula, version) : MacOS.sdk(version)
return if !MacOS.sdk_root_needed? && sdk.source != :xcode
return if !MacOS.sdk_root_needed? && sdk&.source != :xcode
sdk = sdk.path

View File

@ -108,7 +108,7 @@ module Superenv
# @private
def setup_build_environment(formula = nil)
sdk = formula ? MacOS.sdk_for_formula(formula) : MacOS.sdk
if MacOS.sdk_root_needed? || sdk.source == :xcode
if MacOS.sdk_root_needed? || sdk&.source == :xcode
self["HOMEBREW_SDKROOT"] = sdk.path
self["HOMEBREW_DEVELOPER_DIR"] = if sdk.source == :xcode
MacOS::Xcode.prefix

View File

@ -106,10 +106,12 @@ class Keg
bad_name.sub(PREFIX_PLACEHOLDER, HOMEBREW_PREFIX)
elsif bad_name.start_with? CELLAR_PLACEHOLDER
bad_name.sub(CELLAR_PLACEHOLDER, HOMEBREW_CELLAR)
elsif (file.dylib? || file.mach_o_bundle?) && (file.parent + bad_name).exist?
elsif (file.dylib? || file.mach_o_bundle?) && (file.dirname/bad_name).exist?
"@loader_path/#{bad_name}"
elsif file.mach_o_executable? && (lib + bad_name).exist?
elsif file.mach_o_executable? && (lib/bad_name).exist?
"#{lib}/#{bad_name}"
elsif file.mach_o_executable? && (libexec/"lib"/bad_name).exist?
"#{libexec}/lib/#{bad_name}"
elsif bad_name.start_with?("@rpath") && ENV["HOMEBREW_RELOCATE_METAVARS"]
expand_rpath file, bad_name
elsif (abs_name = find_dylib(bad_name)) && abs_name.exist?

View File

@ -224,7 +224,7 @@ class Pathname
return archive_ext if archive_ext
# Don't treat version numbers as extname.
return "" if basename.match?(/\b\d+\.\d+[^\.]*\Z/) && !basename.end_with?(".7z")
return "" if basename.match?(/\b\d+\.\d+[^.]*\Z/) && !basename.end_with?(".7z")
File.extname(basename)
end
@ -398,15 +398,6 @@ class Pathname
basename.to_s == ".DS_Store"
end
# https://bugs.ruby-lang.org/issues/9915
if RUBY_VERSION == "2.0.0"
prepend Module.new {
def inspect
super.force_encoding(@path.encoding)
end
}
end
def binary_executable?
false
end

View File

@ -2,21 +2,6 @@
require "active_support/core_ext/object/blank"
class String
# String.chomp, but if result is empty: returns nil instead.
# Allows `chuzzle || foo` short-circuits.
# TODO: Deprecate.
def chuzzle
s = chomp
s unless s.empty?
end
end
class NilClass
# TODO: Deprecate.
def chuzzle; end
end
# Used by the inreplace function (in `utils.rb`).
module StringInreplaceExtension
attr_accessor :errors
@ -41,7 +26,7 @@ module StringInreplaceExtension
# Looks for Makefile style variable definitions and replaces the
# value with "new_value", or removes the definition entirely.
def change_make_var!(flag, new_value)
return if gsub!(/^#{Regexp.escape(flag)}[ \t]*[\\?\+\:\!]?=[ \t]*((?:.*\\\n)*.*)$/, "#{flag}=#{new_value}", false)
return if gsub!(/^#{Regexp.escape(flag)}[ \t]*[\\?+:!]?=[ \t]*((?:.*\\\n)*.*)$/, "#{flag}=#{new_value}", false)
errors << "expected to change #{flag.inspect} to #{new_value.inspect}"
end
@ -50,7 +35,7 @@ module StringInreplaceExtension
def remove_make_var!(flags)
Array(flags).each do |flag|
# Also remove trailing \n, if present.
unless gsub!(/^#{Regexp.escape(flag)}[ \t]*[\\?\+\:\!]?=(?:.*\\\n)*.*$\n?/, "", false)
unless gsub!(/^#{Regexp.escape(flag)}[ \t]*[\\?+:!]?=(?:.*\\\n)*.*$\n?/, "", false)
errors << "expected to remove #{flag.inspect}"
end
end
@ -58,6 +43,6 @@ module StringInreplaceExtension
# Finds the specified variable
def get_make_var(flag)
self[/^#{Regexp.escape(flag)}[ \t]*[\\?\+\:\!]?=[ \t]*((?:.*\\\n)*.*)$/, 1]
self[/^#{Regexp.escape(flag)}[ \t]*[\\?+:!]?=[ \t]*((?:.*\\\n)*.*)$/, 1]
end
end

View File

@ -1172,7 +1172,7 @@ class Formula
begin
yield self, staging
rescue
staging.retain! if Homebrew.args.interactive? || ARGV.debug?
staging.retain! if Homebrew.args.interactive? || Homebrew.args.debug?
raise
ensure
cp Dir["config.log", "CMakeCache.txt"], logs
@ -1822,7 +1822,7 @@ class Formula
end
end
rescue Exception # rubocop:disable Lint/RescueException
staging.retain! if ARGV.debug?
staging.retain! if Homebrew.args.debug?
raise
end
end
@ -2090,7 +2090,6 @@ class Formula
private
def prepare_patches
active_spec.add_legacy_patches(patches) if respond_to?(:patches)
patchlist.grep(DATAPatch) { |p| p.path = path }
end
@ -2171,7 +2170,10 @@ class Formula
raise "You cannot override Formula#brew in class #{name}"
when :test
define_method(:test_defined?) { true }
when :patches
odeprecated "a Formula#patches definition", "'patch do' block calls"
when :options
odeprecated "a Formula#options definition", "'option do' block calls"
instance = allocate
specs.each do |spec|
@ -2385,6 +2387,7 @@ class Formula
@devel ||= SoftwareSpec.new
return @devel unless block_given?
odeprecated "'devel' blocks in formulae", "'head' blocks or @-versioned formulae"
@devel.instance_eval(&block)
end
@ -2668,7 +2671,7 @@ class Formula
# regex /foo-(\d+(?:\.\d+)+)\.tar/
# end</pre>
def livecheck(&block)
@livecheck ||= Livecheck.new
@livecheck ||= Livecheck.new(self)
return @livecheck unless block_given?
@livecheckable = true

View File

@ -59,7 +59,7 @@ class FormulaInstaller
@git = false
@verbose = Homebrew.args.verbose?
@quiet = Homebrew.args.quiet?
@debug = ARGV.debug?
@debug = Homebrew.args.debug?
@installed_as_dependency = false
@installed_on_request = true
@options = Options.new
@ -100,7 +100,7 @@ class FormulaInstaller
return false if !formula.bottled? && !formula.local_bottle_path
return true if force_bottle?
return false if build_from_source? || build_bottle? || interactive?
return false if ARGV.cc
return false if Homebrew.args.cc
return false unless options.empty?
return false if formula.bottle_disabled?
@ -141,7 +141,6 @@ class FormulaInstaller
def prelude
Tab.clear_cache
verify_deps_exist unless ignore_deps?
lock
check_install_sanity
end
@ -221,6 +220,8 @@ class FormulaInstaller
end
def install
lock
start_time = Time.now
if !formula.bottle_unneeded? && !pour_bottle? && DevelopmentTools.installed?
Homebrew::Install.perform_build_from_source_checks
@ -417,7 +418,7 @@ class FormulaInstaller
req_map.each_pair do |dependent, reqs|
reqs.each do |req|
next if dependent.installed? && req.name == "maximummacos"
next if dependent.latest_version_installed? && req.name == "maximummacos"
@requirement_messages << "#{dependent}: #{req.message}"
fatals << req if req.fatal?
@ -453,13 +454,16 @@ class FormulaInstaller
build = effective_build_options_for(dependent)
install_bottle_for_dependent = install_bottle_for?(dependent, build)
keep_build_test = false
keep_build_test ||= runtime_requirements.include?(req)
keep_build_test ||= req.test? && include_test? && dependent == f
keep_build_test ||= req.build? && !install_bottle_for_dependent && !dependent.latest_version_installed?
if req.prune_from_option?(build)
Requirement.prune
elsif req.satisfied?
Requirement.prune
elsif include_test? && req.test?
next
elsif !runtime_requirements.include?(req) && install_bottle_for_dependent
elsif (req.build? || req.test?) && !keep_build_test
Requirement.prune
elsif (dep = formula_deps_map[dependent.name]) && dep.build?
Requirement.prune
@ -486,13 +490,13 @@ class FormulaInstaller
inherited_options.fetch(dependent.name, []),
)
keep_build_test = false
keep_build_test ||= dep.test? && include_test? && Homebrew.args.include_formula_test_deps?(dependent)
keep_build_test ||= dep.build? && !install_bottle_for?(dependent, build) && !dependent.latest_version_installed?
if dep.prune_from_option?(build)
Dependency.prune
elsif dep.test? && !dep.build? && !include_test?
Dependency.prune
elsif dep.build? && !dep.test? && install_bottle_for?(dependent, build)
Dependency.prune
elsif dep.prune_if_build_and_not_dependent?(dependent)
elsif (dep.build? || dep.test?) && !keep_build_test
Dependency.prune
elsif dep.satisfied?(inherited_options[dep.name])
Dependency.skip
@ -568,6 +572,7 @@ class FormulaInstaller
fi.build_from_source = Homebrew.args.build_formula_from_source?(df)
fi.force_bottle = false
fi.include_test = Homebrew.args.include_formula_test_deps?(df)
fi.verbose = verbose?
fi.quiet = quiet?
fi.debug = debug?
@ -589,7 +594,7 @@ class FormulaInstaller
linked_keg.unlink
end
if df.installed?
if df.latest_version_installed?
installed_keg = Keg.new(df.prefix)
tmp_keg = Pathname.new("#{installed_keg}.tmp")
installed_keg.rename(tmp_keg)
@ -610,6 +615,7 @@ class FormulaInstaller
fi.options &= df.options
fi.build_from_source = Homebrew.args.build_formula_from_source?(df)
fi.force_bottle = false
fi.include_test = Homebrew.args.include_formula_test_deps?(df)
fi.verbose = verbose?
fi.quiet = quiet?
fi.debug = debug?
@ -723,11 +729,11 @@ class FormulaInstaller
args << "--interactive" if interactive?
args << "--verbose" if verbose?
args << "--debug" if debug?
args << "--cc=#{ARGV.cc}" if ARGV.cc
args << "--cc=#{Homebrew.args.cc}" if Homebrew.args.cc
args << "--keep-tmp" if Homebrew.args.keep_tmp?
if ARGV.env
args << "--env=#{ARGV.env}"
if Homebrew.args.env.present?
args << "--env=#{Homebrew.args.env}"
elsif formula.env.std? || formula.deps.select(&:build?).any? { |d| d.name == "scons" }
args << "--env=std"
end
@ -740,7 +746,7 @@ class FormulaInstaller
formula.options.each do |opt|
name = opt.name[/^([^=]+)=$/, 1]
value = ARGV.value(name) if name
value = Homebrew.args.value(name) if name
args << "--#{name}=#{value}" if value
end
@ -964,9 +970,10 @@ class FormulaInstaller
end
def fetch_dependencies
deps = compute_dependencies
return if ignore_deps?
return if deps.empty? || ignore_deps?
deps = compute_dependencies
return if deps.empty?
deps.each { |dep, _options| fetch_dependency(dep) }
end

View File

@ -44,7 +44,7 @@ class FormulaVersions
rescue *IGNORED_EXCEPTIONS => e
# We rescue these so that we can skip bad versions and
# continue walking the history
odebug "#{e} in #{name} at revision #{rev}", e.backtrace if ARGV.debug?
odebug "#{e} in #{name} at revision #{rev}", e.backtrace if Homebrew.args.debug?
rescue FormulaUnavailableError
nil
ensure

View File

@ -9,6 +9,8 @@ require "extend/cachable"
module Formulary
extend Cachable
URL_START_REGEX = %r{(https?|ftp|file)://}.freeze
def self.enable_factory_cache!
@factory_cache = true
end
@ -130,7 +132,7 @@ module Formulary
private
def load_file
$stderr.puts "#{$PROGRAM_NAME} (#{self.class.name}): loading #{path}" if ARGV.debug?
$stderr.puts "#{$PROGRAM_NAME} (#{self.class.name}): loading #{path}" if Homebrew.args.debug?
raise FormulaUnavailableError, name unless path.file?
Formulary.load_formula_from_path(name, path)
@ -141,7 +143,7 @@ module Formulary
class BottleLoader < FormulaLoader
def initialize(bottle_name)
case bottle_name
when %r{(https?|ftp|file)://}
when URL_START_REGEX
# The name of the formula is found between the last slash and the last hyphen.
formula_name = File.basename(bottle_name)[/(.+)-/, 1]
resource = Resource.new(formula_name) { url bottle_name }
@ -205,21 +207,20 @@ module Formulary
def load_file
if url =~ %r{githubusercontent.com/[\w-]+/[\w-]+/[a-f0-9]{40}(/Formula)?/([\w+-.@]+).rb}
formula_name = Regexp.last_match(2)
opoo <<~EOS
Unsupported installation from a commit URL!
Consider using `brew extract #{formula_name} ...` instead!"
This will extract your desired #{formula_name} version to a stable tap instead of
installing from a commit URL that cannnot receive updates or fixes!
EOS
odeprecated "Installation of #{formula_name} from a GitHub commit URL",
"'brew extract #{formula_name}' to stable tap on GitHub"
elsif url.match?(%r{^(https?|ftp)://})
odeprecated "Non-checksummed download of #{name} formula file from an arbitrary URL",
"'brew extract' or 'brew create' and 'brew tap-new' to create a "\
"formula file in a tap on GitHub"
end
HOMEBREW_CACHE_FORMULA.mkpath
FileUtils.rm_f(path)
curl_download url, to: path
super
rescue MethodDeprecatedError => e
if url =~ %r{github.com/([\w-]+)/homebrew-([\w-]+)/}
e.issues_url = "https://github.com/#{Regexp.last_match(1)}/homebrew-#{Regexp.last_match(2)}/issues/new"
if url =~ %r{github.com/([\w-]+)/([\w-]+)/}
e.issues_url = "https://github.com/#{Regexp.last_match(1)}/#{Regexp.last_match(2)}/issues/new"
end
raise
end
@ -307,7 +308,7 @@ module Formulary
end
def klass
$stderr.puts "#{$PROGRAM_NAME} (#{self.class.name}): loading #{path}" if ARGV.debug?
$stderr.puts "#{$PROGRAM_NAME} (#{self.class.name}): loading #{path}" if Homebrew.args.debug?
namespace = "FormulaNamespace#{Digest::MD5.hexdigest(contents)}"
Formulary.load_formula(name, path, contents, namespace)
end
@ -418,7 +419,7 @@ module Formulary
case ref
when Pathname::BOTTLE_EXTNAME_RX
return BottleLoader.new(ref)
when %r{(https?|ftp|file)://}
when URL_START_REGEX
return FromUrlLoader.new(ref)
when HOMEBREW_TAP_FORMULA_REGEX
return TapLoader.new(ref, from: from)
@ -483,20 +484,4 @@ module Formulary
]).find(&:file?)
end.compact
end
def self.find_with_priority(ref, spec = :stable)
possible_pinned_tap_formulae = tap_paths(ref, Dir["#{HOMEBREW_LIBRARY}/PinnedTaps/*/*/"]).map(&:realpath)
raise TapFormulaAmbiguityError.new(ref, possible_pinned_tap_formulae) if possible_pinned_tap_formulae.size > 1
if possible_pinned_tap_formulae.size == 1
selected_formula = factory(possible_pinned_tap_formulae.first, spec)
if core_path(ref).file?
odisabled "the brew tap-pin command",
"fully-scoped user/tap/formula naming when installing and in dependency references"
end
selected_formula
else
factory(ref, spec)
end
end
end

View File

@ -35,13 +35,10 @@ require "env_config"
require "config"
require "os"
require "extend/ARGV"
require "cli/args"
require "messages"
require "system_command"
ARGV.extend(HomebrewArgvExtension)
HOMEBREW_PRODUCT = ENV["HOMEBREW_PRODUCT"]
HOMEBREW_VERSION = ENV["HOMEBREW_VERSION"]
HOMEBREW_WWW = "https://brew.sh"

View File

@ -103,7 +103,7 @@ module Homebrew
help_lines = command_help_lines(path)
return if help_lines.blank?
Formatter.wrap(help_lines.join.gsub(/^ /, ""), COMMAND_DESC_WIDTH)
Formatter.wrap(help_lines.join.delete_prefix(" "), COMMAND_DESC_WIDTH)
.sub("@hide_from_man_page ", "")
.sub(/^\* /, "#{Tty.bold}Usage: brew#{Tty.reset} ")
.gsub(/`(.*?)`/m, "#{Tty.bold}\\1#{Tty.reset}")

View File

@ -37,11 +37,11 @@ module Homebrew
end
def check_cc_argv
return unless ARGV.cc
return unless Homebrew.args.cc
@checks ||= Diagnostic::Checks.new
opoo <<~EOS
You passed `--cc=#{ARGV.cc}`.
You passed `--cc=#{Homebrew.args.cc}`.
#{@checks.please_create_pull_requests}
EOS
end

View File

@ -117,6 +117,10 @@ class Keg
path/"lib"
end
def libexec
path/"libexec"
end
def text_files
text_files = []
return text_files unless which("file") && which("xargs")

View File

@ -33,7 +33,7 @@ module Language
next if build.without? python_formula.to_s
version = major_minor_version python
ENV["PYTHONPATH"] = if python_formula.installed?
ENV["PYTHONPATH"] = if python_formula.latest_version_installed?
nil
else
homebrew_site_packages(python)

View File

@ -10,7 +10,8 @@ class Livecheck
# e.g. `Not maintained`
attr_reader :skip_msg
def initialize
def initialize(formula)
@formula = formula
@regex = nil
@skip = false
@skip_msg = nil
@ -44,7 +45,14 @@ class Livecheck
def url(val = nil)
return @url if val.nil?
@url = val
@url = case val
when :head, :stable, :devel
@formula.send(val).url
when :homepage
@formula.homepage
else
val
end
end
# Returns a Hash of all instance variable values.

View File

@ -8,7 +8,7 @@ class Locale
REGION_REGEX = /(?:[A-Z]{2}|\d{3})/.freeze # ISO 3166-1 or UN M.49
SCRIPT_REGEX = /(?:[A-Z][a-z]{3})/.freeze # ISO 15924
LOCALE_REGEX = /\A((?:#{LANGUAGE_REGEX}|#{REGION_REGEX}|#{SCRIPT_REGEX})(?:\-|$)){1,3}\Z/.freeze
LOCALE_REGEX = /\A((?:#{LANGUAGE_REGEX}|#{REGION_REGEX}|#{SCRIPT_REGEX})(?:-|$)){1,3}\Z/.freeze
def self.parse(string)
string = string.to_s
@ -16,7 +16,7 @@ class Locale
raise ParserError, "'#{string}' cannot be parsed to a #{self}" unless string.match?(LOCALE_REGEX)
scan = proc do |regex|
string.scan(/(?:\-|^)(#{regex})(?:\-|$)/).flatten.first
string.scan(/(?:-|^)(#{regex})(?:-|$)/).flatten.first
end
language = scan.call(LANGUAGE_REGEX)

View File

@ -97,11 +97,9 @@ can take several different forms:
You can still access these formulae by using a special syntax, e.g.
`homebrew/dupes/vim` or `homebrew/versions/node4`.
* An arbitrary file or URL:
Homebrew can install formulae via URL, e.g.
`https://raw.githubusercontent.com/Homebrew/homebrew-core/master/Formula/git.rb`,
or from a local path. It can point to either a formula file or a bottle.
In the case of a URL, the downloaded file will be cached for later use.
* An arbitrary file:
Homebrew can install formulae from a local path. It can point to either a
formula file or a bottle.
## ENVIRONMENT

View File

@ -209,7 +209,7 @@ class Migrator
rescue Exception => e # rubocop:disable Lint/RescueException
onoe "Error occurred while migrating."
puts e
puts e.backtrace if ARGV.debug?
puts e.backtrace if Homebrew.args.debug?
puts "Backing up..."
ignore_interrupts { backup_oldname }
ensure
@ -318,7 +318,7 @@ class Migrator
rescue Exception => e # rubocop:disable Lint/RescueException
onoe "An unexpected error occurred during linking"
puts e
puts e.backtrace if ARGV.debug?
puts e.backtrace if Homebrew.args.debug?
ignore_interrupts { new_keg.unlink }
raise
end

View File

@ -42,11 +42,7 @@ module OS
end
def languages
@languages ||= [
*ARGV.value("language")&.split(","),
*ENV["HOMEBREW_LANGUAGES"]&.split(","),
*ENV["LANG"]&.slice(/[a-z]+/),
].uniq
@languages ||= [*ENV["LANG"]&.slice(/[a-z]+/)].uniq
end
def language

View File

@ -60,9 +60,11 @@ module OS
def languages
@languages ||= [
*ARGV.value("language")&.split(","),
*Homebrew.args.value("language")&.split(","),
*ENV["HOMEBREW_LANGUAGES"]&.split(","),
*Open3.capture2("defaults", "read", "-g", "AppleLanguages")[0].scan(/[^ \n"(),]+/),
*Open3.capture2("defaults", "read", "-g", "AppleLanguages")
.first
.scan(/[^ \n"(),]+/),
].uniq
end

View File

@ -5,7 +5,7 @@ class Keg
return if file.dylib_id == id
@require_relocation = true
odebug "Changing dylib ID of #{file}\n from #{file.dylib_id}\n to #{id}" if ARGV.debug?
odebug "Changing dylib ID of #{file}\n from #{file.dylib_id}\n to #{id}" if Homebrew.args.debug?
MachO::Tools.change_dylib_id(file, id, strict: false)
rescue MachO::MachOError
onoe <<~EOS
@ -20,7 +20,7 @@ class Keg
return if old == new
@require_relocation = true
odebug "Changing install name in #{file}\n from #{old}\n to #{new}" if ARGV.debug?
odebug "Changing install name in #{file}\n from #{old}\n to #{new}" if Homebrew.args.debug?
MachO::Tools.change_install_name(file, old, new, strict: false)
rescue MachO::MachOError
onoe <<~EOS

View File

@ -169,6 +169,7 @@ end
# Legacy patches have no checksum and are not cached.
class LegacyPatch < ExternalPatch
def initialize(strip, url)
odeprecated "legacy patches", "'patch do' blocks"
super(strip)
resource.url(url)
resource.download_strategy = CurlDownloadStrategy

View File

@ -35,8 +35,8 @@ module Homebrew
fi.installed_as_dependency = tab.installed_as_dependency
fi.installed_on_request = tab.installed_on_request
end
fi.fetch
fi.prelude
fi.fetch
oh1 "Reinstalling #{Formatter.identifier(f.full_name)} #{options.to_a.join " "}"

View File

@ -111,7 +111,7 @@ class JavaRequirement < Requirement
rescue FormulaUnavailableError
nil
end
javas << jdk.bin/"java" if jdk&.installed?
javas << jdk.bin/"java" if jdk&.latest_version_installed?
javas << which("java")
javas
end

View File

@ -72,7 +72,7 @@ class Resource
# directory. Subclasses that override stage should implement the tmp
# dir using {Mktemp} so that works with all subtypes.
def stage(target = nil, &block)
raise ArgumentError, "target directory or block is required" if target.blank? && block.blank?
raise ArgumentError, "target directory or block is required" if !target && block.blank?
prepare_patches
fetch_patches(skip_downloaded: true)

View File

@ -129,7 +129,7 @@ module RuboCop
string = stanza.stanza_node.children[2]
return string.str_content if string.str_type?
string.to_s.gsub(%r{.*"([a-z0-9]+\:\/\/[^"]+)".*}m, '\1')
string.to_s.gsub(%r{.*"([a-z0-9]+://[^"]+)".*}m, '\1')
end
def url_match_homepage?(stanza)

View File

@ -10,6 +10,11 @@ module RuboCop
# - `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
# `aspell`: options and resources should be grouped by language
COMPONENT_WHITELIST = %w[
aspell
].freeze
def audit_formula(_node, _class_node, _parent_class_node, body_node)
component_precedence_list = [
[{ name: :include, type: :method_call }],
@ -34,6 +39,8 @@ module RuboCop
[{ name: :deprecated_option, type: :method_call }],
[{ name: :depends_on, type: :method_call }],
[{ name: :uses_from_macos, type: :method_call }],
[{ name: :on_macos, type: :block_call }],
[{ name: :on_linux, type: :block_call }],
[{ name: :conflicts_with, type: :method_call }],
[{ name: :skip_clean, type: :method_call }],
[{ name: :cxxstdlib_check, type: :method_call }],
@ -49,50 +56,115 @@ module RuboCop
[{ 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(body_node, component[:name]).to_a
when :block_call
relevant_components += find_blocks(body_node, component[:name]).to_a
when :method_definition
relevant_components << find_method_def(body_node, component[:name])
end
end
relevant_components.delete_if(&:nil?)
end
@present_components, @offensive_nodes = check_order(component_precedence_list, body_node)
# 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
component_precedence_list = [
[{ name: :depends_on, type: :method_call }],
[{ name: :resource, type: :block_call }],
[{ name: :patch, type: :method_call }, { name: :patch, type: :block_call }],
]
on_macos_blocks = find_blocks(body_node, :on_macos)
if on_macos_blocks.length > 1
@offensive_node = on_macos_blocks.second
@offense_source_range = on_macos_blocks.second.source_range
problem "there can only be one `on_macos` block in a formula."
end
check_on_os_block_content(component_precedence_list, on_macos_blocks.first) if on_macos_blocks.any?
on_linux_blocks = find_blocks(body_node, :on_linux)
if on_linux_blocks.length > 1
@offensive_node = on_linux_blocks.second
@offense_source_range = on_linux_blocks.second.source_range
problem "there can only be one `on_linux` block in a formula."
end
check_on_os_block_content(component_precedence_list, on_linux_blocks.first) if on_linux_blocks.any?
resource_blocks = find_blocks(body_node, :resource)
resource_blocks.each do |resource_block|
on_macos_blocks = find_blocks(resource_block.body, :on_macos)
on_linux_blocks = find_blocks(resource_block.body, :on_linux)
if on_macos_blocks.length.zero? && on_linux_blocks.length.zero?
# Found nothing. Try without .body as depending on the code,
# on_macos or on_linux might be in .body or not ...
on_macos_blocks = find_blocks(resource_block, :on_macos)
on_linux_blocks = find_blocks(resource_block, :on_linux)
next if on_macos_blocks.length.zero? && on_linux_blocks.length.zero?
end
@offensive_node = resource_block
@offense_source_range = resource_block.source_range
if on_macos_blocks.length > 1
problem "there can only be one `on_macos` block in a resource block."
next
end
if on_linux_blocks.length > 1
problem "there can only be one `on_linux` block in a resource block."
next
end
if on_macos_blocks.length == 1 && on_linux_blocks.length.zero?
problem "you need to define an `on_linux` block within your resource block."
next
end
if on_macos_blocks.length.zero? && on_linux_blocks.length == 1
problem "you need to define an `on_macos` block within your resource block."
next
end
on_macos_block = on_macos_blocks.first
on_linux_block = on_linux_blocks.first
child_nodes = on_macos_block.body.child_nodes
if child_nodes[0].method_name.to_s != "url" && child_nodes[1].method_name.to_s != "sha256"
problem "only an url and a sha256 (in the right order) are allowed in a `on_macos` " \
"block within a resource block."
next
end
child_nodes = on_linux_block.body.child_nodes
if child_nodes[0].method_name.to_s != "url" && child_nodes[1].method_name.to_s != "sha256"
problem "only an url and a sha256 (in the right order) are allowed in a `on_linux` " \
"block within a resource block."
end
end
end
# `aspell`: options and resources should be grouped by language
WHITELIST = %w[
aspell
].freeze
def check_on_os_block_content(component_precedence_list, on_os_block)
_, offensive_node = check_order(component_precedence_list, on_os_block.body)
component_problem(*offensive_node) if offensive_node
on_os_block.body.child_nodes.each do |child|
valid_node = depends_on_node?(child)
# Check for RuboCop::AST::SendNode instances only, as we are checking the
# method_name for patches and resources.
next unless child.instance_of? RuboCop::AST::SendNode
# Method to format message for reporting component precedence violations
def component_problem(c1, c2)
return if WHITELIST.include?(@formula_name)
valid_node ||= child.method_name.to_s == "patch"
valid_node ||= child.method_name.to_s == "resource"
problem "`#{format_component(c1)}` (line #{line_number(c1)}) " \
"should be put before `#{format_component(c2)}` " \
"(line #{line_number(c2)})"
@offensive_node = on_os_block
@offense_source_range = on_os_block.source_range
unless valid_node
problem "`#{on_os_block.method_name}` can only include `depends_on`, `patch` and `resource` nodes."
end
end
end
# autocorrect method gets called just after component_problem method call
def autocorrect(_node)
return if @offensive_nodes.nil?
succeeding_node = @offensive_nodes[0]
preceding_node = @offensive_nodes[1]
lambda do |corrector|
@ -130,6 +202,52 @@ module RuboCop
return [idx, comp.index(node1), comp] if comp.member?(node1)
end
end
def check_order(component_precedence_list, body_node)
present_components = component_precedence_list.map do |components|
components.flat_map do |component|
case component[:type]
when :method_call
find_method_calls_by_name(body_node, component[:name]).to_a
when :block_call
find_blocks(body_node, component[:name]).to_a
when :method_definition
find_method_def(body_node, component[:name])
end
end.compact
end
# Check if each present_components is above rest of the present_components
offensive_nodes = nil
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)
break if offensive_nodes
end
end
[present_components, offensive_nodes]
end
# Method to format message for reporting component precedence violations
def component_problem(c1, c2)
return if COMPONENT_WHITELIST.include?(@formula_name)
problem "`#{format_component(c1)}` (line #{line_number(c1)}) " \
"should be put before `#{format_component(c2)}` " \
"(line #{line_number(c2)})"
end
# Node pattern method to match
# `depends_on` variants
def_node_matcher :depends_on_node?, <<~EOS
{(if _ (send nil? :depends_on ...) nil?)
(send nil? :depends_on ...)}
EOS
end
end
end

View File

@ -153,7 +153,7 @@ module RuboCop
find_instance_method_call(body_node, :build, :include?) do |method|
arg = parameters(method).first
next unless match = regex_match_group(arg, /^\-\-(.*)$/)
next unless match = regex_match_group(arg, /^--(.*)$/)
problem "Reference '#{match[1]}' without dashes"
end
@ -403,7 +403,7 @@ module RuboCop
path = parameters(method).first
next unless path.str_type?
next unless match = regex_match_group(path, /^[^\*{},]+$/)
next unless match = regex_match_group(path, /^[^*{},]+$/)
problem "Dir([\"#{string_content(path)}\"]) is unnecessary; just use \"#{match[0]}\""
end

View File

@ -13,11 +13,12 @@ module RuboCop
https://downloads.sourceforge.net/project/bittwist/
https://downloads.sourceforge.net/project/launch4j/
https://github.com/ChrisJohnsen/tmux-MacOSX-pasteboard/archive/
https://github.com/obihann/archey-osx/archive/
https://github.com/obihann/archey-osx
https://github.com/sindresorhus/macos-wallpaper/archive/
https://raw.githubusercontent.com/liyanage/macosx-shell-scripts/
https://osxbook.com/book/bonus/chapter8/core/download/gcore
https://naif.jpl.nasa.gov/pub/naif/toolkit/C/MacIntel_OSX_AppleC_64bit/packages/
https://artifacts.videolan.org/x264/release-macos/
].freeze
# These are formulae that, sadly, require an upstream binary to bootstrap.
@ -48,6 +49,12 @@ module RuboCop
urls = find_every_func_call_by_name(body_node, :url)
mirrors = find_every_func_call_by_name(body_node, :mirror)
# Identify livecheck urls, to skip some checks for them
livecheck_url = if (livecheck = find_every_func_call_by_name(body_node, :livecheck).first) &&
(livecheck_url = find_every_func_call_by_name(livecheck.parent, :url).first)
string_content(parameters(livecheck_url).first)
end
# GNU urls; doesn't apply to mirrors
gnu_pattern = %r{^(?:https?|ftp)://ftpmirror.gnu.org/(.*)}
audit_urls(urls, gnu_pattern) do |match, url|
@ -63,9 +70,21 @@ module RuboCop
apache_pattern = %r{^https?://(?:[^/]*\.)?apache\.org/(?:dyn/closer\.cgi\?path=/?|dist/)(.*)}i
audit_urls(urls, apache_pattern) do |match, url|
next if url == livecheck_url
problem "#{url} should be `https://www.apache.org/dyn/closer.lua?path=#{match[1]}`"
end
version_control_pattern = %r{^(cvs|bzr|hg|fossil)://}
audit_urls(urls, version_control_pattern) do |match, _|
problem "Use of the #{match[1]}:// scheme is deprecated, pass `:using => :#{match[1]}` instead"
end
svn_pattern = %r{^svn\+http://}
audit_urls(urls, svn_pattern) do |_, _|
problem "Use of the svn+http:// scheme is deprecated, pass `:using => :svn` instead"
end
audit_urls(mirrors, /.*/) do |_, mirror|
urls.each do |url|
url_string = string_content(parameters(url).first)
@ -148,7 +167,7 @@ module RuboCop
problem "Don't use /download in SourceForge urls (url is #{url})." if url.end_with?("/download")
if url.match?(%r{^https?://sourceforge\.})
if url.match?(%r{^https?://sourceforge\.}) && url != livecheck_url
problem "Use https://downloads.sourceforge.net to get geolocation (url is #{url})."
end
@ -220,7 +239,7 @@ module RuboCop
# Use new-style archive downloads
archive_gh_pattern = %r{https://.*github.*/(?:tar|zip)ball/}
audit_urls(urls, archive_gh_pattern) do |_, url|
next if url.match?(/\.git$/)
next if url.end_with?(".git")
problem "Use /archive/ URLs for GitHub tarballs (url is #{url})."
end

View File

@ -221,6 +221,7 @@ class SoftwareSpec
end
end
# TODO
def add_legacy_patches(list)
list = Patch.normalize_legacy_patches(list)
list.each { |p| p.owner = self }

View File

@ -77,7 +77,7 @@ module Homebrew
case output_type
when :print
args << "--debug" if ARGV.debug?
args << "--debug" if Homebrew.args.debug?
args << "--display-cop-names" if Homebrew.args.display_cop_names?
args << "--format" << "simple" if files
system(cache_env, "rubocop", *args)

View File

@ -34,7 +34,7 @@ class SystemCommand
end
def run!
puts redact_secrets(command.shelljoin.gsub('\=', "="), @secrets) if verbose? || ARGV.debug?
puts redact_secrets(command.shelljoin.gsub('\=', "="), @secrets) if verbose? || Homebrew.args.debug?
@output = []

View File

@ -88,7 +88,7 @@ class SystemConfig
_, err, status = system_command("java", args: ["-version"], print_stderr: false)
return "N/A" unless status.success?
err[/java version "([\d\._]+)"/, 1] || "N/A"
err[/java version "([\d._]+)"/, 1] || "N/A"
end
def describe_git
@ -100,7 +100,7 @@ class SystemConfig
def describe_curl
out, = system_command(curl_executable, args: ["--version"])
if /^curl (?<curl_version>[\d\.]+)/ =~ out
if /^curl (?<curl_version>[\d.]+)/ =~ out
"#{curl_version} => #{curl_executable}"
else
"N/A"

View File

@ -1,89 +0,0 @@
# frozen_string_literal: true
require "extend/ARGV"
describe HomebrewArgvExtension do
subject { argv.extend(described_class) }
let(:argv) { ["mxcl"] }
describe "#named" do
let(:argv) { ["foo", "--debug", "-v"] }
it "returns an array of non-option arguments" do
expect(subject.send(:named)).to eq ["foo"]
end
context "when there are no named arguments" do
let(:argv) { [] }
it "returns an empty array" do
expect(subject.send(:named)).to be_empty
end
end
end
describe "#options_only" do
let(:argv) { ["--foo", "-vds", "a", "b", "cdefg"] }
it "returns an array of option arguments" do
expect(subject.send("options_only")).to eq ["--foo", "-vds"]
end
end
describe "#empty?" do
let(:argv) { [] }
it "returns true if it is empty" do
expect(subject).to be_empty
end
end
describe "#switch?" do
let(:argv) { ["-ns", "-i", "--bar", "-a-bad-arg"] }
it "returns true if the given string is a switch" do
%w[n s i].each do |s|
expect(subject.send("switch?", s)).to be true
end
end
it "returns false if the given string is not a switch" do
%w[b ns bar --bar -n a bad arg].each do |s|
expect(subject.send("switch?", s)).to be false
end
end
end
describe "#flag?" do
let(:argv) { ["--foo", "-bq", "--bar"] }
it "returns true if the given string is a flag" do
expect(subject.send("flag?", "--foo")).to eq true
expect(subject.send("flag?", "--bar")).to eq true
end
it "returns true if there is a switch with the same initial character" do
expect(subject.send("flag?", "--baz")).to eq true
expect(subject.send("flag?", "--qux")).to eq true
end
it "returns false if there is no matching flag" do
expect(subject.send("flag?", "--frotz")).to eq false
expect(subject.send("flag?", "--debug")).to eq false
end
end
describe "#value" do
let(:argv) { ["--foo=", "--bar=ab"] }
it "returns the value for a given string" do
expect(subject.value("foo")).to eq ""
expect(subject.value("bar")).to eq "ab"
end
it "returns nil if there is no matching argument" do
expect(subject.value("baz")).to be nil
end
end
end

View File

@ -39,11 +39,11 @@ describe Cask::Audit, :cask do
let(:cask) { instance_double(Cask::Cask) }
let(:download) { false }
let(:check_token_conflicts) { false }
let(:token_conflicts) { false }
let(:fake_system_command) { class_double(SystemCommand) }
let(:audit) {
described_class.new(cask, download: download,
check_token_conflicts: check_token_conflicts,
token_conflicts: token_conflicts,
command: fake_system_command)
}
@ -517,7 +517,7 @@ describe Cask::Audit, :cask do
describe "token conflicts" do
let(:cask_token) { "with-binary" }
let(:check_token_conflicts) { true }
let(:token_conflicts) { true }
context "when cask token conflicts with a core formula" do
let(:formula_names) { %w[with-binary other-formula] }

View File

@ -21,7 +21,13 @@ describe Cask::Cmd::Audit, :cask do
expect(Cask::CaskLoader).to receive(:load).with(cask_token).and_return(cask)
expect(Cask::Auditor).to receive(:audit)
.with(cask, audit_download: false, audit_appcast: false, check_token_conflicts: false, quarantine: true)
.with(cask, audit_download: false,
audit_appcast: false,
audit_token_conflicts: false,
audit_new_cask: false,
audit_online: false,
audit_strict: false,
quarantine: true)
.and_return(true)
described_class.run(cask_token)
@ -32,7 +38,13 @@ describe Cask::Cmd::Audit, :cask do
it "does not download the Cask per default" do
allow(Cask::CaskLoader).to receive(:load).and_return(cask)
expect(Cask::Auditor).to receive(:audit)
.with(cask, audit_download: false, audit_appcast: false, check_token_conflicts: false, quarantine: true)
.with(cask, audit_download: false,
audit_appcast: false,
audit_token_conflicts: false,
audit_new_cask: false,
audit_online: false,
audit_strict: false,
quarantine: true)
.and_return(true)
described_class.run("casktoken")
@ -41,7 +53,13 @@ describe Cask::Cmd::Audit, :cask do
it "download a Cask if --download flag is set" do
allow(Cask::CaskLoader).to receive(:load).and_return(cask)
expect(Cask::Auditor).to receive(:audit)
.with(cask, audit_download: true, audit_appcast: false, check_token_conflicts: false, quarantine: true)
.with(cask, audit_download: true,
audit_appcast: false,
audit_token_conflicts: false,
audit_new_cask: false,
audit_online: false,
audit_strict: false,
quarantine: true)
.and_return(true)
described_class.run("casktoken", "--download")
@ -52,7 +70,13 @@ describe Cask::Cmd::Audit, :cask do
it "does not check for token conflicts per default" do
allow(Cask::CaskLoader).to receive(:load).and_return(cask)
expect(Cask::Auditor).to receive(:audit)
.with(cask, audit_download: false, audit_appcast: false, check_token_conflicts: false, quarantine: true)
.with(cask, audit_download: false,
audit_appcast: false,
audit_token_conflicts: false,
audit_new_cask: false,
audit_online: false,
audit_strict: false,
quarantine: true)
.and_return(true)
described_class.run("casktoken")
@ -61,10 +85,112 @@ describe Cask::Cmd::Audit, :cask do
it "checks for token conflicts if --token-conflicts flag is set" do
allow(Cask::CaskLoader).to receive(:load).and_return(cask)
expect(Cask::Auditor).to receive(:audit)
.with(cask, audit_download: false, audit_appcast: false, check_token_conflicts: true, quarantine: true)
.with(cask, audit_download: false,
audit_appcast: false,
audit_token_conflicts: true,
audit_new_cask: false,
audit_online: false,
audit_strict: false,
quarantine: true)
.and_return(true)
described_class.run("casktoken", "--token-conflicts")
end
end
describe "rules for checking strictly" do
it "does not check strictly per default" do
allow(Cask::CaskLoader).to receive(:load).and_return(cask)
expect(Cask::Auditor).to receive(:audit)
.with(cask, audit_download: false,
audit_appcast: false,
audit_token_conflicts: false,
audit_new_cask: false,
audit_online: false,
audit_strict: false,
quarantine: true)
.and_return(true)
described_class.run("casktoken")
end
it "checks strictly if --strict flag is set" do
allow(Cask::CaskLoader).to receive(:load).and_return(cask)
expect(Cask::Auditor).to receive(:audit)
.with(cask, audit_download: false,
audit_appcast: false,
audit_token_conflicts: true,
audit_new_cask: false,
audit_online: false,
audit_strict: true,
quarantine: true)
.and_return(true)
described_class.run("casktoken", "--strict")
end
end
describe "rules for checking online" do
it "does not check online per default" do
allow(Cask::CaskLoader).to receive(:load).and_return(cask)
expect(Cask::Auditor).to receive(:audit)
.with(cask, audit_download: false,
audit_appcast: false,
audit_token_conflicts: false,
audit_new_cask: false,
audit_online: false,
audit_strict: false,
quarantine: true)
.and_return(true)
described_class.run("casktoken")
end
it "checks online if --online flag is set" do
allow(Cask::CaskLoader).to receive(:load).and_return(cask)
expect(Cask::Auditor).to receive(:audit)
.with(cask, audit_download: true,
audit_appcast: true,
audit_token_conflicts: false,
audit_new_cask: false,
audit_online: true,
audit_strict: false,
quarantine: true)
.and_return(true)
described_class.run("casktoken", "--online")
end
end
describe "rules for checking new casks" do
it "does not check new casks per default" do
allow(Cask::CaskLoader).to receive(:load).and_return(cask)
expect(Cask::Auditor).to receive(:audit)
.with(cask, audit_download: false,
audit_appcast: false,
audit_token_conflicts: false,
audit_new_cask: false,
audit_online: false,
audit_strict: false,
quarantine: true)
.and_return(true)
described_class.run("casktoken")
end
it "checks new casks if --new-cask flag is set" do
allow(Cask::CaskLoader).to receive(:load).and_return(cask)
expect(Cask::Auditor).to receive(:audit)
.with(cask, audit_download: true,
audit_appcast: true,
audit_token_conflicts: true,
audit_new_cask: true,
audit_online: true,
audit_strict: true,
quarantine: true)
.and_return(true)
described_class.run("casktoken", "--new-cask")
end
end
end

View File

@ -2,6 +2,7 @@
require_relative "shared_examples/requires_cask_token"
require_relative "shared_examples/invalid_option"
require "utils"
describe Cask::Cmd::Info, :cask do
it_behaves_like "a command that requires a Cask token"
@ -139,7 +140,16 @@ describe Cask::Cmd::Info, :cask do
EOS
end
it "can run be run with a url twice", :needs_network do
it "can run be run with a url twice and returns analytics", :needs_network do
analytics = {
"analytics" => {
"install" => {
"30d" => { "docker" => 1000 }, "90d" => { "docker" => 2000 }, "365d" => { "docker" => 3000 }
},
},
}
expect(Utils::Analytics).to receive(:formulae_brew_sh_json).twice.with("cask/docker.json")
.and_return(analytics)
expect {
described_class.run("https://raw.githubusercontent.com/Homebrew/homebrew-cask" \
"/d0b2c58652ae5eff20a7a4ac93292a08b250912b/Casks/docker.rb")
@ -155,6 +165,8 @@ describe Cask::Cmd::Info, :cask do
Docker CE
==> Artifacts
Docker.app (App)
==> Analytics
install: 1,000 (30 days), 2,000 (90 days), 3,000 (365 days)
==> Downloading https://raw.githubusercontent.com/Homebrew/homebrew-cask/d0b2c58652ae5eff20a7a4ac93292a08b250912b/Casks/docker.rb.
docker: 2.0.0.2-ce-mac81,30215 (auto_updates)
https://www.docker.com/community-edition
@ -164,6 +176,8 @@ describe Cask::Cmd::Info, :cask do
Docker CE
==> Artifacts
Docker.app (App)
==> Analytics
install: 1,000 (30 days), 2,000 (90 days), 3,000 (365 days)
EOS
end
end

View File

@ -9,7 +9,7 @@ end
describe "brew --cache", :integration_test do
it "prints all cache files for a given Formula" do
expect { brew "--cache", testball }
.to output(%r{#{HOMEBREW_CACHE}/downloads/[\da-f]{64}\-\-testball\-}).to_stdout
.to output(%r{#{HOMEBREW_CACHE}/downloads/[\da-f]{64}--testball-}).to_stdout
.and not_to_output.to_stderr
.and be_a_success
end

View File

@ -68,7 +68,7 @@ describe "brew install", :integration_test do
# and there will be the git requirement, but we cannot instantiate git
# formula since we only have testball1 formula.
expect { brew "install", "testball1", "--HEAD", "--ignore-dependencies" }
.to output(%r{#{HOMEBREW_CELLAR}/testball1/HEAD\-d5eb689}).to_stdout
.to output(%r{#{HOMEBREW_CELLAR}/testball1/HEAD-d5eb689}).to_stdout
.and output(/Cloning into/).to_stderr
.and be_a_success
expect(HOMEBREW_CELLAR/"testball1/HEAD-d5eb689/foo/test").not_to be_a_file

View File

@ -3,11 +3,12 @@
shared_examples "parseable arguments" do
subject(:method_name) do |example|
example.metadata[:example_group][:parent_example_group][:description]
.gsub(/^Homebrew\./, "")
.delete_prefix("Homebrew.")
end
let(:command_name) do
method_name.gsub(/_args$/, "").tr("_", "-")
method_name.delete_suffix("_args")
.tr("_", "-")
end
it "can parse arguments" do

Some files were not shown because too many files have changed in this diff Show More