Merge branch 'master' into check-for-master-no-refactor
This commit is contained in:
commit
2d6bd04007
@ -15,26 +15,27 @@ matrix:
|
|||||||
rvm: system
|
rvm: system
|
||||||
- os: linux
|
- os: linux
|
||||||
sudo: false
|
sudo: false
|
||||||
rvm: 2.0.0
|
rvm: 2.3.3
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- export HOMEBREW_NO_AUTO_UPDATE=1
|
- export HOMEBREW_NO_AUTO_UPDATE=1
|
||||||
- export HOMEBREW_DEVELOPER=1
|
- export HOMEBREW_DEVELOPER=1
|
||||||
- git clone --depth=1 https://github.com/Homebrew/homebrew-test-bot Library/Taps/homebrew/homebrew-test-bot
|
|
||||||
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then
|
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then
|
||||||
|
git clone --depth=1 https://github.com/Homebrew/homebrew-test-bot Library/Taps/homebrew/homebrew-test-bot;
|
||||||
HOMEBREW_REPOSITORY="$(brew --repo)";
|
HOMEBREW_REPOSITORY="$(brew --repo)";
|
||||||
sudo chown -R "$USER" "$HOMEBREW_REPOSITORY/Library/Taps";
|
sudo chown -R "$USER" "$HOMEBREW_REPOSITORY/Library/Taps";
|
||||||
mv "$HOMEBREW_REPOSITORY/Library/Taps" "$PWD/Library";
|
mv "$HOMEBREW_REPOSITORY/Library/Taps" "$PWD/Library";
|
||||||
sudo rm -rf "$HOMEBREW_REPOSITORY";
|
sudo rm -rf "$HOMEBREW_REPOSITORY";
|
||||||
sudo ln -s "$PWD" "$HOMEBREW_REPOSITORY";
|
sudo ln -s "$PWD" "$HOMEBREW_REPOSITORY";
|
||||||
else
|
else
|
||||||
|
umask 022;
|
||||||
|
git clone --depth=1 https://github.com/Homebrew/homebrew-test-bot Library/Taps/homebrew/homebrew-test-bot;
|
||||||
git fetch --unshallow;
|
git fetch --unshallow;
|
||||||
export PATH="$PWD/bin:$PATH";
|
export PATH="$PWD/bin:$PATH";
|
||||||
HOMEBREW_CORE_TAP_DIR="$(brew --repo "homebrew/core")";
|
HOMEBREW_CORE_TAP_DIR="$(brew --repo "homebrew/core")";
|
||||||
mkdir -p "$HOMEBREW_CORE_TAP_DIR";
|
mkdir -p "$HOMEBREW_CORE_TAP_DIR";
|
||||||
HOMEBREW_TEST_BOT_TAP_DIR="$(brew --repo "homebrew/test-bot")";
|
HOMEBREW_TEST_BOT_TAP_DIR="$(brew --repo "homebrew/test-bot")";
|
||||||
ln -s "$HOMEBREW_TEST_BOT_TAP_DIR/.git" "$HOMEBREW_TEST_BOT_TAP_DIR/Formula" "$HOMEBREW_CORE_TAP_DIR";
|
ln -s "$HOMEBREW_TEST_BOT_TAP_DIR/.git" "$HOMEBREW_TEST_BOT_TAP_DIR/Formula" "$HOMEBREW_CORE_TAP_DIR";
|
||||||
umask 022;
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
script:
|
script:
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
AllCops:
|
AllCops:
|
||||||
TargetRubyVersion: 2.0
|
TargetRubyVersion: 2.3
|
||||||
Exclude:
|
Exclude:
|
||||||
- '**/Casks/**/*'
|
- '**/Casks/**/*'
|
||||||
- '**/vendor/**/*'
|
- '**/vendor/**/*'
|
||||||
@ -119,7 +119,7 @@ Style/Encoding:
|
|||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
# dashes in filenames are typical
|
# dashes in filenames are typical
|
||||||
Style/FileName:
|
Naming/FileName:
|
||||||
Regex: !ruby/regexp /^[\w\@\-\+\.]+(\.rb)?$/
|
Regex: !ruby/regexp /^[\w\@\-\+\.]+(\.rb)?$/
|
||||||
|
|
||||||
# falsely flags e.g. curl formatting arguments as format strings
|
# falsely flags e.g. curl formatting arguments as format strings
|
||||||
@ -189,8 +189,25 @@ Style/TrailingCommaInArguments:
|
|||||||
EnforcedStyleForMultiline: comma
|
EnforcedStyleForMultiline: comma
|
||||||
|
|
||||||
# we have too many variables like sha256 where this harms readability
|
# we have too many variables like sha256 where this harms readability
|
||||||
Style/VariableNumber:
|
Naming/VariableNumber:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
Style/WordArray:
|
Style/WordArray:
|
||||||
MinSize: 4
|
MinSize: 4
|
||||||
|
|
||||||
|
# we want to add this slowly and manually
|
||||||
|
Style/FrozenStringLiteralComment:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
# generally rescuing StandardError is fine
|
||||||
|
Lint/RescueWithoutErrorClass:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
# implicitly allow EOS as we use it everywhere
|
||||||
|
Naming/HeredocDelimiterNaming:
|
||||||
|
Blacklist:
|
||||||
|
- END, EOD, EOF
|
||||||
|
|
||||||
|
# we output how to use interpolated strings too often
|
||||||
|
Lint/InterpolationCheck:
|
||||||
|
Enabled: false
|
||||||
|
|||||||
@ -42,12 +42,12 @@ Style/HashSyntax:
|
|||||||
EnforcedStyle: ruby19_no_mixed_keys
|
EnforcedStyle: ruby19_no_mixed_keys
|
||||||
|
|
||||||
# we won't change backward compatible method names
|
# we won't change backward compatible method names
|
||||||
Style/MethodName:
|
Naming/MethodName:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'compat/**/*'
|
- 'compat/**/*'
|
||||||
|
|
||||||
# we won't change backward compatible predicate names
|
# we won't change backward compatible predicate names
|
||||||
Style/PredicateName:
|
Naming/PredicateName:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'compat/**/*'
|
- 'compat/**/*'
|
||||||
NameWhitelist: is_32_bit?, is_64_bit?
|
NameWhitelist: is_32_bit?, is_64_bit?
|
||||||
|
|||||||
@ -81,7 +81,7 @@ Security/MarshalLoad:
|
|||||||
- 'utils/fork.rb'
|
- 'utils/fork.rb'
|
||||||
|
|
||||||
# Offense count: 1
|
# Offense count: 1
|
||||||
Style/AccessorMethodName:
|
Naming/AccessorMethodName:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'extend/ENV/super.rb'
|
- 'extend/ENV/super.rb'
|
||||||
|
|
||||||
@ -136,10 +136,3 @@ Style/MutableConstant:
|
|||||||
- 'formulary.rb'
|
- 'formulary.rb'
|
||||||
- 'tab.rb'
|
- 'tab.rb'
|
||||||
- 'tap.rb'
|
- 'tap.rb'
|
||||||
|
|
||||||
# Offense count: 8
|
|
||||||
Style/OpMethod:
|
|
||||||
Exclude:
|
|
||||||
- 'dependencies.rb'
|
|
||||||
- 'install_renamed.rb'
|
|
||||||
- 'options.rb'
|
|
||||||
|
|||||||
@ -105,7 +105,8 @@ begin
|
|||||||
possible_tap = OFFICIAL_CMD_TAPS.find { |_, cmds| cmds.include?(cmd) }
|
possible_tap = OFFICIAL_CMD_TAPS.find { |_, cmds| cmds.include?(cmd) }
|
||||||
possible_tap = Tap.fetch(possible_tap.first) if possible_tap
|
possible_tap = Tap.fetch(possible_tap.first) if possible_tap
|
||||||
|
|
||||||
if possible_tap && !possible_tap.installed?
|
odie "Unknown command: #{cmd}" if !possible_tap || possible_tap.installed?
|
||||||
|
|
||||||
brew_uid = HOMEBREW_BREW_FILE.stat.uid
|
brew_uid = HOMEBREW_BREW_FILE.stat.uid
|
||||||
tap_commands = []
|
tap_commands = []
|
||||||
if Process.uid.zero? && !brew_uid.zero?
|
if Process.uid.zero? && !brew_uid.zero?
|
||||||
@ -114,9 +115,6 @@ begin
|
|||||||
tap_commands += %W[#{HOMEBREW_BREW_FILE} tap #{possible_tap}]
|
tap_commands += %W[#{HOMEBREW_BREW_FILE} tap #{possible_tap}]
|
||||||
safe_system(*tap_commands)
|
safe_system(*tap_commands)
|
||||||
exec HOMEBREW_BREW_FILE, cmd, *ARGV
|
exec HOMEBREW_BREW_FILE, cmd, *ARGV
|
||||||
else
|
|
||||||
odie "Unknown command: #{cmd}"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
rescue UsageError => e
|
rescue UsageError => e
|
||||||
require "cmd/help"
|
require "cmd/help"
|
||||||
|
|||||||
@ -23,7 +23,7 @@ HOMEBREW_VERSION="$(git -C "$HOMEBREW_REPOSITORY" describe --tags --dirty --abbr
|
|||||||
HOMEBREW_USER_AGENT_VERSION="$HOMEBREW_VERSION"
|
HOMEBREW_USER_AGENT_VERSION="$HOMEBREW_VERSION"
|
||||||
if [[ -z "$HOMEBREW_VERSION" ]]
|
if [[ -z "$HOMEBREW_VERSION" ]]
|
||||||
then
|
then
|
||||||
HOMEBREW_VERSION=">1.2.0 (no git repository)"
|
HOMEBREW_VERSION=">1.2.0 (shallow or no git repository)"
|
||||||
HOMEBREW_USER_AGENT_VERSION="1.X.Y"
|
HOMEBREW_USER_AGENT_VERSION="1.X.Y"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -105,7 +105,14 @@ then
|
|||||||
HOMEBREW_OS_USER_AGENT_VERSION="Mac OS X $HOMEBREW_MACOS_VERSION"
|
HOMEBREW_OS_USER_AGENT_VERSION="Mac OS X $HOMEBREW_MACOS_VERSION"
|
||||||
|
|
||||||
printf -v HOMEBREW_MACOS_VERSION_NUMERIC "%02d%02d%02d" ${HOMEBREW_MACOS_VERSION//./ }
|
printf -v HOMEBREW_MACOS_VERSION_NUMERIC "%02d%02d%02d" ${HOMEBREW_MACOS_VERSION//./ }
|
||||||
if [[ "$HOMEBREW_MACOS_VERSION_NUMERIC" -lt "100900" &&
|
if [[ "$HOMEBREW_MACOS_VERSION_NUMERIC" -lt "101000" ]]
|
||||||
|
then
|
||||||
|
HOMEBREW_SYSTEM_CURL_TOO_OLD="1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# The system Curl is too old for some modern HTTPS certificates on
|
||||||
|
# older macOS versions.
|
||||||
|
if [[ -n "$HOMEBREW_SYSTEM_CURL_TOO_OLD" &&
|
||||||
-x "$HOMEBREW_PREFIX/opt/curl/bin/curl" ]]
|
-x "$HOMEBREW_PREFIX/opt/curl/bin/curl" ]]
|
||||||
then
|
then
|
||||||
HOMEBREW_CURL="$HOMEBREW_PREFIX/opt/curl/bin/curl"
|
HOMEBREW_CURL="$HOMEBREW_PREFIX/opt/curl/bin/curl"
|
||||||
|
|||||||
@ -112,6 +112,10 @@ class Build
|
|||||||
formula.extend(Debrew::Formula) if ARGV.debug?
|
formula.extend(Debrew::Formula) if ARGV.debug?
|
||||||
|
|
||||||
formula.brew do |_formula, staging|
|
formula.brew do |_formula, staging|
|
||||||
|
# For head builds, HOMEBREW_FORMULA_PREFIX should include the commit,
|
||||||
|
# which is not known until after the formula has been staged.
|
||||||
|
ENV["HOMEBREW_FORMULA_PREFIX"] = formula.prefix
|
||||||
|
|
||||||
staging.retain! if ARGV.keep_tmp?
|
staging.retain! if ARGV.keep_tmp?
|
||||||
formula.patch
|
formula.patch
|
||||||
|
|
||||||
|
|||||||
@ -33,7 +33,7 @@ module Hbc
|
|||||||
# We want to extract nested containers before we
|
# We want to extract nested containers before we
|
||||||
# handle any other artifacts.
|
# handle any other artifacts.
|
||||||
#
|
#
|
||||||
TYPES = [
|
CLASSES = [
|
||||||
PreflightBlock,
|
PreflightBlock,
|
||||||
Uninstall,
|
Uninstall,
|
||||||
NestedContainer,
|
NestedContainer,
|
||||||
@ -60,12 +60,9 @@ module Hbc
|
|||||||
Zap,
|
Zap,
|
||||||
].freeze
|
].freeze
|
||||||
|
|
||||||
def self.for_cask(cask, options = {})
|
def self.for_cask(cask)
|
||||||
odebug "Determining which artifacts are present in Cask #{cask}"
|
odebug "Determining which artifacts are present in Cask #{cask}"
|
||||||
|
CLASSES.flat_map { |klass| klass.for_cask(cask) }
|
||||||
TYPES
|
|
||||||
.select { |klass| klass.me?(cask) }
|
|
||||||
.map { |klass| klass.new(cask, options) }
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,34 +1,28 @@
|
|||||||
module Hbc
|
module Hbc
|
||||||
module Artifact
|
module Artifact
|
||||||
class Base
|
class AbstractArtifact
|
||||||
extend Predicable
|
extend Predicable
|
||||||
|
|
||||||
def self.artifact_name
|
def self.english_name
|
||||||
@artifact_name ||= name.sub(/^.*:/, "").gsub(/(.)([A-Z])/, '\1_\2').downcase
|
@english_name ||= name.sub(/^.*:/, "").gsub(/(.)([A-Z])/, '\1 \2')
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.artifact_english_name
|
def self.english_article
|
||||||
@artifact_english_name ||= name.sub(/^.*:/, "").gsub(/(.)([A-Z])/, '\1 \2')
|
@english_article ||= (english_name =~ /^[aeiou]/i) ? "an" : "a"
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.artifact_english_article
|
def self.dsl_key
|
||||||
@artifact_english_article ||= (artifact_english_name =~ /^[aeiou]/i) ? "an" : "a"
|
@dsl_key ||= name.sub(/^.*:/, "").gsub(/(.)([A-Z])/, '\1_\2').downcase.to_sym
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.artifact_dsl_key
|
def self.dirmethod
|
||||||
@artifact_dsl_key ||= artifact_name.to_sym
|
@dirmethod ||= "#{dsl_key}dir".to_sym
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.artifact_dirmethod
|
def self.for_cask(cask)
|
||||||
@artifact_dirmethod ||= "#{artifact_name}dir".to_sym
|
cask.artifacts[dsl_key].to_a
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.me?(cask)
|
|
||||||
cask.artifacts[artifact_dsl_key].any?
|
|
||||||
end
|
|
||||||
|
|
||||||
attr_reader :force
|
|
||||||
|
|
||||||
# TODO: this sort of logic would make more sense in dsl.rb, or a
|
# TODO: this sort of logic would make more sense in dsl.rb, or a
|
||||||
# constructor called from dsl.rb, so long as that isn't slow.
|
# constructor called from dsl.rb, so long as that isn't slow.
|
||||||
def self.read_script_arguments(arguments, stanza, default_arguments = {}, override_arguments = {}, key = nil)
|
def self.read_script_arguments(arguments, stanza, default_arguments = {}, override_arguments = {}, key = nil)
|
||||||
@ -63,17 +57,14 @@ module Hbc
|
|||||||
[executable, arguments]
|
[executable, arguments]
|
||||||
end
|
end
|
||||||
|
|
||||||
def summary
|
attr_reader :cask
|
||||||
{}
|
|
||||||
|
def initialize(cask)
|
||||||
|
@cask = cask
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_predicate :force?, :verbose?
|
def to_s
|
||||||
|
"#{summarize} (#{self.class.english_name})"
|
||||||
def initialize(cask, command: SystemCommand, force: false, verbose: false)
|
|
||||||
@cask = cask
|
|
||||||
@command = command
|
|
||||||
@force = force
|
|
||||||
@verbose = verbose
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -1,39 +1,51 @@
|
|||||||
require "hbc/artifact/base"
|
require "hbc/artifact/abstract_artifact"
|
||||||
|
|
||||||
module Hbc
|
module Hbc
|
||||||
module Artifact
|
module Artifact
|
||||||
class AbstractFlightBlock < Base
|
class AbstractFlightBlock < AbstractArtifact
|
||||||
def self.artifact_dsl_key
|
def self.dsl_key
|
||||||
super.to_s.sub(/_block$/, "").to_sym
|
super.to_s.sub(/_block$/, "").to_sym
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.uninstall_artifact_dsl_key
|
def self.uninstall_dsl_key
|
||||||
artifact_dsl_key.to_s.prepend("uninstall_").to_sym
|
dsl_key.to_s.prepend("uninstall_").to_sym
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.class_for_dsl_key(dsl_key)
|
def self.for_cask(cask)
|
||||||
Object.const_get("Hbc::DSL::#{dsl_key.to_s.split("_").collect(&:capitalize).join}")
|
[dsl_key, uninstall_dsl_key].flat_map do |key|
|
||||||
|
[*cask.artifacts[key]].map { |block| new(cask, key => block) }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.me?(cask)
|
attr_reader :directives
|
||||||
cask.artifacts[artifact_dsl_key].any? ||
|
|
||||||
cask.artifacts[uninstall_artifact_dsl_key].any?
|
def initialize(cask, **directives)
|
||||||
|
super(cask)
|
||||||
|
@directives = directives
|
||||||
end
|
end
|
||||||
|
|
||||||
def install_phase
|
def install_phase(**)
|
||||||
abstract_phase(self.class.artifact_dsl_key)
|
abstract_phase(self.class.dsl_key)
|
||||||
end
|
end
|
||||||
|
|
||||||
def uninstall_phase
|
def uninstall_phase(**)
|
||||||
abstract_phase(self.class.uninstall_artifact_dsl_key)
|
abstract_phase(self.class.uninstall_dsl_key)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def abstract_phase(dsl_key)
|
def class_for_dsl_key(dsl_key)
|
||||||
@cask.artifacts[dsl_key].each do |block|
|
namespace = self.class.name.to_s.sub(/::.*::.*$/, "")
|
||||||
self.class.class_for_dsl_key(dsl_key).new(@cask).instance_eval(&block)
|
self.class.const_get("#{namespace}::DSL::#{dsl_key.to_s.split("_").collect(&:capitalize).join}")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def abstract_phase(dsl_key)
|
||||||
|
return if (block = directives[dsl_key]).nil?
|
||||||
|
class_for_dsl_key(dsl_key).new(cask).instance_eval(&block)
|
||||||
|
end
|
||||||
|
|
||||||
|
def summarize
|
||||||
|
directives.keys.map(&:to_s).join(", ")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
require "pathname"
|
require "pathname"
|
||||||
require "timeout"
|
require "timeout"
|
||||||
|
|
||||||
require "hbc/artifact/base"
|
require "hbc/artifact/abstract_artifact"
|
||||||
|
|
||||||
module Hbc
|
module Hbc
|
||||||
module Artifact
|
module Artifact
|
||||||
class UninstallBase < Base
|
class AbstractUninstall < AbstractArtifact
|
||||||
ORDERED_DIRECTIVES = [
|
ORDERED_DIRECTIVES = [
|
||||||
:early_script,
|
:early_script,
|
||||||
:launchctl,
|
:launchctl,
|
||||||
@ -20,26 +20,42 @@ module Hbc
|
|||||||
:rmdir,
|
:rmdir,
|
||||||
].freeze
|
].freeze
|
||||||
|
|
||||||
def dispatch_uninstall_directives
|
def self.from_args(cask, **directives)
|
||||||
directives_set = @cask.artifacts[stanza]
|
new(cask, directives)
|
||||||
ohai "Running #{stanza} process for #{@cask}; your password may be necessary"
|
|
||||||
|
|
||||||
directives_set.each do |directives|
|
|
||||||
warn_for_unknown_directives(directives)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
ORDERED_DIRECTIVES.each do |directive_sym|
|
attr_reader :directives
|
||||||
directives_set.select { |h| h.key?(directive_sym) }.each do |directives|
|
|
||||||
args = directives[directive_sym]
|
def initialize(cask, directives)
|
||||||
send("uninstall_#{directive_sym}", *(args.is_a?(Hash) ? [args] : args))
|
super(cask)
|
||||||
|
directives[:signal] = [*directives[:signal]].flatten.each_slice(2).to_a
|
||||||
|
@directives = directives
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_h
|
||||||
|
directives.to_h
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def summarize
|
||||||
|
to_h.map { |key, val| [*val].map { |v| "#{key.inspect} => #{v.inspect}" }.join(", ") }.join(", ")
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def dispatch_uninstall_directives(**options)
|
||||||
|
ohai "Running #{stanza} process for #{@cask}; your password may be necessary"
|
||||||
|
|
||||||
|
warn_for_unknown_directives(directives)
|
||||||
|
|
||||||
|
ORDERED_DIRECTIVES.each do |directive_sym|
|
||||||
|
next unless directives.key?(directive_sym)
|
||||||
|
args = directives[directive_sym]
|
||||||
|
send("uninstall_#{directive_sym}", *(args.is_a?(Hash) ? [args] : args), **options)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def stanza
|
def stanza
|
||||||
self.class.artifact_dsl_key
|
self.class.dsl_key
|
||||||
end
|
end
|
||||||
|
|
||||||
def warn_for_unknown_directives(directives)
|
def warn_for_unknown_directives(directives)
|
||||||
@ -51,18 +67,18 @@ module Hbc
|
|||||||
# Preserve prior functionality of script which runs first. Should rarely be needed.
|
# Preserve prior functionality of script which runs first. Should rarely be needed.
|
||||||
# :early_script should not delete files, better defer that to :script.
|
# :early_script should not delete files, better defer that to :script.
|
||||||
# If Cask writers never need :early_script it may be removed in the future.
|
# If Cask writers never need :early_script it may be removed in the future.
|
||||||
def uninstall_early_script(directives)
|
def uninstall_early_script(directives, **options)
|
||||||
uninstall_script(directives, directive_name: :early_script)
|
uninstall_script(directives, directive_name: :early_script, **options)
|
||||||
end
|
end
|
||||||
|
|
||||||
# :launchctl must come before :quit/:signal for cases where app would instantly re-launch
|
# :launchctl must come before :quit/:signal for cases where app would instantly re-launch
|
||||||
def uninstall_launchctl(*services)
|
def uninstall_launchctl(*services, command: nil, **_)
|
||||||
services.each do |service|
|
services.each do |service|
|
||||||
ohai "Removing launchctl service #{service}"
|
ohai "Removing launchctl service #{service}"
|
||||||
[false, true].each do |with_sudo|
|
[false, true].each do |with_sudo|
|
||||||
plist_status = @command.run("/bin/launchctl", args: ["list", service], sudo: with_sudo, print_stderr: false).stdout
|
plist_status = command.run("/bin/launchctl", args: ["list", service], sudo: with_sudo, print_stderr: false).stdout
|
||||||
if plist_status =~ /^\{/
|
if plist_status =~ /^\{/
|
||||||
@command.run!("/bin/launchctl", args: ["remove", service], sudo: with_sudo)
|
command.run!("/bin/launchctl", args: ["remove", service], sudo: with_sudo)
|
||||||
sleep 1
|
sleep 1
|
||||||
end
|
end
|
||||||
paths = ["/Library/LaunchAgents/#{service}.plist",
|
paths = ["/Library/LaunchAgents/#{service}.plist",
|
||||||
@ -70,19 +86,19 @@ module Hbc
|
|||||||
paths.each { |elt| elt.prepend(ENV["HOME"]) } unless with_sudo
|
paths.each { |elt| elt.prepend(ENV["HOME"]) } unless with_sudo
|
||||||
paths = paths.map { |elt| Pathname(elt) }.select(&:exist?)
|
paths = paths.map { |elt| Pathname(elt) }.select(&:exist?)
|
||||||
paths.each do |path|
|
paths.each do |path|
|
||||||
@command.run!("/bin/rm", args: ["-f", "--", path], sudo: with_sudo)
|
command.run!("/bin/rm", args: ["-f", "--", path], sudo: with_sudo)
|
||||||
end
|
end
|
||||||
# undocumented and untested: pass a path to uninstall :launchctl
|
# undocumented and untested: pass a path to uninstall :launchctl
|
||||||
next unless Pathname(service).exist?
|
next unless Pathname(service).exist?
|
||||||
@command.run!("/bin/launchctl", args: ["unload", "-w", "--", service], sudo: with_sudo)
|
command.run!("/bin/launchctl", args: ["unload", "-w", "--", service], sudo: with_sudo)
|
||||||
@command.run!("/bin/rm", args: ["-f", "--", service], sudo: with_sudo)
|
command.run!("/bin/rm", args: ["-f", "--", service], sudo: with_sudo)
|
||||||
sleep 1
|
sleep 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def running_processes(bundle_id)
|
def running_processes(bundle_id, command: nil)
|
||||||
@command.run!("/bin/launchctl", args: ["list"]).stdout.lines
|
command.run!("/bin/launchctl", args: ["list"]).stdout.lines
|
||||||
.map { |line| line.chomp.split("\t") }
|
.map { |line| line.chomp.split("\t") }
|
||||||
.map { |pid, state, id| [pid.to_i, state.to_i, id] }
|
.map { |pid, state, id| [pid.to_i, state.to_i, id] }
|
||||||
.select do |fields|
|
.select do |fields|
|
||||||
@ -92,16 +108,16 @@ module Hbc
|
|||||||
end
|
end
|
||||||
|
|
||||||
# :quit/:signal must come before :kext so the kext will not be in use by a running process
|
# :quit/:signal must come before :kext so the kext will not be in use by a running process
|
||||||
def uninstall_quit(*bundle_ids)
|
def uninstall_quit(*bundle_ids, command: nil, **_)
|
||||||
bundle_ids.each do |bundle_id|
|
bundle_ids.each do |bundle_id|
|
||||||
ohai "Quitting application ID #{bundle_id}"
|
ohai "Quitting application ID #{bundle_id}"
|
||||||
next if running_processes(bundle_id).empty?
|
next if running_processes(bundle_id, command: command).empty?
|
||||||
@command.run!("/usr/bin/osascript", args: ["-e", %Q(tell application id "#{bundle_id}" to quit)], sudo: true)
|
command.run!("/usr/bin/osascript", args: ["-e", %Q(tell application id "#{bundle_id}" to quit)], sudo: true)
|
||||||
|
|
||||||
begin
|
begin
|
||||||
Timeout.timeout(3) do
|
Timeout.timeout(3) do
|
||||||
Kernel.loop do
|
Kernel.loop do
|
||||||
break if running_processes(bundle_id).empty?
|
break if running_processes(bundle_id, command: command).empty?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
rescue Timeout::Error
|
rescue Timeout::Error
|
||||||
@ -111,15 +127,15 @@ module Hbc
|
|||||||
end
|
end
|
||||||
|
|
||||||
# :signal should come after :quit so it can be used as a backup when :quit fails
|
# :signal should come after :quit so it can be used as a backup when :quit fails
|
||||||
def uninstall_signal(*signals)
|
def uninstall_signal(*signals, command: nil, **_)
|
||||||
signals.flatten.each_slice(2) do |pair|
|
signals.each do |pair|
|
||||||
unless pair.size == 2
|
unless pair.size == 2
|
||||||
raise CaskInvalidError.new(@cask, "Each #{stanza} :signal must consist of 2 elements.")
|
raise CaskInvalidError.new(cask, "Each #{stanza} :signal must consist of 2 elements.")
|
||||||
end
|
end
|
||||||
|
|
||||||
signal, bundle_id = pair
|
signal, bundle_id = pair
|
||||||
ohai "Signalling '#{signal}' to application ID '#{bundle_id}'"
|
ohai "Signalling '#{signal}' to application ID '#{bundle_id}'"
|
||||||
pids = running_processes(bundle_id).map(&:first)
|
pids = running_processes(bundle_id, command: command).map(&:first)
|
||||||
next unless pids.any?
|
next unless pids.any?
|
||||||
# Note that unlike :quit, signals are sent from the current user (not
|
# Note that unlike :quit, signals are sent from the current user (not
|
||||||
# upgraded to the superuser). This is a todo item for the future, but
|
# upgraded to the superuser). This is a todo item for the future, but
|
||||||
@ -133,10 +149,10 @@ module Hbc
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def uninstall_login_item(*login_items)
|
def uninstall_login_item(*login_items, command: nil, **_)
|
||||||
login_items.each do |name|
|
login_items.each do |name|
|
||||||
ohai "Removing login item #{name}"
|
ohai "Removing login item #{name}"
|
||||||
@command.run!("/usr/bin/osascript",
|
command.run!("/usr/bin/osascript",
|
||||||
args: ["-e", %Q(tell application "System Events" to delete every login item whose name is "#{name}")],
|
args: ["-e", %Q(tell application "System Events" to delete every login item whose name is "#{name}")],
|
||||||
sudo: false)
|
sudo: false)
|
||||||
sleep 1
|
sleep 1
|
||||||
@ -144,23 +160,24 @@ module Hbc
|
|||||||
end
|
end
|
||||||
|
|
||||||
# :kext should be unloaded before attempting to delete the relevant file
|
# :kext should be unloaded before attempting to delete the relevant file
|
||||||
def uninstall_kext(*kexts)
|
def uninstall_kext(*kexts, command: nil, **_)
|
||||||
kexts.each do |kext|
|
kexts.each do |kext|
|
||||||
ohai "Unloading kernel extension #{kext}"
|
ohai "Unloading kernel extension #{kext}"
|
||||||
is_loaded = @command.run!("/usr/sbin/kextstat", args: ["-l", "-b", kext], sudo: true).stdout
|
is_loaded = command.run!("/usr/sbin/kextstat", args: ["-l", "-b", kext], sudo: true).stdout
|
||||||
if is_loaded.length > 1
|
if is_loaded.length > 1
|
||||||
@command.run!("/sbin/kextunload", args: ["-b", kext], sudo: true)
|
command.run!("/sbin/kextunload", args: ["-b", kext], sudo: true)
|
||||||
sleep 1
|
sleep 1
|
||||||
end
|
end
|
||||||
@command.run!("/usr/sbin/kextfind", args: ["-b", kext], sudo: true).stdout.chomp.lines.each do |kext_path|
|
command.run!("/usr/sbin/kextfind", args: ["-b", kext], sudo: true).stdout.chomp.lines.each do |kext_path|
|
||||||
ohai "Removing kernel extension #{kext_path}"
|
ohai "Removing kernel extension #{kext_path}"
|
||||||
@command.run!("/bin/rm", args: ["-rf", kext_path], sudo: true)
|
command.run!("/bin/rm", args: ["-rf", kext_path], sudo: true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# :script must come before :pkgutil, :delete, or :trash so that the script file is not already deleted
|
# :script must come before :pkgutil, :delete, or :trash so that the script file is not already deleted
|
||||||
def uninstall_script(directives, directive_name: :script)
|
def uninstall_script(directives, directive_name: :script, force: false, command: nil, **_)
|
||||||
|
# TODO: Create a common `Script` class to run this and Artifact::Installer.
|
||||||
executable, script_arguments = self.class.read_script_arguments(directives,
|
executable, script_arguments = self.class.read_script_arguments(directives,
|
||||||
"uninstall",
|
"uninstall",
|
||||||
{ must_succeed: true, sudo: false },
|
{ must_succeed: true, sudo: false },
|
||||||
@ -168,25 +185,25 @@ module Hbc
|
|||||||
directive_name)
|
directive_name)
|
||||||
|
|
||||||
ohai "Running uninstall script #{executable}"
|
ohai "Running uninstall script #{executable}"
|
||||||
raise CaskInvalidError.new(@cask, "#{stanza} :#{directive_name} without :executable.") if executable.nil?
|
raise CaskInvalidError.new(cask, "#{stanza} :#{directive_name} without :executable.") if executable.nil?
|
||||||
executable_path = @cask.staged_path.join(executable)
|
executable_path = cask.staged_path.join(executable)
|
||||||
|
|
||||||
unless executable_path.exist?
|
unless executable_path.exist?
|
||||||
message = "uninstall script #{executable} does not exist"
|
message = "uninstall script #{executable} does not exist"
|
||||||
raise CaskError, "#{message}." unless force?
|
raise CaskError, "#{message}." unless force
|
||||||
opoo "#{message}, skipping."
|
opoo "#{message}, skipping."
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@command.run("/bin/chmod", args: ["--", "+x", executable_path])
|
command.run("/bin/chmod", args: ["--", "+x", executable_path])
|
||||||
@command.run(executable_path, script_arguments)
|
command.run(executable_path, script_arguments)
|
||||||
sleep 1
|
sleep 1
|
||||||
end
|
end
|
||||||
|
|
||||||
def uninstall_pkgutil(*pkgs)
|
def uninstall_pkgutil(*pkgs, command: nil, **_)
|
||||||
ohai "Uninstalling packages:"
|
ohai "Uninstalling packages:"
|
||||||
pkgs.each do |regex|
|
pkgs.each do |regex|
|
||||||
Hbc::Pkg.all_matching(regex, @command).each do |pkg|
|
Hbc::Pkg.all_matching(regex, command).each do |pkg|
|
||||||
puts pkg.package_id
|
puts pkg.package_id
|
||||||
pkg.uninstall
|
pkg.uninstall
|
||||||
end
|
end
|
||||||
@ -215,28 +232,28 @@ module Hbc
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def uninstall_delete(*paths)
|
def uninstall_delete(*paths, command: nil, **_)
|
||||||
return if paths.empty?
|
return if paths.empty?
|
||||||
|
|
||||||
ohai "Removing files:"
|
ohai "Removing files:"
|
||||||
each_resolved_path(:delete, paths) do |path, resolved_paths|
|
each_resolved_path(:delete, paths) do |path, resolved_paths|
|
||||||
puts path
|
puts path
|
||||||
@command.run!("/usr/bin/xargs", args: ["-0", "--", "/bin/rm", "-r", "-f", "--"], input: resolved_paths.join("\0"), sudo: true)
|
command.run!("/usr/bin/xargs", args: ["-0", "--", "/bin/rm", "-r", "-f", "--"], input: resolved_paths.join("\0"), sudo: true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def uninstall_trash(*paths)
|
def uninstall_trash(*paths, **options)
|
||||||
return if paths.empty?
|
return if paths.empty?
|
||||||
|
|
||||||
resolved_paths = each_resolved_path(:trash, paths).to_a
|
resolved_paths = each_resolved_path(:trash, paths).to_a
|
||||||
|
|
||||||
ohai "Trashing files:"
|
ohai "Trashing files:"
|
||||||
puts resolved_paths.map(&:first)
|
puts resolved_paths.map(&:first)
|
||||||
trash_paths(*resolved_paths.flat_map(&:last))
|
trash_paths(*resolved_paths.flat_map(&:last), **options)
|
||||||
end
|
end
|
||||||
|
|
||||||
def trash_paths(*paths)
|
def trash_paths(*paths, command: nil, **_)
|
||||||
@command.run!("/usr/bin/osascript", args: ["-e", <<-'EOS'.undent, *paths])
|
command.run!("/usr/bin/osascript", args: ["-e", <<-'EOS'.undent, *paths])
|
||||||
on run argv
|
on run argv
|
||||||
repeat with i from 1 to (count argv)
|
repeat with i from 1 to (count argv)
|
||||||
set item i of argv to (item i of argv as POSIX file)
|
set item i of argv to (item i of argv as POSIX file)
|
||||||
@ -260,7 +277,7 @@ module Hbc
|
|||||||
EOS
|
EOS
|
||||||
end
|
end
|
||||||
|
|
||||||
def uninstall_rmdir(*directories)
|
def uninstall_rmdir(*directories, command: nil, **_)
|
||||||
return if directories.empty?
|
return if directories.empty?
|
||||||
|
|
||||||
ohai "Removing directories if empty:"
|
ohai "Removing directories if empty:"
|
||||||
@ -268,10 +285,10 @@ module Hbc
|
|||||||
puts path
|
puts path
|
||||||
resolved_paths.select(&:directory?).each do |resolved_path|
|
resolved_paths.select(&:directory?).each do |resolved_path|
|
||||||
if (ds_store = resolved_path.join(".DS_Store")).exist?
|
if (ds_store = resolved_path.join(".DS_Store")).exist?
|
||||||
@command.run!("/bin/rm", args: ["-f", "--", ds_store], sudo: true, print_stderr: false)
|
command.run!("/bin/rm", args: ["-f", "--", ds_store], sudo: true, print_stderr: false)
|
||||||
end
|
end
|
||||||
|
|
||||||
@command.run("/bin/rmdir", args: ["--", resolved_path], sudo: true, print_stderr: false)
|
command.run("/bin/rmdir", args: ["--", resolved_path], sudo: true, print_stderr: false)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -5,21 +5,32 @@ require "hbc/utils/hash_validator"
|
|||||||
module Hbc
|
module Hbc
|
||||||
module Artifact
|
module Artifact
|
||||||
class Artifact < Moved
|
class Artifact < Moved
|
||||||
def self.artifact_english_name
|
def self.english_name
|
||||||
"Generic Artifact"
|
"Generic Artifact"
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.artifact_dirmethod
|
def self.from_args(cask, *args)
|
||||||
:appdir
|
source_string, target_hash = args
|
||||||
|
|
||||||
|
if source_string.nil?
|
||||||
|
raise CaskInvalidError.new(cask.token, "no source given for #{english_name}")
|
||||||
|
end
|
||||||
|
|
||||||
|
unless target_hash.is_a?(Hash)
|
||||||
|
raise CaskInvalidError.new(cask.token, "target required for #{english_name} '#{source_string}'")
|
||||||
end
|
end
|
||||||
|
|
||||||
def load_specification(artifact_spec)
|
|
||||||
source_string, target_hash = artifact_spec
|
|
||||||
raise CaskInvalidError.new(@cask.token, "no source given for artifact") if source_string.nil?
|
|
||||||
@source = @cask.staged_path.join(source_string)
|
|
||||||
raise CaskInvalidError.new(@cask.token, "target required for generic artifact #{source_string}") unless target_hash.is_a?(Hash)
|
|
||||||
target_hash.extend(HashValidator).assert_valid_keys(:target)
|
target_hash.extend(HashValidator).assert_valid_keys(:target)
|
||||||
@target = Pathname.new(target_hash[:target])
|
|
||||||
|
new(cask, source_string, **target_hash)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.resolve_target(target)
|
||||||
|
Pathname(target)
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize(cask, source, target: nil)
|
||||||
|
super(cask, source, target: target)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -3,13 +3,13 @@ require "hbc/artifact/symlinked"
|
|||||||
module Hbc
|
module Hbc
|
||||||
module Artifact
|
module Artifact
|
||||||
class Binary < Symlinked
|
class Binary < Symlinked
|
||||||
def link
|
def link(command: nil, **options)
|
||||||
super
|
super(command: command, **options)
|
||||||
return if source.executable?
|
return if source.executable?
|
||||||
if source.writable?
|
if source.writable?
|
||||||
FileUtils.chmod "+x", source
|
FileUtils.chmod "+x", source
|
||||||
else
|
else
|
||||||
@command.run!("/bin/chmod", args: ["+x", source], sudo: true)
|
command.run!("/bin/chmod", args: ["+x", source], sudo: true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,30 +1,83 @@
|
|||||||
require "hbc/artifact/base"
|
require "hbc/artifact/abstract_artifact"
|
||||||
|
|
||||||
module Hbc
|
module Hbc
|
||||||
module Artifact
|
module Artifact
|
||||||
class Installer < Base
|
class Installer < AbstractArtifact
|
||||||
def install_phase
|
VALID_KEYS = Set.new [
|
||||||
@cask.artifacts[self.class.artifact_dsl_key].each do |artifact|
|
:manual,
|
||||||
if artifact.manual
|
:script,
|
||||||
|
]
|
||||||
|
|
||||||
|
module ManualInstaller
|
||||||
|
def install_phase(**)
|
||||||
puts <<-EOS.undent
|
puts <<-EOS.undent
|
||||||
To complete the installation of Cask #{@cask}, you must also
|
To complete the installation of Cask #{cask}, you must also
|
||||||
run the installer at
|
run the installer at
|
||||||
|
|
||||||
'#{@cask.staged_path.join(artifact.manual)}'
|
'#{path}'
|
||||||
|
|
||||||
EOS
|
EOS
|
||||||
else
|
|
||||||
executable, script_arguments = self.class.read_script_arguments(artifact.script,
|
|
||||||
self.class.artifact_dsl_key.to_s,
|
|
||||||
{ must_succeed: true, sudo: false },
|
|
||||||
print_stdout: true)
|
|
||||||
ohai "Running #{self.class.artifact_dsl_key} script #{executable}"
|
|
||||||
raise CaskInvalidError.new(@cask, "#{self.class.artifact_dsl_key} missing executable") if executable.nil?
|
|
||||||
executable_path = @cask.staged_path.join(executable)
|
|
||||||
@command.run("/bin/chmod", args: ["--", "+x", executable_path]) if File.exist?(executable_path)
|
|
||||||
@command.run(executable_path, script_arguments)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
module ScriptInstaller
|
||||||
|
def install_phase(command: nil, **_)
|
||||||
|
ohai "Running #{self.class.dsl_key} script '#{path.relative_path_from(cask.staged_path)}'"
|
||||||
|
FileUtils.chmod "+x", path unless path.executable?
|
||||||
|
command.run(path, **args)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.from_args(cask, **args)
|
||||||
|
raise CaskInvalidError.new(cask, "'installer' stanza requires an argument.") if args.empty?
|
||||||
|
|
||||||
|
if args.key?(:script) && !args[:script].respond_to?(:key?)
|
||||||
|
if args.key?(:executable)
|
||||||
|
raise CaskInvalidError.new(cask, "'installer' stanza gave arguments for both :script and :executable.")
|
||||||
|
end
|
||||||
|
|
||||||
|
args[:executable] = args[:script]
|
||||||
|
args.delete(:script)
|
||||||
|
args = { script: args }
|
||||||
|
end
|
||||||
|
|
||||||
|
unless args.keys.count == 1
|
||||||
|
raise CaskInvalidError.new(cask, "invalid 'installer' stanza: Only one of #{VALID_KEYS.inspect} is permitted.")
|
||||||
|
end
|
||||||
|
|
||||||
|
args.extend(HashValidator).assert_valid_keys(*VALID_KEYS)
|
||||||
|
new(cask, **args)
|
||||||
|
end
|
||||||
|
|
||||||
|
attr_reader :path, :args
|
||||||
|
|
||||||
|
def initialize(cask, **args)
|
||||||
|
super(cask)
|
||||||
|
|
||||||
|
if args.key?(:manual)
|
||||||
|
@path = cask.staged_path.join(args[:manual])
|
||||||
|
@args = []
|
||||||
|
extend(ManualInstaller)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
path, @args = self.class.read_script_arguments(
|
||||||
|
args[:script], self.class.dsl_key.to_s, { must_succeed: true, sudo: false }, print_stdout: true
|
||||||
|
)
|
||||||
|
raise CaskInvalidError.new(cask, "#{self.class.dsl_key} missing executable") if path.nil?
|
||||||
|
|
||||||
|
path = Pathname(path)
|
||||||
|
@path = path.absolute? ? path : cask.staged_path.join(path)
|
||||||
|
extend(ScriptInstaller)
|
||||||
|
end
|
||||||
|
|
||||||
|
def summarize
|
||||||
|
path.relative_path_from(cask.staged_path).to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_h
|
||||||
|
{ path: path.relative_path_from(cask.staged_path).to_s }.tap do |h|
|
||||||
|
h[:args] = args unless is_a?(ManualInstaller)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -4,63 +4,61 @@ module Hbc
|
|||||||
module Artifact
|
module Artifact
|
||||||
class Moved < Relocated
|
class Moved < Relocated
|
||||||
def self.english_description
|
def self.english_description
|
||||||
"#{artifact_english_name}s"
|
"#{english_name}s"
|
||||||
end
|
end
|
||||||
|
|
||||||
def install_phase
|
def install_phase(**options)
|
||||||
each_artifact(&method(:move))
|
move(**options)
|
||||||
end
|
end
|
||||||
|
|
||||||
def uninstall_phase
|
def uninstall_phase(**options)
|
||||||
each_artifact(&method(:delete))
|
delete(**options)
|
||||||
|
end
|
||||||
|
|
||||||
|
def summarize_installed
|
||||||
|
if target.exist?
|
||||||
|
"#{printable_target} (#{target.abv})"
|
||||||
|
else
|
||||||
|
Formatter.error(printable_target, label: "Missing #{self.class.english_name}")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def move
|
def move(force: false, command: nil, **options)
|
||||||
if Utils.path_occupied?(target)
|
if Utils.path_occupied?(target)
|
||||||
message = "It seems there is already #{self.class.artifact_english_article} #{self.class.artifact_english_name} at '#{target}'"
|
message = "It seems there is already #{self.class.english_article} #{self.class.english_name} at '#{target}'"
|
||||||
raise CaskError, "#{message}." unless force?
|
raise CaskError, "#{message}." unless force
|
||||||
opoo "#{message}; overwriting."
|
opoo "#{message}; overwriting."
|
||||||
delete
|
delete(force: force, command: command, **options)
|
||||||
end
|
end
|
||||||
|
|
||||||
unless source.exist?
|
unless source.exist?
|
||||||
raise CaskError, "It seems the #{self.class.artifact_english_name} source '#{source}' is not there."
|
raise CaskError, "It seems the #{self.class.english_name} source '#{source}' is not there."
|
||||||
end
|
end
|
||||||
|
|
||||||
ohai "Moving #{self.class.artifact_english_name} '#{source.basename}' to '#{target}'."
|
ohai "Moving #{self.class.english_name} '#{source.basename}' to '#{target}'."
|
||||||
target.dirname.mkpath
|
target.dirname.mkpath
|
||||||
|
|
||||||
if target.parent.writable?
|
if target.parent.writable?
|
||||||
FileUtils.move(source, target)
|
FileUtils.move(source, target)
|
||||||
else
|
else
|
||||||
SystemCommand.run("/bin/mv", args: [source, target], sudo: true)
|
command.run("/bin/mv", args: [source, target], sudo: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
add_altname_metadata target, source.basename.to_s
|
add_altname_metadata(target, source.basename, command: command)
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete
|
def delete(force: false, command: nil, **_)
|
||||||
ohai "Removing #{self.class.artifact_english_name} '#{target}'."
|
ohai "Removing #{self.class.english_name} '#{target}'."
|
||||||
raise CaskError, "Cannot remove undeletable #{self.class.artifact_english_name}." if MacOS.undeletable?(target)
|
raise CaskError, "Cannot remove undeletable #{self.class.english_name}." if MacOS.undeletable?(target)
|
||||||
|
|
||||||
return unless Utils.path_occupied?(target)
|
return unless Utils.path_occupied?(target)
|
||||||
|
|
||||||
if target.parent.writable? && !force
|
if target.parent.writable? && !force
|
||||||
target.rmtree
|
target.rmtree
|
||||||
else
|
else
|
||||||
Utils.gain_permissions_remove(target, command: @command)
|
Utils.gain_permissions_remove(target, command: command)
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def summarize_artifact(artifact_spec)
|
|
||||||
load_specification artifact_spec
|
|
||||||
|
|
||||||
if target.exist?
|
|
||||||
"#{printable_target} (#{target.abv})"
|
|
||||||
else
|
|
||||||
Formatter.error(printable_target, label: "Missing #{self.class.artifact_english_name}")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,23 +1,31 @@
|
|||||||
require "hbc/artifact/base"
|
require "hbc/artifact/abstract_artifact"
|
||||||
|
|
||||||
module Hbc
|
module Hbc
|
||||||
module Artifact
|
module Artifact
|
||||||
class NestedContainer < Base
|
class NestedContainer < AbstractArtifact
|
||||||
def install_phase
|
attr_reader :path
|
||||||
@cask.artifacts[:nested_container].each { |container| extract(container) }
|
|
||||||
|
def initialize(cask, path)
|
||||||
|
super(cask)
|
||||||
|
@path = cask.staged_path.join(path)
|
||||||
end
|
end
|
||||||
|
|
||||||
def extract(container_relative_path)
|
def install_phase(**options)
|
||||||
source = @cask.staged_path.join(container_relative_path)
|
extract(**options)
|
||||||
container = Container.for_path(source, @command)
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def extract(command: nil, verbose: nil, **_)
|
||||||
|
container = Container.for_path(path, command)
|
||||||
|
|
||||||
unless container
|
unless container
|
||||||
raise CaskError, "Aw dang, could not identify nested container at '#{source}'"
|
raise CaskError, "Aw dang, could not identify nested container at '#{source}'"
|
||||||
end
|
end
|
||||||
|
|
||||||
ohai "Extracting nested container #{source.basename}"
|
ohai "Extracting nested container #{path.relative_path_from(cask.staged_path)}"
|
||||||
container.new(@cask, source, @command, verbose: verbose?).extract
|
container.new(cask, path, command, verbose: verbose).extract
|
||||||
FileUtils.remove_entry_secure(source)
|
FileUtils.remove_entry_secure(path)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
require "hbc/artifact/base"
|
require "hbc/artifact/abstract_artifact"
|
||||||
|
|
||||||
require "hbc/utils/hash_validator"
|
require "hbc/utils/hash_validator"
|
||||||
|
|
||||||
@ -6,62 +6,57 @@ require "vendor/plist/plist"
|
|||||||
|
|
||||||
module Hbc
|
module Hbc
|
||||||
module Artifact
|
module Artifact
|
||||||
class Pkg < Base
|
class Pkg < AbstractArtifact
|
||||||
attr_reader :pkg_relative_path
|
attr_reader :pkg_relative_path
|
||||||
|
|
||||||
def self.artifact_dsl_key
|
def self.from_args(cask, path, **options)
|
||||||
:pkg
|
options.extend(HashValidator).assert_valid_keys(:allow_untrusted, :choices)
|
||||||
|
new(cask, path, **options)
|
||||||
end
|
end
|
||||||
|
|
||||||
def load_pkg_description(pkg_description)
|
attr_reader :path, :options
|
||||||
@pkg_relative_path = pkg_description.shift
|
|
||||||
@pkg_install_opts = pkg_description.shift
|
def initialize(cask, path, **options)
|
||||||
begin
|
super(cask)
|
||||||
if @pkg_install_opts.respond_to?(:keys)
|
@path = cask.staged_path.join(path)
|
||||||
@pkg_install_opts.extend(HashValidator).assert_valid_keys(:allow_untrusted, :choices)
|
@options = options
|
||||||
elsif @pkg_install_opts
|
|
||||||
raise
|
|
||||||
end
|
|
||||||
raise if pkg_description.nil?
|
|
||||||
rescue StandardError
|
|
||||||
raise CaskInvalidError.new(@cask, "Bad pkg stanza")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def pkg_install_opts(opt)
|
def summarize
|
||||||
@pkg_install_opts[opt] if @pkg_install_opts.respond_to?(:keys)
|
path.relative_path_from(cask.staged_path).to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
def install_phase
|
def install_phase(**options)
|
||||||
@cask.artifacts[:pkg].each { |pkg_description| run_installer(pkg_description) }
|
run_installer(**options)
|
||||||
end
|
end
|
||||||
|
|
||||||
def run_installer(pkg_description)
|
private
|
||||||
load_pkg_description pkg_description
|
|
||||||
ohai "Running installer for #{@cask}; your password may be necessary."
|
def run_installer(command: nil, verbose: false, **options)
|
||||||
|
ohai "Running installer for #{cask}; your password may be necessary."
|
||||||
ohai "Package installers may write to any location; options such as --appdir are ignored."
|
ohai "Package installers may write to any location; options such as --appdir are ignored."
|
||||||
source = @cask.staged_path.join(pkg_relative_path)
|
unless path.exist?
|
||||||
unless source.exist?
|
raise CaskError, "pkg source file not found: '#{path.relative_path_from(cask.staged_path)}'"
|
||||||
raise CaskError, "pkg source file not found: '#{source}'"
|
|
||||||
end
|
end
|
||||||
args = [
|
args = [
|
||||||
"-pkg", source,
|
"-pkg", path,
|
||||||
"-target", "/"
|
"-target", "/"
|
||||||
]
|
]
|
||||||
args << "-verboseR" if verbose?
|
args << "-verboseR" if verbose
|
||||||
args << "-allowUntrusted" if pkg_install_opts :allow_untrusted
|
args << "-allowUntrusted" if options.fetch(:allow_untrusted, false)
|
||||||
with_choices_file do |choices_path|
|
with_choices_file do |choices_path|
|
||||||
args << "-applyChoiceChangesXML" << choices_path if choices_path
|
args << "-applyChoiceChangesXML" << choices_path if choices_path
|
||||||
@command.run!("/usr/sbin/installer", sudo: true, args: args, print_stdout: true)
|
command.run!("/usr/sbin/installer", sudo: true, args: args, print_stdout: true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def with_choices_file
|
def with_choices_file
|
||||||
return yield nil unless pkg_install_opts(:choices)
|
choices = options.fetch(:choices, {})
|
||||||
|
return yield nil if choices.empty?
|
||||||
|
|
||||||
Tempfile.open(["choices", ".xml"]) do |file|
|
Tempfile.open(["choices", ".xml"]) do |file|
|
||||||
begin
|
begin
|
||||||
file.write Plist::Emit.dump(pkg_install_opts(:choices))
|
file.write Plist::Emit.dump(choices)
|
||||||
file.close
|
file.close
|
||||||
yield file.path
|
yield file.path
|
||||||
ensure
|
ensure
|
||||||
|
|||||||
@ -3,7 +3,7 @@ require "hbc/artifact/moved"
|
|||||||
module Hbc
|
module Hbc
|
||||||
module Artifact
|
module Artifact
|
||||||
class Prefpane < Moved
|
class Prefpane < Moved
|
||||||
def self.artifact_english_name
|
def self.english_name
|
||||||
"Preference Pane"
|
"Preference Pane"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -3,22 +3,24 @@ require "hbc/artifact/moved"
|
|||||||
module Hbc
|
module Hbc
|
||||||
module Artifact
|
module Artifact
|
||||||
class Qlplugin < Moved
|
class Qlplugin < Moved
|
||||||
def self.artifact_english_name
|
def self.english_name
|
||||||
"QuickLook Plugin"
|
"QuickLook Plugin"
|
||||||
end
|
end
|
||||||
|
|
||||||
def install_phase
|
def install_phase(**options)
|
||||||
super
|
super(**options)
|
||||||
reload_quicklook
|
reload_quicklook(**options)
|
||||||
end
|
end
|
||||||
|
|
||||||
def uninstall_phase
|
def uninstall_phase(**options)
|
||||||
super
|
super(**options)
|
||||||
reload_quicklook
|
reload_quicklook(**options)
|
||||||
end
|
end
|
||||||
|
|
||||||
def reload_quicklook
|
private
|
||||||
@command.run!("/usr/bin/qlmanage", args: ["-r"])
|
|
||||||
|
def reload_quicklook(command: nil, **_)
|
||||||
|
command.run!("/usr/bin/qlmanage", args: ["-r"])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,65 +1,79 @@
|
|||||||
require "hbc/artifact/base"
|
require "hbc/artifact/abstract_artifact"
|
||||||
|
|
||||||
require "hbc/utils/hash_validator"
|
require "hbc/utils/hash_validator"
|
||||||
|
|
||||||
module Hbc
|
module Hbc
|
||||||
module Artifact
|
module Artifact
|
||||||
class Relocated < Base
|
class Relocated < AbstractArtifact
|
||||||
def summary
|
def self.from_args(cask, *args)
|
||||||
{
|
source_string, target_hash = args
|
||||||
english_description: self.class.english_description,
|
|
||||||
contents: @cask.artifacts[self.class.artifact_dsl_key].map(&method(:summarize_artifact)).compact,
|
if target_hash
|
||||||
}
|
raise CaskInvalidError unless target_hash.respond_to?(:keys)
|
||||||
|
target_hash.extend(HashValidator).assert_valid_keys(:target)
|
||||||
|
end
|
||||||
|
|
||||||
|
target_hash ||= {}
|
||||||
|
|
||||||
|
new(cask, source_string, **target_hash)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.resolve_target(target)
|
||||||
|
Hbc.public_send(dirmethod).join(target)
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_reader :source, :target
|
attr_reader :source, :target
|
||||||
|
|
||||||
def printable_target
|
def initialize(cask, source, target: nil)
|
||||||
target.to_s.sub(/^#{ENV['HOME']}(#{File::SEPARATOR}|$)/, "~/")
|
super(cask)
|
||||||
|
|
||||||
|
@source_string = source.to_s
|
||||||
|
@target_string = target.to_s
|
||||||
|
source = cask.staged_path.join(source)
|
||||||
|
@source = source
|
||||||
|
target ||= source.basename
|
||||||
|
@target = self.class.resolve_target(target)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_a
|
||||||
|
[@source_string].tap do |ary|
|
||||||
|
ary << { target: @target_string } unless @target_string.empty?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def summarize
|
||||||
|
target_string = @target_string.empty? ? "" : " -> #{@target_string}"
|
||||||
|
"#{@source_string}#{target_string}"
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
ALT_NAME_ATTRIBUTE = "com.apple.metadata:kMDItemAlternateNames".freeze
|
ALT_NAME_ATTRIBUTE = "com.apple.metadata:kMDItemAlternateNames".freeze
|
||||||
|
|
||||||
# Try to make the asset searchable under the target name. Spotlight
|
# Try to make the asset searchable under the target name. Spotlight
|
||||||
# respects this attribute for many filetypes, but ignores it for App
|
# respects this attribute for many filetypes, but ignores it for App
|
||||||
# bundles. Alfred 2.2 respects it even for App bundles.
|
# bundles. Alfred 2.2 respects it even for App bundles.
|
||||||
def add_altname_metadata(file, altname)
|
def add_altname_metadata(file, altname, command: nil)
|
||||||
return if altname.casecmp(file.basename).zero?
|
return if altname.to_s.casecmp(file.basename.to_s).zero?
|
||||||
odebug "Adding #{ALT_NAME_ATTRIBUTE} metadata"
|
odebug "Adding #{ALT_NAME_ATTRIBUTE} metadata"
|
||||||
altnames = @command.run("/usr/bin/xattr",
|
altnames = command.run("/usr/bin/xattr",
|
||||||
args: ["-p", ALT_NAME_ATTRIBUTE, file.to_s],
|
args: ["-p", ALT_NAME_ATTRIBUTE, file],
|
||||||
print_stderr: false).stdout.sub(/\A\((.*)\)\Z/, '\1')
|
print_stderr: false).stdout.sub(/\A\((.*)\)\Z/, '\1')
|
||||||
odebug "Existing metadata is: '#{altnames}'"
|
odebug "Existing metadata is: '#{altnames}'"
|
||||||
altnames.concat(", ") unless altnames.empty?
|
altnames.concat(", ") unless altnames.empty?
|
||||||
altnames.concat(%Q("#{altname}"))
|
altnames.concat(%Q("#{altname}"))
|
||||||
altnames = "(#{altnames})"
|
altnames = "(#{altnames})"
|
||||||
|
|
||||||
# Some packges are shipped as u=rx (e.g. Bitcoin Core)
|
# Some packages are shipped as u=rx (e.g. Bitcoin Core)
|
||||||
@command.run!("/bin/chmod", args: ["--", "u+rw", file, file.realpath])
|
command.run!("/bin/chmod", args: ["--", "u+rw", file, file.realpath])
|
||||||
|
|
||||||
@command.run!("/usr/bin/xattr",
|
command.run!("/usr/bin/xattr",
|
||||||
args: ["-w", ALT_NAME_ATTRIBUTE, altnames, file],
|
args: ["-w", ALT_NAME_ATTRIBUTE, altnames, file],
|
||||||
print_stderr: false)
|
print_stderr: false)
|
||||||
end
|
end
|
||||||
|
|
||||||
def each_artifact
|
def printable_target
|
||||||
@cask.artifacts[self.class.artifact_dsl_key].each do |artifact|
|
target.to_s.sub(/^#{ENV['HOME']}(#{File::SEPARATOR}|$)/, "~/")
|
||||||
load_specification(artifact)
|
|
||||||
yield
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def load_specification(artifact_spec)
|
|
||||||
source_string, target_hash = artifact_spec
|
|
||||||
raise CaskInvalidError if source_string.nil?
|
|
||||||
@source = @cask.staged_path.join(source_string)
|
|
||||||
if target_hash
|
|
||||||
raise CaskInvalidError unless target_hash.respond_to?(:keys)
|
|
||||||
target_hash.extend(HashValidator).assert_valid_keys(:target)
|
|
||||||
@target = Hbc.send(self.class.artifact_dirmethod).join(target_hash[:target])
|
|
||||||
else
|
|
||||||
@target = Hbc.send(self.class.artifact_dirmethod).join(source.basename)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,10 +1,22 @@
|
|||||||
require "hbc/artifact/base"
|
require "hbc/artifact/abstract_artifact"
|
||||||
|
|
||||||
module Hbc
|
module Hbc
|
||||||
module Artifact
|
module Artifact
|
||||||
class StageOnly < Base
|
class StageOnly < AbstractArtifact
|
||||||
def self.artifact_dsl_key
|
def self.from_args(cask, *args)
|
||||||
:stage_only
|
if args != [true]
|
||||||
|
raise CaskInvalidError.new(cask.token, "'stage_only' takes only a single argument: true")
|
||||||
|
end
|
||||||
|
|
||||||
|
new(cask)
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize(cask)
|
||||||
|
super(cask)
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_a
|
||||||
|
[true]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -3,11 +3,11 @@ require "hbc/artifact/moved"
|
|||||||
module Hbc
|
module Hbc
|
||||||
module Artifact
|
module Artifact
|
||||||
class Suite < Moved
|
class Suite < Moved
|
||||||
def self.artifact_english_name
|
def self.english_name
|
||||||
"App Suite"
|
"App Suite"
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.artifact_dirmethod
|
def self.dirmethod
|
||||||
:appdir
|
:appdir
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -8,47 +8,18 @@ module Hbc
|
|||||||
end
|
end
|
||||||
|
|
||||||
def self.english_description
|
def self.english_description
|
||||||
"#{artifact_english_name} #{link_type_english_name}s"
|
"#{english_name} #{link_type_english_name}s"
|
||||||
end
|
end
|
||||||
|
|
||||||
def install_phase
|
def install_phase(**options)
|
||||||
each_artifact(&method(:link))
|
link(**options)
|
||||||
end
|
end
|
||||||
|
|
||||||
def uninstall_phase
|
def uninstall_phase(**options)
|
||||||
each_artifact(&method(:unlink))
|
unlink(**options)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
def summarize_installed
|
||||||
|
|
||||||
def link
|
|
||||||
unless source.exist?
|
|
||||||
raise CaskError, "It seems the #{self.class.link_type_english_name.downcase} source '#{source}' is not there."
|
|
||||||
end
|
|
||||||
|
|
||||||
if target.exist? && !target.symlink?
|
|
||||||
raise CaskError, "It seems there is already #{self.class.artifact_english_article} #{self.class.artifact_english_name} at '#{target}'; not linking."
|
|
||||||
end
|
|
||||||
|
|
||||||
ohai "Linking #{self.class.artifact_english_name} '#{source.basename}' to '#{target}'."
|
|
||||||
create_filesystem_link(source, target)
|
|
||||||
end
|
|
||||||
|
|
||||||
def unlink
|
|
||||||
return unless target.symlink?
|
|
||||||
ohai "Unlinking #{self.class.artifact_english_name} '#{target}'."
|
|
||||||
target.delete
|
|
||||||
end
|
|
||||||
|
|
||||||
def create_filesystem_link(source, target)
|
|
||||||
target.dirname.mkpath
|
|
||||||
@command.run!("/bin/ln", args: ["-h", "-f", "-s", "--", source, target])
|
|
||||||
add_altname_metadata source, target.basename.to_s
|
|
||||||
end
|
|
||||||
|
|
||||||
def summarize_artifact(artifact_spec)
|
|
||||||
load_specification artifact_spec
|
|
||||||
|
|
||||||
if target.symlink? && target.exist? && target.readlink.exist?
|
if target.symlink? && target.exist? && target.readlink.exist?
|
||||||
"#{printable_target} -> #{target.readlink} (#{target.readlink.abv})"
|
"#{printable_target} -> #{target.readlink} (#{target.readlink.abv})"
|
||||||
else
|
else
|
||||||
@ -61,6 +32,33 @@ module Hbc
|
|||||||
Formatter.error(string, label: "Broken Link")
|
Formatter.error(string, label: "Broken Link")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def link(**options)
|
||||||
|
unless source.exist?
|
||||||
|
raise CaskError, "It seems the #{self.class.link_type_english_name.downcase} source '#{source}' is not there."
|
||||||
|
end
|
||||||
|
|
||||||
|
if target.exist? && !target.symlink?
|
||||||
|
raise CaskError, "It seems there is already #{self.class.english_article} #{self.class.english_name} at '#{target}'; not linking."
|
||||||
|
end
|
||||||
|
|
||||||
|
ohai "Linking #{self.class.english_name} '#{source.basename}' to '#{target}'."
|
||||||
|
create_filesystem_link(**options)
|
||||||
|
end
|
||||||
|
|
||||||
|
def unlink(**)
|
||||||
|
return unless target.symlink?
|
||||||
|
ohai "Unlinking #{self.class.english_name} '#{target}'."
|
||||||
|
target.delete
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_filesystem_link(command: nil, **_)
|
||||||
|
target.dirname.mkpath
|
||||||
|
command.run!("/bin/ln", args: ["-h", "-f", "-s", "--", source, target])
|
||||||
|
add_altname_metadata(source, target.basename, command: command)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
require "hbc/artifact/uninstall_base"
|
require "hbc/artifact/abstract_uninstall"
|
||||||
|
|
||||||
module Hbc
|
module Hbc
|
||||||
module Artifact
|
module Artifact
|
||||||
class Uninstall < UninstallBase
|
class Uninstall < AbstractUninstall
|
||||||
def uninstall_phase
|
def uninstall_phase(**options)
|
||||||
dispatch_uninstall_directives
|
dispatch_uninstall_directives(**options)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
require "hbc/artifact/uninstall_base"
|
require "hbc/artifact/abstract_uninstall"
|
||||||
|
|
||||||
module Hbc
|
module Hbc
|
||||||
module Artifact
|
module Artifact
|
||||||
class Zap < UninstallBase
|
class Zap < AbstractUninstall
|
||||||
def zap_phase
|
def zap_phase(**options)
|
||||||
dispatch_uninstall_directives
|
dispatch_uninstall_directives(**options)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -214,12 +214,10 @@ module Hbc
|
|||||||
end
|
end
|
||||||
|
|
||||||
def check_generic_artifacts
|
def check_generic_artifacts
|
||||||
cask.artifacts[:artifact].each do |source, target_hash|
|
cask.artifacts[:artifact].each do |artifact|
|
||||||
unless target_hash.is_a?(Hash) && target_hash[:target]
|
unless artifact.target.absolute?
|
||||||
add_error "target required for generic artifact #{source}"
|
add_error "target must be absolute path for #{artifact.class.english_name} #{artifact.source}"
|
||||||
next
|
|
||||||
end
|
end
|
||||||
add_error "target must be absolute path for generic artifact #{source}" unless Pathname.new(target_hash[:target]).absolute?
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -17,7 +17,7 @@ module Hbc
|
|||||||
@token = token
|
@token = token
|
||||||
@sourcefile_path = sourcefile_path
|
@sourcefile_path = sourcefile_path
|
||||||
@tap = tap
|
@tap = tap
|
||||||
@dsl = DSL.new(@token)
|
@dsl = DSL.new(self)
|
||||||
return unless block_given?
|
return unless block_given?
|
||||||
@dsl.instance_eval(&block)
|
@dsl.instance_eval(&block)
|
||||||
@dsl.language_eval
|
@dsl.language_eval
|
||||||
@ -41,6 +41,14 @@ module Hbc
|
|||||||
.reverse
|
.reverse
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def full_name
|
||||||
|
if @tap.nil? || @tap == Hbc.default_tap
|
||||||
|
token
|
||||||
|
else
|
||||||
|
"#{@tap}/#{token}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def installed?
|
def installed?
|
||||||
!versions.empty?
|
!versions.empty?
|
||||||
end
|
end
|
||||||
|
|||||||
@ -56,7 +56,7 @@ module Hbc
|
|||||||
|
|
||||||
class FromURILoader < FromPathLoader
|
class FromURILoader < FromPathLoader
|
||||||
def self.can_load?(ref)
|
def self.can_load?(ref)
|
||||||
ref.to_s.match?(::URI.regexp)
|
ref.to_s.match?(::URI::DEFAULT_PARSER.make_regexp)
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_reader :url
|
attr_reader :url
|
||||||
@ -116,6 +116,22 @@ module Hbc
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class FromInstanceLoader
|
||||||
|
attr_reader :cask
|
||||||
|
|
||||||
|
def self.can_load?(ref)
|
||||||
|
ref.is_a?(Cask)
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize(cask)
|
||||||
|
@cask = cask
|
||||||
|
end
|
||||||
|
|
||||||
|
def load
|
||||||
|
cask
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
class NullLoader < FromPathLoader
|
class NullLoader < FromPathLoader
|
||||||
def self.can_load?(*)
|
def self.can_load?(*)
|
||||||
true
|
true
|
||||||
@ -149,6 +165,7 @@ module Hbc
|
|||||||
|
|
||||||
def self.for(ref)
|
def self.for(ref)
|
||||||
[
|
[
|
||||||
|
FromInstanceLoader,
|
||||||
FromURILoader,
|
FromURILoader,
|
||||||
FromTapLoader,
|
FromTapLoader,
|
||||||
FromTapPathLoader,
|
FromTapPathLoader,
|
||||||
|
|||||||
@ -42,41 +42,32 @@ module Hbc
|
|||||||
@args = process_arguments(*args)
|
@args = process_arguments(*args)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.warn_unavailable_with_suggestion(cask_token, e)
|
|
||||||
exact_match, partial_matches = Search.search(cask_token)
|
|
||||||
error_message = e.message
|
|
||||||
if exact_match
|
|
||||||
error_message.concat(" Did you mean:\n#{exact_match}")
|
|
||||||
elsif !partial_matches.empty?
|
|
||||||
error_message.concat(" Did you mean one of:\n")
|
|
||||||
.concat(Formatter.columns(partial_matches.take(20)))
|
|
||||||
end
|
|
||||||
onoe error_message
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def casks(alternative: -> { [] })
|
def casks(alternative: -> { [] })
|
||||||
return to_enum(:casks, alternative: alternative) unless block_given?
|
return @casks if defined?(@casks)
|
||||||
|
|
||||||
count = 0
|
|
||||||
|
|
||||||
casks = args.empty? ? alternative.call : args
|
casks = args.empty? ? alternative.call : args
|
||||||
|
@casks = casks.map { |cask| CaskLoader.load(cask) }
|
||||||
casks.each do |cask_or_token|
|
|
||||||
begin
|
|
||||||
yield cask_or_token.respond_to?(:token) ? cask_or_token : CaskLoader.load(cask_or_token)
|
|
||||||
count += 1
|
|
||||||
rescue CaskUnavailableError => e
|
rescue CaskUnavailableError => e
|
||||||
cask_token = cask_or_token
|
reason = [e.reason, suggestion_message(e.token)].join(" ")
|
||||||
self.class.warn_unavailable_with_suggestion cask_token, e
|
raise e.class.new(e.token, reason)
|
||||||
rescue CaskError => e
|
|
||||||
onoe e.message
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return :empty if casks.length.zero?
|
def suggestion_message(cask_token)
|
||||||
(count == casks.length) ? :complete : :incomplete
|
exact_match, partial_matches = Search.search(cask_token)
|
||||||
|
|
||||||
|
if exact_match.nil? && partial_matches.count == 1
|
||||||
|
exact_match = partial_matches.first
|
||||||
|
end
|
||||||
|
|
||||||
|
if exact_match
|
||||||
|
"Did you mean “#{exact_match}”?"
|
||||||
|
elsif !partial_matches.empty?
|
||||||
|
"Did you mean one of these?\n"
|
||||||
|
.concat(Formatter.columns(partial_matches.take(20)))
|
||||||
|
else
|
||||||
|
""
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -7,10 +7,6 @@ module Hbc
|
|||||||
end
|
end
|
||||||
|
|
||||||
def run
|
def run
|
||||||
raise CaskError, "Cat incomplete." if cat_casks == :incomplete
|
|
||||||
end
|
|
||||||
|
|
||||||
def cat_casks
|
|
||||||
casks.each do |cask|
|
casks.each do |cask|
|
||||||
puts File.open(cask.sourcefile_path, &:read)
|
puts File.open(cask.sourcefile_path, &:read)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -4,23 +4,20 @@ module Hbc
|
|||||||
def initialize(*)
|
def initialize(*)
|
||||||
super
|
super
|
||||||
raise CaskUnspecifiedError if args.empty?
|
raise CaskUnspecifiedError if args.empty?
|
||||||
raise ArgumentError, "Only one Cask can be created at a time." if args.count > 1
|
raise ArgumentError, "Only one Cask can be edited at a time." if args.count > 1
|
||||||
end
|
end
|
||||||
|
|
||||||
def run
|
def run
|
||||||
cask_token = args.first
|
cask = casks.first
|
||||||
cask_path = begin
|
cask_path = cask.sourcefile_path
|
||||||
CaskLoader.load(cask_token).sourcefile_path
|
odebug "Opening editor for Cask #{cask.token}"
|
||||||
|
exec_editor cask_path
|
||||||
rescue CaskUnavailableError => e
|
rescue CaskUnavailableError => e
|
||||||
reason = e.reason.empty? ? "" : "#{e.reason} "
|
reason = e.reason.empty? ? "" : "#{e.reason} "
|
||||||
reason.concat("Run #{Formatter.identifier("brew cask create #{e.token}")} to create a new Cask.")
|
reason.concat("Run #{Formatter.identifier("brew cask create #{e.token}")} to create a new Cask.")
|
||||||
raise e.class.new(e.token, reason)
|
raise e.class.new(e.token, reason)
|
||||||
end
|
end
|
||||||
|
|
||||||
odebug "Opening editor for Cask #{cask_token}"
|
|
||||||
exec_editor cask_path
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.help
|
def self.help
|
||||||
"edits the given Cask"
|
"edits the given Cask"
|
||||||
end
|
end
|
||||||
|
|||||||
@ -9,10 +9,6 @@ module Hbc
|
|||||||
end
|
end
|
||||||
|
|
||||||
def run
|
def run
|
||||||
raise CaskError, "Fetch incomplete." if fetch_casks == :incomplete
|
|
||||||
end
|
|
||||||
|
|
||||||
def fetch_casks
|
|
||||||
casks.each do |cask|
|
casks.each do |cask|
|
||||||
ohai "Downloading external files for Cask #{cask}"
|
ohai "Downloading external files for Cask #{cask}"
|
||||||
downloaded_path = Download.new(cask, force: force?).perform
|
downloaded_path = Download.new(cask, force: force?).perform
|
||||||
|
|||||||
@ -69,12 +69,10 @@ module Hbc
|
|||||||
|
|
||||||
def self.artifact_info(cask)
|
def self.artifact_info(cask)
|
||||||
ohai "Artifacts"
|
ohai "Artifacts"
|
||||||
DSL::ORDINARY_ARTIFACT_TYPES.each do |type|
|
DSL::ORDINARY_ARTIFACT_CLASSES.flat_map { |klass| klass.for_cask(cask) }
|
||||||
next if cask.artifacts[type].empty?
|
.select { |artifact| artifact.respond_to?(:install_phase) }
|
||||||
cask.artifacts[type].each do |artifact|
|
.each do |artifact|
|
||||||
activatable_item = (type == :stage_only) ? "<none>" : artifact.first
|
puts artifact.to_s
|
||||||
puts "#{activatable_item} (#{type})"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -10,10 +10,6 @@ module Hbc
|
|||||||
end
|
end
|
||||||
|
|
||||||
def run
|
def run
|
||||||
raise CaskError, "Install incomplete." if install_casks == :incomplete
|
|
||||||
end
|
|
||||||
|
|
||||||
def install_casks
|
|
||||||
casks.each do |cask|
|
casks.each do |cask|
|
||||||
begin
|
begin
|
||||||
Installer.new(cask, binaries: binaries?,
|
Installer.new(cask, binaries: binaries?,
|
||||||
|
|||||||
@ -12,7 +12,7 @@ module Hbc
|
|||||||
if args.all? { |t| t =~ %r{^https?://} && t !~ /\.rb$/ }
|
if args.all? { |t| t =~ %r{^https?://} && t !~ /\.rb$/ }
|
||||||
self.class.appcask_checkpoint_for_url(args)
|
self.class.appcask_checkpoint_for_url(args)
|
||||||
else
|
else
|
||||||
self.class.appcask_checkpoint(args, calculate?)
|
self.class.appcask_checkpoint(casks, calculate?)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -23,33 +23,27 @@ module Hbc
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.appcask_checkpoint(cask_tokens, calculate)
|
def self.appcask_checkpoint(casks, calculate)
|
||||||
count = 0
|
casks.each do |cask|
|
||||||
|
|
||||||
cask_tokens.each do |cask_token|
|
|
||||||
cask = CaskLoader.load(cask_token)
|
|
||||||
|
|
||||||
if cask.appcast.nil?
|
if cask.appcast.nil?
|
||||||
opoo "Cask '#{cask}' is missing an `appcast` stanza."
|
opoo "Cask '#{cask}' is missing an `appcast` stanza."
|
||||||
else
|
else
|
||||||
if calculate
|
checkpoint = if calculate
|
||||||
result = cask.appcast.calculate_checkpoint
|
result = cask.appcast.calculate_checkpoint
|
||||||
|
result[:checkpoint]
|
||||||
checkpoint = result[:checkpoint]
|
|
||||||
else
|
else
|
||||||
checkpoint = cask.appcast.checkpoint
|
cask.appcast.checkpoint
|
||||||
end
|
end
|
||||||
|
|
||||||
if checkpoint.nil?
|
if calculate && checkpoint.nil?
|
||||||
onoe "Could not retrieve `appcast` checkpoint for cask '#{cask}': #{result[:command_result].stderr}"
|
onoe "Could not retrieve `appcast` checkpoint for cask '#{cask}': #{result[:command_result].stderr}"
|
||||||
|
elsif casks.count > 1
|
||||||
|
puts "#{checkpoint} #{cask}"
|
||||||
else
|
else
|
||||||
puts((cask_tokens.count > 1) ? "#{checkpoint} #{cask}" : checkpoint)
|
puts checkpoint
|
||||||
count += 1
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
count == cask_tokens.count
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.help
|
def self.help
|
||||||
|
|||||||
@ -7,10 +7,6 @@ module Hbc
|
|||||||
end
|
end
|
||||||
|
|
||||||
def run
|
def run
|
||||||
raise CaskError, "Dump incomplete." if dump_casks == :incomplet
|
|
||||||
end
|
|
||||||
|
|
||||||
def dump_casks
|
|
||||||
casks.each(&:dumpcask)
|
casks.each(&:dumpcask)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@ module Hbc
|
|||||||
class InternalStanza < AbstractInternalCommand
|
class InternalStanza < AbstractInternalCommand
|
||||||
# Syntax
|
# Syntax
|
||||||
#
|
#
|
||||||
# brew cask _stanza <stanza_name> [ --table | --yaml | --inspect | --quiet ] [ <cask_token> ... ]
|
# brew cask _stanza <stanza_name> [ --quiet ] [ --table | --yaml ] [ <cask_token> ... ]
|
||||||
#
|
#
|
||||||
# If no tokens are given, then data for all Casks is returned.
|
# If no tokens are given, then data for all Casks is returned.
|
||||||
#
|
#
|
||||||
@ -14,41 +14,16 @@ module Hbc
|
|||||||
# Examples
|
# Examples
|
||||||
#
|
#
|
||||||
# brew cask _stanza appcast --table
|
# brew cask _stanza appcast --table
|
||||||
# brew cask _stanza app --table alfred google-chrome adium voicemac logisim vagrant
|
# brew cask _stanza app --table alfred google-chrome adium vagrant
|
||||||
# brew cask _stanza url --table alfred google-chrome adium voicemac logisim vagrant
|
# brew cask _stanza url --table alfred google-chrome adium vagrant
|
||||||
# brew cask _stanza version --table alfred google-chrome adium voicemac logisim vagrant
|
# brew cask _stanza version --table alfred google-chrome adium vagrant
|
||||||
# brew cask _stanza artifacts --table --inspect alfred google-chrome adium voicemac logisim vagrant
|
# brew cask _stanza artifacts --table alfred google-chrome adium vagrant
|
||||||
# brew cask _stanza artifacts --table --yaml alfred google-chrome adium voicemac logisim vagrant
|
# brew cask _stanza artifacts --table --yaml alfred google-chrome adium vagrant
|
||||||
#
|
#
|
||||||
|
|
||||||
# TODO: this should be retrievable from Hbc::DSL
|
ARTIFACTS =
|
||||||
ARTIFACTS = Set.new [
|
DSL::ORDINARY_ARTIFACT_CLASSES.map(&:dsl_key) +
|
||||||
:app,
|
DSL::ARTIFACT_BLOCK_CLASSES.map(&:dsl_key)
|
||||||
:suite,
|
|
||||||
:artifact,
|
|
||||||
:prefpane,
|
|
||||||
:qlplugin,
|
|
||||||
:dictionary,
|
|
||||||
:font,
|
|
||||||
:service,
|
|
||||||
:colorpicker,
|
|
||||||
:binary,
|
|
||||||
:input_method,
|
|
||||||
:internet_plugin,
|
|
||||||
:audio_unit_plugin,
|
|
||||||
:vst_plugin,
|
|
||||||
:vst3_plugin,
|
|
||||||
:screen_saver,
|
|
||||||
:pkg,
|
|
||||||
:installer,
|
|
||||||
:stage_only,
|
|
||||||
:nested_container,
|
|
||||||
:uninstall,
|
|
||||||
:preflight,
|
|
||||||
:postflight,
|
|
||||||
:uninstall_preflight,
|
|
||||||
:uninstall_postflight,
|
|
||||||
]
|
|
||||||
|
|
||||||
option "--table", :table, false
|
option "--table", :table, false
|
||||||
option "--quiet", :quiet, false
|
option "--quiet", :quiet, false
|
||||||
@ -68,16 +43,9 @@ module Hbc
|
|||||||
@stanza = args.shift.to_sym
|
@stanza = args.shift.to_sym
|
||||||
|
|
||||||
@format = :to_yaml if yaml?
|
@format = :to_yaml if yaml?
|
||||||
@format = :inspect if inspect?
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def run
|
def run
|
||||||
return unless print_stanzas == :incomplete
|
|
||||||
exit 1 if quiet?
|
|
||||||
raise CaskError, "Print incomplete."
|
|
||||||
end
|
|
||||||
|
|
||||||
def print_stanzas
|
|
||||||
if ARTIFACTS.include?(stanza)
|
if ARTIFACTS.include?(stanza)
|
||||||
artifact_name = stanza
|
artifact_name = stanza
|
||||||
@stanza = :artifacts
|
@stanza = :artifacts
|
||||||
@ -93,7 +61,7 @@ module Hbc
|
|||||||
end
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
value = cask.send(@stanza)
|
value = cask.send(stanza)
|
||||||
rescue StandardError
|
rescue StandardError
|
||||||
opoo "failure calling '#{stanza}' on Cask '#{cask}'" unless quiet?
|
opoo "failure calling '#{stanza}' on Cask '#{cask}'" unless quiet?
|
||||||
puts ""
|
puts ""
|
||||||
@ -106,11 +74,25 @@ module Hbc
|
|||||||
next
|
next
|
||||||
end
|
end
|
||||||
|
|
||||||
value = value.fetch(artifact_name).to_a.flatten if artifact_name
|
if stanza == :artifacts
|
||||||
|
value = Hash[
|
||||||
|
value.map do |k, v|
|
||||||
|
v = v.map do |a|
|
||||||
|
next a.to_a if a.respond_to?(:to_a)
|
||||||
|
next a.to_h if a.respond_to?(:to_h)
|
||||||
|
a
|
||||||
|
end
|
||||||
|
|
||||||
if @format
|
[k, v]
|
||||||
puts value.send(@format)
|
end
|
||||||
elsif artifact_name || value.is_a?(Symbol)
|
]
|
||||||
|
|
||||||
|
value = value.fetch(artifact_name) if artifact_name
|
||||||
|
end
|
||||||
|
|
||||||
|
if format
|
||||||
|
puts value.send(format)
|
||||||
|
elsif value.is_a?(Symbol)
|
||||||
puts value.inspect
|
puts value.inspect
|
||||||
else
|
else
|
||||||
puts value.to_s
|
puts value.to_s
|
||||||
|
|||||||
@ -3,6 +3,7 @@ module Hbc
|
|||||||
class List < AbstractCommand
|
class List < AbstractCommand
|
||||||
option "-1", :one, false
|
option "-1", :one, false
|
||||||
option "--versions", :versions, false
|
option "--versions", :versions, false
|
||||||
|
option "--full-name", :full_name, false
|
||||||
|
|
||||||
option "-l", (lambda do |*|
|
option "-l", (lambda do |*|
|
||||||
one = true # rubocop:disable Lint/UselessAssignment
|
one = true # rubocop:disable Lint/UselessAssignment
|
||||||
@ -10,8 +11,7 @@ module Hbc
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
def run
|
def run
|
||||||
retval = args.any? ? list : list_installed
|
args.any? ? list : list_installed
|
||||||
raise CaskError, "Listing incomplete." if retval == :incomplete
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def list
|
def list
|
||||||
@ -30,9 +30,9 @@ module Hbc
|
|||||||
end
|
end
|
||||||
|
|
||||||
def self.list_artifacts(cask)
|
def self.list_artifacts(cask)
|
||||||
Artifact.for_cask(cask).each do |artifact|
|
Artifact.for_cask(cask).group_by(&:class).each do |klass, artifacts|
|
||||||
summary = artifact.summary
|
next unless klass.respond_to?(:english_description)
|
||||||
ohai summary[:english_description], summary[:contents] unless summary.empty?
|
ohai klass.english_description, artifacts.map(&:summarize_installed)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -43,11 +43,11 @@ module Hbc
|
|||||||
puts installed_casks.map(&:to_s)
|
puts installed_casks.map(&:to_s)
|
||||||
elsif versions?
|
elsif versions?
|
||||||
puts installed_casks.map(&self.class.method(:format_versioned))
|
puts installed_casks.map(&self.class.method(:format_versioned))
|
||||||
|
elsif full_name?
|
||||||
|
puts installed_casks.map(&:full_name).sort &tap_and_name_comparison
|
||||||
elsif !installed_casks.empty?
|
elsif !installed_casks.empty?
|
||||||
puts Formatter.columns(installed_casks.map(&:to_s))
|
puts Formatter.columns(installed_casks.map(&:to_s))
|
||||||
end
|
end
|
||||||
|
|
||||||
installed_casks.empty? ? :empty : :complete
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.format_versioned(cask)
|
def self.format_versioned(cask)
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
module Hbc
|
module Hbc
|
||||||
class CLI
|
class CLI
|
||||||
class Reinstall < Install
|
class Reinstall < Install
|
||||||
def install_casks
|
def run
|
||||||
casks.each do |cask|
|
casks.each do |cask|
|
||||||
Installer.new(cask, binaries: binaries?,
|
Installer.new(cask, binaries: binaries?,
|
||||||
verbose: verbose?,
|
verbose: verbose?,
|
||||||
|
|||||||
@ -2,9 +2,13 @@ module Hbc
|
|||||||
class CLI
|
class CLI
|
||||||
class Search < AbstractCommand
|
class Search < AbstractCommand
|
||||||
def run
|
def run
|
||||||
|
if args.empty?
|
||||||
|
puts Formatter.columns(CLI.nice_listing(Hbc.all_tokens))
|
||||||
|
else
|
||||||
results = self.class.search(*args)
|
results = self.class.search(*args)
|
||||||
self.class.render_results(*results)
|
self.class.render_results(*results)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def self.extract_regexp(string)
|
def self.extract_regexp(string)
|
||||||
if string =~ %r{^/(.*)/$}
|
if string =~ %r{^/(.*)/$}
|
||||||
@ -15,8 +19,17 @@ module Hbc
|
|||||||
end
|
end
|
||||||
|
|
||||||
def self.search_remote(query)
|
def self.search_remote(query)
|
||||||
matches = GitHub.search_code(user: "caskroom", path: "Casks",
|
matches = begin
|
||||||
filename: query, extension: "rb")
|
GitHub.search_code(
|
||||||
|
user: "caskroom",
|
||||||
|
path: "Casks",
|
||||||
|
filename: query,
|
||||||
|
extension: "rb",
|
||||||
|
)
|
||||||
|
rescue GitHub::Error => error
|
||||||
|
opoo "Error searching on GitHub: #{error}\n"
|
||||||
|
[]
|
||||||
|
end
|
||||||
matches.map do |match|
|
matches.map do |match|
|
||||||
tap = Tap.fetch(match["repository"]["full_name"])
|
tap = Tap.fetch(match["repository"]["full_name"])
|
||||||
next if tap.installed?
|
next if tap.installed?
|
||||||
|
|||||||
@ -9,10 +9,6 @@ module Hbc
|
|||||||
end
|
end
|
||||||
|
|
||||||
def run
|
def run
|
||||||
raise CaskError, "Uninstall incomplete." if uninstall_casks == :incomplete
|
|
||||||
end
|
|
||||||
|
|
||||||
def uninstall_casks
|
|
||||||
casks.each do |cask|
|
casks.each do |cask|
|
||||||
odebug "Uninstalling Cask #{cask}"
|
odebug "Uninstalling Cask #{cask}"
|
||||||
|
|
||||||
|
|||||||
@ -9,10 +9,6 @@ module Hbc
|
|||||||
end
|
end
|
||||||
|
|
||||||
def run
|
def run
|
||||||
raise CaskError, "Zap incomplete." if zap_casks == :incomplete
|
|
||||||
end
|
|
||||||
|
|
||||||
def zap_casks
|
|
||||||
casks.each do |cask|
|
casks.each do |cask|
|
||||||
odebug "Zapping Cask #{cask}"
|
odebug "Zapping Cask #{cask}"
|
||||||
Installer.new(cask, verbose: verbose?, force: force?).zap
|
Installer.new(cask, verbose: verbose?, force: force?).zap
|
||||||
|
|||||||
@ -16,7 +16,7 @@ module Hbc
|
|||||||
|
|
||||||
def target_file
|
def target_file
|
||||||
return @path.basename if @nested
|
return @path.basename if @nested
|
||||||
URI.decode(File.basename(@cask.url.path))
|
CGI.unescape(File.basename(@cask.url.path))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
require "set"
|
require "set"
|
||||||
require "locale"
|
require "locale"
|
||||||
|
|
||||||
|
require "hbc/artifact"
|
||||||
|
|
||||||
require "hbc/dsl/appcast"
|
require "hbc/dsl/appcast"
|
||||||
require "hbc/dsl/base"
|
require "hbc/dsl/base"
|
||||||
require "hbc/dsl/caveats"
|
require "hbc/dsl/caveats"
|
||||||
@ -8,7 +10,6 @@ require "hbc/dsl/conflicts_with"
|
|||||||
require "hbc/dsl/container"
|
require "hbc/dsl/container"
|
||||||
require "hbc/dsl/depends_on"
|
require "hbc/dsl/depends_on"
|
||||||
require "hbc/dsl/gpg"
|
require "hbc/dsl/gpg"
|
||||||
require "hbc/dsl/installer"
|
|
||||||
require "hbc/dsl/postflight"
|
require "hbc/dsl/postflight"
|
||||||
require "hbc/dsl/preflight"
|
require "hbc/dsl/preflight"
|
||||||
require "hbc/dsl/stanza_proxy"
|
require "hbc/dsl/stanza_proxy"
|
||||||
@ -18,39 +19,35 @@ require "hbc/dsl/version"
|
|||||||
|
|
||||||
module Hbc
|
module Hbc
|
||||||
class DSL
|
class DSL
|
||||||
ORDINARY_ARTIFACT_TYPES = [
|
ORDINARY_ARTIFACT_CLASSES = [
|
||||||
:app,
|
Artifact::Installer,
|
||||||
:artifact,
|
Artifact::App,
|
||||||
:audio_unit_plugin,
|
Artifact::Artifact,
|
||||||
:binary,
|
Artifact::AudioUnitPlugin,
|
||||||
:colorpicker,
|
Artifact::Binary,
|
||||||
:dictionary,
|
Artifact::Colorpicker,
|
||||||
:font,
|
Artifact::Dictionary,
|
||||||
:input_method,
|
Artifact::Font,
|
||||||
:internet_plugin,
|
Artifact::InputMethod,
|
||||||
:pkg,
|
Artifact::InternetPlugin,
|
||||||
:prefpane,
|
Artifact::Pkg,
|
||||||
:qlplugin,
|
Artifact::Prefpane,
|
||||||
:screen_saver,
|
Artifact::Qlplugin,
|
||||||
:service,
|
Artifact::ScreenSaver,
|
||||||
:stage_only,
|
Artifact::Service,
|
||||||
:suite,
|
Artifact::StageOnly,
|
||||||
:vst_plugin,
|
Artifact::Suite,
|
||||||
:vst3_plugin,
|
Artifact::VstPlugin,
|
||||||
|
Artifact::Vst3Plugin,
|
||||||
|
Artifact::Uninstall,
|
||||||
|
Artifact::Zap,
|
||||||
].freeze
|
].freeze
|
||||||
|
|
||||||
ACTIVATABLE_ARTIFACT_TYPES = ([:installer, *ORDINARY_ARTIFACT_TYPES] - [:stage_only]).freeze
|
ACTIVATABLE_ARTIFACT_TYPES = (ORDINARY_ARTIFACT_CLASSES.map(&:dsl_key) - [:stage_only]).freeze
|
||||||
|
|
||||||
SPECIAL_ARTIFACT_TYPES = [
|
ARTIFACT_BLOCK_CLASSES = [
|
||||||
:uninstall,
|
Artifact::PreflightBlock,
|
||||||
:zap,
|
Artifact::PostflightBlock,
|
||||||
].freeze
|
|
||||||
|
|
||||||
ARTIFACT_BLOCK_TYPES = [
|
|
||||||
:preflight,
|
|
||||||
:postflight,
|
|
||||||
:uninstall_preflight,
|
|
||||||
:uninstall_postflight,
|
|
||||||
].freeze
|
].freeze
|
||||||
|
|
||||||
DSL_METHODS = Set.new [
|
DSL_METHODS = Set.new [
|
||||||
@ -72,15 +69,15 @@ module Hbc
|
|||||||
:url,
|
:url,
|
||||||
:version,
|
:version,
|
||||||
:appdir,
|
:appdir,
|
||||||
*ORDINARY_ARTIFACT_TYPES,
|
*ORDINARY_ARTIFACT_CLASSES.map(&:dsl_key),
|
||||||
*ACTIVATABLE_ARTIFACT_TYPES,
|
*ACTIVATABLE_ARTIFACT_TYPES,
|
||||||
*SPECIAL_ARTIFACT_TYPES,
|
*ARTIFACT_BLOCK_CLASSES.flat_map { |klass| [klass.dsl_key, klass.uninstall_dsl_key] },
|
||||||
*ARTIFACT_BLOCK_TYPES,
|
|
||||||
].freeze
|
].freeze
|
||||||
|
|
||||||
attr_reader :token
|
attr_reader :token, :cask
|
||||||
def initialize(token)
|
def initialize(cask)
|
||||||
@token = token
|
@cask = cask
|
||||||
|
@token = cask.token
|
||||||
end
|
end
|
||||||
|
|
||||||
def name(*args)
|
def name(*args)
|
||||||
@ -93,12 +90,14 @@ module Hbc
|
|||||||
return instance_variable_get("@#{stanza}") if should_return
|
return instance_variable_get("@#{stanza}") if should_return
|
||||||
|
|
||||||
if instance_variable_defined?("@#{stanza}")
|
if instance_variable_defined?("@#{stanza}")
|
||||||
raise CaskInvalidError.new(token, "'#{stanza}' stanza may only appear once")
|
raise CaskInvalidError.new(cask, "'#{stanza}' stanza may only appear once.")
|
||||||
end
|
end
|
||||||
|
|
||||||
instance_variable_set("@#{stanza}", yield)
|
instance_variable_set("@#{stanza}", yield)
|
||||||
|
rescue CaskInvalidError
|
||||||
|
raise
|
||||||
rescue StandardError => e
|
rescue StandardError => e
|
||||||
raise CaskInvalidError.new(token, "'#{stanza}' stanza failed with: #{e}")
|
raise CaskInvalidError.new(cask, "'#{stanza}' stanza failed with: #{e}")
|
||||||
end
|
end
|
||||||
|
|
||||||
def homepage(homepage = nil)
|
def homepage(homepage = nil)
|
||||||
@ -113,7 +112,7 @@ module Hbc
|
|||||||
return unless default
|
return unless default
|
||||||
|
|
||||||
unless @language_blocks.default.nil?
|
unless @language_blocks.default.nil?
|
||||||
raise CaskInvalidError.new(token, "Only one default language may be defined")
|
raise CaskInvalidError.new(cask, "Only one default language may be defined.")
|
||||||
end
|
end
|
||||||
|
|
||||||
@language_blocks.default = block
|
@language_blocks.default = block
|
||||||
@ -162,8 +161,8 @@ module Hbc
|
|||||||
begin
|
begin
|
||||||
DSL::Container.new(*args).tap do |container|
|
DSL::Container.new(*args).tap do |container|
|
||||||
# TODO: remove this backward-compatibility section after removing nested_container
|
# TODO: remove this backward-compatibility section after removing nested_container
|
||||||
if container && container.nested
|
if container&.nested
|
||||||
artifacts[:nested_container] << container.nested
|
artifacts[:nested_container] << Artifact::NestedContainer.new(cask, container.nested)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -173,7 +172,7 @@ module Hbc
|
|||||||
def version(arg = nil)
|
def version(arg = nil)
|
||||||
set_unique_stanza(:version, arg.nil?) do
|
set_unique_stanza(:version, arg.nil?) do
|
||||||
if !arg.is_a?(String) && arg != :latest
|
if !arg.is_a?(String) && arg != :latest
|
||||||
raise CaskInvalidError.new(token, "invalid 'version' value: '#{arg.inspect}'")
|
raise CaskInvalidError.new(cask, "invalid 'version' value: '#{arg.inspect}'")
|
||||||
end
|
end
|
||||||
DSL::Version.new(arg)
|
DSL::Version.new(arg)
|
||||||
end
|
end
|
||||||
@ -182,7 +181,7 @@ module Hbc
|
|||||||
def sha256(arg = nil)
|
def sha256(arg = nil)
|
||||||
set_unique_stanza(:sha256, arg.nil?) do
|
set_unique_stanza(:sha256, arg.nil?) do
|
||||||
if !arg.is_a?(String) && arg != :no_check
|
if !arg.is_a?(String) && arg != :no_check
|
||||||
raise CaskInvalidError.new(token, "invalid 'sha256' value: '#{arg.inspect}'")
|
raise CaskInvalidError.new(cask, "invalid 'sha256' value: '#{arg.inspect}'")
|
||||||
end
|
end
|
||||||
arg
|
arg
|
||||||
end
|
end
|
||||||
@ -195,7 +194,7 @@ module Hbc
|
|||||||
begin
|
begin
|
||||||
@depends_on.load(*args)
|
@depends_on.load(*args)
|
||||||
rescue RuntimeError => e
|
rescue RuntimeError => e
|
||||||
raise CaskInvalidError.new(token, e)
|
raise CaskInvalidError.new(cask, e)
|
||||||
end
|
end
|
||||||
@depends_on
|
@depends_on
|
||||||
end
|
end
|
||||||
@ -237,39 +236,29 @@ module Hbc
|
|||||||
set_unique_stanza(:auto_updates, auto_updates.nil?) { auto_updates }
|
set_unique_stanza(:auto_updates, auto_updates.nil?) { auto_updates }
|
||||||
end
|
end
|
||||||
|
|
||||||
ORDINARY_ARTIFACT_TYPES.each do |type|
|
ORDINARY_ARTIFACT_CLASSES.each do |klass|
|
||||||
|
type = klass.dsl_key
|
||||||
|
|
||||||
define_method(type) do |*args|
|
define_method(type) do |*args|
|
||||||
if type == :stage_only
|
begin
|
||||||
if args != [true]
|
if [*artifacts.keys, type].include?(:stage_only) && (artifacts.keys & ACTIVATABLE_ARTIFACT_TYPES).any?
|
||||||
raise CaskInvalidError.new(token, "'stage_only' takes a single argument: true")
|
raise CaskInvalidError.new(cask, "'stage_only' must be the only activatable artifact.")
|
||||||
end
|
end
|
||||||
|
|
||||||
unless (artifacts.keys & ACTIVATABLE_ARTIFACT_TYPES).empty?
|
artifacts[type].add(klass.from_args(cask, *args))
|
||||||
raise CaskInvalidError.new(token, "'stage_only' must be the only activatable artifact")
|
rescue CaskInvalidError
|
||||||
end
|
raise
|
||||||
end
|
|
||||||
|
|
||||||
artifacts[type].add(args)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def installer(*args)
|
|
||||||
return artifacts[:installer] if args.empty?
|
|
||||||
artifacts[:installer] << DSL::Installer.new(*args)
|
|
||||||
raise "'stage_only' must be the only activatable artifact" if artifacts.key?(:stage_only)
|
|
||||||
rescue StandardError => e
|
rescue StandardError => e
|
||||||
raise CaskInvalidError.new(token, e)
|
raise CaskInvalidError.new(cask, "invalid '#{klass.dsl_key}' stanza: #{e}")
|
||||||
end
|
end
|
||||||
|
|
||||||
SPECIAL_ARTIFACT_TYPES.each do |type|
|
|
||||||
define_method(type) do |*args|
|
|
||||||
artifacts[type].merge(args)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
ARTIFACT_BLOCK_TYPES.each do |type|
|
ARTIFACT_BLOCK_CLASSES.each do |klass|
|
||||||
define_method(type) do |&block|
|
[klass.dsl_key, klass.uninstall_dsl_key].each do |dsl_key|
|
||||||
artifacts[type] << block
|
define_method(dsl_key) do |&block|
|
||||||
|
artifacts[dsl_key] << block
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -1,32 +0,0 @@
|
|||||||
module Hbc
|
|
||||||
class DSL
|
|
||||||
class Installer
|
|
||||||
VALID_KEYS = Set.new [
|
|
||||||
:manual,
|
|
||||||
:script,
|
|
||||||
]
|
|
||||||
|
|
||||||
attr_accessor(*VALID_KEYS)
|
|
||||||
|
|
||||||
def initialize(*parameters)
|
|
||||||
raise CaskInvalidError.new(token, "'installer' stanza requires an argument") if parameters.empty?
|
|
||||||
parameters = {}.merge(*parameters)
|
|
||||||
if parameters.key?(:script) && !parameters[:script].respond_to?(:key?)
|
|
||||||
if parameters.key?(:executable)
|
|
||||||
raise CaskInvalidError.new(token, "'installer' stanza gave arguments for both :script and :executable")
|
|
||||||
end
|
|
||||||
parameters[:executable] = parameters[:script]
|
|
||||||
parameters.delete(:script)
|
|
||||||
parameters = { script: parameters }
|
|
||||||
end
|
|
||||||
unless parameters.keys.length == 1
|
|
||||||
raise "invalid 'installer' stanza: only one of #{VALID_KEYS.inspect} is permitted"
|
|
||||||
end
|
|
||||||
key = parameters.keys.first
|
|
||||||
raise "invalid 'installer' stanza key: '#{key.inspect}'" unless VALID_KEYS.include?(key)
|
|
||||||
writer_method = "#{key}=".to_sym
|
|
||||||
send(writer_method, parameters[key])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@ -49,7 +49,7 @@ module Hbc
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
DIVIDERS.keys.each do |divider|
|
DIVIDERS.each_key do |divider|
|
||||||
define_divider_methods(divider)
|
define_divider_methods(divider)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -159,7 +159,7 @@ module Hbc
|
|||||||
odebug "Extracting primary container"
|
odebug "Extracting primary container"
|
||||||
|
|
||||||
FileUtils.mkdir_p @cask.staged_path
|
FileUtils.mkdir_p @cask.staged_path
|
||||||
container = if @cask.container && @cask.container.type
|
container = if @cask.container&.type
|
||||||
Container.from_type(@cask.container.type)
|
Container.from_type(@cask.container.type)
|
||||||
else
|
else
|
||||||
Container.for_path(@downloaded_path, @command)
|
Container.for_path(@downloaded_path, @command)
|
||||||
@ -177,7 +177,7 @@ module Hbc
|
|||||||
already_installed_artifacts = []
|
already_installed_artifacts = []
|
||||||
|
|
||||||
odebug "Installing artifacts"
|
odebug "Installing artifacts"
|
||||||
artifacts = Artifact.for_cask(@cask, command: @command, verbose: verbose?, force: force?)
|
artifacts = Artifact.for_cask(@cask)
|
||||||
odebug "#{artifacts.length} artifact/s defined", artifacts
|
odebug "#{artifacts.length} artifact/s defined", artifacts
|
||||||
|
|
||||||
artifacts.each do |artifact|
|
artifacts.each do |artifact|
|
||||||
@ -188,7 +188,7 @@ module Hbc
|
|||||||
next unless binaries?
|
next unless binaries?
|
||||||
end
|
end
|
||||||
|
|
||||||
artifact.install_phase
|
artifact.install_phase(command: @command, verbose: verbose?, force: force?)
|
||||||
already_installed_artifacts.unshift(artifact)
|
already_installed_artifacts.unshift(artifact)
|
||||||
end
|
end
|
||||||
rescue StandardError => e
|
rescue StandardError => e
|
||||||
@ -196,7 +196,7 @@ module Hbc
|
|||||||
already_installed_artifacts.each do |artifact|
|
already_installed_artifacts.each do |artifact|
|
||||||
next unless artifact.respond_to?(:uninstall_phase)
|
next unless artifact.respond_to?(:uninstall_phase)
|
||||||
odebug "Reverting installation of artifact of class #{artifact.class}"
|
odebug "Reverting installation of artifact of class #{artifact.class}"
|
||||||
artifact.uninstall_phase
|
artifact.uninstall_phase(command: @command, verbose: verbose?, force: force?)
|
||||||
end
|
end
|
||||||
ensure
|
ensure
|
||||||
purge_versioned_files
|
purge_versioned_files
|
||||||
@ -361,7 +361,7 @@ module Hbc
|
|||||||
|
|
||||||
savedir = @cask.metadata_subdir("Casks", timestamp: :now, create: true)
|
savedir = @cask.metadata_subdir("Casks", timestamp: :now, create: true)
|
||||||
FileUtils.copy @cask.sourcefile_path, savedir
|
FileUtils.copy @cask.sourcefile_path, savedir
|
||||||
old_savedir.rmtree unless old_savedir.nil?
|
old_savedir&.rmtree
|
||||||
end
|
end
|
||||||
|
|
||||||
def uninstall
|
def uninstall
|
||||||
@ -374,25 +374,27 @@ module Hbc
|
|||||||
|
|
||||||
def uninstall_artifacts
|
def uninstall_artifacts
|
||||||
odebug "Un-installing artifacts"
|
odebug "Un-installing artifacts"
|
||||||
artifacts = Artifact.for_cask(@cask, command: @command, verbose: verbose?, force: force?)
|
artifacts = Artifact.for_cask(@cask)
|
||||||
|
|
||||||
odebug "#{artifacts.length} artifact/s defined", artifacts
|
odebug "#{artifacts.length} artifact/s defined", artifacts
|
||||||
|
|
||||||
artifacts.each do |artifact|
|
artifacts.each do |artifact|
|
||||||
next unless artifact.respond_to?(:uninstall_phase)
|
next unless artifact.respond_to?(:uninstall_phase)
|
||||||
odebug "Un-installing artifact of class #{artifact.class}"
|
odebug "Un-installing artifact of class #{artifact.class}"
|
||||||
artifact.uninstall_phase
|
artifact.uninstall_phase(command: @command, verbose: verbose?, force: force?)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def zap
|
def zap
|
||||||
ohai %Q(Implied "brew cask uninstall #{@cask}")
|
ohai %Q(Implied "brew cask uninstall #{@cask}")
|
||||||
uninstall_artifacts
|
uninstall_artifacts
|
||||||
if Artifact::Zap.me?(@cask)
|
if (zap_stanzas = Artifact::Zap.for_cask(@cask)).empty?
|
||||||
ohai "Dispatching zap stanza"
|
|
||||||
Artifact::Zap.new(@cask, command: @command).zap_phase
|
|
||||||
else
|
|
||||||
opoo "No zap stanza present for Cask '#{@cask}'"
|
opoo "No zap stanza present for Cask '#{@cask}'"
|
||||||
|
else
|
||||||
|
ohai "Dispatching zap stanza"
|
||||||
|
zap_stanzas.each do |stanza|
|
||||||
|
stanza.zap_phase(command: @command, verbose: verbose?, force: force?)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
ohai "Removing all staged versions of Cask '#{@cask}'"
|
ohai "Removing all staged versions of Cask '#{@cask}'"
|
||||||
purge_caskroom_path
|
purge_caskroom_path
|
||||||
|
|||||||
@ -4,7 +4,7 @@ module Hbc
|
|||||||
index = 0 if index == :first
|
index = 0 if index == :first
|
||||||
index = 1 if index == :second
|
index = 1 if index == :second
|
||||||
index = -1 if index == :last
|
index = -1 if index == :last
|
||||||
Hbc.appdir.join(@cask.artifacts[:app].to_a.at(index).first, "Contents", "Info.plist")
|
@cask.artifacts[:app].to_a.at(index).target.join("Contents", "Info.plist")
|
||||||
end
|
end
|
||||||
|
|
||||||
def plist_exec(cmd)
|
def plist_exec(cmd)
|
||||||
|
|||||||
@ -61,7 +61,7 @@ module Hbc
|
|||||||
end
|
end
|
||||||
|
|
||||||
def assert_success
|
def assert_success
|
||||||
return if processed_status && processed_status.success?
|
return if processed_status&.success?
|
||||||
raise CaskCommandFailedError.new(command, processed_output[:stdout], processed_output[:stderr], processed_status)
|
raise CaskCommandFailedError.new(command, processed_output[:stdout], processed_output[:stderr], processed_status)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -163,7 +163,7 @@ class Caveats
|
|||||||
|
|
||||||
def plist_caveats
|
def plist_caveats
|
||||||
s = []
|
s = []
|
||||||
if f.plist || (keg && keg.plist_installed?)
|
if f.plist || (keg&.plist_installed?)
|
||||||
plist_domain = f.plist_path.basename(".plist")
|
plist_domain = f.plist_path.basename(".plist")
|
||||||
|
|
||||||
# we readlink because this path probably doesn't exist since caveats
|
# we readlink because this path probably doesn't exist since caveats
|
||||||
|
|||||||
@ -6,6 +6,10 @@ module Homebrew
|
|||||||
module Cleanup
|
module Cleanup
|
||||||
@disk_cleanup_size = 0
|
@disk_cleanup_size = 0
|
||||||
|
|
||||||
|
class << self
|
||||||
|
attr_reader :disk_cleanup_size
|
||||||
|
end
|
||||||
|
|
||||||
module_function
|
module_function
|
||||||
|
|
||||||
def cleanup
|
def cleanup
|
||||||
@ -21,10 +25,6 @@ module Homebrew
|
|||||||
@disk_cleanup_size += path_size
|
@disk_cleanup_size += path_size
|
||||||
end
|
end
|
||||||
|
|
||||||
def disk_cleanup_size
|
|
||||||
@disk_cleanup_size
|
|
||||||
end
|
|
||||||
|
|
||||||
def unremovable_kegs
|
def unremovable_kegs
|
||||||
@unremovable_kegs ||= []
|
@unremovable_kegs ||= []
|
||||||
end
|
end
|
||||||
|
|||||||
@ -19,15 +19,13 @@ class String
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def cask
|
|
||||||
$LOAD_PATH.unshift("#{HOMEBREW_LIBRARY_PATH}/cask/lib")
|
|
||||||
require "hbc"
|
|
||||||
end
|
|
||||||
|
|
||||||
module Homebrew
|
module Homebrew
|
||||||
module_function
|
module_function
|
||||||
|
|
||||||
def irb
|
def irb
|
||||||
|
$LOAD_PATH.unshift("#{HOMEBREW_LIBRARY_PATH}/cask/lib")
|
||||||
|
require "hbc"
|
||||||
|
|
||||||
if ARGV.include? "--examples"
|
if ARGV.include? "--examples"
|
||||||
puts "'v8'.f # => instance of the v8 formula"
|
puts "'v8'.f # => instance of the v8 formula"
|
||||||
puts ":hub.f.installed?"
|
puts ":hub.f.installed?"
|
||||||
|
|||||||
@ -39,15 +39,7 @@ module Homebrew
|
|||||||
filtered_list
|
filtered_list
|
||||||
elsif ARGV.named.empty?
|
elsif ARGV.named.empty?
|
||||||
if ARGV.include? "--full-name"
|
if ARGV.include? "--full-name"
|
||||||
full_names = Formula.installed.map(&:full_name).sort do |a, b|
|
full_names = Formula.installed.map(&:full_name).sort &tap_and_name_comparison
|
||||||
if a.include?("/") && !b.include?("/")
|
|
||||||
1
|
|
||||||
elsif !a.include?("/") && b.include?("/")
|
|
||||||
-1
|
|
||||||
else
|
|
||||||
a <=> b
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return if full_names.empty?
|
return if full_names.empty?
|
||||||
puts Formatter.columns(full_names)
|
puts Formatter.columns(full_names)
|
||||||
else
|
else
|
||||||
|
|||||||
@ -55,7 +55,7 @@ module Homebrew
|
|||||||
else
|
else
|
||||||
n, d = ObserverPathnameExtension.counts
|
n, d = ObserverPathnameExtension.counts
|
||||||
print "Pruned #{n} symbolic links "
|
print "Pruned #{n} symbolic links "
|
||||||
print "and #{d} directories " if d > 0
|
print "and #{d} directories " if d.positive?
|
||||||
puts "from #{HOMEBREW_PREFIX}"
|
puts "from #{HOMEBREW_PREFIX}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -67,7 +67,7 @@ module Homebrew
|
|||||||
|
|
||||||
ohai "Searching blacklisted, migrated and deleted formulae..."
|
ohai "Searching blacklisted, migrated and deleted formulae..."
|
||||||
if reason = Homebrew::MissingFormula.reason(query, silent: true)
|
if reason = Homebrew::MissingFormula.reason(query, silent: true)
|
||||||
if count > 0
|
if count.positive?
|
||||||
puts
|
puts
|
||||||
puts "If you meant #{query.inspect} specifically:"
|
puts "If you meant #{query.inspect} specifically:"
|
||||||
end
|
end
|
||||||
|
|||||||
@ -119,10 +119,10 @@ module Homebrew
|
|||||||
when :print
|
when :print
|
||||||
args << "--display-cop-names" if ARGV.include? "--display-cop-names"
|
args << "--display-cop-names" if ARGV.include? "--display-cop-names"
|
||||||
args << "--format" << "simple" if files
|
args << "--format" << "simple" if files
|
||||||
system(cache_env, "rubocop", *args)
|
system(cache_env, "rubocop", "_#{HOMEBREW_RUBOCOP_VERSION}_", *args)
|
||||||
!$CHILD_STATUS.success?
|
!$CHILD_STATUS.success?
|
||||||
when :json
|
when :json
|
||||||
json, _, status = Open3.capture3(cache_env, "rubocop", "--format", "json", *args)
|
json, _, status = Open3.capture3(cache_env, "rubocop", "_#{HOMEBREW_RUBOCOP_VERSION}_", "--format", "json", *args)
|
||||||
# exit status of 1 just means violations were found; other numbers mean
|
# exit status of 1 just means violations were found; other numbers mean
|
||||||
# execution errors.
|
# execution errors.
|
||||||
# exitstatus can also be nil if RuboCop process crashes, e.g. due to
|
# exitstatus can also be nil if RuboCop process crashes, e.g. due to
|
||||||
|
|||||||
@ -64,10 +64,10 @@ module Homebrew
|
|||||||
if tap.installed?
|
if tap.installed?
|
||||||
info += tap.pinned? ? "pinned" : "unpinned"
|
info += tap.pinned? ? "pinned" : "unpinned"
|
||||||
info += ", private" if tap.private?
|
info += ", private" if tap.private?
|
||||||
if (formula_count = tap.formula_files.size) > 0
|
if (formula_count = tap.formula_files.size).positive?
|
||||||
info += ", #{Formatter.pluralize(formula_count, "formula")}"
|
info += ", #{Formatter.pluralize(formula_count, "formula")}"
|
||||||
end
|
end
|
||||||
if (command_count = tap.command_files.size) > 0
|
if (command_count = tap.command_files.size).positive?
|
||||||
info += ", #{Formatter.pluralize(command_count, "command")}"
|
info += ", #{Formatter.pluralize(command_count, "command")}"
|
||||||
end
|
end
|
||||||
info += ", no formulae/commands" if (formula_count + command_count).zero?
|
info += ", no formulae/commands" if (formula_count + command_count).zero?
|
||||||
|
|||||||
@ -77,7 +77,7 @@ module Homebrew
|
|||||||
def unlinkapps_unlink?(target_app, opts = {})
|
def unlinkapps_unlink?(target_app, opts = {})
|
||||||
# Skip non-symlinks and symlinks that don't point into the Homebrew prefix.
|
# Skip non-symlinks and symlinks that don't point into the Homebrew prefix.
|
||||||
app = target_app.readlink.to_s if target_app.symlink?
|
app = target_app.readlink.to_s if target_app.symlink?
|
||||||
return false unless app && app.start_with?(*UNLINKAPPS_PREFIXES)
|
return false unless app&.start_with?(*UNLINKAPPS_PREFIXES)
|
||||||
|
|
||||||
if opts.fetch(:prune, false)
|
if opts.fetch(:prune, false)
|
||||||
!File.exist?(app) # Remove only broken symlinks in prune mode.
|
!File.exist?(app) # Remove only broken symlinks in prune mode.
|
||||||
|
|||||||
@ -124,7 +124,7 @@ module Homebrew
|
|||||||
return if ENV["HOMEBREW_UPDATE_TEST"]
|
return if ENV["HOMEBREW_UPDATE_TEST"]
|
||||||
core_tap = CoreTap.instance
|
core_tap = CoreTap.instance
|
||||||
return if core_tap.installed?
|
return if core_tap.installed?
|
||||||
CoreTap.ensure_installed! quiet: false
|
CoreTap.ensure_installed!
|
||||||
revision = core_tap.git_head
|
revision = core_tap.git_head
|
||||||
ENV["HOMEBREW_UPDATE_BEFORE_HOMEBREW_HOMEBREW_CORE"] = revision
|
ENV["HOMEBREW_UPDATE_BEFORE_HOMEBREW_HOMEBREW_CORE"] = revision
|
||||||
ENV["HOMEBREW_UPDATE_AFTER_HOMEBREW_HOMEBREW_CORE"] = revision
|
ENV["HOMEBREW_UPDATE_AFTER_HOMEBREW_HOMEBREW_CORE"] = revision
|
||||||
@ -203,6 +203,7 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
|
|
||||||
new_homebrew_repository = Pathname.new "/usr/local/Homebrew"
|
new_homebrew_repository = Pathname.new "/usr/local/Homebrew"
|
||||||
|
new_homebrew_repository.rmdir_if_possible
|
||||||
if new_homebrew_repository.exist?
|
if new_homebrew_repository.exist?
|
||||||
ofail <<-EOS.undent
|
ofail <<-EOS.undent
|
||||||
#{new_homebrew_repository} already exists.
|
#{new_homebrew_repository} already exists.
|
||||||
|
|||||||
@ -385,6 +385,12 @@ EOS
|
|||||||
|
|
||||||
if ! git --version >/dev/null 2>&1
|
if ! git --version >/dev/null 2>&1
|
||||||
then
|
then
|
||||||
|
# we need a new enough curl to install git
|
||||||
|
if [[ -n "$HOMEBREW_SYSTEM_CURL_TOO_OLD" &&
|
||||||
|
! -x "$HOMEBREW_PREFIX/opt/curl/bin/curl" ]]
|
||||||
|
then
|
||||||
|
brew install curl
|
||||||
|
fi
|
||||||
# we cannot install brewed git if homebrew/core is unavailable.
|
# we cannot install brewed git if homebrew/core is unavailable.
|
||||||
[[ -d "$HOMEBREW_LIBRARY/Taps/homebrew/homebrew-core" ]] && brew install git
|
[[ -d "$HOMEBREW_LIBRARY/Taps/homebrew/homebrew-core" ]] && brew install git
|
||||||
unset GIT_EXECUTABLE
|
unset GIT_EXECUTABLE
|
||||||
|
|||||||
@ -13,16 +13,16 @@ if [[ -n "$HOMEBREW_MACOS" ]]
|
|||||||
then
|
then
|
||||||
if [[ "$HOMEBREW_PROCESSOR" = "Intel" ]]
|
if [[ "$HOMEBREW_PROCESSOR" = "Intel" ]]
|
||||||
then
|
then
|
||||||
ruby_URL="https://homebrew.bintray.com/bottles-portable/portable-ruby-2.0.0-p648.leopard_64.bottle.tar.gz"
|
ruby_URL="https://homebrew.bintray.com/bottles-portable/portable-ruby-2.3.3.leopard_64.bottle.1.tar.gz"
|
||||||
ruby_SHA="5c1240abe4be91c9774a0089c2a38a8ccfff87c009e8e5786730c659d5e633f7"
|
ruby_SHA="34ce9e4c9c1be28db564d744165aa29291426f8a3d2ef806ba4f0b9175aedb2b"
|
||||||
else
|
else
|
||||||
ruby_URL=""
|
ruby_URL=""
|
||||||
ruby_SHA=""
|
ruby_SHA=""
|
||||||
fi
|
fi
|
||||||
elif [[ -n "$HOMEBREW_LINUX" ]]
|
elif [[ -n "$HOMEBREW_LINUX" ]]
|
||||||
then
|
then
|
||||||
ruby_URL="https://homebrew.bintray.com/bottles-portable/portable-ruby-2.0.0-p648.x86_64_linux.bottle.tar.gz"
|
ruby_URL="https://homebrew.bintray.com/bottles-portable/portable-ruby-2.3.3.x86_64_linux.bottle.tar.gz"
|
||||||
ruby_SHA="dbb5118a22a6a75cc77e62544a3d8786d383fab1bdaf8c154951268807357bf0"
|
ruby_SHA="543c18bd33a300e6c16671437b1e0f17b03bb64e6a485fc15ff7de1eb1a0bc2a"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
fetch() {
|
fetch() {
|
||||||
@ -45,20 +45,25 @@ fetch() {
|
|||||||
curl_args[${#curl_args[*]}]="--progress-bar"
|
curl_args[${#curl_args[*]}]="--progress-bar"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ "$HOMEBREW_MACOS_VERSION_NUMERIC" -lt "100600" ]]
|
||||||
|
then
|
||||||
|
curl_args[${#curl_args[*]}]="--insecure"
|
||||||
|
fi
|
||||||
|
|
||||||
temporary_path="$CACHED_LOCATION.incomplete"
|
temporary_path="$CACHED_LOCATION.incomplete"
|
||||||
|
|
||||||
mkdir -p "$HOMEBREW_CACHE"
|
mkdir -p "$HOMEBREW_CACHE"
|
||||||
[[ -n "$HOMEBREW_QUIET" ]] || echo "==> Downloading $VENDOR_URL"
|
[[ -n "$HOMEBREW_QUIET" ]] || echo "==> Downloading $VENDOR_URL" >&2
|
||||||
if [[ -f "$CACHED_LOCATION" ]]
|
if [[ -f "$CACHED_LOCATION" ]]
|
||||||
then
|
then
|
||||||
[[ -n "$HOMEBREW_QUIET" ]] || echo "Already downloaded: $CACHED_LOCATION"
|
[[ -n "$HOMEBREW_QUIET" ]] || echo "Already downloaded: $CACHED_LOCATION" >&2
|
||||||
else
|
else
|
||||||
if [[ -f "$temporary_path" ]]
|
if [[ -f "$temporary_path" ]]
|
||||||
then
|
then
|
||||||
"$HOMEBREW_CURL" "${curl_args[@]}" -C - "$VENDOR_URL" -o "$temporary_path"
|
"$HOMEBREW_CURL" "${curl_args[@]}" -C - "$VENDOR_URL" -o "$temporary_path"
|
||||||
if [[ $? -eq 33 ]]
|
if [[ $? -eq 33 ]]
|
||||||
then
|
then
|
||||||
[[ -n "$HOMEBREW_QUIET" ]] || echo "Trying a full download"
|
[[ -n "$HOMEBREW_QUIET" ]] || echo "Trying a full download" >&2
|
||||||
rm -f "$temporary_path"
|
rm -f "$temporary_path"
|
||||||
"$HOMEBREW_CURL" "${curl_args[@]}" "$VENDOR_URL" -o "$temporary_path"
|
"$HOMEBREW_CURL" "${curl_args[@]}" "$VENDOR_URL" -o "$temporary_path"
|
||||||
fi
|
fi
|
||||||
@ -135,7 +140,7 @@ install() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
safe_cd "$VENDOR_DIR"
|
safe_cd "$VENDOR_DIR"
|
||||||
[[ -n "$HOMEBREW_QUIET" ]] || echo "==> Unpacking $(basename "$VENDOR_URL")"
|
[[ -n "$HOMEBREW_QUIET" ]] || echo "==> Pouring $(basename "$VENDOR_URL")" >&2
|
||||||
tar "$tar_args" "$CACHED_LOCATION"
|
tar "$tar_args" "$CACHED_LOCATION"
|
||||||
safe_cd "$VENDOR_DIR/portable-$VENDOR_NAME"
|
safe_cd "$VENDOR_DIR/portable-$VENDOR_NAME"
|
||||||
|
|
||||||
|
|||||||
@ -3,4 +3,8 @@ module SharedEnvExtension
|
|||||||
odeprecated "ENV.j1", "ENV.deparallelize"
|
odeprecated "ENV.j1", "ENV.deparallelize"
|
||||||
deparallelize
|
deparallelize
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def java_cache
|
||||||
|
# odeprecated "ENV.java_cache"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -16,7 +16,7 @@ end
|
|||||||
# This formula serves as the base class for several very similar
|
# This formula serves as the base class for several very similar
|
||||||
# formulae for Amazon Web Services related tools.
|
# formulae for Amazon Web Services related tools.
|
||||||
class AmazonWebServicesFormula < Formula
|
class AmazonWebServicesFormula < Formula
|
||||||
# Use this method to peform a standard install for Java-based tools,
|
# Use this method to perform a standard install for Java-based tools,
|
||||||
# keeping the .jars out of HOMEBREW_PREFIX/lib
|
# keeping the .jars out of HOMEBREW_PREFIX/lib
|
||||||
def install
|
def install
|
||||||
odeprecated "AmazonWebServicesFormula#install", "Formula#install"
|
odeprecated "AmazonWebServicesFormula#install", "Formula#install"
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
# RuboCop version used for `brew style` and `brew cask style`
|
# RuboCop version used for `brew style` and `brew cask style`
|
||||||
HOMEBREW_RUBOCOP_VERSION = "0.49.1".freeze
|
HOMEBREW_RUBOCOP_VERSION = "0.50.0"
|
||||||
HOMEBREW_RUBOCOP_CASK_VERSION = "~> 0.13.1".freeze # has to be updated when RuboCop version changes
|
HOMEBREW_RUBOCOP_CASK_VERSION = "~> 0.14.2" # has to be updated when RuboCop version changes
|
||||||
|
|||||||
@ -57,7 +57,7 @@ module Debrew
|
|||||||
input.chomp!
|
input.chomp!
|
||||||
|
|
||||||
i = input.to_i
|
i = input.to_i
|
||||||
if i > 0
|
if i.positive?
|
||||||
choice = menu.entries[i - 1]
|
choice = menu.entries[i - 1]
|
||||||
else
|
else
|
||||||
possible = menu.entries.find_all { |e| e.name.start_with?(input) }
|
possible = menu.entries.find_all { |e| e.name.start_with?(input) }
|
||||||
|
|||||||
@ -16,7 +16,7 @@ module IRB
|
|||||||
workspace = WorkSpace.new(binding)
|
workspace = WorkSpace.new(binding)
|
||||||
irb = Irb.new(workspace)
|
irb = Irb.new(workspace)
|
||||||
|
|
||||||
@CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC]
|
@CONF[:IRB_RC]&.call(irb.context)
|
||||||
@CONF[:MAIN_CONTEXT] = irb.context
|
@CONF[:MAIN_CONTEXT] = irb.context
|
||||||
|
|
||||||
trap("SIGINT") do
|
trap("SIGINT") do
|
||||||
|
|||||||
@ -51,7 +51,7 @@ class Dependency
|
|||||||
end
|
end
|
||||||
|
|
||||||
def modify_build_environment
|
def modify_build_environment
|
||||||
env_proc.call unless env_proc.nil?
|
env_proc&.call
|
||||||
end
|
end
|
||||||
|
|
||||||
def inspect
|
def inspect
|
||||||
|
|||||||
@ -54,6 +54,7 @@ module Homebrew
|
|||||||
|
|
||||||
def audit
|
def audit
|
||||||
Homebrew.inject_dump_stats!(FormulaAuditor, /^audit_/) if ARGV.switch? "D"
|
Homebrew.inject_dump_stats!(FormulaAuditor, /^audit_/) if ARGV.switch? "D"
|
||||||
|
Homebrew.auditing = true
|
||||||
|
|
||||||
formula_count = 0
|
formula_count = 0
|
||||||
problem_count = 0
|
problem_count = 0
|
||||||
@ -201,19 +202,24 @@ class FormulaAuditor
|
|||||||
@specs = %w[stable devel head].map { |s| formula.send(s) }.compact
|
@specs = %w[stable devel head].map { |s| formula.send(s) }.compact
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.check_http_content(url, name, user_agents: [:default])
|
def self.check_http_content(url, user_agents: [:default], check_content: false, strict: false, require_http: false)
|
||||||
return unless url.start_with? "http"
|
return unless url.start_with? "http"
|
||||||
|
|
||||||
details = nil
|
details = nil
|
||||||
user_agent = nil
|
user_agent = nil
|
||||||
hash_needed = url.start_with?("http:") && name != "curl"
|
hash_needed = url.start_with?("http:") && !require_http
|
||||||
user_agents.each do |ua|
|
user_agents.each do |ua|
|
||||||
details = http_content_headers_and_checksum(url, hash_needed: hash_needed, user_agent: ua)
|
details = http_content_headers_and_checksum(url, hash_needed: hash_needed, user_agent: ua)
|
||||||
user_agent = ua
|
user_agent = ua
|
||||||
break if details[:status].to_s.start_with?("2")
|
break if details[:status].to_s.start_with?("2")
|
||||||
end
|
end
|
||||||
|
|
||||||
return "The URL #{url} is not reachable" unless details[:status]
|
unless details[:status]
|
||||||
|
# Hack around https://github.com/Homebrew/brew/issues/3199
|
||||||
|
return if MacOS.version == :el_capitan
|
||||||
|
return "The URL #{url} is not reachable"
|
||||||
|
end
|
||||||
|
|
||||||
unless details[:status].start_with? "2"
|
unless details[:status].start_with? "2"
|
||||||
return "The URL #{url} is not reachable (HTTP status code #{details[:status]})"
|
return "The URL #{url} is not reachable (HTTP status code #{details[:status]})"
|
||||||
end
|
end
|
||||||
@ -236,8 +242,32 @@ class FormulaAuditor
|
|||||||
details[:content_length] == secure_details[:content_length]
|
details[:content_length] == secure_details[:content_length]
|
||||||
file_match = details[:file_hash] == secure_details[:file_hash]
|
file_match = details[:file_hash] == secure_details[:file_hash]
|
||||||
|
|
||||||
return if !etag_match && !content_length_match && !file_match
|
if etag_match || content_length_match || file_match
|
||||||
"The URL #{url} could use HTTPS rather than HTTP"
|
return "The URL #{url} should use HTTPS rather than HTTP"
|
||||||
|
end
|
||||||
|
|
||||||
|
return unless check_content
|
||||||
|
|
||||||
|
no_protocol_file_contents = %r{https?:\\?/\\?/}
|
||||||
|
details[:file] = details[:file].gsub(no_protocol_file_contents, "/")
|
||||||
|
secure_details[:file] = secure_details[:file].gsub(no_protocol_file_contents, "/")
|
||||||
|
|
||||||
|
# Check for the same content after removing all protocols
|
||||||
|
if details[:file] == secure_details[:file]
|
||||||
|
return "The URL #{url} should use HTTPS rather than HTTP"
|
||||||
|
end
|
||||||
|
|
||||||
|
return unless strict
|
||||||
|
|
||||||
|
# Same size, different content after normalization
|
||||||
|
# (typical causes: Generated ID, Timestamp, Unix time)
|
||||||
|
if details[:file].length == secure_details[:file].length
|
||||||
|
return "The URL #{url} may be able to use HTTPS rather than HTTP. Please verify it in a browser."
|
||||||
|
end
|
||||||
|
|
||||||
|
lenratio = (100 * secure_details[:file].length / details[:file].length).to_i
|
||||||
|
return unless (90..110).cover?(lenratio)
|
||||||
|
"The URL #{url} may be able to use HTTPS rather than HTTP. Please verify it in a browser."
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.http_content_headers_and_checksum(url, hash_needed: false, user_agent: :default)
|
def self.http_content_headers_and_checksum(url, hash_needed: false, user_agent: :default)
|
||||||
@ -260,6 +290,7 @@ class FormulaAuditor
|
|||||||
etag: headers[%r{ETag: ([wW]\/)?"(([^"]|\\")*)"}, 2],
|
etag: headers[%r{ETag: ([wW]\/)?"(([^"]|\\")*)"}, 2],
|
||||||
content_length: headers[/Content-Length: (\d+)/, 1],
|
content_length: headers[/Content-Length: (\d+)/, 1],
|
||||||
file_hash: output_hash,
|
file_hash: output_hash,
|
||||||
|
file: output,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -327,7 +358,7 @@ class FormulaAuditor
|
|||||||
end
|
end
|
||||||
valid_alias_names = [alias_name_major, alias_name_major_minor]
|
valid_alias_names = [alias_name_major, alias_name_major_minor]
|
||||||
|
|
||||||
if formula.tap && !formula.tap.core_tap?
|
unless formula.tap&.core_tap?
|
||||||
versioned_aliases.map! { |a| "#{formula.tap}/#{a}" }
|
versioned_aliases.map! { |a| "#{formula.tap}/#{a}" }
|
||||||
valid_alias_names.map! { |a| "#{formula.tap}/#{a}" }
|
valid_alias_names.map! { |a| "#{formula.tap}/#{a}" }
|
||||||
end
|
end
|
||||||
@ -356,21 +387,6 @@ class FormulaAuditor
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def audit_class
|
|
||||||
if @strict
|
|
||||||
unless formula.test_defined?
|
|
||||||
problem "A `test do` test block should be added"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
classes = %w[GithubGistFormula ScriptFileFormula AmazonWebServicesFormula]
|
|
||||||
klass = classes.find do |c|
|
|
||||||
Object.const_defined?(c) && formula.class < Object.const_get(c)
|
|
||||||
end
|
|
||||||
|
|
||||||
problem "#{klass} is deprecated, use Formula instead" if klass
|
|
||||||
end
|
|
||||||
|
|
||||||
# core aliases + tap alias names + tap alias full name
|
# core aliases + tap alias names + tap alias full name
|
||||||
@@aliases ||= Formula.aliases + Formula.tap_aliases
|
@@aliases ||= Formula.aliases + Formula.tap_aliases
|
||||||
|
|
||||||
@ -403,6 +419,7 @@ class FormulaAuditor
|
|||||||
|
|
||||||
@@local_official_taps_name_map ||= Tap.select(&:official?).flat_map(&:formula_names)
|
@@local_official_taps_name_map ||= Tap.select(&:official?).flat_map(&:formula_names)
|
||||||
.each_with_object({}) do |tap_formula_full_name, name_map|
|
.each_with_object({}) do |tap_formula_full_name, name_map|
|
||||||
|
next if tap_formula_full_name.start_with?("homebrew/science/")
|
||||||
tap_formula_name = tap_formula_full_name.split("/").last
|
tap_formula_name = tap_formula_full_name.split("/").last
|
||||||
name_map[tap_formula_name] ||= []
|
name_map[tap_formula_name] ||= []
|
||||||
name_map[tap_formula_name] << tap_formula_full_name
|
name_map[tap_formula_name] << tap_formula_full_name
|
||||||
@ -413,6 +430,7 @@ class FormulaAuditor
|
|||||||
|
|
||||||
if @online
|
if @online
|
||||||
Homebrew.search_taps(name, silent: true).each do |tap_formula_full_name|
|
Homebrew.search_taps(name, silent: true).each do |tap_formula_full_name|
|
||||||
|
next if tap_formula_full_name.start_with?("homebrew/science/")
|
||||||
tap_formula_name = tap_formula_full_name.split("/").last
|
tap_formula_name = tap_formula_full_name.split("/").last
|
||||||
next if tap_formula_name != name
|
next if tap_formula_name != name
|
||||||
same_name_tap_formulae << tap_formula_full_name
|
same_name_tap_formulae << tap_formula_full_name
|
||||||
@ -563,10 +581,11 @@ class FormulaAuditor
|
|||||||
|
|
||||||
return unless @online
|
return unless @online
|
||||||
|
|
||||||
return unless DevelopmentTools.curl_handles_most_https_homepages?
|
return unless DevelopmentTools.curl_handles_most_https_certificates?
|
||||||
if http_content_problem = FormulaAuditor.check_http_content(homepage,
|
if http_content_problem = FormulaAuditor.check_http_content(homepage,
|
||||||
formula.name,
|
user_agents: [:browser, :default],
|
||||||
user_agents: [:browser, :default])
|
check_content: true,
|
||||||
|
strict: @strict)
|
||||||
problem http_content_problem
|
problem http_content_problem
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -616,13 +635,14 @@ class FormulaAuditor
|
|||||||
end
|
end
|
||||||
|
|
||||||
%w[Stable Devel HEAD].each do |name|
|
%w[Stable Devel HEAD].each do |name|
|
||||||
next unless spec = formula.send(name.downcase)
|
spec_name = name.downcase.to_sym
|
||||||
|
next unless spec = formula.send(spec_name)
|
||||||
|
|
||||||
ra = ResourceAuditor.new(spec, online: @online, strict: @strict).audit
|
ra = ResourceAuditor.new(spec, spec_name, online: @online, strict: @strict).audit
|
||||||
problems.concat ra.problems.map { |problem| "#{name}: #{problem}" }
|
problems.concat ra.problems.map { |problem| "#{name}: #{problem}" }
|
||||||
|
|
||||||
spec.resources.each_value do |resource|
|
spec.resources.each_value do |resource|
|
||||||
ra = ResourceAuditor.new(resource, online: @online, strict: @strict).audit
|
ra = ResourceAuditor.new(resource, spec_name, online: @online, strict: @strict).audit
|
||||||
problems.concat ra.problems.map { |problem|
|
problems.concat ra.problems.map { |problem|
|
||||||
"#{name} resource #{resource.name.inspect}: #{problem}"
|
"#{name} resource #{resource.name.inspect}: #{problem}"
|
||||||
}
|
}
|
||||||
@ -687,7 +707,7 @@ class FormulaAuditor
|
|||||||
end
|
end
|
||||||
|
|
||||||
stable = formula.stable
|
stable = formula.stable
|
||||||
case stable && stable.url
|
case stable&.url
|
||||||
when /[\d\._-](alpha|beta|rc\d)/
|
when /[\d\._-](alpha|beta|rc\d)/
|
||||||
matched = Regexp.last_match(1)
|
matched = Regexp.last_match(1)
|
||||||
version_prefix = stable.version.to_s.sub(/\d+$/, "")
|
version_prefix = stable.version.to_s.sub(/\d+$/, "")
|
||||||
@ -865,8 +885,8 @@ class FormulaAuditor
|
|||||||
|
|
||||||
problem "Use spaces instead of tabs for indentation" if line =~ /^[ ]*\t/
|
problem "Use spaces instead of tabs for indentation" if line =~ /^[ ]*\t/
|
||||||
|
|
||||||
if line.include?("ENV.x11")
|
if line.include?("ENV.java_cache")
|
||||||
problem "Use \"depends_on :x11\" instead of \"ENV.x11\""
|
problem "In-formula ENV.java_cache usage has been deprecated & should be removed."
|
||||||
end
|
end
|
||||||
|
|
||||||
# Avoid hard-coding compilers
|
# Avoid hard-coding compilers
|
||||||
@ -882,14 +902,6 @@ class FormulaAuditor
|
|||||||
problem "Use ENV instead of invoking '#{Regexp.last_match(1)}' to modify the environment"
|
problem "Use ENV instead of invoking '#{Regexp.last_match(1)}' to modify the environment"
|
||||||
end
|
end
|
||||||
|
|
||||||
if formula.name != "wine" && line =~ /ENV\.universal_binary/
|
|
||||||
problem "macOS has been 64-bit only since 10.6 so ENV.universal_binary is deprecated."
|
|
||||||
end
|
|
||||||
|
|
||||||
if line =~ /build\.universal\?/
|
|
||||||
problem "macOS has been 64-bit only so build.universal? is deprecated."
|
|
||||||
end
|
|
||||||
|
|
||||||
if line =~ /version == ['"]HEAD['"]/
|
if line =~ /version == ['"]HEAD['"]/
|
||||||
problem "Use 'build.head?' instead of inspecting 'version'"
|
problem "Use 'build.head?' instead of inspecting 'version'"
|
||||||
end
|
end
|
||||||
@ -930,12 +942,6 @@ class FormulaAuditor
|
|||||||
problem "Use build instead of ARGV to check options"
|
problem "Use build instead of ARGV to check options"
|
||||||
end
|
end
|
||||||
|
|
||||||
problem "Use new-style option definitions" if line.include?("def options")
|
|
||||||
|
|
||||||
if line.end_with?("def test")
|
|
||||||
problem "Use new-style test definitions (test do)"
|
|
||||||
end
|
|
||||||
|
|
||||||
if line.include?("MACOS_VERSION")
|
if line.include?("MACOS_VERSION")
|
||||||
problem "Use MacOS.version instead of MACOS_VERSION"
|
problem "Use MacOS.version instead of MACOS_VERSION"
|
||||||
end
|
end
|
||||||
@ -949,11 +955,6 @@ class FormulaAuditor
|
|||||||
problem "\"#{$&}\" is deprecated, use a comparison to MacOS.version instead"
|
problem "\"#{$&}\" is deprecated, use a comparison to MacOS.version instead"
|
||||||
end
|
end
|
||||||
|
|
||||||
if line =~ /skip_clean\s+:all/
|
|
||||||
problem "`skip_clean :all` is deprecated; brew no longer strips symbols\n" \
|
|
||||||
"\tPass explicit paths to prevent Homebrew from removing empty folders."
|
|
||||||
end
|
|
||||||
|
|
||||||
if line =~ /depends_on [A-Z][\w:]+\.new$/
|
if line =~ /depends_on [A-Z][\w:]+\.new$/
|
||||||
problem "`depends_on` can take requirement classes instead of instances"
|
problem "`depends_on` can take requirement classes instead of instances"
|
||||||
end
|
end
|
||||||
@ -992,30 +993,6 @@ class FormulaAuditor
|
|||||||
problem "Use `assert_match` instead of `assert ...include?`"
|
problem "Use `assert_match` instead of `assert ...include?`"
|
||||||
end
|
end
|
||||||
|
|
||||||
if line.include?('system "npm", "install"') && !line.include?("Language::Node") &&
|
|
||||||
formula.name !~ /^kibana(\@\d+(\.\d+)?)?$/
|
|
||||||
problem "Use Language::Node for npm install args"
|
|
||||||
end
|
|
||||||
|
|
||||||
if line.include?("fails_with :llvm")
|
|
||||||
problem "'fails_with :llvm' is now a no-op so should be removed"
|
|
||||||
end
|
|
||||||
|
|
||||||
if line =~ /system\s+['"](otool|install_name_tool|lipo)/ && formula.name != "cctools"
|
|
||||||
problem "Use ruby-macho instead of calling #{Regexp.last_match(1)}"
|
|
||||||
end
|
|
||||||
|
|
||||||
if formula.tap.to_s == "homebrew/core"
|
|
||||||
["OS.mac?", "OS.linux?"].each do |check|
|
|
||||||
next unless line.include?(check)
|
|
||||||
problem "Don't use #{check}; Homebrew/core only supports macOS"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if line =~ /((revision|version_scheme)\s+0)/
|
|
||||||
problem "'#{Regexp.last_match(1)}' should be removed"
|
|
||||||
end
|
|
||||||
|
|
||||||
return unless @strict
|
return unless @strict
|
||||||
|
|
||||||
problem "`#{Regexp.last_match(1)}` in formulae is deprecated" if line =~ /(env :(std|userpaths))/
|
problem "`#{Regexp.last_match(1)}` in formulae is deprecated" if line =~ /(env :(std|userpaths))/
|
||||||
@ -1041,7 +1018,7 @@ class FormulaAuditor
|
|||||||
def audit_reverse_migration
|
def audit_reverse_migration
|
||||||
# Only enforce for new formula being re-added to core and official taps
|
# Only enforce for new formula being re-added to core and official taps
|
||||||
return unless @strict
|
return unless @strict
|
||||||
return unless formula.tap && formula.tap.official?
|
return unless formula.tap&.official?
|
||||||
return unless formula.tap.tap_migrations.key?(formula.name)
|
return unless formula.tap.tap_migrations.key?(formula.name)
|
||||||
|
|
||||||
problem <<-EOS.undent
|
problem <<-EOS.undent
|
||||||
@ -1116,10 +1093,10 @@ class FormulaAuditor
|
|||||||
end
|
end
|
||||||
|
|
||||||
class ResourceAuditor
|
class ResourceAuditor
|
||||||
attr_reader :problems
|
attr_reader :name, :version, :checksum, :url, :mirrors, :using, :specs, :owner
|
||||||
attr_reader :version, :checksum, :using, :specs, :url, :mirrors, :name
|
attr_reader :spec_name, :problems
|
||||||
|
|
||||||
def initialize(resource, options = {})
|
def initialize(resource, spec_name, options = {})
|
||||||
@name = resource.name
|
@name = resource.name
|
||||||
@version = resource.version
|
@version = resource.version
|
||||||
@checksum = resource.checksum
|
@checksum = resource.checksum
|
||||||
@ -1127,6 +1104,8 @@ class ResourceAuditor
|
|||||||
@mirrors = resource.mirrors
|
@mirrors = resource.mirrors
|
||||||
@using = resource.using
|
@using = resource.using
|
||||||
@specs = resource.specs
|
@specs = resource.specs
|
||||||
|
@owner = resource.owner
|
||||||
|
@spec_name = spec_name
|
||||||
@online = options[:online]
|
@online = options[:online]
|
||||||
@strict = options[:strict]
|
@strict = options[:strict]
|
||||||
@problems = []
|
@problems = []
|
||||||
@ -1203,11 +1182,29 @@ class ResourceAuditor
|
|||||||
problem "Redundant :using value in URL"
|
problem "Redundant :using value in URL"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.curl_openssl_and_deps
|
||||||
|
@curl_openssl_and_deps ||= begin
|
||||||
|
formulae_names = ["curl", "openssl"]
|
||||||
|
formulae_names += formulae_names.flat_map do |f|
|
||||||
|
Formula[f].recursive_dependencies.map(&:name)
|
||||||
|
end
|
||||||
|
formulae_names.uniq
|
||||||
|
rescue FormulaUnavailableError
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def audit_urls
|
def audit_urls
|
||||||
urls = [url] + mirrors
|
urls = [url] + mirrors
|
||||||
|
|
||||||
if name == "curl" && !urls.find { |u| u.start_with?("http://") }
|
curl_openssl_or_deps = ResourceAuditor.curl_openssl_and_deps.include?(owner.name)
|
||||||
problem "should always include at least one HTTP url"
|
|
||||||
|
if spec_name == :stable && curl_openssl_or_deps
|
||||||
|
problem "should not use xz tarballs" if url.end_with?(".xz")
|
||||||
|
|
||||||
|
unless urls.find { |u| u.start_with?("http://") }
|
||||||
|
problem "should always include at least one HTTP mirror"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return unless @online
|
return unless @online
|
||||||
@ -1219,7 +1216,7 @@ class ResourceAuditor
|
|||||||
# A `brew mirror`'ed URL is usually not yet reachable at the time of
|
# A `brew mirror`'ed URL is usually not yet reachable at the time of
|
||||||
# pull request.
|
# pull request.
|
||||||
next if url =~ %r{^https://dl.bintray.com/homebrew/mirror/}
|
next if url =~ %r{^https://dl.bintray.com/homebrew/mirror/}
|
||||||
if http_content_problem = FormulaAuditor.check_http_content(url, name)
|
if http_content_problem = FormulaAuditor.check_http_content(url, require_http: curl_openssl_or_deps)
|
||||||
problem http_content_problem
|
problem http_content_problem
|
||||||
end
|
end
|
||||||
elsif strategy <= GitDownloadStrategy
|
elsif strategy <= GitDownloadStrategy
|
||||||
@ -1228,6 +1225,7 @@ class ResourceAuditor
|
|||||||
end
|
end
|
||||||
elsif strategy <= SubversionDownloadStrategy
|
elsif strategy <= SubversionDownloadStrategy
|
||||||
next unless DevelopmentTools.subversion_handles_most_https_certificates?
|
next unless DevelopmentTools.subversion_handles_most_https_certificates?
|
||||||
|
next unless Utils.svn_available?
|
||||||
unless Utils.svn_remote_exists url
|
unless Utils.svn_remote_exists url
|
||||||
problem "The URL #{url} is not a valid svn URL"
|
problem "The URL #{url} is not a valid svn URL"
|
||||||
end
|
end
|
||||||
|
|||||||
@ -47,7 +47,7 @@ BOTTLE_ERB = <<-EOS.freeze
|
|||||||
<% elsif cellar != BottleSpecification::DEFAULT_CELLAR %>
|
<% elsif cellar != BottleSpecification::DEFAULT_CELLAR %>
|
||||||
cellar "<%= cellar %>"
|
cellar "<%= cellar %>"
|
||||||
<% end %>
|
<% end %>
|
||||||
<% if rebuild > 0 %>
|
<% if rebuild.positive? %>
|
||||||
rebuild <%= rebuild %>
|
rebuild <%= rebuild %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% checksums.each do |checksum_type, checksum_values| %>
|
<% checksums.each do |checksum_type, checksum_values| %>
|
||||||
@ -186,7 +186,7 @@ module Homebrew
|
|||||||
ohai "Determining #{f.full_name} bottle rebuild..."
|
ohai "Determining #{f.full_name} bottle rebuild..."
|
||||||
versions = FormulaVersions.new(f)
|
versions = FormulaVersions.new(f)
|
||||||
rebuilds = versions.bottle_version_map("origin/master")[f.pkg_version]
|
rebuilds = versions.bottle_version_map("origin/master")[f.pkg_version]
|
||||||
rebuilds.pop if rebuilds.last.to_i > 0
|
rebuilds.pop if rebuilds.last.to_i.positive?
|
||||||
rebuild = rebuilds.empty? ? 0 : rebuilds.max.to_i + 1
|
rebuild = rebuilds.empty? ? 0 : rebuilds.max.to_i + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -283,7 +283,7 @@ module Homebrew
|
|||||||
raise
|
raise
|
||||||
ensure
|
ensure
|
||||||
ignore_interrupts do
|
ignore_interrupts do
|
||||||
original_tab.write if original_tab
|
original_tab&.write
|
||||||
unless ARGV.include? "--skip-relocation"
|
unless ARGV.include? "--skip-relocation"
|
||||||
keg.replace_placeholders_with_locations changed_files
|
keg.replace_placeholders_with_locations changed_files
|
||||||
end
|
end
|
||||||
|
|||||||
@ -89,7 +89,8 @@ module Homebrew
|
|||||||
|
|
||||||
def check_for_duplicate_pull_requests(formula)
|
def check_for_duplicate_pull_requests(formula)
|
||||||
pull_requests = fetch_pull_requests(formula)
|
pull_requests = fetch_pull_requests(formula)
|
||||||
return unless pull_requests && !pull_requests.empty?
|
return unless pull_requests
|
||||||
|
return if pull_requests.empty?
|
||||||
duplicates_message = <<-EOS.undent
|
duplicates_message = <<-EOS.undent
|
||||||
These open pull requests may be duplicates:
|
These open pull requests may be duplicates:
|
||||||
#{pull_requests.map { |pr| "#{pr["title"]} #{pr["html_url"]}" }.join("\n")}
|
#{pull_requests.map { |pr| "#{pr["title"]} #{pr["html_url"]}" }.join("\n")}
|
||||||
@ -124,7 +125,7 @@ module Homebrew
|
|||||||
Formula.each do |f|
|
Formula.each do |f|
|
||||||
if is_devel && f.devel && f.devel.url && f.devel.url.match(base_url)
|
if is_devel && f.devel && f.devel.url && f.devel.url.match(base_url)
|
||||||
guesses << f
|
guesses << f
|
||||||
elsif f.stable && f.stable.url && f.stable.url.match(base_url)
|
elsif f.stable&.url && f.stable.url.match(base_url)
|
||||||
guesses << f
|
guesses << f
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -296,9 +297,7 @@ module Homebrew
|
|||||||
ohai "git fetch --unshallow origin" if shallow
|
ohai "git fetch --unshallow origin" if shallow
|
||||||
ohai "git checkout --no-track -b #{branch} origin/master"
|
ohai "git checkout --no-track -b #{branch} origin/master"
|
||||||
ohai "git commit --no-edit --verbose --message='#{formula.name} #{new_formula_version}#{devel_message}' -- #{formula.path}"
|
ohai "git commit --no-edit --verbose --message='#{formula.name} #{new_formula_version}#{devel_message}' -- #{formula.path}"
|
||||||
ohai "hub fork --no-remote"
|
ohai "hub fork # read $HUB_REMOTE"
|
||||||
ohai "hub fork"
|
|
||||||
ohai "hub fork (to read $HUB_REMOTE)"
|
|
||||||
ohai "git push --set-upstream $HUB_REMOTE #{branch}:#{branch}"
|
ohai "git push --set-upstream $HUB_REMOTE #{branch}:#{branch}"
|
||||||
ohai "hub pull-request --browse -m '#{formula.name} #{new_formula_version}#{devel_message}'"
|
ohai "hub pull-request --browse -m '#{formula.name} #{new_formula_version}#{devel_message}'"
|
||||||
ohai "git checkout -"
|
ohai "git checkout -"
|
||||||
@ -308,9 +307,9 @@ module Homebrew
|
|||||||
safe_system "git", "commit", "--no-edit", "--verbose",
|
safe_system "git", "commit", "--no-edit", "--verbose",
|
||||||
"--message=#{formula.name} #{new_formula_version}#{devel_message}",
|
"--message=#{formula.name} #{new_formula_version}#{devel_message}",
|
||||||
"--", formula.path
|
"--", formula.path
|
||||||
safe_system "hub", "fork", "--no-remote"
|
remote = Utils.popen_read("hub fork 2>&1")[/remote:? (\S+)/, 1]
|
||||||
quiet_system "hub", "fork"
|
# repeat for hub 2.2 backwards compatibility:
|
||||||
remote = Utils.popen_read("hub fork 2>&1")[/fatal: remote (.+) already exists\./, 1]
|
remote = Utils.popen_read("hub fork 2>&1")[/remote:? (\S+)/, 1] if remote.to_s.empty?
|
||||||
odie "cannot get remote from 'hub'!" if remote.to_s.empty?
|
odie "cannot get remote from 'hub'!" if remote.to_s.empty?
|
||||||
safe_system "git", "push", "--set-upstream", remote, "#{branch}:#{branch}"
|
safe_system "git", "push", "--set-upstream", remote, "#{branch}:#{branch}"
|
||||||
pr_message = <<-EOS.undent
|
pr_message = <<-EOS.undent
|
||||||
|
|||||||
@ -69,13 +69,13 @@ module Homebrew
|
|||||||
tap = nil
|
tap = nil
|
||||||
|
|
||||||
ARGV.named.each do |arg|
|
ARGV.named.each do |arg|
|
||||||
if arg.to_i > 0
|
if arg.to_i.positive?
|
||||||
issue = arg
|
issue = arg
|
||||||
url = "https://github.com/Homebrew/homebrew-core/pull/#{arg}"
|
url = "https://github.com/Homebrew/homebrew-core/pull/#{arg}"
|
||||||
tap = CoreTap.instance
|
tap = CoreTap.instance
|
||||||
elsif (testing_match = arg.match %r{/job/Homebrew.*Testing/(\d+)/})
|
elsif (testing_match = arg.match %r{/job/Homebrew.*Testing/(\d+)/})
|
||||||
tap = ARGV.value("tap")
|
tap = ARGV.value("tap")
|
||||||
tap = if tap && tap.start_with?("homebrew/")
|
tap = if tap&.start_with?("homebrew/")
|
||||||
Tap.fetch("homebrew", tap.strip_prefix("homebrew/"))
|
Tap.fetch("homebrew", tap.strip_prefix("homebrew/"))
|
||||||
elsif tap
|
elsif tap
|
||||||
odie "Tap option did not start with \"homebrew/\": #{tap}"
|
odie "Tap option did not start with \"homebrew/\": #{tap}"
|
||||||
@ -350,7 +350,7 @@ module Homebrew
|
|||||||
files << Regexp.last_match(1) if line =~ %r{^\+\+\+ b/(.*)}
|
files << Regexp.last_match(1) if line =~ %r{^\+\+\+ b/(.*)}
|
||||||
end
|
end
|
||||||
files.each do |file|
|
files.each do |file|
|
||||||
if tap && tap.formula_file?(file)
|
if tap&.formula_file?(file)
|
||||||
formula_name = File.basename(file, ".rb")
|
formula_name = File.basename(file, ".rb")
|
||||||
formulae << formula_name unless formulae.include?(formula_name)
|
formulae << formula_name unless formulae.include?(formula_name)
|
||||||
else
|
else
|
||||||
|
|||||||
@ -10,10 +10,8 @@ module Homebrew
|
|||||||
|
|
||||||
def release_notes
|
def release_notes
|
||||||
previous_tag = ARGV.named.first
|
previous_tag = ARGV.named.first
|
||||||
unless previous_tag
|
previous_tag ||= Utils.popen_read("git tag --list --sort=-version:refname")
|
||||||
previous_tag = Utils.popen_read("git tag --list --sort=-version:refname")
|
|
||||||
.lines.first.chomp
|
.lines.first.chomp
|
||||||
end
|
|
||||||
odie "Could not find any previous tags!" unless previous_tag
|
odie "Could not find any previous tags!" unless previous_tag
|
||||||
|
|
||||||
end_ref = ARGV.named[1] || "origin/master"
|
end_ref = ARGV.named[1] || "origin/master"
|
||||||
|
|||||||
@ -114,7 +114,7 @@ class DevelopmentTools
|
|||||||
@non_apple_gcc_version = {}
|
@non_apple_gcc_version = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
def curl_handles_most_https_homepages?
|
def curl_handles_most_https_certificates?
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -522,7 +522,7 @@ module Homebrew
|
|||||||
homebrew_owned = @found.all? do |path|
|
homebrew_owned = @found.all? do |path|
|
||||||
Pathname.new(path).realpath.to_s.start_with? "#{HOMEBREW_CELLAR}/gettext"
|
Pathname.new(path).realpath.to_s.start_with? "#{HOMEBREW_CELLAR}/gettext"
|
||||||
end
|
end
|
||||||
return if gettext && gettext.linked_keg.directory? && homebrew_owned
|
return if gettext&.linked_keg&.directory? && homebrew_owned
|
||||||
|
|
||||||
inject_file_list @found, <<-EOS.undent
|
inject_file_list @found, <<-EOS.undent
|
||||||
gettext files detected at a system prefix.
|
gettext files detected at a system prefix.
|
||||||
@ -540,7 +540,7 @@ module Homebrew
|
|||||||
rescue
|
rescue
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
if libiconv && libiconv.linked_keg.directory?
|
if libiconv&.linked_keg&.directory?
|
||||||
unless libiconv.keg_only?
|
unless libiconv.keg_only?
|
||||||
<<-EOS.undent
|
<<-EOS.undent
|
||||||
A libiconv formula is installed and linked.
|
A libiconv formula is installed and linked.
|
||||||
|
|||||||
@ -331,21 +331,11 @@ class CurlDownloadStrategy < AbstractFileDownloadStrategy
|
|||||||
if cached_location.exist?
|
if cached_location.exist?
|
||||||
puts "Already downloaded: #{cached_location}"
|
puts "Already downloaded: #{cached_location}"
|
||||||
else
|
else
|
||||||
had_incomplete_download = temporary_path.exist?
|
|
||||||
begin
|
begin
|
||||||
_fetch
|
_fetch
|
||||||
rescue ErrorDuringExecution
|
rescue ErrorDuringExecution
|
||||||
# 33 == range not supported
|
|
||||||
# try wiping the incomplete download and retrying once
|
|
||||||
unless $CHILD_STATUS.exitstatus == 33 && had_incomplete_download
|
|
||||||
raise CurlDownloadStrategyError, @url
|
raise CurlDownloadStrategyError, @url
|
||||||
end
|
end
|
||||||
|
|
||||||
ohai "Trying a full download"
|
|
||||||
temporary_path.unlink
|
|
||||||
had_incomplete_download = false
|
|
||||||
retry
|
|
||||||
end
|
|
||||||
ignore_interrupts { temporary_path.rename(cached_location) }
|
ignore_interrupts { temporary_path.rename(cached_location) }
|
||||||
end
|
end
|
||||||
rescue CurlDownloadStrategyError
|
rescue CurlDownloadStrategyError
|
||||||
|
|||||||
@ -416,7 +416,7 @@ class BuildError < RuntimeError
|
|||||||
|
|
||||||
puts
|
puts
|
||||||
|
|
||||||
if issues && !issues.empty?
|
unless issues&.empty?
|
||||||
puts "These open issues may also help:"
|
puts "These open issues may also help:"
|
||||||
puts issues.map { |i| "#{i["title"]} #{i["html_url"]}" }.join("\n")
|
puts issues.map { |i| "#{i["title"]} #{i["html_url"]}" }.join("\n")
|
||||||
end
|
end
|
||||||
|
|||||||
@ -144,10 +144,10 @@ module HomebrewArgvExtension
|
|||||||
def value(name)
|
def value(name)
|
||||||
arg_prefix = "--#{name}="
|
arg_prefix = "--#{name}="
|
||||||
flag_with_value = find { |arg| arg.start_with?(arg_prefix) }
|
flag_with_value = find { |arg| arg.start_with?(arg_prefix) }
|
||||||
flag_with_value.strip_prefix(arg_prefix) if flag_with_value
|
flag_with_value&.strip_prefix(arg_prefix)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns an array of values that were given as a comma-seperated list.
|
# Returns an array of values that were given as a comma-separated list.
|
||||||
# @see value
|
# @see value
|
||||||
def values(name)
|
def values(name)
|
||||||
return unless val = value(name)
|
return unless val = value(name)
|
||||||
@ -236,7 +236,7 @@ module HomebrewArgvExtension
|
|||||||
|
|
||||||
def bottle_arch
|
def bottle_arch
|
||||||
arch = value "bottle-arch"
|
arch = value "bottle-arch"
|
||||||
arch.to_sym if arch
|
arch&.to_sym
|
||||||
end
|
end
|
||||||
|
|
||||||
def build_from_source?
|
def build_from_source?
|
||||||
|
|||||||
@ -28,7 +28,7 @@ module EnvActivation
|
|||||||
end
|
end
|
||||||
|
|
||||||
def clear_sensitive_environment!
|
def clear_sensitive_environment!
|
||||||
ENV.keys.each do |key|
|
ENV.each_key do |key|
|
||||||
next unless /(cookie|key|token)/i =~ key
|
next unless /(cookie|key|token)/i =~ key
|
||||||
ENV.delete key
|
ENV.delete key
|
||||||
end
|
end
|
||||||
|
|||||||
@ -260,10 +260,6 @@ module SharedEnvExtension
|
|||||||
set_cpu_flags(flags)
|
set_cpu_flags(flags)
|
||||||
end
|
end
|
||||||
|
|
||||||
def java_cache
|
|
||||||
append "_JAVA_OPTIONS", "-Duser.home=#{HOMEBREW_CACHE}/java_cache"
|
|
||||||
end
|
|
||||||
|
|
||||||
# ld64 is a newer linker provided for Xcode 2.5
|
# ld64 is a newer linker provided for Xcode 2.5
|
||||||
# @private
|
# @private
|
||||||
def ld64
|
def ld64
|
||||||
|
|||||||
@ -233,8 +233,8 @@ module Stdenv
|
|||||||
|
|
||||||
def make_jobs
|
def make_jobs
|
||||||
# '-j' requires a positive integral argument
|
# '-j' requires a positive integral argument
|
||||||
if self["HOMEBREW_MAKE_JOBS"].to_i > 0
|
if (jobs = self["HOMEBREW_MAKE_JOBS"].to_i).positive?
|
||||||
self["HOMEBREW_MAKE_JOBS"].to_i
|
jobs
|
||||||
else
|
else
|
||||||
Hardware::CPU.cores
|
Hardware::CPU.cores
|
||||||
end
|
end
|
||||||
|
|||||||
@ -9,7 +9,7 @@ class DevelopmentTools
|
|||||||
@locate[key] = if (located_tool = original_locate(tool))
|
@locate[key] = if (located_tool = original_locate(tool))
|
||||||
located_tool
|
located_tool
|
||||||
elsif MacOS.version > :tiger
|
elsif MacOS.version > :tiger
|
||||||
path = Utils.popen_read("/usr/bin/xcrun", "-no-cache", "-find", tool).chomp
|
path = Utils.popen_read("/usr/bin/xcrun", "-no-cache", "-find", tool, err: :close).chomp
|
||||||
Pathname.new(path) if File.executable?(path)
|
Pathname.new(path) if File.executable?(path)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -43,11 +43,16 @@ class DevelopmentTools
|
|||||||
end
|
end
|
||||||
|
|
||||||
def custom_installation_instructions
|
def custom_installation_instructions
|
||||||
if MacOS.version > :tiger
|
if MacOS.version > :leopard
|
||||||
<<-EOS.undent
|
<<-EOS.undent
|
||||||
Install GNU's GCC
|
Install GNU's GCC
|
||||||
brew install gcc
|
brew install gcc
|
||||||
EOS
|
EOS
|
||||||
|
elsif MacOS.version > :tiger
|
||||||
|
<<-EOS.undent
|
||||||
|
Install GNU's GCC
|
||||||
|
brew install gcc@4.6
|
||||||
|
EOS
|
||||||
else
|
else
|
||||||
# Tiger doesn't ship with apple-gcc42, and this is required to build
|
# Tiger doesn't ship with apple-gcc42, and this is required to build
|
||||||
# some software that doesn't build properly with FSF GCC.
|
# some software that doesn't build properly with FSF GCC.
|
||||||
@ -55,7 +60,7 @@ class DevelopmentTools
|
|||||||
Install Apple's GCC
|
Install Apple's GCC
|
||||||
brew install apple-gcc42
|
brew install apple-gcc42
|
||||||
or GNU's GCC
|
or GNU's GCC
|
||||||
brew install gcc
|
brew install gcc@4.6
|
||||||
EOS
|
EOS
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -77,10 +82,10 @@ class DevelopmentTools
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def curl_handles_most_https_homepages?
|
def curl_handles_most_https_certificates?
|
||||||
# The system Curl is too old for some modern HTTPS homepages on
|
# The system Curl is too old for some modern HTTPS certificates on
|
||||||
# older macOS versions.
|
# older macOS versions.
|
||||||
MacOS.version >= :el_capitan
|
ENV["HOMEBREW_SYSTEM_CURL_TOO_OLD"].nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
def subversion_handles_most_https_certificates?
|
def subversion_handles_most_https_certificates?
|
||||||
|
|||||||
@ -195,8 +195,9 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
|
|
||||||
def check_ruby_version
|
def check_ruby_version
|
||||||
ruby_version = "2.0"
|
ruby_version = "2.3.3"
|
||||||
return if RUBY_VERSION[/\d\.\d/] == ruby_version
|
return if RUBY_VERSION == ruby_version
|
||||||
|
return if ARGV.homebrew_developer? && OS::Mac.prerelease?
|
||||||
|
|
||||||
<<-EOS.undent
|
<<-EOS.undent
|
||||||
Ruby version #{RUBY_VERSION} is unsupported on #{MacOS.version}. Homebrew
|
Ruby version #{RUBY_VERSION} is unsupported on #{MacOS.version}. Homebrew
|
||||||
|
|||||||
@ -96,9 +96,13 @@ module Superenv
|
|||||||
self["SDKROOT"] = MacOS.sdk_path
|
self["SDKROOT"] = MacOS.sdk_path
|
||||||
end
|
end
|
||||||
|
|
||||||
# Filter out symbols known not to be defined on 10.11 since GNU Autotools
|
# Filter out symbols known not to be defined since GNU Autotools can't
|
||||||
# can't reliably figure this out with Xcode 8 on its own yet.
|
# reliably figure this out with Xcode 8 and above.
|
||||||
if MacOS.version == "10.11" && MacOS::Xcode.installed? && MacOS::Xcode.version >= "8.0"
|
if MacOS.version == "10.12" && MacOS::Xcode.installed? && MacOS::Xcode.version >= "9.0"
|
||||||
|
%w[fmemopen futimens open_memstream utimensat].each do |s|
|
||||||
|
ENV["ac_cv_func_#{s}"] = "no"
|
||||||
|
end
|
||||||
|
elsif MacOS.version == "10.11" && MacOS::Xcode.installed? && MacOS::Xcode.version >= "8.0"
|
||||||
%w[basename_r clock_getres clock_gettime clock_settime dirname_r
|
%w[basename_r clock_getres clock_gettime clock_settime dirname_r
|
||||||
getentropy mkostemp mkostemps timingsafe_bcmp].each do |s|
|
getentropy mkostemp mkostemps timingsafe_bcmp].each do |s|
|
||||||
ENV["ac_cv_func_#{s}"] = "no"
|
ENV["ac_cv_func_#{s}"] = "no"
|
||||||
|
|||||||
@ -50,6 +50,8 @@ module Hardware
|
|||||||
:broadwell
|
:broadwell
|
||||||
when 0x37fc219f # Skylake
|
when 0x37fc219f # Skylake
|
||||||
:skylake
|
:skylake
|
||||||
|
when 0x0f817246 # Kaby Lake
|
||||||
|
:kabylake
|
||||||
else
|
else
|
||||||
:dunno
|
:dunno
|
||||||
end
|
end
|
||||||
|
|||||||
@ -60,7 +60,7 @@ module StringInreplaceExtension
|
|||||||
result
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
# Looks for Makefile style variable defintions and replaces the
|
# Looks for Makefile style variable definitions and replaces the
|
||||||
# value with "new_value", or removes the definition entirely.
|
# value with "new_value", or removes the definition entirely.
|
||||||
def change_make_var!(flag, new_value)
|
def change_make_var!(flag, new_value)
|
||||||
return if gsub!(/^#{Regexp.escape(flag)}[ \t]*=[ \t]*(.*)$/, "#{flag}=#{new_value}", false)
|
return if gsub!(/^#{Regexp.escape(flag)}[ \t]*=[ \t]*(.*)$/, "#{flag}=#{new_value}", false)
|
||||||
|
|||||||
@ -472,7 +472,7 @@ class Formula
|
|||||||
return true if devel && tab.devel_version && tab.devel_version < devel.version
|
return true if devel && tab.devel_version && tab.devel_version < devel.version
|
||||||
|
|
||||||
if options[:fetch_head]
|
if options[:fetch_head]
|
||||||
return false unless head && head.downloader.is_a?(VCSDownloadStrategy)
|
return false unless head&.downloader.is_a?(VCSDownloadStrategy)
|
||||||
downloader = head.downloader
|
downloader = head.downloader
|
||||||
downloader.shutup! unless ARGV.verbose?
|
downloader.shutup! unless ARGV.verbose?
|
||||||
downloader.commit_outdated?(version.version.commit)
|
downloader.commit_outdated?(version.version.commit)
|
||||||
@ -1115,8 +1115,8 @@ class Formula
|
|||||||
|
|
||||||
# @private
|
# @private
|
||||||
def unlock
|
def unlock
|
||||||
@lock.unlock unless @lock.nil?
|
@lock&.unlock
|
||||||
@oldname_lock.unlock unless @oldname_lock.nil?
|
@oldname_lock&.unlock
|
||||||
end
|
end
|
||||||
|
|
||||||
def migration_needed?
|
def migration_needed?
|
||||||
@ -1182,7 +1182,8 @@ class Formula
|
|||||||
# Returns false if the formula wasn't installed with an alias.
|
# Returns false if the formula wasn't installed with an alias.
|
||||||
def installed_alias_target_changed?
|
def installed_alias_target_changed?
|
||||||
target = current_installed_alias_target
|
target = current_installed_alias_target
|
||||||
target && target.name != name
|
return false unless target
|
||||||
|
target.name != name
|
||||||
end
|
end
|
||||||
|
|
||||||
# Is this formula the target of an alias used to install an old formula?
|
# Is this formula the target of an alias used to install an old formula?
|
||||||
@ -1440,13 +1441,14 @@ class Formula
|
|||||||
# True if this formula is provided by Homebrew itself
|
# True if this formula is provided by Homebrew itself
|
||||||
# @private
|
# @private
|
||||||
def core_formula?
|
def core_formula?
|
||||||
tap && tap.core_tap?
|
tap&.core_tap?
|
||||||
end
|
end
|
||||||
|
|
||||||
# True if this formula is provided by external Tap
|
# True if this formula is provided by external Tap
|
||||||
# @private
|
# @private
|
||||||
def tap?
|
def tap?
|
||||||
tap && !tap.core_tap?
|
return false unless tap
|
||||||
|
!tap.core_tap?
|
||||||
end
|
end
|
||||||
|
|
||||||
# @private
|
# @private
|
||||||
@ -1525,10 +1527,10 @@ class Formula
|
|||||||
"oldname" => oldname,
|
"oldname" => oldname,
|
||||||
"aliases" => aliases,
|
"aliases" => aliases,
|
||||||
"versions" => {
|
"versions" => {
|
||||||
"stable" => (stable.version.to_s if stable),
|
"stable" => stable&.version.to_s,
|
||||||
"bottle" => bottle ? true : false,
|
"bottle" => bottle ? true : false,
|
||||||
"devel" => (devel.version.to_s if devel),
|
"devel" => devel&.version.to_s,
|
||||||
"head" => (head.version.to_s if head),
|
"head" => head&.version.to_s,
|
||||||
},
|
},
|
||||||
"revision" => revision,
|
"revision" => revision,
|
||||||
"version_scheme" => version_scheme,
|
"version_scheme" => version_scheme,
|
||||||
@ -1570,7 +1572,7 @@ class Formula
|
|||||||
"root_url" => bottle_spec.root_url,
|
"root_url" => bottle_spec.root_url,
|
||||||
}
|
}
|
||||||
bottle_info["files"] = {}
|
bottle_info["files"] = {}
|
||||||
bottle_spec.collector.keys.each do |os|
|
bottle_spec.collector.keys.each do |os| # rubocop:disable Performance/HashEachMethods
|
||||||
checksum = bottle_spec.collector[os]
|
checksum = bottle_spec.collector[os]
|
||||||
bottle_info["files"][os] = {
|
bottle_info["files"][os] = {
|
||||||
"url" => "#{bottle_spec.root_url}/#{Bottle::Filename.create(self, os, bottle_spec.rebuild)}",
|
"url" => "#{bottle_spec.root_url}/#{Bottle::Filename.create(self, os, bottle_spec.rebuild)}",
|
||||||
@ -1613,6 +1615,7 @@ class Formula
|
|||||||
def run_test
|
def run_test
|
||||||
@prefix_returns_versioned_prefix = true
|
@prefix_returns_versioned_prefix = true
|
||||||
old_home = ENV["HOME"]
|
old_home = ENV["HOME"]
|
||||||
|
old_java_opts = ENV["_JAVA_OPTIONS"]
|
||||||
old_curl_home = ENV["CURL_HOME"]
|
old_curl_home = ENV["CURL_HOME"]
|
||||||
old_tmpdir = ENV["TMPDIR"]
|
old_tmpdir = ENV["TMPDIR"]
|
||||||
old_temp = ENV["TEMP"]
|
old_temp = ENV["TEMP"]
|
||||||
@ -1626,6 +1629,7 @@ class Formula
|
|||||||
ENV["TERM"] = "dumb"
|
ENV["TERM"] = "dumb"
|
||||||
ENV["PATH"] = PATH.new(old_path).append(HOMEBREW_PREFIX/"bin")
|
ENV["PATH"] = PATH.new(old_path).append(HOMEBREW_PREFIX/"bin")
|
||||||
ENV["HOMEBREW_PATH"] = nil
|
ENV["HOMEBREW_PATH"] = nil
|
||||||
|
ENV["_JAVA_OPTIONS"] = "#{old_java_opts} -Duser.home=#{HOMEBREW_CACHE}/java_cache"
|
||||||
|
|
||||||
ENV.clear_sensitive_environment!
|
ENV.clear_sensitive_environment!
|
||||||
|
|
||||||
@ -1646,6 +1650,7 @@ class Formula
|
|||||||
ensure
|
ensure
|
||||||
@testpath = nil
|
@testpath = nil
|
||||||
ENV["HOME"] = old_home
|
ENV["HOME"] = old_home
|
||||||
|
ENV["_JAVA_OPTIONS"] = old_java_opts
|
||||||
ENV["CURL_HOME"] = old_curl_home
|
ENV["CURL_HOME"] = old_curl_home
|
||||||
ENV["TMPDIR"] = old_tmpdir
|
ENV["TMPDIR"] = old_tmpdir
|
||||||
ENV["TEMP"] = old_temp
|
ENV["TEMP"] = old_temp
|
||||||
@ -1888,11 +1893,13 @@ class Formula
|
|||||||
mkdir_p env_home
|
mkdir_p env_home
|
||||||
|
|
||||||
old_home = ENV["HOME"]
|
old_home = ENV["HOME"]
|
||||||
|
old_java_opts = ENV["_JAVA_OPTIONS"]
|
||||||
old_curl_home = ENV["CURL_HOME"]
|
old_curl_home = ENV["CURL_HOME"]
|
||||||
old_path = ENV["HOMEBREW_PATH"]
|
old_path = ENV["HOMEBREW_PATH"]
|
||||||
|
|
||||||
unless ARGV.interactive?
|
unless ARGV.interactive?
|
||||||
ENV["HOME"] = env_home
|
ENV["HOME"] = env_home
|
||||||
|
ENV["_JAVA_OPTIONS"] = "#{old_java_opts} -Duser.home=#{HOMEBREW_CACHE}/java_cache"
|
||||||
ENV["CURL_HOME"] = old_curl_home || old_home
|
ENV["CURL_HOME"] = old_curl_home || old_home
|
||||||
end
|
end
|
||||||
ENV["HOMEBREW_PATH"] = nil
|
ENV["HOMEBREW_PATH"] = nil
|
||||||
@ -1907,6 +1914,7 @@ class Formula
|
|||||||
@buildpath = nil
|
@buildpath = nil
|
||||||
unless ARGV.interactive?
|
unless ARGV.interactive?
|
||||||
ENV["HOME"] = old_home
|
ENV["HOME"] = old_home
|
||||||
|
ENV["_JAVA_OPTIONS"] = old_java_opts
|
||||||
ENV["CURL_HOME"] = old_curl_home
|
ENV["CURL_HOME"] = old_curl_home
|
||||||
end
|
end
|
||||||
ENV["HOMEBREW_PATH"] = old_path
|
ENV["HOMEBREW_PATH"] = old_path
|
||||||
|
|||||||
@ -85,13 +85,12 @@ class FormulaInstaller
|
|||||||
return false if @pour_failed
|
return false if @pour_failed
|
||||||
|
|
||||||
bottle = formula.bottle
|
bottle = formula.bottle
|
||||||
return false unless bottle
|
return false if !bottle && !formula.local_bottle_path
|
||||||
return true if force_bottle?
|
return true if force_bottle?
|
||||||
return false if build_from_source? || build_bottle? || interactive?
|
return false if build_from_source? || build_bottle? || interactive?
|
||||||
return false if ARGV.cc
|
return false if ARGV.cc
|
||||||
return false unless options.empty?
|
return false unless options.empty?
|
||||||
return false if formula.bottle_disabled?
|
return false if formula.bottle_disabled?
|
||||||
return true if formula.local_bottle_path
|
|
||||||
unless formula.pour_bottle?
|
unless formula.pour_bottle?
|
||||||
if install_bottle_options[:warn] && formula.pour_bottle_check_unsatisfied_reason
|
if install_bottle_options[:warn] && formula.pour_bottle_check_unsatisfied_reason
|
||||||
opoo <<-EOS.undent
|
opoo <<-EOS.undent
|
||||||
@ -270,7 +269,7 @@ class FormulaInstaller
|
|||||||
oh1 "Installing #{Formatter.identifier(formula.full_name)} #{options}".strip
|
oh1 "Installing #{Formatter.identifier(formula.full_name)} #{options}".strip
|
||||||
end
|
end
|
||||||
|
|
||||||
if formula.tap && !formula.tap.private?
|
unless formula.tap&.private?
|
||||||
action = "#{formula.full_name} #{options}".strip
|
action = "#{formula.full_name} #{options}".strip
|
||||||
Utils::Analytics.report_event("install", action)
|
Utils::Analytics.report_event("install", action)
|
||||||
|
|
||||||
@ -561,7 +560,7 @@ class FormulaInstaller
|
|||||||
end
|
end
|
||||||
raise
|
raise
|
||||||
else
|
else
|
||||||
ignore_interrupts { tmp_keg.rmtree if tmp_keg && tmp_keg.directory? }
|
ignore_interrupts { tmp_keg.rmtree if tmp_keg&.directory? }
|
||||||
end
|
end
|
||||||
|
|
||||||
def caveats
|
def caveats
|
||||||
@ -604,6 +603,12 @@ class FormulaInstaller
|
|||||||
|
|
||||||
# let's reset Utils.git_available? if we just installed git
|
# let's reset Utils.git_available? if we just installed git
|
||||||
Utils.clear_git_available_cache if formula.name == "git"
|
Utils.clear_git_available_cache if formula.name == "git"
|
||||||
|
|
||||||
|
# use installed curl when it's needed and available
|
||||||
|
if formula.name == "curl" &&
|
||||||
|
!DevelopmentTools.curl_handles_most_https_certificates?
|
||||||
|
ENV["HOMEBREW_CURL"] = formula.opt_bin/"curl"
|
||||||
|
end
|
||||||
ensure
|
ensure
|
||||||
unlock
|
unlock
|
||||||
end
|
end
|
||||||
|
|||||||
@ -45,11 +45,15 @@ module Homebrew
|
|||||||
@failed == true
|
@failed == true
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_writer :raise_deprecation_exceptions
|
attr_writer :raise_deprecation_exceptions, :auditing
|
||||||
|
|
||||||
def raise_deprecation_exceptions?
|
def raise_deprecation_exceptions?
|
||||||
@raise_deprecation_exceptions == true
|
@raise_deprecation_exceptions == true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def auditing?
|
||||||
|
@auditing == true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -7,8 +7,7 @@ class Gpg
|
|||||||
next unless gpg_short_version
|
next unless gpg_short_version
|
||||||
gpg_version = Version.create(gpg_short_version.to_s)
|
gpg_version = Version.create(gpg_short_version.to_s)
|
||||||
@version = gpg_version
|
@version = gpg_version
|
||||||
gpg_version == Version.create("2.1") ||
|
gpg_version >= Version.create("2.0")
|
||||||
gpg_version == Version.create("2.0")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -38,12 +37,30 @@ class Gpg
|
|||||||
Key-Length: 2048
|
Key-Length: 2048
|
||||||
Subkey-Type: RSA
|
Subkey-Type: RSA
|
||||||
Subkey-Length: 2048
|
Subkey-Length: 2048
|
||||||
Passphrase: ''
|
|
||||||
Name-Real: Testing
|
Name-Real: Testing
|
||||||
Name-Email: testing@foo.bar
|
Name-Email: testing@foo.bar
|
||||||
Expire-Date: 1d
|
Expire-Date: 1d
|
||||||
|
%no-protection
|
||||||
%commit
|
%commit
|
||||||
EOS
|
EOS
|
||||||
system GPG_EXECUTABLE, "--batch", "--gen-key", "batch.gpg"
|
system GPG_EXECUTABLE, "--batch", "--gen-key", "batch.gpg"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.cleanup_test_processes!
|
||||||
|
odie "No GPG present to test against!" unless available?
|
||||||
|
gpgconf = Pathname.new(GPG_EXECUTABLE).parent/"gpgconf"
|
||||||
|
|
||||||
|
system gpgconf, "--kill", "gpg-agent"
|
||||||
|
system gpgconf, "--homedir", "keyrings/live", "--kill",
|
||||||
|
"gpg-agent"
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.test(path)
|
||||||
|
create_test_key(path)
|
||||||
|
begin
|
||||||
|
yield
|
||||||
|
ensure
|
||||||
|
cleanup_test_processes!
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -16,12 +16,12 @@ module InstallRenamed
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def +(path)
|
def +(other)
|
||||||
super(path).extend(InstallRenamed)
|
super(other).extend(InstallRenamed)
|
||||||
end
|
end
|
||||||
|
|
||||||
def /(path)
|
def /(other)
|
||||||
super(path).extend(InstallRenamed)
|
super(other).extend(InstallRenamed)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|||||||
@ -338,7 +338,7 @@ class Keg
|
|||||||
dir if dir.directory? && dir.children.any? { |f| f.basename.to_s.start_with?("_") }
|
dir if dir.directory? && dir.children.any? { |f| f.basename.to_s.start_with?("_") }
|
||||||
when :fish then path/"share/fish/vendor_completions.d"
|
when :fish then path/"share/fish/vendor_completions.d"
|
||||||
end
|
end
|
||||||
dir && dir.directory? && !dir.children.empty?
|
dir&.directory? && !dir.children.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
def functions_installed?(shell)
|
def functions_installed?(shell)
|
||||||
|
|||||||
@ -156,7 +156,7 @@ class Keg
|
|||||||
libtool_files = []
|
libtool_files = []
|
||||||
|
|
||||||
path.find do |pn|
|
path.find do |pn|
|
||||||
next if pn.symlink? || pn.directory? || pn.extname != ".la"
|
next if pn.symlink? || pn.directory? || ![".la", ".lai"].include?(pn.extname)
|
||||||
libtool_files << pn
|
libtool_files << pn
|
||||||
end
|
end
|
||||||
libtool_files
|
libtool_files
|
||||||
|
|||||||
@ -23,7 +23,7 @@ module Language
|
|||||||
else
|
else
|
||||||
homebrew_site_packages(version)
|
homebrew_site_packages(version)
|
||||||
end
|
end
|
||||||
block.call python, version if block
|
block&.call python, version
|
||||||
end
|
end
|
||||||
ENV["PYTHONPATH"] = original_pythonpath
|
ENV["PYTHONPATH"] = original_pythonpath
|
||||||
end
|
end
|
||||||
|
|||||||
@ -44,8 +44,6 @@ class Locale
|
|||||||
raise ParserError, "'#{value}' does not match #{regex}" unless value =~ regex
|
raise ParserError, "'#{value}' does not match #{regex}" unless value =~ regex
|
||||||
instance_variable_set(:"@#{key}", value)
|
instance_variable_set(:"@#{key}", value)
|
||||||
end
|
end
|
||||||
|
|
||||||
self
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def include?(other)
|
def include?(other)
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
brew-cask(1) - a friendly binary installer for macOS
|
brew-cask(1) - a friendly binary installer for macOS
|
||||||
========================================================
|
====================================================
|
||||||
|
|
||||||
## SYNOPSIS
|
## SYNOPSIS
|
||||||
|
|
||||||
@ -101,9 +101,10 @@ names, and other aspects of this manual are still subject to change.
|
|||||||
Reinstall the given Cask.
|
Reinstall the given Cask.
|
||||||
|
|
||||||
* `search` or `-S` [<text> | /<regexp>/]:
|
* `search` or `-S` [<text> | /<regexp>/]:
|
||||||
Without an argument, display all Casks available for install; otherwise
|
Without an argument, display all locally available Casks for install; no
|
||||||
perform a substring search of known Cask tokens for <text> or, if the
|
online search is performed.
|
||||||
text is delimited by slashes (/<regexp>/), it is interpreted as a
|
Otherwise perform a substring search of known Cask tokens for <text> or,
|
||||||
|
if the text is delimited by slashes (/<regexp>/), it is interpreted as a
|
||||||
Ruby regular expression.
|
Ruby regular expression.
|
||||||
|
|
||||||
* `style` [--fix] [ <token> ... ]:
|
* `style` [--fix] [ <token> ... ]:
|
||||||
|
|||||||
@ -31,7 +31,7 @@ module Homebrew
|
|||||||
#{Formatter.url("https://pip.readthedocs.io/en/stable/installing/")}
|
#{Formatter.url("https://pip.readthedocs.io/en/stable/installing/")}
|
||||||
EOS
|
EOS
|
||||||
when "pil" then <<-EOS.undent
|
when "pil" then <<-EOS.undent
|
||||||
Instead of PIL, consider `pip install pillow` or `brew install Homebrew/science/pillow`.
|
Instead of PIL, consider `pip2 install pillow`.
|
||||||
EOS
|
EOS
|
||||||
when "macruby" then <<-EOS.undent
|
when "macruby" then <<-EOS.undent
|
||||||
MacRuby is not packaged and is on an indefinite development hiatus.
|
MacRuby is not packaged and is on an indefinite development hiatus.
|
||||||
@ -53,7 +53,7 @@ module Homebrew
|
|||||||
ruin SSH's security.
|
ruin SSH's security.
|
||||||
EOS
|
EOS
|
||||||
when "gsutil" then <<-EOS.undent
|
when "gsutil" then <<-EOS.undent
|
||||||
Install gsutil with `pip install gsutil`
|
Install gsutil with `pip2 install gsutil`
|
||||||
EOS
|
EOS
|
||||||
when "gfortran" then <<-EOS.undent
|
when "gfortran" then <<-EOS.undent
|
||||||
GNU Fortran is now provided as part of GCC, and can be installed with:
|
GNU Fortran is now provided as part of GCC, and can be installed with:
|
||||||
|
|||||||
@ -69,29 +69,29 @@ class Options
|
|||||||
@options.each(*args, &block)
|
@options.each(*args, &block)
|
||||||
end
|
end
|
||||||
|
|
||||||
def <<(o)
|
def <<(other)
|
||||||
@options << o
|
@options << other
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
def +(o)
|
def +(other)
|
||||||
self.class.new(@options + o)
|
self.class.new(@options + other)
|
||||||
end
|
end
|
||||||
|
|
||||||
def -(o)
|
def -(other)
|
||||||
self.class.new(@options - o)
|
self.class.new(@options - other)
|
||||||
end
|
end
|
||||||
|
|
||||||
def &(o)
|
def &(other)
|
||||||
self.class.new(@options & o)
|
self.class.new(@options & other)
|
||||||
end
|
end
|
||||||
|
|
||||||
def |(o)
|
def |(other)
|
||||||
self.class.new(@options | o)
|
self.class.new(@options | other)
|
||||||
end
|
end
|
||||||
|
|
||||||
def *(arg)
|
def *(other)
|
||||||
@options.to_a * arg
|
@options.to_a * other
|
||||||
end
|
end
|
||||||
|
|
||||||
def empty?
|
def empty?
|
||||||
|
|||||||
@ -11,7 +11,7 @@ module OS
|
|||||||
module Mac
|
module Mac
|
||||||
module_function
|
module_function
|
||||||
|
|
||||||
::MacOS = self # rubocop:disable Style/ConstantName
|
::MacOS = self # rubocop:disable Naming/ConstantName
|
||||||
|
|
||||||
raise "Loaded OS::Mac on generic OS!" if ENV["HOMEBREW_TEST_GENERIC_OS"]
|
raise "Loaded OS::Mac on generic OS!" if ENV["HOMEBREW_TEST_GENERIC_OS"]
|
||||||
|
|
||||||
@ -34,12 +34,12 @@ module OS
|
|||||||
|
|
||||||
def prerelease?
|
def prerelease?
|
||||||
# TODO: bump version when new OS is released
|
# TODO: bump version when new OS is released
|
||||||
version >= "10.13"
|
version >= "10.14"
|
||||||
end
|
end
|
||||||
|
|
||||||
def outdated_release?
|
def outdated_release?
|
||||||
# TODO: bump version when new OS is released
|
# TODO: bump version when new OS is released
|
||||||
version < "10.10"
|
version < "10.11"
|
||||||
end
|
end
|
||||||
|
|
||||||
def cat
|
def cat
|
||||||
@ -104,7 +104,7 @@ module OS
|
|||||||
# Returns the path to an SDK or nil, following the rules set by #sdk.
|
# Returns the path to an SDK or nil, following the rules set by #sdk.
|
||||||
def sdk_path(v = nil)
|
def sdk_path(v = nil)
|
||||||
s = sdk(v)
|
s = sdk(v)
|
||||||
s.path unless s.nil?
|
s&.path
|
||||||
end
|
end
|
||||||
|
|
||||||
# See these issues for some history:
|
# See these issues for some history:
|
||||||
@ -129,8 +129,8 @@ module OS
|
|||||||
paths << path if path.exist?
|
paths << path if path.exist?
|
||||||
end
|
end
|
||||||
|
|
||||||
# Finally, some users make their MacPorts or Fink directorie
|
# Finally, some users make their MacPorts or Fink directories
|
||||||
# read-only in order to try out Homebrew, but this doens't work as
|
# read-only in order to try out Homebrew, but this doesn't work as
|
||||||
# some build scripts error out when trying to read from these now
|
# some build scripts error out when trying to read from these now
|
||||||
# unreadable paths.
|
# unreadable paths.
|
||||||
%w[/sw /opt/local].map { |p| Pathname.new(p) }.each do |path|
|
%w[/sw /opt/local].map { |p| Pathname.new(p) }.each do |path|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ require "formula"
|
|||||||
class LinkageChecker
|
class LinkageChecker
|
||||||
attr_reader :keg, :formula
|
attr_reader :keg, :formula
|
||||||
attr_reader :brewed_dylibs, :system_dylibs, :broken_dylibs, :variable_dylibs
|
attr_reader :brewed_dylibs, :system_dylibs, :broken_dylibs, :variable_dylibs
|
||||||
attr_reader :undeclared_deps, :reverse_links
|
attr_reader :undeclared_deps, :unnecessary_deps, :reverse_links
|
||||||
|
|
||||||
def initialize(keg, formula = nil)
|
def initialize(keg, formula = nil)
|
||||||
@keg = keg
|
@keg = keg
|
||||||
@ -16,6 +16,7 @@ class LinkageChecker
|
|||||||
@variable_dylibs = Set.new
|
@variable_dylibs = Set.new
|
||||||
@undeclared_deps = []
|
@undeclared_deps = []
|
||||||
@reverse_links = Hash.new { |h, k| h[k] = Set.new }
|
@reverse_links = Hash.new { |h, k| h[k] = Set.new }
|
||||||
|
@unnecessary_deps = []
|
||||||
check_dylibs
|
check_dylibs
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -51,7 +52,7 @@ class LinkageChecker
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@undeclared_deps = check_undeclared_deps if formula
|
@undeclared_deps, @unnecessary_deps = check_undeclared_deps if formula
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_undeclared_deps
|
def check_undeclared_deps
|
||||||
@ -77,6 +78,12 @@ class LinkageChecker
|
|||||||
a <=> b
|
a <=> b
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
unnecessary_deps = declared_dep_names.reject do |full_name|
|
||||||
|
name = full_name.split("/").last
|
||||||
|
next true if Formula[name].bin.directory?
|
||||||
|
@brewed_dylibs.keys.map { |x| x.split("/").last }.include?(name)
|
||||||
|
end
|
||||||
|
[undeclared_deps, unnecessary_deps]
|
||||||
end
|
end
|
||||||
|
|
||||||
def display_normal_output
|
def display_normal_output
|
||||||
@ -84,7 +91,8 @@ class LinkageChecker
|
|||||||
display_items "Homebrew libraries", @brewed_dylibs
|
display_items "Homebrew libraries", @brewed_dylibs
|
||||||
display_items "Variable-referenced libraries", @variable_dylibs
|
display_items "Variable-referenced libraries", @variable_dylibs
|
||||||
display_items "Missing libraries", @broken_dylibs
|
display_items "Missing libraries", @broken_dylibs
|
||||||
display_items "Possible undeclared dependencies", @undeclared_deps
|
display_items "Undeclared dependencies with linkage", @undeclared_deps
|
||||||
|
display_items "Dependencies with no linkage", @unnecessary_deps
|
||||||
end
|
end
|
||||||
|
|
||||||
def display_reverse_output
|
def display_reverse_output
|
||||||
@ -102,6 +110,7 @@ class LinkageChecker
|
|||||||
|
|
||||||
def display_test_output
|
def display_test_output
|
||||||
display_items "Missing libraries", @broken_dylibs
|
display_items "Missing libraries", @broken_dylibs
|
||||||
|
display_items "Possible unnecessary dependencies", @unnecessary_deps
|
||||||
puts "No broken dylib links" if @broken_dylibs.empty?
|
puts "No broken dylib links" if @broken_dylibs.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -113,6 +122,10 @@ class LinkageChecker
|
|||||||
!@undeclared_deps.empty?
|
!@undeclared_deps.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def unnecessary_deps?
|
||||||
|
!@unnecessary_deps.empty?
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# Whether or not dylib is a harmless broken link, meaning that it's
|
# Whether or not dylib is a harmless broken link, meaning that it's
|
||||||
|
|||||||
@ -12,6 +12,7 @@ module OS
|
|||||||
mountain_lion: "10.8",
|
mountain_lion: "10.8",
|
||||||
lion: "10.7",
|
lion: "10.7",
|
||||||
snow_leopard: "10.6",
|
snow_leopard: "10.6",
|
||||||
|
leopard_64: "10.5",
|
||||||
leopard: "10.5",
|
leopard: "10.5",
|
||||||
tiger: "10.4",
|
tiger: "10.4",
|
||||||
}.freeze
|
}.freeze
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user