From 1a7e2789356e16a1415d24c097cba8f0262f521b Mon Sep 17 00:00:00 2001 From: phinze Date: Sat, 13 Oct 2012 16:48:25 -0500 Subject: [PATCH] a bona fide cask install test; and more splitting I chose Caffeine since it's relatively small to download. Eventually I'd like to switch this up so we bundle a dmg, zip, etc that the test suite wires in to verify that we do the Right Thing (tm) with all those file types. Probably will want to support `file://` URLs in Casks to help us for that use case. --- lib/cask.rb | 95 ++----------------------------------------- lib/cask/actions.rb | 23 +++++++++++ lib/cask/installer.rb | 73 +++++++++++++++++++++++++++++++++ test/cask_test.rb | 15 +++++++ 4 files changed, 115 insertions(+), 91 deletions(-) create mode 100644 lib/cask/actions.rb create mode 100644 lib/cask/installer.rb diff --git a/lib/cask.rb b/lib/cask.rb index 1e836e5c2..df9b62d4a 100644 --- a/lib/cask.rb +++ b/lib/cask.rb @@ -13,14 +13,17 @@ require 'cask/cli/install' require 'cask/cli/linkapps' require 'cask/cli/list' require 'cask/cli/search' +require 'cask/actions' require 'cask/dsl' require 'cask/exceptions' +require 'cask/installer' require 'cask/scopes' require 'plist/parser' class Cask - include Cask::Scopes + include Cask::Actions include Cask::DSL + include Cask::Scopes def self.tapspath HOMEBREW_PREFIX.join "Library", "Taps" @@ -56,43 +59,10 @@ class Cask @title = title end - VALID_SUFFIXES = ['dmg', 'pkg', 'app'] - def destination_path HOMEBREW_CELLAR.join(self.title).join(self.version) end - def install - downloader = CurlDownloadStrategy.new(self.title, SoftwareSpec.new(self.url.to_s, self.version)) - downloaded_path = downloader.fetch - - FileUtils.mkdir_p destination_path - - _with_extracted_mountpoints(downloaded_path) do |mountpoint| - puts `ditto '#{mountpoint}' '#{destination_path}'` - end - - ohai "Success! #{self} installed to #{destination_path}" - end - - def linkapps - destination_path.entries.select { |f| f.basename.to_s =~ /.app$/ }.each do |app| - symlink_destination = HOME_APPS.join(app.basename) - symlink_target = destination_path.join(app) - if symlink_destination.symlink? - puts "#{symlink_destination} exists but is symlink; removing and relinking" - puts "#{symlink_destination} -> #{symlink_target}" - symlink_destination.delete - symlink_destination.make_symlink(symlink_target) - elsif symlink_destination.directory? || symlink_destination.file? - puts "#{symlink_destination} already exists and is not a symlink, not linking #{self}" - else - puts "#{symlink_destination} -> #{symlink_target}" - symlink_destination.make_symlink(symlink_target) - end - end - end - def installed? return false unless destination_path.exist? destination_path.entries.any? do |f| @@ -100,63 +70,6 @@ class Cask end end - def _with_extracted_mountpoints(path) - if _dmg?(path) - File.open(path) do |dmg| - xml_str = `hdiutil mount -plist -nobrowse -readonly -noidme -mountrandom /tmp '#{dmg.path}'` - hdiutil_info = Plist::parse_xml(xml_str) - raise Exception.new("No disk entities returned by mount at #{dmg.path}") unless hdiutil_info.has_key?("system-entities") - mounts = hdiutil_info["system-entities"].collect { |entity| - entity["mount-point"] - }.compact - begin - mounts.each do |mountpoint| - yield Pathname.new(mountpoint) - end - ensure - mounts.each do |mountpoint| - `hdiutil eject '#{mountpoint}'` - end - end - end - elsif _zip?(path) - destdir = "/tmp/brewcask_#{@title}_extracted" - `mkdir -p '#{destdir}'` - `unzip -d '#{destdir}' '#{path}'` - begin - yield destdir - ensure - `rm -rf '#{destdir}'` - end - elsif _tar_bzip?(path) - destdir = "/tmp/brewcask_#{@title}_extracted" - `mkdir -p '#{destdir}'` - `tar jxf '#{path}' -C '#{destdir}'` - begin - yield destdir - ensure - `rm -rf '#{destdir}'` - end - else - raise "uh oh, could not identify type of #{path}" - end - end - - def _dmg?(path) - output = `hdiutil imageinfo '#{path}' 2>/dev/null` - output != '' - end - - def _zip?(path) - output = `file -Izb '#{path}'` - output.chomp.include? 'compressed-encoding=application/zip; charset=binary; charset=binary' - end - - def _tar_bzip?(path) - output = `file -Izb '#{path}'` - output.chomp == 'application/x-tar; charset=binary compressed-encoding=application/x-bzip2; charset=binary; charset=binary' - end - def to_s @title end diff --git a/lib/cask/actions.rb b/lib/cask/actions.rb new file mode 100644 index 000000000..a9d4c6c50 --- /dev/null +++ b/lib/cask/actions.rb @@ -0,0 +1,23 @@ +module Cask::Actions + def install + Cask::Installer.install(self) + end + + def linkapps + destination_path.entries.select { |f| f.basename.to_s =~ /.app$/ }.each do |app| + symlink_destination = HOME_APPS.join(app.basename) + symlink_target = destination_path.join(app) + if symlink_destination.symlink? + puts "#{symlink_destination} exists but is symlink; removing and relinking" + puts "#{symlink_destination} -> #{symlink_target}" + symlink_destination.delete + symlink_destination.make_symlink(symlink_target) + elsif symlink_destination.directory? || symlink_destination.file? + puts "#{symlink_destination} already exists and is not a symlink, not linking #{self}" + else + puts "#{symlink_destination} -> #{symlink_target}" + symlink_destination.make_symlink(symlink_target) + end + end + end +end diff --git a/lib/cask/installer.rb b/lib/cask/installer.rb new file mode 100644 index 000000000..145a04bcd --- /dev/null +++ b/lib/cask/installer.rb @@ -0,0 +1,73 @@ +class Cask::Installer + class << self + def install(cask) + downloader = CurlDownloadStrategy.new(cask.title, SoftwareSpec.new(cask.url.to_s, cask.version)) + downloaded_path = downloader.fetch + + FileUtils.mkdir_p cask.destination_path + + _with_extracted_mountpoints(downloaded_path) do |mountpoint| + puts `ditto '#{mountpoint}' '#{cask.destination_path}'` + end + + ohai "Success! #{cask} installed to #{cask.destination_path}" + end + + def _with_extracted_mountpoints(path) + if _dmg?(path) + File.open(path) do |dmg| + xml_str = `hdiutil mount -plist -nobrowse -readonly -noidme -mountrandom /tmp '#{dmg.path}'` + hdiutil_info = Plist::parse_xml(xml_str) + raise Exception.new("No disk entities returned by mount at #{dmg.path}") unless hdiutil_info.has_key?("system-entities") + mounts = hdiutil_info["system-entities"].collect { |entity| + entity["mount-point"] + }.compact + begin + mounts.each do |mountpoint| + yield Pathname.new(mountpoint) + end + ensure + mounts.each do |mountpoint| + `hdiutil eject '#{mountpoint}'` + end + end + end + elsif _zip?(path) + destdir = "/tmp/brewcask_#{@title}_extracted" + `mkdir -p '#{destdir}'` + `unzip -d '#{destdir}' '#{path}'` + begin + yield destdir + ensure + `rm -rf '#{destdir}'` + end + elsif _tar_bzip?(path) + destdir = "/tmp/brewcask_#{@title}_extracted" + `mkdir -p '#{destdir}'` + `tar jxf '#{path}' -C '#{destdir}'` + begin + yield destdir + ensure + `rm -rf '#{destdir}'` + end + else + raise "uh oh, could not identify type of #{path}" + end + end + + def _dmg?(path) + output = `hdiutil imageinfo '#{path}' 2>/dev/null` + output != '' + end + + def _zip?(path) + output = `file -Izb '#{path}'` + output.chomp.include? 'compressed-encoding=application/zip; charset=binary; charset=binary' + end + + def _tar_bzip?(path) + output = `file -Izb '#{path}'` + output.chomp == 'application/x-tar; charset=binary compressed-encoding=application/x-bzip2; charset=binary; charset=binary' + end + end +end diff --git a/test/cask_test.rb b/test/cask_test.rb index cb1da0f17..3a5f6ba9b 100644 --- a/test/cask_test.rb +++ b/test/cask_test.rb @@ -22,4 +22,19 @@ describe Cask do all_casks.each { |cask| cask.must_be_kind_of String } end end + + describe "install" do + it "downloads and installs a nice fresh Cask" do + caffeine = Cask.load('caffeine') + + shutup do + caffeine.install + end + + dest_path = HOMEBREW_CELLAR/'caffeine'/caffeine.version + dest_path.must_be :directory? + application = dest_path/'Caffeine.app' + application.must_be :directory? + end + end end