require 'download_strategy' require 'formula_support' require 'plist/parser' require 'uri' HOME_APPS = Pathname.new(File.expand_path("~/Applications")) class Cask; end require 'cask/cli' require 'cask/cli/edit' require 'cask/cli/install' require 'cask/cli/linkapps' require 'cask/cli/list' require 'cask/cli/search' require 'cask/dsl' require 'cask/exceptions' require 'cask/scopes' require 'plist/parser' class Cask include Cask::Scopes include Cask::DSL def self.tapspath HOMEBREW_PREFIX.join "Library", "Taps" end def self.cellarpath HOMEBREW_CELLAR end def self.init HOMEBREW_CACHE.mkpath HOME_APPS.mkpath end def self.path(cask_title) cask_title = all.grep(/#{cask_title}$/).first unless cask_title =~ /\// tapspath.join(cask_title.sub("/", "/Casks/") + ".rb") unless cask_title.nil? end def self.load(cask_title) cask_path = path(cask_title) raise CaskUnavailableError, cask_title unless cask_path require cask_path const_get(cask_title.split('/').last.split('-').map(&:capitalize).join).new end def self.title self.name.gsub(/([a-z\d])([A-Z])/,'\1-\2').downcase end attr_reader :title def initialize(title=self.class.title) @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| f.basename.to_s =~ /.app$/ 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 end