aboutsummaryrefslogtreecommitdiffstats
path: root/Library
diff options
context:
space:
mode:
Diffstat (limited to 'Library')
-rw-r--r--Library/Homebrew/blacklist.rb10
-rw-r--r--Library/Homebrew/brew.rb18
-rw-r--r--Library/Homebrew/brew.sh10
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/moved.rb7
-rw-r--r--Library/Homebrew/cask/lib/hbc/artifact/symlinked.rb15
-rw-r--r--Library/Homebrew/cask/lib/hbc/auditor.rb17
-rw-r--r--Library/Homebrew/cask/lib/hbc/cask.rb5
-rw-r--r--Library/Homebrew/cask/lib/hbc/checkable.rb10
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli.rb4
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/doctor.rb4
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/info.rb10
-rw-r--r--Library/Homebrew/cask/lib/hbc/cli/style.rb2
-rw-r--r--Library/Homebrew/cask/lib/hbc/dsl.rb39
-rw-r--r--Library/Homebrew/cask/lib/hbc/dsl/base.rb2
-rw-r--r--Library/Homebrew/cask/lib/hbc/dsl/caveats.rb6
-rw-r--r--Library/Homebrew/cask/lib/hbc/installer.rb2
-rw-r--r--Library/Homebrew/cask/lib/hbc/utils.rb15
-rw-r--r--Library/Homebrew/cask/spec/locale_spec.rb72
-rw-r--r--Library/Homebrew/cask/test/cask/dsl_test.rb50
-rw-r--r--Library/Homebrew/cmd/doctor.rb6
-rw-r--r--Library/Homebrew/cmd/help.rb11
-rw-r--r--Library/Homebrew/cmd/info.rb4
-rw-r--r--Library/Homebrew/cmd/install.rb10
-rw-r--r--Library/Homebrew/cmd/list.rb6
-rw-r--r--Library/Homebrew/cmd/update-report.rb5
-rw-r--r--Library/Homebrew/compat.rb1
-rw-r--r--Library/Homebrew/compat/utils.rb8
-rw-r--r--Library/Homebrew/debrew.rb2
-rw-r--r--Library/Homebrew/descriptions.rb4
-rw-r--r--Library/Homebrew/dev-cmd/bottle.rb6
-rw-r--r--Library/Homebrew/dev-cmd/tests.rb2
-rw-r--r--Library/Homebrew/dev-cmd/update-test.rb13
-rw-r--r--Library/Homebrew/diagnostic.rb20
-rw-r--r--Library/Homebrew/exceptions.rb15
-rw-r--r--Library/Homebrew/extend/os/mac/diagnostic.rb11
-rw-r--r--Library/Homebrew/formula_installer.rb6
-rw-r--r--Library/Homebrew/language/python.rb28
-rw-r--r--Library/Homebrew/locale.rb68
-rw-r--r--Library/Homebrew/manpages/brew.1.md.erb18
-rw-r--r--Library/Homebrew/migrator.rb6
-rw-r--r--Library/Homebrew/os/mac.rb18
-rw-r--r--Library/Homebrew/requirements.rb2
-rw-r--r--Library/Homebrew/test/test_diagnostic.rb2
-rw-r--r--Library/Homebrew/test/test_os_mac_language.rb10
-rw-r--r--Library/Homebrew/test/test_utils.rb36
-rw-r--r--Library/Homebrew/utils.rb97
-rw-r--r--Library/Homebrew/utils/formatter.rb52
-rw-r--r--Library/Homebrew/utils/github.rb10
-rw-r--r--Library/Homebrew/utils/tty.rb64
49 files changed, 617 insertions, 222 deletions
diff --git a/Library/Homebrew/blacklist.rb b/Library/Homebrew/blacklist.rb
index 4312d0bf3..1c79da159 100644
--- a/Library/Homebrew/blacklist.rb
+++ b/Library/Homebrew/blacklist.rb
@@ -16,7 +16,7 @@ def blacklisted?(name)
Homebrew provides pip via: `brew install python`. However you will then
have two Pythons installed on your Mac, so alternatively you can install
pip via the instructions at:
- https://pip.readthedocs.io/en/stable/installing/
+ #{Formatter.url("https://pip.readthedocs.io/en/stable/installing/")}
EOS
when "pil" then <<-EOS.undent
Instead of PIL, consider `pip install pillow` or `brew install Homebrew/python/pillow`.
@@ -24,7 +24,7 @@ def blacklisted?(name)
when "macruby" then <<-EOS.undent
MacRuby is not packaged and is on an indefinite development hiatus.
You can read more about it at:
- https://github.com/MacRuby/MacRuby
+ #{Formatter.url("https://github.com/MacRuby/MacRuby")}
EOS
when /(lib)?lzma/
"lzma is now part of the xz formula."
@@ -50,7 +50,7 @@ def blacklisted?(name)
To install Clojure you should install Leiningen:
brew install leiningen
and then follow the tutorial:
- https://github.com/technomancy/leiningen/blob/stable/doc/TUTORIAL.md
+ #{Formatter.url("https://github.com/technomancy/leiningen/blob/stable/doc/TUTORIAL.md")}
EOS
when "osmium" then <<-EOS.undent
The creator of Osmium requests that it not be packaged and that people
@@ -65,8 +65,8 @@ def blacklisted?(name)
brew install typesafe-activator
You can read more about this change at:
- https://www.playframework.com/documentation/2.3.x/Migration23
- https://www.playframework.com/documentation/2.3.x/Highlights23
+ #{Formatter.url("https://www.playframework.com/documentation/2.3.x/Migration23")}
+ #{Formatter.url("https://www.playframework.com/documentation/2.3.x/Highlights23")}
EOS
when "haskell-platform" then <<-EOS.undent
We no longer package haskell-platform. Consider installing ghc
diff --git a/Library/Homebrew/brew.rb b/Library/Homebrew/brew.rb
index 1ba3fb8c2..4ab360995 100644
--- a/Library/Homebrew/brew.rb
+++ b/Library/Homebrew/brew.rb
@@ -32,20 +32,17 @@ begin
empty_argv = ARGV.empty?
help_flag_list = %w[-h --help --usage -?]
- help_flag = false
+ help_flag = !ENV["HOMEBREW_HELP"].nil?
internal_cmd = true
cmd = nil
ARGV.dup.each_with_index do |arg, i|
break if help_flag && cmd
- if help_flag_list.include?(arg)
- # Option-style help: Both `--help <cmd>` and `<cmd> --help` are fine.
- help_flag = true
- elsif arg == "help" && !cmd
+ if arg == "help" && !cmd
# Command-style help: `help <cmd>` is fine, but `<cmd> help` is not.
help_flag = true
- elsif !cmd
+ elsif !cmd && !help_flag_list.include?(arg)
cmd = ARGV.delete_at(i)
end
end
@@ -75,12 +72,9 @@ begin
end
# Usage instructions should be displayed if and only if one of:
- # - a help flag is passed AND an internal command is matched
+ # - a help flag is passed AND a command is matched
# - a help flag is passed AND there is no command specified
# - no arguments are passed
- #
- # It should never affect external commands so they can handle usage
- # arguments themselves.
if empty_argv || help_flag
require "cmd/help"
Homebrew.help cmd, empty_argv: empty_argv
@@ -147,8 +141,8 @@ rescue Exception => e
Utils::Analytics.report_exception(e)
onoe e
if internal_cmd && defined?(OS::ISSUES_URL)
- $stderr.puts "#{Tty.white}Please report this bug:"
- $stderr.puts " #{Tty.em}#{OS::ISSUES_URL}#{Tty.reset}"
+ $stderr.puts "#{Tty.bold}Please report this bug:#{Tty.reset}"
+ $stderr.puts " #{Formatter.url(OS::ISSUES_URL)}"
end
$stderr.puts e.backtrace
exit 1
diff --git a/Library/Homebrew/brew.sh b/Library/Homebrew/brew.sh
index 1ccd8832a..8ffee44b3 100644
--- a/Library/Homebrew/brew.sh
+++ b/Library/Homebrew/brew.sh
@@ -183,6 +183,15 @@ then
set -- "$@" -v
fi
+for arg in "$@"
+do
+ if [[ $arg = "--help" || $arg = "-h" || $arg = "--usage" || $arg = "-?" ]]
+ then
+ export HOMEBREW_HELP="1"
+ break
+ fi
+done
+
HOMEBREW_ARG_COUNT="$#"
HOMEBREW_COMMAND="$1"
shift
@@ -272,6 +281,7 @@ setup-analytics
report-analytics-screenview-command
update-preinstall() {
+ [[ -z "$HOMEBREW_HELP" ]] || return
[[ -z "$HOMEBREW_NO_AUTO_UPDATE" ]] || return
[[ -z "$HOMEBREW_UPDATE_PREINSTALL" ]] || return
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/moved.rb b/Library/Homebrew/cask/lib/hbc/artifact/moved.rb
index 6095887e3..22124005c 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/moved.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/moved.rb
@@ -79,13 +79,10 @@ module Hbc
load_specification artifact_spec
if target.exist?
- target_abv = " (#{target.abv})"
+ "#{printable_target} (#{target.abv})"
else
- warning = "Missing #{self.class.artifact_english_name}"
- warning = "#{Tty.red}#{warning}#{Tty.reset}: "
+ Formatter.error(printable_target, label: "Missing #{self.class.artifact_english_name}")
end
-
- "#{warning}#{printable_target}#{target_abv}"
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/artifact/symlinked.rb b/Library/Homebrew/cask/lib/hbc/artifact/symlinked.rb
index 3ab45cccc..46dd42322 100644
--- a/Library/Homebrew/cask/lib/hbc/artifact/symlinked.rb
+++ b/Library/Homebrew/cask/lib/hbc/artifact/symlinked.rb
@@ -57,12 +57,17 @@ module Hbc
def summarize_artifact(artifact_spec)
load_specification artifact_spec
- return unless self.class.islink?(target)
-
- link_description = "#{Tty.red}Broken Link#{Tty.reset}: " unless target.exist?
- target_readlink_abv = " (#{target.readlink.abv})" if target.readlink.exist?
+ if self.class.islink?(target) && target.exist? && target.readlink.exist?
+ "#{printable_target} -> #{target.readlink} (#{target.readlink.abv})"
+ else
+ string = if self.class.islink?(target)
+ "#{printable_target} -> #{target.readlink}"
+ else
+ printable_target
+ end
- "#{link_description}#{printable_target} -> #{target.readlink}#{target_readlink_abv}"
+ Formatter.error(string, label: "Broken Link")
+ end
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/auditor.rb b/Library/Homebrew/cask/lib/hbc/auditor.rb
index 6b0c1c476..ee1b50938 100644
--- a/Library/Homebrew/cask/lib/hbc/auditor.rb
+++ b/Library/Homebrew/cask/lib/hbc/auditor.rb
@@ -1,6 +1,23 @@
module Hbc
class Auditor
def self.audit(cask, audit_download: false, check_token_conflicts: false)
+ saved_languages = MacOS.instance_variable_get(:@languages)
+
+ if languages_blocks = cask.instance_variable_get(:@dsl).instance_variable_get(:@language_blocks)
+ languages_blocks.keys.each do |languages|
+ ohai "Auditing language: #{languages.map { |lang| "'#{lang}'" }.join(", ")}"
+ MacOS.instance_variable_set(:@languages, languages)
+ audit_cask_instance(Hbc.load(cask.sourcefile_path), audit_download, check_token_conflicts)
+ CLI::Cleanup.run(cask.token) if audit_download
+ end
+ else
+ audit_cask_instance(cask, audit_download, check_token_conflicts)
+ end
+ ensure
+ MacOS.instance_variable_set(:@languages, saved_languages)
+ end
+
+ def self.audit_cask_instance(cask, audit_download, check_token_conflicts)
download = audit_download && Download.new(cask)
audit = Audit.new(cask, download: download,
check_token_conflicts: check_token_conflicts)
diff --git a/Library/Homebrew/cask/lib/hbc/cask.rb b/Library/Homebrew/cask/lib/hbc/cask.rb
index 756b05b83..1e2056efc 100644
--- a/Library/Homebrew/cask/lib/hbc/cask.rb
+++ b/Library/Homebrew/cask/lib/hbc/cask.rb
@@ -11,7 +11,10 @@ module Hbc
@token = token
@sourcefile_path = sourcefile_path
@dsl = dsl || DSL.new(@token)
- @dsl.instance_eval(&block) if block_given?
+ if block_given?
+ @dsl.instance_eval(&block)
+ @dsl.language_eval
+ end
end
DSL::DSL_METHODS.each do |method_name|
diff --git a/Library/Homebrew/cask/lib/hbc/checkable.rb b/Library/Homebrew/cask/lib/hbc/checkable.rb
index 42c47ea78..03f052629 100644
--- a/Library/Homebrew/cask/lib/hbc/checkable.rb
+++ b/Library/Homebrew/cask/lib/hbc/checkable.rb
@@ -28,11 +28,11 @@ module Hbc
def result
if errors?
- "#{Tty.red}failed#{Tty.reset}"
+ Formatter.error("failed")
elsif warnings?
- "#{Tty.yellow}warning#{Tty.reset}"
+ Formatter.warning("warning")
else
- "#{Tty.green}passed#{Tty.reset}"
+ Formatter.success("passed")
end
end
@@ -40,11 +40,11 @@ module Hbc
summary = ["#{summary_header}: #{result}"]
errors.each do |error|
- summary << " #{Tty.red}-#{Tty.reset} #{error}"
+ summary << " #{Formatter.error("-")} #{error}"
end
warnings.each do |warning|
- summary << " #{Tty.yellow}-#{Tty.reset} #{warning}"
+ summary << " #{Formatter.warning("-")} #{warning}"
end
summary.join("\n")
diff --git a/Library/Homebrew/cask/lib/hbc/cli.rb b/Library/Homebrew/cask/lib/hbc/cli.rb
index 3f67e131d..f637ae7af 100644
--- a/Library/Homebrew/cask/lib/hbc/cli.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli.rb
@@ -179,6 +179,10 @@ module Hbc
def self.parser
# If you modify these arguments, please update USAGE.md
@parser ||= OptionParser.new do |opts|
+ opts.on("--language STRING") do
+ # handled in OS::Mac
+ end
+
OPTIONS.each do |option, method|
opts.on("#{option}" "PATH", Pathname) do |path|
Hbc.public_send(method, path)
diff --git a/Library/Homebrew/cask/lib/hbc/cli/doctor.rb b/Library/Homebrew/cask/lib/hbc/cli/doctor.rb
index 34f000b29..e36999200 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/doctor.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/doctor.rb
@@ -122,11 +122,11 @@ module Hbc
end
def self.notfound_string
- "#{Tty.red}Not Found - Unknown Error#{Tty.reset}"
+ Formatter.error("Not Found - Unknown Error")
end
def self.error_string(string = "Error")
- "#{Tty.red}(#{string})#{Tty.reset}"
+ Formatter.error("(#{string})")
end
def self.render_with_none(string)
diff --git a/Library/Homebrew/cask/lib/hbc/cli/info.rb b/Library/Homebrew/cask/lib/hbc/cli/info.rb
index 7fbdff3eb..0957ba4fd 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/info.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/info.rb
@@ -18,16 +18,16 @@ module Hbc
def self.info(cask)
puts "#{cask.token}: #{cask.version}"
- puts formatted_url(cask.homepage) if cask.homepage
+ puts Formatter.url(cask.homepage) if cask.homepage
installation_info(cask)
- puts "From: #{formatted_url(github_info(cask))}" if github_info(cask)
+ puts "From: #{Formatter.url(github_info(cask))}" if github_info(cask)
name_info(cask)
artifact_info(cask)
Installer.print_caveats(cask)
end
def self.formatted_url(url)
- "#{Tty.em}#{url}#{Tty.reset}"
+ "#{Tty.underline}#{url}#{Tty.reset}"
end
def self.installation_info(cask)
@@ -37,7 +37,7 @@ module Hbc
puts versioned_staged_path.to_s
.concat(" (")
- .concat(versioned_staged_path.exist? ? versioned_staged_path.abv : "#{Tty.red}does not exist#{Tty.reset}")
+ .concat(versioned_staged_path.exist? ? versioned_staged_path.abv : Formatter.error("does not exist"))
.concat(")")
end
else
@@ -47,7 +47,7 @@ module Hbc
def self.name_info(cask)
ohai cask.name.size > 1 ? "Names" : "Name"
- puts cask.name.empty? ? "#{Tty.red}None#{Tty.reset}" : cask.name
+ puts cask.name.empty? ? Formatter.error("None") : cask.name
end
def self.github_info(cask)
diff --git a/Library/Homebrew/cask/lib/hbc/cli/style.rb b/Library/Homebrew/cask/lib/hbc/cli/style.rb
index 66117da8b..bb179fb0c 100644
--- a/Library/Homebrew/cask/lib/hbc/cli/style.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli/style.rb
@@ -30,7 +30,7 @@ module Hbc
begin
Homebrew.install_gem_setup_path! "rubocop-cask", RUBOCOP_CASK_VERSION, "rubocop"
rescue SystemExit
- raise CaskError, $stderr.string.chomp.sub("#{Tty.red}Error#{Tty.reset}: ", "")
+ raise CaskError, Tty.strip_ansi($stderr.string).chomp.sub(/\AError: /, "")
end
end
end
diff --git a/Library/Homebrew/cask/lib/hbc/dsl.rb b/Library/Homebrew/cask/lib/hbc/dsl.rb
index 83c0bf1fb..8e0a7715a 100644
--- a/Library/Homebrew/cask/lib/hbc/dsl.rb
+++ b/Library/Homebrew/cask/lib/hbc/dsl.rb
@@ -1,4 +1,5 @@
require "set"
+require "locale"
require "hbc/dsl/appcast"
require "hbc/dsl/base"
@@ -64,6 +65,7 @@ module Hbc
:depends_on,
:gpg,
:homepage,
+ :language,
:license,
:name,
:sha256,
@@ -98,6 +100,43 @@ module Hbc
@homepage ||= homepage
end
+ def language(*args, default: false, &block)
+ if !args.empty? && block_given?
+ @language_blocks ||= {}
+ @language_blocks[args] = block
+
+ return unless default
+
+ unless @language_blocks.default.nil?
+ raise CaskInvalidError.new(token, "Only one default language may be defined")
+ end
+
+ @language_blocks.default = block
+ else
+ language_eval
+ end
+ end
+
+ def language_eval
+ return @language if instance_variable_defined?(:@language)
+
+ if @language_blocks.nil? || @language_blocks.empty?
+ return @language = nil
+ end
+
+ MacOS.languages.map(&Locale.method(:parse)).each do |locale|
+ key = @language_blocks.keys.detect { |strings|
+ strings.any? { |string| locale.include?(string) }
+ }
+
+ next if key.nil?
+
+ return @language = @language_blocks[key].call
+ end
+
+ @language = @language_blocks.default.call
+ end
+
def url(*args, &block)
url_given = !args.empty? || block_given?
return @url unless url_given
diff --git a/Library/Homebrew/cask/lib/hbc/dsl/base.rb b/Library/Homebrew/cask/lib/hbc/dsl/base.rb
index ccf93dae9..20a3cec61 100644
--- a/Library/Homebrew/cask/lib/hbc/dsl/base.rb
+++ b/Library/Homebrew/cask/lib/hbc/dsl/base.rb
@@ -8,7 +8,7 @@ module Hbc
@command = command
end
- def_delegators :@cask, :token, :version, :caskroom_path, :staged_path, :appdir
+ def_delegators :@cask, :token, :version, :caskroom_path, :staged_path, :appdir, :language
def system_command(executable, options = {})
@command.run!(executable, options)
diff --git a/Library/Homebrew/cask/lib/hbc/dsl/caveats.rb b/Library/Homebrew/cask/lib/hbc/dsl/caveats.rb
index 5efd7d562..9dd9abab1 100644
--- a/Library/Homebrew/cask/lib/hbc/dsl/caveats.rb
+++ b/Library/Homebrew/cask/lib/hbc/dsl/caveats.rb
@@ -102,12 +102,12 @@ module Hbc
A report has been made to Apple about this app. Their certificate will hopefully be revoked.
See the public report at
- https://openradar.appspot.com/#{radar_number}
+ #{Formatter.url("https://openradar.appspot.com/#{radar_number}")}
If this report is accurate, please duplicate it at
- https://bugreport.apple.com/
+ #{Formatter.url("https://bugreport.apple.com/")}
If this report is a mistake, please let us know by opening an issue at
- https://github.com/caskroom/homebrew-cask/issues/new
+ #{Formatter.url("https://github.com/caskroom/homebrew-cask/issues/new")}
EOS
end
diff --git a/Library/Homebrew/cask/lib/hbc/installer.rb b/Library/Homebrew/cask/lib/hbc/installer.rb
index f0cc0d1a9..4d29acb75 100644
--- a/Library/Homebrew/cask/lib/hbc/installer.rb
+++ b/Library/Homebrew/cask/lib/hbc/installer.rb
@@ -87,7 +87,7 @@ module Hbc
s = if MacOS.version >= :lion && !ENV["HOMEBREW_NO_EMOJI"]
(ENV["HOMEBREW_INSTALL_BADGE"] || "\xf0\x9f\x8d\xba") + " "
else
- "#{Tty.blue}==>#{Tty.reset} #{Tty.white}Success!#{Tty.reset} "
+ Formatter.headline("Success! ", color: :blue)
end
s << "#{@cask} was successfully installed!"
end
diff --git a/Library/Homebrew/cask/lib/hbc/utils.rb b/Library/Homebrew/cask/lib/hbc/utils.rb
index 9159544a6..d42d78ef7 100644
--- a/Library/Homebrew/cask/lib/hbc/utils.rb
+++ b/Library/Homebrew/cask/lib/hbc/utils.rb
@@ -32,12 +32,7 @@ end
def odebug(title, *sput)
return unless Hbc.respond_to?(:debug)
return unless Hbc.debug
-
- width = Tty.width * 4 - 6
- if $stdout.tty? && title.to_s.length > width
- title = title.to_s[0, width - 3] + "..."
- end
- puts "#{Tty.magenta}==>#{Tty.reset} #{Tty.white}#{title}#{Tty.reset}"
+ puts Formatter.headline(title, color: :magenta)
puts sput unless sput.empty?
end
@@ -151,12 +146,10 @@ module Hbc
def self.error_message_with_suggestions
<<-EOS.undent
Most likely, this means you have an outdated version of Homebrew-Cask. Please run:
+ #{UPDATE_CMD}
- #{Tty.green}#{UPDATE_CMD}
-
- #{Tty.reset}If this doesn’t fix the problem, please report this bug:
-
- #{Tty.em}#{ISSUES_URL}#{Tty.reset}
+ If this doesn’t fix the problem, please report this bug:
+ #{Formatter.url(ISSUES_URL)}
EOS
end
diff --git a/Library/Homebrew/cask/spec/locale_spec.rb b/Library/Homebrew/cask/spec/locale_spec.rb
new file mode 100644
index 000000000..98a2de913
--- /dev/null
+++ b/Library/Homebrew/cask/spec/locale_spec.rb
@@ -0,0 +1,72 @@
+require "spec_helper"
+require "locale"
+
+describe Locale do
+ describe "::parse" do
+ it "parses a string in the correct format" do
+ expect(described_class.parse("zh")).to eql(described_class.new("zh", nil, nil))
+ expect(described_class.parse("zh-CN")).to eql(described_class.new("zh", "CN", nil))
+ expect(described_class.parse("zh-Hans")).to eql(described_class.new("zh", nil, "Hans"))
+ expect(described_class.parse("zh-CN-Hans")).to eql(described_class.new("zh", "CN", "Hans"))
+ end
+
+ context "raises a ParserError when given" do
+ it "an empty string" do
+ expect{ described_class.parse("") }.to raise_error(Locale::ParserError)
+ end
+
+ it "a string in a wrong format" do
+ expect { described_class.parse("zh_CN_Hans") }.to raise_error(Locale::ParserError)
+ expect { described_class.parse("zhCNHans") }.to raise_error(Locale::ParserError)
+ expect { described_class.parse("zh-CN_Hans") }.to raise_error(Locale::ParserError)
+ expect { described_class.parse("zhCN") }.to raise_error(Locale::ParserError)
+ expect { described_class.parse("zh_Hans") }.to raise_error(Locale::ParserError)
+ end
+ end
+ end
+
+ describe "::new" do
+ it "raises an ArgumentError when all arguments are nil" do
+ expect { described_class.new(nil, nil, nil) }.to raise_error(ArgumentError)
+ end
+
+ it "raises a ParserError when one of the arguments does not match the locale format" do
+ expect { described_class.new("ZH", nil, nil) }.to raise_error(Locale::ParserError)
+ expect { described_class.new(nil, "cn", nil) }.to raise_error(Locale::ParserError)
+ expect { described_class.new(nil, nil, "hans") }.to raise_error(Locale::ParserError)
+ end
+ end
+
+ subject { described_class.new("zh", "CN", "Hans") }
+
+ describe "#include?" do
+ it { is_expected.to include("zh") }
+ it { is_expected.to include("zh-CN") }
+ it { is_expected.to include("CN") }
+ it { is_expected.to include("CN-Hans") }
+ it { is_expected.to include("Hans") }
+ it { is_expected.to include("zh-CN-Hans") }
+ end
+
+ describe "#eql?" do
+ subject { described_class.new("zh", "CN", "Hans") }
+
+ context "all parts match" do
+ it { is_expected.to eql("zh-CN-Hans") }
+ it { is_expected.to eql(subject) }
+ end
+
+ context "only some parts match" do
+ it { is_expected.to_not eql("zh") }
+ it { is_expected.to_not eql("zh-CN") }
+ it { is_expected.to_not eql("CN") }
+ it { is_expected.to_not eql("CN-Hans") }
+ it { is_expected.to_not eql("Hans") }
+ end
+
+ it "does not raise if 'other' cannot be parsed" do
+ expect { subject.eql?("zh_CN_Hans") }.not_to raise_error
+ expect(subject.eql?("zh_CN_Hans")).to be false
+ end
+ end
+end
diff --git a/Library/Homebrew/cask/test/cask/dsl_test.rb b/Library/Homebrew/cask/test/cask/dsl_test.rb
index ccf2f1a24..053eae1e1 100644
--- a/Library/Homebrew/cask/test/cask/dsl_test.rb
+++ b/Library/Homebrew/cask/test/cask/dsl_test.rb
@@ -122,6 +122,56 @@ describe Hbc::DSL do
end
end
+ describe "language stanza" do
+ it "allows multilingual casks" do
+ cask = lambda do
+ Hbc::Cask.new("cask-with-apps") do
+ language "zh" do
+ sha256 "abc123"
+ "zh-CN"
+ end
+
+ language "en-US", default: true do
+ sha256 "xyz789"
+ "en-US"
+ end
+
+ url "https://example.org/#{language}.zip"
+ end
+ end
+
+ MacOS.stubs(languages: ["zh"])
+ cask.call.language.must_equal "zh-CN"
+ cask.call.sha256.must_equal "abc123"
+ cask.call.url.to_s.must_equal "https://example.org/zh-CN.zip"
+
+ MacOS.stubs(languages: ["zh-XX"])
+ cask.call.language.must_equal "zh-CN"
+ cask.call.sha256.must_equal "abc123"
+ cask.call.url.to_s.must_equal "https://example.org/zh-CN.zip"
+
+ MacOS.stubs(languages: ["en"])
+ cask.call.language.must_equal "en-US"
+ cask.call.sha256.must_equal "xyz789"
+ cask.call.url.to_s.must_equal "https://example.org/en-US.zip"
+
+ MacOS.stubs(languages: ["xx-XX"])
+ cask.call.language.must_equal "en-US"
+ cask.call.sha256.must_equal "xyz789"
+ cask.call.url.to_s.must_equal "https://example.org/en-US.zip"
+
+ MacOS.stubs(languages: ["xx-XX", "zh", "en"])
+ cask.call.language.must_equal "zh-CN"
+ cask.call.sha256.must_equal "abc123"
+ cask.call.url.to_s.must_equal "https://example.org/zh-CN.zip"
+
+ MacOS.stubs(languages: ["xx-XX", "en-US", "zh"])
+ cask.call.language.must_equal "en-US"
+ cask.call.sha256.must_equal "xyz789"
+ cask.call.url.to_s.must_equal "https://example.org/en-US.zip"
+ end
+ end
+
describe "app stanza" do
it "allows you to specify app stanzas" do
cask = Hbc::Cask.new("cask-with-apps") do
diff --git a/Library/Homebrew/cmd/doctor.rb b/Library/Homebrew/cmd/doctor.rb
index df4bba419..cca2dca03 100644
--- a/Library/Homebrew/cmd/doctor.rb
+++ b/Library/Homebrew/cmd/doctor.rb
@@ -44,9 +44,9 @@ module Homebrew
next if out.nil? || out.empty?
if first_warning
$stderr.puts <<-EOS.undent
- #{Tty.white}Please note that these warnings are just used to help the Homebrew maintainers
- with debugging if you file an issue. If everything you use Homebrew for is
- working fine: please don't worry and just ignore them. Thanks!#{Tty.reset}
+ #{Tty.bold}Please note that these warnings are just used to help the Homebrew maintainers
+ with debugging if you file an issue. If everything you use Homebrew for is
+ working fine: please don't worry and just ignore them. Thanks!#{Tty.reset}
EOS
end
diff --git a/Library/Homebrew/cmd/help.rb b/Library/Homebrew/cmd/help.rb
index 793c765ca..982e24965 100644
--- a/Library/Homebrew/cmd/help.rb
+++ b/Library/Homebrew/cmd/help.rb
@@ -41,6 +41,8 @@ module Homebrew
if cmd
cmd = HOMEBREW_INTERNAL_COMMAND_ALIASES.fetch(cmd, cmd)
path = Commands.path(cmd)
+ path ||= which("brew-#{cmd}")
+ path ||= which("brew-#{cmd}.rb")
end
# Display command-specific (or generic) help in response to `UsageError`.
@@ -63,7 +65,7 @@ module Homebrew
exit 0
end
- # Resume execution in `brew.rb` for external/unknown commands.
+ # Resume execution in `brew.rb` for unknown commands.
return if path.nil?
# Display help for internal command (or generic help if undocumented).
@@ -79,9 +81,10 @@ module Homebrew
else
help_lines.map do |line|
line.slice(2..-1)
- .sub(/^ \* /, "#{Tty.highlight}brew#{Tty.reset} ")
- .gsub(/`(.*?)`/, "#{Tty.highlight}\\1#{Tty.reset}")
- .gsub(/<(.*?)>/, "#{Tty.em}\\1#{Tty.reset}")
+ .sub(/^ \* /, "#{Tty.bold}brew#{Tty.reset} ")
+ .gsub(/`(.*?)`/, "#{Tty.bold}\\1#{Tty.reset}")
+ .gsub(%r{<([^\s]+?://[^\s]+?)>}) { |url| Formatter.url(url) }
+ .gsub(/<(.*?)>/, "#{Tty.underline}\\1#{Tty.reset}")
.gsub("@hide_from_man_page", "")
end.join.strip
end
diff --git a/Library/Homebrew/cmd/info.rb b/Library/Homebrew/cmd/info.rb
index 857f1090e..fefabf85f 100644
--- a/Library/Homebrew/cmd/info.rb
+++ b/Library/Homebrew/cmd/info.rb
@@ -119,7 +119,7 @@ module Homebrew
puts "#{f.full_name}: #{specs * ", "}#{" [#{attrs * ", "}]" unless attrs.empty?}"
puts f.desc if f.desc
- puts "#{Tty.em}#{f.homepage}#{Tty.reset}" if f.homepage
+ puts Formatter.url(f.homepage) if f.homepage
conflicts = f.conflicts.map(&:name).sort!
puts "Conflicts with: #{conflicts*", "}" unless conflicts.empty?
@@ -135,7 +135,7 @@ module Homebrew
end
end
- puts "From: #{Tty.em}#{github_info(f)}#{Tty.reset}"
+ puts "From: #{Formatter.url(github_info(f))}"
unless f.deps.empty?
ohai "Dependencies"
diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb
index 328df07ce..ffb7eeab3 100644
--- a/Library/Homebrew/cmd/install.rb
+++ b/Library/Homebrew/cmd/install.rb
@@ -201,16 +201,6 @@ module Homebrew
puts_columns(taps_search_results)
puts "To install one of them, run (for example):\n brew install #{taps_search_results.first}"
end
-
- # If they haven't updated in 48 hours (172800 seconds), that
- # might explain the error
- master = HOMEBREW_REPOSITORY/".git/refs/heads/master"
- return unless master.exist? && (Time.now.to_i - File.mtime(master).to_i) > 172800
- ohai "You haven't updated Homebrew in a while."
- puts <<-EOS.undent
- A formula for #{e.name} might have been added recently.
- Run `brew update` to get the latest Homebrew updates!
- EOS
end
end
end
diff --git a/Library/Homebrew/cmd/list.rb b/Library/Homebrew/cmd/list.rb
index ac13d9c86..01af678a7 100644
--- a/Library/Homebrew/cmd/list.rb
+++ b/Library/Homebrew/cmd/list.rb
@@ -106,7 +106,11 @@ module Homebrew
names = if ARGV.named.empty?
Formula.racks
else
- ARGV.named.map { |n| HOMEBREW_CELLAR+n }.select(&:exist?)
+ racks = ARGV.named.map { |n| HOMEBREW_CELLAR+n }
+ racks.select do |rack|
+ Homebrew.failed = true unless rack.exist?
+ rack.exist?
+ end
end
if ARGV.include? "--pinned"
pinned_versions = {}
diff --git a/Library/Homebrew/cmd/update-report.rb b/Library/Homebrew/cmd/update-report.rb
index a7077d8db..a76167feb 100644
--- a/Library/Homebrew/cmd/update-report.rb
+++ b/Library/Homebrew/cmd/update-report.rb
@@ -113,6 +113,7 @@ module Homebrew
end
def install_core_tap_if_necessary
+ return if ENV["HOMEBREW_UPDATE_TEST"]
core_tap = CoreTap.instance
return if core_tap.installed?
CoreTap.ensure_installed! quiet: false
@@ -282,13 +283,13 @@ module Homebrew
EOS
rescue => e
ofail <<-EOS.undent
- #{Tty.white}Failed to migrate HOMEBREW_REPOSITORY to #{new_homebrew_repository}!
+ #{Tty.bold}Failed to migrate HOMEBREW_REPOSITORY to #{new_homebrew_repository}!#{Tty.reset}
The error was:
#{e}
Please try to resolve this error yourself and then run `brew update` again to
complete the migration. If you need help please +1 an existing error or comment
with your new error in issue:
- #{Tty.em}https://github.com/Homebrew/brew/issues/987#{Tty.reset}
+ #{Formatter.url("https://github.com/Homebrew/brew/issues/987")}
EOS
$stderr.puts e.backtrace
end
diff --git a/Library/Homebrew/compat.rb b/Library/Homebrew/compat.rb
index 57c018c04..69b45683a 100644
--- a/Library/Homebrew/compat.rb
+++ b/Library/Homebrew/compat.rb
@@ -16,3 +16,4 @@ require "compat/dependency_collector"
require "compat/language/haskell"
require "compat/xcode"
require "compat/software_spec"
+require "compat/utils"
diff --git a/Library/Homebrew/compat/utils.rb b/Library/Homebrew/compat/utils.rb
index 7de5e85c3..7b529f04e 100644
--- a/Library/Homebrew/compat/utils.rb
+++ b/Library/Homebrew/compat/utils.rb
@@ -8,3 +8,11 @@ def shell_profile
else "~/.bash_profile"
end
end
+
+module Tty
+ module_function
+
+ def white
+ reset.bold
+ end
+end
diff --git a/Library/Homebrew/debrew.rb b/Library/Homebrew/debrew.rb
index 1c5047a8c..668a0b4d2 100644
--- a/Library/Homebrew/debrew.rb
+++ b/Library/Homebrew/debrew.rb
@@ -111,7 +111,7 @@ module Debrew
begin
puts e.backtrace.first.to_s
- puts "#{Tty.red}#{e.class.name}#{Tty.reset}: #{e}"
+ puts Formatter.error(e, label: e.class.name)
loop do
Menu.choose do |menu|
diff --git a/Library/Homebrew/descriptions.rb b/Library/Homebrew/descriptions.rb
index 0ef4316d3..cc690c050 100644
--- a/Library/Homebrew/descriptions.rb
+++ b/Library/Homebrew/descriptions.rb
@@ -119,12 +119,12 @@ class Descriptions
# Take search results -- a hash mapping formula names to descriptions -- and
# print them.
def print
- blank = "#{Tty.yellow}[no description]#{Tty.reset}"
+ blank = Formatter.warning("[no description]")
@descriptions.keys.sort.each do |full_name|
short_name = short_names[full_name]
printed_name = short_name_counts[short_name] == 1 ? short_name : full_name
description = @descriptions[full_name] || blank
- puts "#{Tty.white}#{printed_name}:#{Tty.reset} #{description}"
+ puts "#{Tty.bold}#{printed_name}:#{Tty.reset} #{description}"
end
end
diff --git a/Library/Homebrew/dev-cmd/bottle.rb b/Library/Homebrew/dev-cmd/bottle.rb
index a087a5e4c..c6a8503b7 100644
--- a/Library/Homebrew/dev-cmd/bottle.rb
+++ b/Library/Homebrew/dev-cmd/bottle.rb
@@ -56,7 +56,7 @@ module Homebrew
return if @put_filenames.include? filename
- puts "#{Tty.red}#{filename}#{Tty.reset}"
+ puts Formatter.error(filename.to_s)
@put_filenames << filename
end
@@ -72,7 +72,7 @@ module Homebrew
if ARGV.verbose?
print_filename.call(string, file) unless linked_libraries.empty?
linked_libraries.each do |lib|
- puts " #{Tty.gray}-->#{Tty.reset} links to #{lib}"
+ puts " #{Tty.bold}-->#{Tty.reset} links to #{lib}"
end
end
@@ -95,7 +95,7 @@ module Homebrew
next unless ARGV.verbose? && !text_matches.empty?
print_filename.call(string, file)
text_matches.first(MAXIMUM_STRING_MATCHES).each do |match, offset|
- puts " #{Tty.gray}-->#{Tty.reset} match '#{match}' at offset #{Tty.em}0x#{offset}#{Tty.reset}"
+ puts " #{Tty.bold}-->#{Tty.reset} match '#{match}' at offset #{Tty.bold}0x#{offset}#{Tty.reset}"
end
if text_matches.size > MAXIMUM_STRING_MATCHES
diff --git a/Library/Homebrew/dev-cmd/tests.rb b/Library/Homebrew/dev-cmd/tests.rb
index 1b6af2850..72f8e0375 100644
--- a/Library/Homebrew/dev-cmd/tests.rb
+++ b/Library/Homebrew/dev-cmd/tests.rb
@@ -9,6 +9,8 @@ module Homebrew
def tests
(HOMEBREW_LIBRARY/"Homebrew").cd do
+ ENV.delete "HOMEBREW_VERBOSE"
+ ENV.delete "VERBOSE"
ENV["HOMEBREW_NO_ANALYTICS_THIS_RUN"] = "1"
ENV["HOMEBREW_DEVELOPER"] = "1"
ENV["TESTOPTS"] = "-v" if ARGV.verbose?
diff --git a/Library/Homebrew/dev-cmd/update-test.rb b/Library/Homebrew/dev-cmd/update-test.rb
index 7f20104d8..8bb0fa057 100644
--- a/Library/Homebrew/dev-cmd/update-test.rb
+++ b/Library/Homebrew/dev-cmd/update-test.rb
@@ -18,7 +18,14 @@ module Homebrew
module_function
def update_test
- ENV["HOMEBREW_UPDATE_TO_TAG"] = "1" if ARGV.include?("--to-tag")
+ ENV["HOMEBREW_UPDATE_TEST"] = "1"
+
+ if ARGV.include?("--to-tag")
+ ENV["HOMEBREW_UPDATE_TO_TAG"] = "1"
+ branch = "stable"
+ else
+ branch = "master"
+ end
cd HOMEBREW_REPOSITORY
start_commit = if commit = ARGV.value("commit")
@@ -59,10 +66,10 @@ module Homebrew
# run brew update
oh1 "Running brew update..."
safe_system "brew", "update", "--verbose"
- actual_end_commit = Utils.popen_read("git", "rev-parse", "master").chomp
+ actual_end_commit = Utils.popen_read("git", "rev-parse", branch).chomp
if start_commit != end_commit && start_commit == actual_end_commit
raise <<-EOS.undent
- brew update didn't update master!
+ brew update didn't update #{branch}!
Start commit: #{start_commit}
Expected end commit: #{end_commit}
Actual end commit: #{actual_end_commit}
diff --git a/Library/Homebrew/diagnostic.rb b/Library/Homebrew/diagnostic.rb
index ca8ade9ff..0db92592c 100644
--- a/Library/Homebrew/diagnostic.rb
+++ b/Library/Homebrew/diagnostic.rb
@@ -389,10 +389,10 @@ module Homebrew
return if HOMEBREW_PREFIX.to_s == "/usr/local"
<<-EOS.undent
- Your Homebrew is not installed to /usr/local
- You can install Homebrew anywhere you want but some bottles (binary
- packages) can only be used in /usr/local and some formulae (packages)
- may not build correctly unless you install in /usr/local. Sorry!
+ Your Homebrew's prefix is not /usr/local.
+ You can install Homebrew anywhere you want but some bottles (binary packages)
+ can only be used with a /usr/local prefix and some formulae (packages)
+ may not build correctly with a non-/usr/local prefix.
EOS
end
@@ -473,7 +473,7 @@ module Homebrew
If you have trouble downloading packages with Homebrew, then maybe this
is the problem? If the following command doesn't work, then try removing
your curlrc:
- curl https://github.com
+ curl #{Formatter.url("https://github.com")}
EOS
end
@@ -610,7 +610,7 @@ module Homebrew
Setting DYLD_INSERT_LIBRARIES can cause Go builds to fail.
Having this set is common if you use this software:
- http://asepsis.binaryage.com/
+ #{Formatter.url("http://asepsis.binaryage.com/")}
EOS
end
@@ -752,7 +752,7 @@ module Homebrew
Without a correctly configured origin, Homebrew won't update
properly. You can solve this by adding the Homebrew remote:
cd #{HOMEBREW_REPOSITORY}
- git remote add origin https://github.com/Homebrew/brew.git
+ git remote add origin #{Formatter.url("https://github.com/Homebrew/brew.git")}
EOS
elsif origin !~ %r{Homebrew/brew(\.git)?$}
<<-EOS.undent
@@ -764,7 +764,7 @@ module Homebrew
Unless you have compelling reasons, consider setting the
origin remote to point at the main repository, located at:
- https://github.com/Homebrew/brew.git
+ #{Formatter.url("https://github.com/Homebrew/brew.git")}
EOS
end
end
@@ -956,8 +956,8 @@ module Homebrew
<<-EOS.undent
A .pydistutils.cfg file was found in $HOME, which may cause Python
builds to fail. See:
- https://bugs.python.org/issue6138
- https://bugs.python.org/issue4655
+ #{Formatter.url("https://bugs.python.org/issue6138")}
+ #{Formatter.url("https://bugs.python.org/issue4655")}
EOS
end
diff --git a/Library/Homebrew/exceptions.rb b/Library/Homebrew/exceptions.rb
index 07658c6e7..1b2b24691 100644
--- a/Library/Homebrew/exceptions.rb
+++ b/Library/Homebrew/exceptions.rb
@@ -294,6 +294,17 @@ class FormulaConflictError < RuntimeError
end
end
+class FormulaAmbiguousPythonError < RuntimeError
+ def initialize(formula)
+ super <<-EOS.undent
+ The version of python to use with the virtualenv in the `#{formula.full_name}` formula
+ cannot be guessed automatically. If the simultaneous use of python and python3
+ is intentional, please add `:using => "python"` or `:using => "python3"` to
+ `virtualenv_install_with_resources` to resolve the ambiguity manually.
+ EOS
+ end
+end
+
class BuildError < RuntimeError
attr_reader :formula, :env
@@ -318,7 +329,7 @@ class BuildError < RuntimeError
def dump
if !ARGV.verbose?
puts
- puts "#{Tty.red}READ THIS#{Tty.reset}: #{Tty.em}#{OS::ISSUES_URL}#{Tty.reset}"
+ puts Formatter.error(Formatter.url(OS::ISSUES_URL), label: "READ THIS")
if formula.tap
case formula.tap.name
when "homebrew/boneyard"
@@ -327,7 +338,7 @@ class BuildError < RuntimeError
else
if issues_url = formula.tap.issues_url
puts "If reporting this issue please do so at (not Homebrew/brew):"
- puts " #{issues_url}"
+ puts " #{Formatter.url(issues_url)}"
end
end
end
diff --git a/Library/Homebrew/extend/os/mac/diagnostic.rb b/Library/Homebrew/extend/os/mac/diagnostic.rb
index 063558f19..0ac95bfd9 100644
--- a/Library/Homebrew/extend/os/mac/diagnostic.rb
+++ b/Library/Homebrew/extend/os/mac/diagnostic.rb
@@ -65,8 +65,8 @@ module Homebrew
return unless MacOS::Xcode.installed? && MacOS::Xcode.outdated?
message = <<-EOS.undent
- Your Xcode (#{MacOS::Xcode.version}) is outdated
- Please update to Xcode #{MacOS::Xcode.latest_version}.
+ Your Xcode (#{MacOS::Xcode.version}) is outdated.
+ Please update to Xcode #{MacOS::Xcode.latest_version} (or delete it).
#{MacOS::Xcode.update_instructions}
EOS
@@ -171,8 +171,7 @@ module Homebrew
end
def check_ruby_version
- ruby_version = MacOS.version >= "10.9" ? "2.0" : "1.8"
- return if RUBY_VERSION[/\d\.\d/] == ruby_version
+ return if RUBY_VERSION[/\d\.\d/] == "2.0"
<<-EOS.undent
Ruby version #{RUBY_VERSION} is unsupported on #{MacOS.version}. Homebrew
@@ -264,8 +263,8 @@ module Homebrew
return if installed_version >= latest_version
<<-EOS.undent
- Your XQuartz (#{installed_version}) is outdated
- Please install XQuartz #{latest_version}:
+ Your XQuartz (#{installed_version}) is outdated.
+ Please install XQuartz #{latest_version} (or delete it):
https://xquartz.macosforge.org
EOS
end
diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb
index 652f87ae3..09c11318e 100644
--- a/Library/Homebrew/formula_installer.rb
+++ b/Library/Homebrew/formula_installer.rb
@@ -214,7 +214,7 @@ class FormulaInstaller
opoo "#{formula.full_name}: #{old_flag} was deprecated; using #{new_flag} instead!"
end
- oh1 "Installing #{Tty.green}#{formula.full_name}#{Tty.reset}" if show_header?
+ oh1 "Installing #{Formatter.identifier(formula.full_name)}" if show_header?
if formula.tap && !formula.tap.private?
options = []
@@ -426,7 +426,7 @@ class FormulaInstaller
if deps.empty? && only_deps?
puts "All dependencies for #{formula.full_name} are satisfied."
elsif !deps.empty?
- oh1 "Installing dependencies for #{formula.full_name}: #{Tty.green}#{deps.map(&:first)*", "}#{Tty.reset}",
+ oh1 "Installing dependencies for #{formula.full_name}: #{deps.map(&:first).map(&Formatter.method(:identifier)).join(", ")}",
truncate: false
deps.each { |dep, options| install_dependency(dep, options) }
end
@@ -476,7 +476,7 @@ class FormulaInstaller
fi.verbose = verbose? && !quieter?
fi.debug = debug?
fi.prelude
- oh1 "Installing #{formula.full_name} dependency: #{Tty.green}#{dep.name}#{Tty.reset}"
+ oh1 "Installing #{formula.full_name} dependency: #{Formatter.identifier(dep.name)}"
fi.install
fi.finish
rescue Exception
diff --git a/Library/Homebrew/language/python.rb b/Library/Homebrew/language/python.rb
index 95259c841..b28b1ca60 100644
--- a/Library/Homebrew/language/python.rb
+++ b/Library/Homebrew/language/python.rb
@@ -139,11 +139,33 @@ module Language
venv
end
+ # Returns true if a formula option for the specified python is currently
+ # active or if the specified python is required by the formula. Valid
+ # inputs are "python", "python3", :python, and :python3. Note that
+ # "with-python", "without-python", "with-python3", and "without-python3"
+ # formula options are handled correctly even if not associated with any
+ # corresponding depends_on statement.
+ # @api private
+ def needs_python?(python)
+ return true if build.with?(python)
+ (requirements.to_a | deps).any? { |r| r.name == python && r.required? }
+ end
+
# Helper method for the common case of installing a Python application.
# Creates a virtualenv in `libexec`, installs all `resource`s defined
- # on the formula, and then installs the formula.
- def virtualenv_install_with_resources
- venv = virtualenv_create(libexec)
+ # on the formula, and then installs the formula. An options hash may be
+ # passed (e.g., :using => "python3") to override the default, guessed
+ # formula preference for python or python3, or to resolve an ambiguous
+ # case where it's not clear whether python or python3 should be the
+ # default guess.
+ def virtualenv_install_with_resources(options = {})
+ python = options[:using]
+ if python.nil?
+ wanted = %w[python python3].select { |py| needs_python?(py) }
+ raise FormulaAmbiguousPythonError, self if wanted.size > 1
+ python = wanted.first || "python"
+ end
+ venv = virtualenv_create(libexec, python)
venv.pip_install resources
venv.pip_install_and_link buildpath
venv
diff --git a/Library/Homebrew/locale.rb b/Library/Homebrew/locale.rb
new file mode 100644
index 000000000..1aff33dae
--- /dev/null
+++ b/Library/Homebrew/locale.rb
@@ -0,0 +1,68 @@
+class Locale
+ class ParserError < ::RuntimeError
+ end
+
+ LANGUAGE_REGEX = /(?:[a-z]{2})/
+ REGION_REGEX = /(?:[A-Z]{2})/
+ SCRIPT_REGEX = /(?:[A-Z][a-z]{3})/
+
+ LOCALE_REGEX = /^(#{LANGUAGE_REGEX})?(?:(?:^|-)(#{REGION_REGEX}))?(?:(?:^|-)(#{SCRIPT_REGEX}))?$/
+
+ def self.parse(string)
+ language, region, script = string.to_s.scan(LOCALE_REGEX)[0]
+
+ if language.nil? && region.nil? && script.nil?
+ raise ParserError, "'#{string}' cannot be parsed to a #{self.class}"
+ end
+
+ new(language, region, script)
+ end
+
+ attr_reader :language, :region, :script
+
+ def initialize(language, region, script)
+ if language.nil? && region.nil? && script.nil?
+ raise ArgumentError, "#{self.class} cannot be empty"
+ end
+
+ {
+ language: language,
+ region: region,
+ script: script,
+ }.each do |key, value|
+ next if value.nil?
+
+ regex = self.class.const_get("#{key.upcase}_REGEX")
+ raise ParserError, "'#{value}' does not match #{regex}" unless value =~ regex
+ instance_variable_set(:"@#{key}", value)
+ end
+
+ self
+ end
+
+ def include?(other)
+ other = self.class.parse(other) unless other.is_a?(self.class)
+
+ [:language, :region, :script].all? { |var|
+ if other.public_send(var).nil?
+ true
+ else
+ public_send(var) == other.public_send(var)
+ end
+ }
+ end
+
+ def eql?(other)
+ other = self.class.parse(other) unless other.is_a?(self.class)
+ [:language, :region, :script].all? { |var|
+ public_send(var) == other.public_send(var)
+ }
+ rescue ParserError
+ false
+ end
+ alias == eql?
+
+ def to_s
+ [@language, @region, @script].compact.join("-")
+ end
+end
diff --git a/Library/Homebrew/manpages/brew.1.md.erb b/Library/Homebrew/manpages/brew.1.md.erb
index bc2140b40..7412d0a69 100644
--- a/Library/Homebrew/manpages/brew.1.md.erb
+++ b/Library/Homebrew/manpages/brew.1.md.erb
@@ -54,7 +54,21 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note
<%= developer_commands.join("\n") %>
-## EXTERNAL COMMANDS
+## OFFICIAL EXTERNAL COMMANDS
+
+ * `bundle`:
+ Bundler for non-Ruby dependencies from Homebrew:
+ <https://github.com/Homebrew/homebrew-bundle>
+
+ * `cask`:
+ Install macOS applications distributed as binaries:
+ <https://github.com/caskroom/homebrew-cask>
+
+ * `services`:
+ Integrates Homebrew formulae with macOS's `launchctl` manager:
+ <https://github.com/Homebrew/homebrew-services>
+
+## CUSTOM EXTERNAL COMMANDS
Homebrew, like `git`(1), supports external commands. These are executable
scripts that reside somewhere in the `PATH`, named `brew-`<cmdname> or
@@ -251,7 +265,7 @@ If your proxy requires authentication:
Homebrew Documentation: <https://github.com/Homebrew/brew/blob/master/docs/>
-`git`(1), `git-log`(1)
+`brew-cask`(1), `git`(1), `git-log`(1)
## AUTHORS
diff --git a/Library/Homebrew/migrator.rb b/Library/Homebrew/migrator.rb
index 4f8cba1ce..fe480cd3b 100644
--- a/Library/Homebrew/migrator.rb
+++ b/Library/Homebrew/migrator.rb
@@ -153,7 +153,7 @@ class Migrator
end
begin
- oh1 "Migrating #{Tty.green}#{oldname}#{Tty.white} to #{Tty.green}#{newname}#{Tty.reset}"
+ oh1 "Migrating #{Formatter.identifier(oldname)} to #{Formatter.identifier(newname)}"
lock
unlink_oldname
move_to_new_directory
@@ -200,7 +200,7 @@ class Migrator
end
def unlink_oldname
- oh1 "Unlinking #{Tty.green}#{oldname}#{Tty.reset}"
+ oh1 "Unlinking #{Formatter.identifier(oldname)}"
old_cellar.subdirs.each do |d|
keg = Keg.new(d)
keg.unlink
@@ -208,7 +208,7 @@ class Migrator
end
def link_newname
- oh1 "Linking #{Tty.green}#{newname}#{Tty.reset}"
+ oh1 "Linking #{Formatter.identifier(newname)}"
new_keg = Keg.new(new_linked_keg_record)
# If old_keg wasn't linked then we just optlink a keg.
diff --git a/Library/Homebrew/os/mac.rb b/Library/Homebrew/os/mac.rb
index 0b0147825..b2f0515a0 100644
--- a/Library/Homebrew/os/mac.rb
+++ b/Library/Homebrew/os/mac.rb
@@ -41,8 +41,24 @@ module OS
version.to_sym
end
+ def languages
+ return @languages unless @languages.nil?
+
+ @languages = Utils.popen_read("defaults", "read", ".GlobalPreferences", "AppleLanguages").scan(/[^ \n"(),]+/)
+
+ if ENV["HOMEBREW_LANGUAGES"]
+ @languages = ENV["HOMEBREW_LANGUAGES"].split(",") + @languages
+ end
+
+ if ARGV.value("language")
+ @languages = ARGV.value("language").split(",") + @languages
+ end
+
+ @languages = @languages.uniq
+ end
+
def language
- @language ||= Utils.popen_read("defaults", "read", ".GlobalPreferences", "AppleLanguages").delete(" \n\"()").sub(/,.*/, "")
+ languages.first
end
def active_developer_dir
diff --git a/Library/Homebrew/requirements.rb b/Library/Homebrew/requirements.rb
index 274ba5c9b..87b315cb7 100644
--- a/Library/Homebrew/requirements.rb
+++ b/Library/Homebrew/requirements.rb
@@ -44,7 +44,7 @@ class XcodeRequirement < Requirement
EOS
else
message + <<-EOS.undent
- Xcode can be installed from https://developer.apple.com/xcode/downloads/
+ Xcode can be installed from #{Formatter.url("https://developer.apple.com/xcode/downloads/")}
EOS
end
end
diff --git a/Library/Homebrew/test/test_diagnostic.rb b/Library/Homebrew/test/test_diagnostic.rb
index 37f56e961..b9b995f0f 100644
--- a/Library/Homebrew/test/test_diagnostic.rb
+++ b/Library/Homebrew/test/test_diagnostic.rb
@@ -85,7 +85,7 @@ class DiagnosticChecksTest < Homebrew::TestCase
def test_check_homebrew_prefix
# the integration tests are run in a special prefix
- assert_match "Your Homebrew is not installed to /usr/local",
+ assert_match "Your Homebrew's prefix is not /usr/local.",
@checks.check_homebrew_prefix
end
diff --git a/Library/Homebrew/test/test_os_mac_language.rb b/Library/Homebrew/test/test_os_mac_language.rb
index 2cdd50917..709913000 100644
--- a/Library/Homebrew/test/test_os_mac_language.rb
+++ b/Library/Homebrew/test/test_os_mac_language.rb
@@ -2,7 +2,15 @@ require "testing_env"
require "os/mac"
class OSMacLanguageTests < Homebrew::TestCase
+ LANGUAGE_REGEX = /\A[a-z]{2}(-[A-Z]{2})?(-[A-Z][a-z]{3})?\Z/
+
+ def test_languages_format
+ OS::Mac.languages.each do |language|
+ assert_match LANGUAGE_REGEX, language
+ end
+ end
+
def test_language_format
- assert_match(/\A[a-z]{2}(-[A-Z]{2})?\Z/, OS::Mac.language)
+ assert_match LANGUAGE_REGEX, OS::Mac.language
end
end
diff --git a/Library/Homebrew/test/test_utils.rb b/Library/Homebrew/test/test_utils.rb
index 422cd6229..cd5a379ab 100644
--- a/Library/Homebrew/test/test_utils.rb
+++ b/Library/Homebrew/test/test_utils.rb
@@ -5,8 +5,11 @@ require "utils/shell"
class TtyTests < Homebrew::TestCase
def test_strip_ansi
- assert_equal "hello",
- Tty.strip_ansi("\033\[36;7mhello\033\[0m")
+ assert_equal "hello", Tty.strip_ansi("\033\[36;7mhello\033\[0m")
+ end
+
+ def test_width
+ assert_kind_of Integer, Tty.width
end
def test_truncate
@@ -21,15 +24,26 @@ class TtyTests < Homebrew::TestCase
def test_no_tty_formatting
$stdout.stubs(:tty?).returns false
- assert_nil Tty.blue
- assert_nil Tty.white
- assert_nil Tty.red
- assert_nil Tty.green
- assert_nil Tty.gray
- assert_nil Tty.yellow
- assert_nil Tty.reset
- assert_nil Tty.em
- assert_nil Tty.highlight
+ assert_equal "", Tty.to_s
+ assert_equal "", Tty.red.to_s
+ assert_equal "", Tty.green.to_s
+ assert_equal "", Tty.yellow.to_s
+ assert_equal "", Tty.blue.to_s
+ assert_equal "", Tty.magenta.to_s
+ assert_equal "", Tty.cyan.to_s
+ assert_equal "", Tty.default.to_s
+ end
+
+ def test_formatting
+ $stdout.stubs(:tty?).returns(true)
+ assert_equal "", Tty.to_s
+ assert_equal "\033[31m", Tty.red.to_s
+ assert_equal "\033[32m", Tty.green.to_s
+ assert_equal "\033[33m", Tty.yellow.to_s
+ assert_equal "\033[34m", Tty.blue.to_s
+ assert_equal "\033[35m", Tty.magenta.to_s
+ assert_equal "\033[36m", Tty.cyan.to_s
+ assert_equal "\033[39m", Tty.default.to_s
end
end
diff --git a/Library/Homebrew/utils.rb b/Library/Homebrew/utils.rb
index 7c68437ca..04d157262 100644
--- a/Library/Homebrew/utils.rb
+++ b/Library/Homebrew/utils.rb
@@ -1,6 +1,7 @@
require "pathname"
require "emoji"
require "exceptions"
+require "utils/formatter"
require "utils/hash"
require "utils/json"
require "utils/inreplace"
@@ -10,85 +11,11 @@ require "utils/git"
require "utils/analytics"
require "utils/github"
require "utils/curl"
-
-class Tty
- class << self
- def strip_ansi(string)
- string.gsub(/\033\[\d+(;\d+)*m/, "")
- end
-
- def blue
- bold 34
- end
-
- def white
- bold 39
- end
-
- def magenta
- bold 35
- end
-
- def red
- underline 31
- end
-
- def yellow
- underline 33
- end
-
- def reset
- escape 0
- end
-
- def em
- underline 39
- end
-
- def green
- bold 32
- end
-
- def gray
- bold 30
- end
-
- def highlight
- bold 39
- end
-
- def width
- `/usr/bin/tput cols`.strip.to_i
- end
-
- def truncate(str)
- w = width
- w > 10 ? str.to_s[0, w - 4] : str
- end
-
- private
-
- def color(n)
- escape "0;#{n}"
- end
-
- def bold(n)
- escape "1;#{n}"
- end
-
- def underline(n)
- escape "4;#{n}"
- end
-
- def escape(n)
- "\033[#{n}m" if $stdout.tty?
- end
- end
-end
+require "utils/tty"
def ohai(title, *sput)
title = Tty.truncate(title) if $stdout.tty? && !ARGV.verbose?
- puts "#{Tty.blue}==>#{Tty.white} #{title}#{Tty.reset}"
+ puts Formatter.headline(title, color: :blue)
puts sput
end
@@ -96,16 +23,16 @@ def oh1(title, options = {})
if $stdout.tty? && !ARGV.verbose? && options.fetch(:truncate, :auto) == :auto
title = Tty.truncate(title)
end
- puts "#{Tty.green}==>#{Tty.white} #{title}#{Tty.reset}"
+ puts Formatter.headline(title, color: :green)
end
# Print a warning (do this rarely)
-def opoo(warning)
- $stderr.puts "#{Tty.yellow}Warning#{Tty.reset}: #{warning}"
+def opoo(message)
+ $stderr.puts Formatter.warning(message, label: "Warning")
end
-def onoe(error)
- $stderr.puts "#{Tty.red}Error#{Tty.reset}: #{error}"
+def onoe(message)
+ $stderr.puts Formatter.error(message, label: "Error")
end
def ofail(error)
@@ -171,9 +98,9 @@ def pretty_installed(f)
if !$stdout.tty?
f.to_s
elsif Emoji.enabled?
- "#{Tty.highlight}#{f} #{Tty.green}#{Emoji.tick}#{Tty.reset}"
+ "#{Tty.bold}#{f} #{Formatter.success(Emoji.tick)}#{Tty.reset}"
else
- "#{Tty.highlight}#{Tty.green}#{f} (installed)#{Tty.reset}"
+ Formatter.success("#{Tty.bold}#{f} (installed)#{Tty.reset}")
end
end
@@ -181,9 +108,9 @@ def pretty_uninstalled(f)
if !$stdout.tty?
f.to_s
elsif Emoji.enabled?
- "#{f} #{Tty.red}#{Emoji.cross}#{Tty.reset}"
+ "#{Tty.bold}#{f} #{Formatter.error(Emoji.cross)}#{Tty.reset}"
else
- "#{Tty.red}#{f} (uninstalled)#{Tty.reset}"
+ Formatter.error("#{Tty.bold}#{f} (uninstalled)#{Tty.reset}")
end
end
diff --git a/Library/Homebrew/utils/formatter.rb b/Library/Homebrew/utils/formatter.rb
new file mode 100644
index 000000000..cb4f041f4
--- /dev/null
+++ b/Library/Homebrew/utils/formatter.rb
@@ -0,0 +1,52 @@
+require "utils/tty"
+
+module Formatter
+ module_function
+
+ def arrow(string, color: nil)
+ prefix("==>", string, color)
+ end
+
+ def headline(string, color: nil)
+ arrow("#{Tty.bold}#{string}#{Tty.reset}", color: color)
+ end
+
+ def identifier(string)
+ "#{Tty.green}#{string}#{Tty.reset}"
+ end
+
+ def success(string, label: nil)
+ label(label, string, :green)
+ end
+
+ def warning(string, label: nil)
+ label(label, string, :yellow)
+ end
+
+ def error(string, label: nil)
+ label(label, string, :red)
+ end
+
+ def url(string)
+ "#{Tty.underline}#{string}#{Tty.no_underline}"
+ end
+
+ def label(label, string, color)
+ label = "#{label}:" unless label.nil?
+ prefix(label, string, color)
+ end
+ private_class_method :label
+
+ def prefix(prefix, string, color)
+ if prefix.nil? && color.nil?
+ string
+ elsif prefix.nil?
+ "#{Tty.send(color)}#{string}#{Tty.reset}"
+ elsif color.nil?
+ "#{prefix} #{string}"
+ else
+ "#{Tty.send(color)}#{prefix}#{Tty.reset} #{string}"
+ end
+ end
+ private_class_method :prefix
+end
diff --git a/Library/Homebrew/utils/github.rb b/Library/Homebrew/utils/github.rb
index b7ec538f9..5611f9aad 100644
--- a/Library/Homebrew/utils/github.rb
+++ b/Library/Homebrew/utils/github.rb
@@ -14,7 +14,7 @@ module GitHub
super <<-EOS.undent
GitHub API Error: #{error}
Try again in #{pretty_ratelimit_reset(reset)}, or create a personal access token:
- #{Tty.em}https://github.com/settings/tokens/new?scopes=&description=Homebrew#{Tty.reset}
+ #{Formatter.url("https://github.com/settings/tokens/new?scopes=&description=Homebrew")}
and then set the token as: export HOMEBREW_GITHUB_API_TOKEN="your_new_token"
EOS
end
@@ -30,7 +30,7 @@ module GitHub
if ENV["HOMEBREW_GITHUB_API_TOKEN"]
message << <<-EOS.undent
HOMEBREW_GITHUB_API_TOKEN may be invalid or expired; check:
- #{Tty.em}https://github.com/settings/tokens#{Tty.reset}
+ #{Formatter.url("https://github.com/settings/tokens")}
EOS
else
message << <<-EOS.undent
@@ -38,7 +38,7 @@ module GitHub
Clear them with:
printf "protocol=https\\nhost=github.com\\n" | git credential-osxkeychain erase
Or create a personal access token:
- #{Tty.em}https://github.com/settings/tokens/new?scopes=&description=Homebrew#{Tty.reset}
+ #{Formatter.url("https://github.com/settings/tokens/new?scopes=&description=Homebrew")}
and then set the token as: export HOMEBREW_GITHUB_API_TOKEN="your_new_token"
EOS
end
@@ -106,14 +106,14 @@ module GitHub
onoe <<-EOS.undent
Your macOS keychain GitHub credentials do not have sufficient scope!
Scopes they have: #{credentials_scopes}
- Create a personal access token: https://github.com/settings/tokens
+ Create a personal access token: #{Formatter.url("https://github.com/settings/tokens")}
and then set HOMEBREW_GITHUB_API_TOKEN as the authentication method instead.
EOS
when :environment
onoe <<-EOS.undent
Your HOMEBREW_GITHUB_API_TOKEN does not have sufficient scope!
Scopes it has: #{credentials_scopes}
- Create a new personal access token: https://github.com/settings/tokens
+ Create a new personal access token: #{Formatter.url("https://github.com/settings/tokens")}
and then set the new HOMEBREW_GITHUB_API_TOKEN as the authentication method instead.
EOS
end
diff --git a/Library/Homebrew/utils/tty.rb b/Library/Homebrew/utils/tty.rb
new file mode 100644
index 000000000..505165dc5
--- /dev/null
+++ b/Library/Homebrew/utils/tty.rb
@@ -0,0 +1,64 @@
+module Tty
+ module_function
+
+ def strip_ansi(string)
+ string.gsub(/\033\[\d+(;\d+)*m/, "")
+ end
+
+ def width
+ `/usr/bin/tput cols`.strip.to_i
+ end
+
+ def truncate(string)
+ (w = width).zero? ? string.to_s : string.to_s[0, w - 4]
+ end
+
+ COLOR_CODES = {
+ red: 31,
+ green: 32,
+ yellow: 33,
+ blue: 34,
+ magenta: 35,
+ cyan: 36,
+ default: 39,
+ }.freeze
+
+ STYLE_CODES = {
+ reset: 0,
+ bold: 1,
+ italic: 3,
+ underline: 4,
+ strikethrough: 9,
+ no_underline: 24,
+ }.freeze
+
+ CODES = COLOR_CODES.merge(STYLE_CODES).freeze
+
+ def append_to_escape_sequence(code)
+ @escape_sequence ||= []
+ @escape_sequence << code
+ self
+ end
+
+ def current_escape_sequence
+ return "" if @escape_sequence.nil?
+ "\033[#{@escape_sequence.join(";")}m"
+ end
+
+ def reset_escape_sequence!
+ @escape_sequence = nil
+ end
+
+ CODES.each do |name, code|
+ define_singleton_method(name) do
+ append_to_escape_sequence(code)
+ end
+ end
+
+ def to_s
+ return "" unless $stdout.tty?
+ current_escape_sequence
+ ensure
+ reset_escape_sequence!
+ end
+end