From 7f5e5124f65566fa20c8cc8ca46f5cb215e09576 Mon Sep 17 00:00:00 2001 From: Roland Walker Date: Wed, 3 Dec 2014 10:32:17 -0500 Subject: [PATCH] DSL: `depends_on :arch` functionality/tests/doc * fill in functionality for the `depends_on :arch` stub * de-document `caveats` method `arch_only` --- doc/CASK_LANGUAGE_REFERENCE.md | 37 ++++++++++++++- doc/cask_language_deltas.md | 4 +- lib/cask/dsl/depends_on.rb | 47 ++++++++++++++++++- lib/cask/installer.rb | 16 +++++++ test/cask/depends_on_test.rb | 18 +++++++ test/cask/dsl_test.rb | 12 +++++ test/cask/installer_test.rb | 8 ++-- .../invalid/invalid-depends-on-arch-value.rb | 11 +++++ test/support/Casks/with-caveats.rb | 5 -- .../support/Casks/with-conditional-caveats.rb | 5 -- .../Casks/with-depends-on-arch-failure.rb | 12 +++++ test/support/Casks/with-depends-on-arch.rb | 12 +++++ 12 files changed, 167 insertions(+), 20 deletions(-) create mode 100644 test/support/Casks/invalid/invalid-depends-on-arch-value.rb create mode 100644 test/support/Casks/with-depends-on-arch-failure.rb create mode 100644 test/support/Casks/with-depends-on-arch.rb diff --git a/doc/CASK_LANGUAGE_REFERENCE.md b/doc/CASK_LANGUAGE_REFERENCE.md index e6893bf7edef..158ea7f9d299 100644 --- a/doc/CASK_LANGUAGE_REFERENCE.md +++ b/doc/CASK_LANGUAGE_REFERENCE.md @@ -232,7 +232,6 @@ The following methods may be called to generate standard warning messages: | `reboot` | users should reboot to complete installation | `assistive_devices` | users should grant the application access to assistive devices | `files_in_usr_local` | the Cask installs files to `/usr/local`, which may confuse Homebrew -| `arch_only(list)` | the Cask only supports certain architectures. Currently valid elements of `list` are `intel-32` and `intel-64` | `x11_required` | the Cask requires X11 to run Example: @@ -586,6 +585,40 @@ depends_on :macos => '>= :mavericks' depends_on :macos => '>= 10.9' ``` +### Depends_on :arch + +The value for `depends_on :arch` may be a symbol or an array of symbols, +listing the hardware compatibility requirements for a Cask. The requirement +is satisfied at install time if any one of multiple `:arch` value matches +the user's hardware. + +The available symbols for hardware are: + +| symbol | meaning | +| ---------- | -------------- | +| `:i386` | 32-bit Intel | +| `:x86_64` | 64-bit Intel | +| `:ppc_7400`| 32-bit PowerPC | +| `:ppc_64` | 64-bit PowerPC | +| `:intel` | Any Intel | +| `:ppc` | Any PowerPC | + +The following are all valid expressions: + +```ruby +depends_on :arch => :x86_64 +depends_on :arch => [:x86_64] # same meaning as above +depends_on :arch => :intel +depends_on :arch => [:i386, :x86_64] # same meaning as above +``` + +Since PowerPC hardware is no longer common, the expression most +frequently needed will be: + +```ruby +depends_on :arch => :x86_64 +``` + ### All Depends_on Keys Several other keys are accepted by `depends_on`, in anticipation of future @@ -596,7 +629,7 @@ functionality: | `:formula` | a Homebrew Formula | `:cask` | *stub - not yet functional* | `:macos` | a string, symbol, array, or expression defining OS X version requirements. -| `:arch` | *stub - not yet functional* +| `:arch` | a symbol or array defining hardware requirements. | `:x11` | *stub - not yet functional* | `:java` | *stub - not yet functional* diff --git a/doc/cask_language_deltas.md b/doc/cask_language_deltas.md index 02ffc902d045..9f5bfb43aad0 100644 --- a/doc/cask_language_deltas.md +++ b/doc/cask_language_deltas.md @@ -54,8 +54,6 @@ features which are available for the current Cask. * [`artifact`](CASK_LANGUAGE_REFERENCE.md#at-least-one-artifact-stanza-is-also-required) * [`depends_on :cask`](CASK_LANGUAGE_REFERENCE.md#depends_on-stanza-details) * *stub* - not yet functional - * [`depends_on :arch`](CASK_LANGUAGE_REFERENCE.md#depends_on-stanza-details) - * *stub* - not yet functional * [`depends_on :x11`](CASK_LANGUAGE_REFERENCE.md#depends_on-stanza-details) * *stub* - not yet functional * [`depends_on :java`](CASK_LANGUAGE_REFERENCE.md#depends_on-stanza-details) @@ -94,6 +92,7 @@ features which are available for the current Cask. | `title` (in interpolations) | [`token`](CASK_LANGUAGE_REFERENCE.md#caveats-as-a-string) | `uninstall :files` | [`uninstall :delete`](CASK_LANGUAGE_REFERENCE.md#uninstall-stanza-details) | `version 'latest'` | [`version :latest`](CASK_LANGUAGE_REFERENCE.md#required-stanzas) +| `arch_only` (within `caveats`) | [`depends_on :arch`](CASK_LANGUAGE_REFERENCE.md#depends_on-stanza-details) ## All Supported Stanzas (1.0) @@ -145,7 +144,6 @@ For use in *eg* interpolation: ## Caveats Mini-DSL (1.0) - * [`arch_only(list)`](CASK_LANGUAGE_REFERENCE.md#caveats-mini-dsl) * [`assistive_devices`](CASK_LANGUAGE_REFERENCE.md#caveats-mini-dsl) * [`files_in_usr_local`](CASK_LANGUAGE_REFERENCE.md#caveats-mini-dsl) * [`logout`](CASK_LANGUAGE_REFERENCE.md#caveats-mini-dsl) diff --git a/lib/cask/dsl/depends_on.rb b/lib/cask/dsl/depends_on.rb index 81d89c208511..c087ae71037d 100644 --- a/lib/cask/dsl/depends_on.rb +++ b/lib/cask/dsl/depends_on.rb @@ -11,7 +11,35 @@ class Cask::DSL::DependsOn :java, ] - attr_accessor :formula, :cask, :arch, :x11, :java + VALID_ARCHES = Set.new [ + # category + :intel, + :ppc, + # specific + :i386, + :x86_64, + :ppc_7400, + :ppc_64, + ] + + # Intentionally undocumented: catch variant spellings. + ARCH_SYNONYMS = { + :x86_32 => :i386, + :x8632 => :i386, + :x8664 => :x86_64, + :intel_32 => :i386, + :intel32 => :i386, + :intel_64 => :x86_64, + :intel64 => :x86_64, + :amd_64 => :x86_64, + :amd64 => :x86_64, + :ppc7400 => :ppc_7400, + :ppc_32 => :ppc_7400, + :ppc32 => :ppc_7400, + :ppc64 => :ppc_64, + } + + attr_accessor :formula, :cask, :x11, :java attr_accessor :pairs def initialize(pairs={}) @@ -69,6 +97,23 @@ def macos=(arg) @pairs[:macos] = @macos end + def arch + @arch + end + + def arch=(arg) + @arch = Array(arg).map do |elt| + elt = elt.to_s.downcase.sub(%r{^:},'').gsub('-','_').to_sym + ARCH_SYNONYMS.key?(elt) ? ARCH_SYNONYMS[elt] : elt + end + @arch.each do |elt| + unless VALID_ARCHES.include?(elt) + raise "invalid 'depends_on :arch' value: #{arg.inspect}" + end + end + @pairs[:arch] = @arch + end + def to_yaml @pairs.to_yaml end diff --git a/lib/cask/installer.rb b/lib/cask/installer.rb index 44a03f4d7c5e..947bbcb12fa5 100644 --- a/lib/cask/installer.rb +++ b/lib/cask/installer.rb @@ -106,6 +106,7 @@ def install_artifacts # override dependencies with --force or perhaps --force-deps def satisfy_dependencies macos_dependencies + arch_dependencies formula_dependencies end @@ -133,6 +134,21 @@ def macos_dependencies end end + def arch_dependencies + if @cask.depends_on and + @cask.depends_on.arch + @current_arch ||= [ + Hardware::CPU.type, + Hardware::CPU.is_32_bit? ? + (Hardware::CPU.intel? ? :i386 : :ppc_7400) : + (Hardware::CPU.intel? ? :x86_64 : :ppc_64) + ] + if Array(@cask.depends_on.arch & @current_arch).count == 0 + raise CaskError.new "Cask #{@cask} depends on hardware architecture being one of #{@cask.depends_on.arch.inspect}, but you are running #{@current_arch.inspect}" + end + end + end + def formula_dependencies # todo The Cask::DependsOn object needs to be more friendly. # Currently @cask.depends_on.formula raises an exception diff --git a/test/cask/depends_on_test.rb b/test/cask/depends_on_test.rb index 3a23ec7c907a..2287c91ced54 100644 --- a/test/cask/depends_on_test.rb +++ b/test/cask/depends_on_test.rb @@ -50,4 +50,22 @@ }.must_raise(CaskError) end end + + describe "depends_on :arch" do + it "succeeds when depends_on :arch is satisfied" do + arch_cask = Cask.load('with-depends-on-arch') + shutup do + Cask::Installer.new(arch_cask).install + end + end + + it "raises an exception when depends_on :arch is not satisfied" do + arch_cask = Cask.load('with-depends-on-arch-failure') + lambda { + shutup do + Cask::Installer.new(arch_cask).install + end + }.must_raise(CaskError) + end + end end diff --git a/test/cask/dsl_test.rb b/test/cask/dsl_test.rb index c77a9376c027..c3656093d4ce 100644 --- a/test/cask/dsl_test.rb +++ b/test/cask/dsl_test.rb @@ -262,6 +262,18 @@ def caveats; <<-EOS.undent end end + describe "depends_on :arch" do + it "allows depends_on :arch to be specified" do + cask = Cask.load('with-depends-on-arch') + cask.depends_on.arch.wont_be_nil + end + it "refuses to load with an invalid depends_on :arch value" do + err = lambda { + invalid_cask = Cask.load('invalid/invalid-depends-on-arch-value') + }.must_raise(CaskInvalidError) + end + end + describe "conflicts_with stanza" do it "allows conflicts_with stanza to be specified" do cask = Cask.load('with-conflicts-with') diff --git a/test/cask/installer_test.rb b/test/cask/installer_test.rb index 30c4112b875d..cb9ab03d9a1f 100644 --- a/test/cask/installer_test.rb +++ b/test/cask/installer_test.rb @@ -44,7 +44,7 @@ it "works with cab-based Casks" do skip unless HOMEBREW_PREFIX.join('bin/cabextract').exist? cab_container = Cask.load('cab-container') - empty = stub(:formula => [], :macos => nil) + empty = stub(:formula => [], :macos => nil, :arch => nil) cab_container.stubs(:depends_on).returns(empty) shutup do @@ -72,7 +72,7 @@ it "works with 7z-based Casks" do skip unless HOMEBREW_PREFIX.join('bin/unar').exist? sevenzip_container = Cask.load('sevenzip-container') - empty = stub(:formula => [], :macos => nil) + empty = stub(:formula => [], :macos => nil, :arch => nil) sevenzip_container.stubs(:depends_on).returns(empty) shutup do @@ -101,7 +101,7 @@ it "works with Stuffit-based Casks" do skip unless HOMEBREW_PREFIX.join('bin/unar').exist? stuffit_container = Cask.load('stuffit-container') - empty = stub(:formula => [], :macos => nil) + empty = stub(:formula => [], :macos => nil, :arch => nil) stuffit_container.stubs(:depends_on).returns(empty) shutup do @@ -117,7 +117,7 @@ it "works with RAR-based Casks" do skip unless HOMEBREW_PREFIX.join('bin/unar').exist? rar_container = Cask.load('rar-container') - empty = stub(:formula => [], :macos => nil) + empty = stub(:formula => [], :macos => nil, :arch => nil) rar_container.stubs(:depends_on).returns(empty) shutup do diff --git a/test/support/Casks/invalid/invalid-depends-on-arch-value.rb b/test/support/Casks/invalid/invalid-depends-on-arch-value.rb new file mode 100644 index 000000000000..0ee34fa8ad8d --- /dev/null +++ b/test/support/Casks/invalid/invalid-depends-on-arch-value.rb @@ -0,0 +1,11 @@ +cask :v1test => 'invalid-depends-on-arch-value' do + version '1.2.3' + sha256 '9203c30951f9aab41ac294bbeb1dcef7bed401ff0b353dcb34d68af32ea51853' + + url TestHelper.local_binary_url('caffeine.zip') + homepage 'http://example.com/invalid-depends-on-arch-value' + + depends_on :arch => :no_such_arch + + app 'Caffeine.app' +end diff --git a/test/support/Casks/with-caveats.rb b/test/support/Casks/with-caveats.rb index edda23ce7034..ae98ace013f5 100644 --- a/test/support/Casks/with-caveats.rb +++ b/test/support/Casks/with-caveats.rb @@ -19,9 +19,4 @@ puts 'Custom text via puts followed by DSL-generated text:' path_environment_variable('/custom/path/bin') end - caveats do - # since both valid arches are specified, no output should be - # generated here during the test - arch_only('intel-32', 'intel-64') - end end diff --git a/test/support/Casks/with-conditional-caveats.rb b/test/support/Casks/with-conditional-caveats.rb index 39b9b93c41cc..c40e13e0d35f 100644 --- a/test/support/Casks/with-conditional-caveats.rb +++ b/test/support/Casks/with-conditional-caveats.rb @@ -10,9 +10,4 @@ caveats do puts 'This caveat is conditional' if false end - caveats do - # since both valid arches are specified, no output should be - # generated here during the test - arch_only('intel-32', 'intel-64') - end end diff --git a/test/support/Casks/with-depends-on-arch-failure.rb b/test/support/Casks/with-depends-on-arch-failure.rb new file mode 100644 index 000000000000..25ee829f2473 --- /dev/null +++ b/test/support/Casks/with-depends-on-arch-failure.rb @@ -0,0 +1,12 @@ +cask :v1test => 'with-depends-on-arch-failure' do + version '1.2.3' + sha256 '9203c30951f9aab41ac294bbeb1dcef7bed401ff0b353dcb34d68af32ea51853' + + url TestHelper.local_binary_url('caffeine.zip') + homepage 'http://example.com/with-depends-on-arch-failure' + + # guarantee mismatched hardware + depends_on :arch => Hardware::CPU.intel? ? :ppc : :intel + + app 'Caffeine.app' +end diff --git a/test/support/Casks/with-depends-on-arch.rb b/test/support/Casks/with-depends-on-arch.rb new file mode 100644 index 000000000000..886203ecd681 --- /dev/null +++ b/test/support/Casks/with-depends-on-arch.rb @@ -0,0 +1,12 @@ +cask :v1test => 'with-depends-on-arch' do + version '1.2.3' + sha256 '9203c30951f9aab41ac294bbeb1dcef7bed401ff0b353dcb34d68af32ea51853' + + url TestHelper.local_binary_url('caffeine.zip') + homepage 'http://example.com/with-depends-on-arch' + + # covers all known hardware; always succeeds + depends_on :arch => [:ppc, :intel] + + app 'Caffeine.app' +end