aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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/cli.rb4
-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/spec/locale_spec.rb72
-rw-r--r--Library/Homebrew/cask/test/cask/dsl_test.rb50
-rw-r--r--Library/Homebrew/locale.rb68
-rw-r--r--Library/Homebrew/os/mac.rb18
-rw-r--r--Library/Homebrew/test/test_os_mac_language.rb10
10 files changed, 281 insertions, 4 deletions
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/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/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/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/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/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/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