diff options
| author | Mike McQuaid | 2016-09-24 20:48:03 +0100 | 
|---|---|---|
| committer | Mike McQuaid | 2016-09-24 20:48:03 +0100 | 
| commit | e767fd3df9d179fca0445cc0bc0fdc061ad857d6 (patch) | |
| tree | 93e9db33313b36eebe7d7fb3aedf0f92cc2c3918 /Library/Homebrew/cask/lib | |
| parent | 7fc241765e3654718235791c32e5638bf7f8e15a (diff) | |
| parent | 232078df57418004bb9bf7abef877e734fcf7005 (diff) | |
| download | brew-e767fd3df9d179fca0445cc0bc0fdc061ad857d6.tar.bz2 | |
Merge branch 'master' into mkdir_with_intermediates
Diffstat (limited to 'Library/Homebrew/cask/lib')
134 files changed, 5932 insertions, 5448 deletions
diff --git a/Library/Homebrew/cask/lib/hbc.rb b/Library/Homebrew/cask/lib/hbc.rb index fd61558ab..62b391638 100644 --- a/Library/Homebrew/cask/lib/hbc.rb +++ b/Library/Homebrew/cask/lib/hbc.rb @@ -40,22 +40,22 @@ require "utils"  require "vendor/plist/plist"  module Hbc -  include Hbc::Locations -  include Hbc::Scopes -  include Hbc::Options -  include Hbc::Utils +  include Locations +  include Scopes +  include Options +  include Utils    def self.init -    Hbc::Cache.ensure_cache_exists -    Hbc::Cache.migrate_legacy_cache +    Cache.ensure_cache_exists +    Cache.migrate_legacy_cache -    Hbc::Caskroom.migrate_caskroom_from_repo_to_prefix -    Hbc::Caskroom.ensure_caskroom_exists +    Caskroom.migrate_caskroom_from_repo_to_prefix +    Caskroom.ensure_caskroom_exists    end    def self.load(query)      odebug "Loading Cask definitions" -    cask = Hbc::Source.for_query(query).load +    cask = Source.for_query(query).load      cask.dumpcask      cask    end diff --git a/Library/Homebrew/cask/lib/hbc/artifact.rb b/Library/Homebrew/cask/lib/hbc/artifact.rb index 73bd582a5..ec808a614 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact.rb @@ -1,5 +1,3 @@ -module Hbc::Artifact; end -  require "hbc/artifact/app"  require "hbc/artifact/artifact" # generic 'artifact' stanza  require "hbc/artifact/binary" @@ -24,42 +22,44 @@ require "hbc/artifact/suite"  require "hbc/artifact/uninstall"  require "hbc/artifact/zap" -module Hbc::Artifact -  # NOTE: order is important here, since we want to extract nested containers -  #       before we handle any other artifacts -  def self.artifacts -    [ -      Hbc::Artifact::PreflightBlock, -      Hbc::Artifact::NestedContainer, -      Hbc::Artifact::Installer, -      Hbc::Artifact::App, -      Hbc::Artifact::Suite, -      Hbc::Artifact::Artifact, # generic 'artifact' stanza -      Hbc::Artifact::Colorpicker, -      Hbc::Artifact::Pkg, -      Hbc::Artifact::Prefpane, -      Hbc::Artifact::Qlplugin, -      Hbc::Artifact::Font, -      Hbc::Artifact::Service, -      Hbc::Artifact::StageOnly, -      Hbc::Artifact::Binary, -      Hbc::Artifact::InputMethod, -      Hbc::Artifact::InternetPlugin, -      Hbc::Artifact::AudioUnitPlugin, -      Hbc::Artifact::VstPlugin, -      Hbc::Artifact::Vst3Plugin, -      Hbc::Artifact::ScreenSaver, -      Hbc::Artifact::Uninstall, -      Hbc::Artifact::PostflightBlock, -      Hbc::Artifact::Zap, -    ] -  end +module Hbc +  module Artifact +    # NOTE: order is important here, since we want to extract nested containers +    #       before we handle any other artifacts +    def self.artifacts +      [ +        PreflightBlock, +        NestedContainer, +        Installer, +        App, +        Suite, +        Artifact, # generic 'artifact' stanza +        Colorpicker, +        Pkg, +        Prefpane, +        Qlplugin, +        Font, +        Service, +        StageOnly, +        Binary, +        InputMethod, +        InternetPlugin, +        AudioUnitPlugin, +        VstPlugin, +        Vst3Plugin, +        ScreenSaver, +        Uninstall, +        PostflightBlock, +        Zap, +      ] +    end -  def self.for_cask(cask) -    odebug "Determining which artifacts are present in Cask #{cask}" -    artifacts.select do |artifact| -      odebug "Checking for artifact class #{artifact}" -      artifact.me?(cask) +    def self.for_cask(cask) +      odebug "Determining which artifacts are present in Cask #{cask}" +      artifacts.select do |artifact| +        odebug "Checking for artifact class #{artifact}" +        artifact.me?(cask) +      end      end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/abstract_flight_block.rb b/Library/Homebrew/cask/lib/hbc/artifact/abstract_flight_block.rb index fcf98d7ad..30709a0b5 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/abstract_flight_block.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/abstract_flight_block.rb @@ -1,36 +1,40 @@  require "hbc/artifact/base" -class Hbc::Artifact::AbstractFlightBlock < Hbc::Artifact::Base -  def self.artifact_dsl_key -    super.to_s.sub(%r{_block$}, "").to_sym -  end - -  def self.uninstall_artifact_dsl_key -    artifact_dsl_key.to_s.prepend("uninstall_").to_sym -  end - -  def self.class_for_dsl_key(dsl_key) -    Object.const_get("Hbc::DSL::#{dsl_key.to_s.split('_').collect(&:capitalize).join}") -  end - -  def self.me?(cask) -    cask.artifacts[artifact_dsl_key].any? || -      cask.artifacts[uninstall_artifact_dsl_key].any? -  end - -  def install_phase -    abstract_phase(self.class.artifact_dsl_key) -  end - -  def uninstall_phase -    abstract_phase(self.class.uninstall_artifact_dsl_key) -  end - -  private - -  def abstract_phase(dsl_key) -    @cask.artifacts[dsl_key].each do |block| -      self.class.class_for_dsl_key(dsl_key).new(@cask).instance_eval(&block) +module Hbc +  module Artifact +    class AbstractFlightBlock < Base +      def self.artifact_dsl_key +        super.to_s.sub(%r{_block$}, "").to_sym +      end + +      def self.uninstall_artifact_dsl_key +        artifact_dsl_key.to_s.prepend("uninstall_").to_sym +      end + +      def self.class_for_dsl_key(dsl_key) +        Object.const_get("Hbc::DSL::#{dsl_key.to_s.split("_").collect(&:capitalize).join}") +      end + +      def self.me?(cask) +        cask.artifacts[artifact_dsl_key].any? || +          cask.artifacts[uninstall_artifact_dsl_key].any? +      end + +      def install_phase +        abstract_phase(self.class.artifact_dsl_key) +      end + +      def uninstall_phase +        abstract_phase(self.class.uninstall_artifact_dsl_key) +      end + +      private + +      def abstract_phase(dsl_key) +        @cask.artifacts[dsl_key].each do |block| +          self.class.class_for_dsl_key(dsl_key).new(@cask).instance_eval(&block) +        end +      end      end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/app.rb b/Library/Homebrew/cask/lib/hbc/artifact/app.rb index bbda16f74..cc6ef61a7 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/app.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/app.rb @@ -1,4 +1,8 @@  require "hbc/artifact/moved" -class Hbc::Artifact::App < Hbc::Artifact::Moved +module Hbc +  module Artifact +    class App < Moved +    end +  end  end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/artifact.rb b/Library/Homebrew/cask/lib/hbc/artifact/artifact.rb index e2c06eb70..cb35821cc 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/artifact.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/artifact.rb @@ -1,20 +1,24 @@  require "hbc/artifact/moved" -class Hbc::Artifact::Artifact < Hbc::Artifact::Moved -  def self.artifact_english_name -    "Generic Artifact" -  end +module Hbc +  module Artifact +    class Artifact < Moved +      def self.artifact_english_name +        "Generic Artifact" +      end -  def self.artifact_dirmethod -    :appdir -  end +      def self.artifact_dirmethod +        :appdir +      end -  def load_specification(artifact_spec) -    source_string, target_hash = artifact_spec -    raise Hbc::CaskInvalidError.new(@cask.token, "no source given for artifact") if source_string.nil? -    @source = @cask.staged_path.join(source_string) -    raise Hbc::CaskInvalidError.new(@cask.token, "target required for generic artifact #{source_string}") unless target_hash.is_a?(Hash) -    target_hash.assert_valid_keys(:target) -    @target = Pathname.new(target_hash[:target]) +      def load_specification(artifact_spec) +        source_string, target_hash = artifact_spec +        raise CaskInvalidError.new(@cask.token, "no source given for artifact") if source_string.nil? +        @source = @cask.staged_path.join(source_string) +        raise CaskInvalidError.new(@cask.token, "target required for generic artifact #{source_string}") unless target_hash.is_a?(Hash) +        target_hash.assert_valid_keys(:target) +        @target = Pathname.new(target_hash[:target]) +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/audio_unit_plugin.rb b/Library/Homebrew/cask/lib/hbc/artifact/audio_unit_plugin.rb index 7f3999306..3bad78073 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/audio_unit_plugin.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/audio_unit_plugin.rb @@ -1,4 +1,8 @@  require "hbc/artifact/moved" -class Hbc::Artifact::AudioUnitPlugin < Hbc::Artifact::Moved +module Hbc +  module Artifact +    class AudioUnitPlugin < Moved +    end +  end  end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/base.rb b/Library/Homebrew/cask/lib/hbc/artifact/base.rb index 9a07cc906..141ab6881 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/base.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/base.rb @@ -1,79 +1,83 @@ -class Hbc::Artifact::Base -  def self.artifact_name -    @artifact_name ||= name.sub(%r{^.*:}, "").gsub(%r{(.)([A-Z])}, '\1_\2').downcase -  end - -  def self.artifact_english_name -    @artifact_english_name ||= name.sub(%r{^.*:}, "").gsub(%r{(.)([A-Z])}, '\1 \2') -  end - -  def self.artifact_english_article -    @artifact_english_article ||= artifact_english_name =~ %r{^[aeiou]}i ? "an" : "a" -  end - -  def self.artifact_dsl_key -    @artifact_dsl_key ||= artifact_name.to_sym -  end - -  def self.artifact_dirmethod -    @artifact_dirmethod ||= "#{artifact_name}dir".to_sym -  end - -  def self.me?(cask) -    cask.artifacts[artifact_dsl_key].any? -  end - -  attr_reader :force - -  def zap_phase -    odebug "Nothing to do. The #{self.class.artifact_name} artifact has no zap phase." -  end - -  # TODO: this sort of logic would make more sense in dsl.rb, or a -  #       constructor called from dsl.rb, so long as that isn't slow. -  def self.read_script_arguments(arguments, stanza, default_arguments = {}, override_arguments = {}, key = nil) -    # TODO: when stanza names are harmonized with class names, -    #       stanza may not be needed as an explicit argument -    description = stanza.to_s -    if key -      arguments = arguments[key] -      description.concat(" #{key.inspect}") -    end - -    # backward-compatible string value -    arguments = { executable: arguments } if arguments.is_a?(String) - -    # key sanity -    permitted_keys = [:args, :input, :executable, :must_succeed, :sudo, :bsexec, :print_stdout, :print_stderr] -    unknown_keys = arguments.keys - permitted_keys -    unless unknown_keys.empty? -      opoo %Q{Unknown arguments to #{description} -- #{unknown_keys.inspect} (ignored). Running "brew update; brew cleanup; brew cask cleanup" will likely fix it.} +module Hbc +  module Artifact +    class Base +      def self.artifact_name +        @artifact_name ||= name.sub(%r{^.*:}, "").gsub(%r{(.)([A-Z])}, '\1_\2').downcase +      end + +      def self.artifact_english_name +        @artifact_english_name ||= name.sub(%r{^.*:}, "").gsub(%r{(.)([A-Z])}, '\1 \2') +      end + +      def self.artifact_english_article +        @artifact_english_article ||= artifact_english_name =~ %r{^[aeiou]}i ? "an" : "a" +      end + +      def self.artifact_dsl_key +        @artifact_dsl_key ||= artifact_name.to_sym +      end + +      def self.artifact_dirmethod +        @artifact_dirmethod ||= "#{artifact_name}dir".to_sym +      end + +      def self.me?(cask) +        cask.artifacts[artifact_dsl_key].any? +      end + +      attr_reader :force + +      def zap_phase +        odebug "Nothing to do. The #{self.class.artifact_name} artifact has no zap phase." +      end + +      # TODO: this sort of logic would make more sense in dsl.rb, or a +      #       constructor called from dsl.rb, so long as that isn't slow. +      def self.read_script_arguments(arguments, stanza, default_arguments = {}, override_arguments = {}, key = nil) +        # TODO: when stanza names are harmonized with class names, +        #       stanza may not be needed as an explicit argument +        description = stanza.to_s +        if key +          arguments = arguments[key] +          description.concat(" #{key.inspect}") +        end + +        # backward-compatible string value +        arguments = { executable: arguments } if arguments.is_a?(String) + +        # key sanity +        permitted_keys = [:args, :input, :executable, :must_succeed, :sudo, :bsexec, :print_stdout, :print_stderr] +        unknown_keys = arguments.keys - permitted_keys +        unless unknown_keys.empty? +          opoo %Q{Unknown arguments to #{description} -- #{unknown_keys.inspect} (ignored). Running "brew update; brew cleanup; brew cask cleanup" will likely fix it.} +        end +        arguments.reject! { |k| !permitted_keys.include?(k) } + +        # key warnings +        override_keys = override_arguments.keys +        ignored_keys = arguments.keys & override_keys +        unless ignored_keys.empty? +          onoe "Some arguments to #{description} will be ignored -- :#{unknown_keys.inspect} (overridden)." +        end + +        # extract executable +        executable = arguments.key?(:executable) ? arguments.delete(:executable) : nil + +        arguments = default_arguments.merge arguments +        arguments.merge! override_arguments + +        [executable, arguments] +      end + +      def summary +        {} +      end + +      def initialize(cask, command: SystemCommand, force: false) +        @cask = cask +        @command = command +        @force = force +      end      end -    arguments.reject! { |k| !permitted_keys.include?(k) } - -    # key warnings -    override_keys = override_arguments.keys -    ignored_keys = arguments.keys & override_keys -    unless ignored_keys.empty? -      onoe "Some arguments to #{description} will be ignored -- :#{unknown_keys.inspect} (overridden)." -    end - -    # extract executable -    executable = arguments.key?(:executable) ? arguments.delete(:executable) : nil - -    arguments = default_arguments.merge arguments -    arguments.merge! override_arguments - -    [executable, arguments] -  end - -  def summary -    {} -  end - -  def initialize(cask, command: Hbc::SystemCommand, force: false) -    @cask = cask -    @command = command -    @force = force    end  end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/binary.rb b/Library/Homebrew/cask/lib/hbc/artifact/binary.rb index ccaebe0c8..646e5c3ad 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/binary.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/binary.rb @@ -1,7 +1,11 @@  require "hbc/artifact/symlinked" -class Hbc::Artifact::Binary < Hbc::Artifact::Symlinked -  def install_phase -    super unless Hbc.no_binaries +module Hbc +  module Artifact +    class Binary < Symlinked +      def install_phase +        super unless Hbc.no_binaries +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/colorpicker.rb b/Library/Homebrew/cask/lib/hbc/artifact/colorpicker.rb index 7b56d0ffc..a866e64a5 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/colorpicker.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/colorpicker.rb @@ -1,4 +1,8 @@  require "hbc/artifact/moved" -class Hbc::Artifact::Colorpicker < Hbc::Artifact::Moved +module Hbc +  module Artifact +    class Colorpicker < Moved +    end +  end  end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/font.rb b/Library/Homebrew/cask/lib/hbc/artifact/font.rb index 9697d9e13..5c64869b6 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/font.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/font.rb @@ -1,4 +1,8 @@  require "hbc/artifact/moved" -class Hbc::Artifact::Font < Hbc::Artifact::Moved +module Hbc +  module Artifact +    class Font < Moved +    end +  end  end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/input_method.rb b/Library/Homebrew/cask/lib/hbc/artifact/input_method.rb index 3c7f3d990..0eb75a6c0 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/input_method.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/input_method.rb @@ -1,4 +1,8 @@  require "hbc/artifact/moved" -class Hbc::Artifact::InputMethod < Hbc::Artifact::Moved +module Hbc +  module Artifact +    class InputMethod < Moved +    end +  end  end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/installer.rb b/Library/Homebrew/cask/lib/hbc/artifact/installer.rb index 2f66397e9..b64b00fe3 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/installer.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/installer.rb @@ -1,41 +1,45 @@  require "hbc/artifact/base" -class Hbc::Artifact::Installer < Hbc::Artifact::Base -  # TODO: for backward compatibility, removeme -  def install -    install_phase -  end +module Hbc +  module Artifact +    class Installer < Base +      # TODO: for backward compatibility, removeme +      def install +        install_phase +      end -  # TODO: for backward compatibility, removeme -  def uninstall -    uninstall_phase -  end +      # TODO: for backward compatibility, removeme +      def uninstall +        uninstall_phase +      end -  def install_phase -    @cask.artifacts[self.class.artifact_dsl_key].each do |artifact| -      if artifact.manual -        puts <<-EOS.undent -          To complete the installation of Cask #{@cask}, you must also -          run the installer at +      def install_phase +        @cask.artifacts[self.class.artifact_dsl_key].each do |artifact| +          if artifact.manual +            puts <<-EOS.undent +              To complete the installation of Cask #{@cask}, you must also +              run the installer at -            '#{@cask.staged_path.join(artifact.manual)}' +                '#{@cask.staged_path.join(artifact.manual)}' -        EOS -      else -        executable, script_arguments = self.class.read_script_arguments(artifact.script, -                                                                        self.class.artifact_dsl_key.to_s, -                                                                        { must_succeed: true, sudo: true }, -                                                                        print_stdout: true) -        ohai "Running #{self.class.artifact_dsl_key} script #{executable}" -        raise Hbc::CaskInvalidError.new(@cask, "#{self.class.artifact_dsl_key} missing executable") if executable.nil? -        executable_path = @cask.staged_path.join(executable) -        @command.run("/bin/chmod", args: ["--", "+x", executable_path]) if File.exist?(executable_path) -        @command.run(executable_path, script_arguments) +            EOS +          else +            executable, script_arguments = self.class.read_script_arguments(artifact.script, +                                                                            self.class.artifact_dsl_key.to_s, +                                                                            { must_succeed: true, sudo: true }, +                                                                            print_stdout: true) +            ohai "Running #{self.class.artifact_dsl_key} script #{executable}" +            raise CaskInvalidError.new(@cask, "#{self.class.artifact_dsl_key} missing executable") if executable.nil? +            executable_path = @cask.staged_path.join(executable) +            @command.run("/bin/chmod", args: ["--", "+x", executable_path]) if File.exist?(executable_path) +            @command.run(executable_path, script_arguments) +          end +        end        end -    end -  end -  def uninstall_phase -    odebug "Nothing to do. The #{self.class.artifact_dsl_key} artifact has no uninstall phase." +      def uninstall_phase +        odebug "Nothing to do. The #{self.class.artifact_dsl_key} artifact has no uninstall phase." +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/internet_plugin.rb b/Library/Homebrew/cask/lib/hbc/artifact/internet_plugin.rb index a44418274..ab8586d69 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/internet_plugin.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/internet_plugin.rb @@ -1,4 +1,8 @@  require "hbc/artifact/moved" -class Hbc::Artifact::InternetPlugin < Hbc::Artifact::Moved +module Hbc +  module Artifact +    class InternetPlugin < Moved +    end +  end  end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/moved.rb b/Library/Homebrew/cask/lib/hbc/artifact/moved.rb index 8565ab836..6095887e3 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/moved.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/moved.rb @@ -1,88 +1,92 @@  require "hbc/artifact/relocated" -class Hbc::Artifact::Moved < Hbc::Artifact::Relocated -  def self.english_description -    "#{artifact_english_name}s" -  end +module Hbc +  module Artifact +    class Moved < Relocated +      def self.english_description +        "#{artifact_english_name}s" +      end -  def install_phase -    each_artifact do |artifact| -      load_specification(artifact) -      next unless preflight_checks -      delete if Hbc::Utils.path_occupied?(target) && force -      move -    end -  end +      def install_phase +        each_artifact do |artifact| +          load_specification(artifact) +          next unless preflight_checks +          delete if Utils.path_occupied?(target) && force +          move +        end +      end -  def uninstall_phase -    each_artifact do |artifact| -      load_specification(artifact) -      next unless File.exist?(target) -      delete -    end -  end +      def uninstall_phase +        each_artifact do |artifact| +          load_specification(artifact) +          next unless File.exist?(target) +          delete +        end +      end -  private +      private -  def each_artifact -    # the sort is for predictability between Ruby versions -    @cask.artifacts[self.class.artifact_dsl_key].sort.each do |artifact| -      yield artifact -    end -  end +      def each_artifact +        # the sort is for predictability between Ruby versions +        @cask.artifacts[self.class.artifact_dsl_key].sort.each do |artifact| +          yield artifact +        end +      end -  def move -    ohai "Moving #{self.class.artifact_english_name} '#{source.basename}' to '#{target}'" -    target.dirname.mkpath -    FileUtils.move(source, target) -    add_altname_metadata target, source.basename.to_s -  end +      def move +        ohai "Moving #{self.class.artifact_english_name} '#{source.basename}' to '#{target}'" +        target.dirname.mkpath +        FileUtils.move(source, target) +        add_altname_metadata target, source.basename.to_s +      end -  def preflight_checks -    if Hbc::Utils.path_occupied?(target) -      if force -        ohai(warning_target_exists { |s| s << "overwriting." }) -      else -        ohai(warning_target_exists { |s| s << "not moving." }) -        return false +      def preflight_checks +        if Utils.path_occupied?(target) +          if force +            ohai(warning_target_exists { |s| s << "overwriting." }) +          else +            ohai(warning_target_exists { |s| s << "not moving." }) +            return false +          end +        end +        unless source.exist? +          message = "It seems the #{self.class.artifact_english_name} source is not there: '#{source}'" +          raise CaskError, message +        end +        true        end -    end -    unless source.exist? -      message = "It seems the #{self.class.artifact_english_name} source is not there: '#{source}'" -      raise Hbc::CaskError, message -    end -    true -  end -  def warning_target_exists -    message_parts = [ -                      "It seems there is already #{self.class.artifact_english_article} #{self.class.artifact_english_name} at '#{target}'", -                    ] -    yield(message_parts) if block_given? -    message_parts.join("; ") -  end +      def warning_target_exists +        message_parts = [ +                          "It seems there is already #{self.class.artifact_english_article} #{self.class.artifact_english_name} at '#{target}'", +                        ] +        yield(message_parts) if block_given? +        message_parts.join("; ") +      end -  def delete -    ohai "Removing #{self.class.artifact_english_name}: '#{target}'" -    if MacOS.undeletable?(target) -      raise Hbc::CaskError, "Cannot remove undeletable #{self.class.artifact_english_name}" -    elsif force -      Hbc::Utils.gain_permissions_remove(target, command: @command) -    else -      target.rmtree -    end -  end +      def delete +        ohai "Removing #{self.class.artifact_english_name}: '#{target}'" +        raise CaskError, "Cannot remove undeletable #{self.class.artifact_english_name}" if MacOS.undeletable?(target) -  def summarize_artifact(artifact_spec) -    load_specification artifact_spec +        if force +          Utils.gain_permissions_remove(target, command: @command) +        else +          target.rmtree +        end +      end -    if target.exist? -      target_abv = " (#{target.abv})" -    else -      warning = "Missing #{self.class.artifact_english_name}" -      warning = "#{Tty.red}#{warning}#{Tty.reset}: " -    end +      def summarize_artifact(artifact_spec) +        load_specification artifact_spec -    "#{warning}#{printable_target}#{target_abv}" +        if target.exist? +          target_abv = " (#{target.abv})" +        else +          warning = "Missing #{self.class.artifact_english_name}" +          warning = "#{Tty.red}#{warning}#{Tty.reset}: " +        end + +        "#{warning}#{printable_target}#{target_abv}" +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/nested_container.rb b/Library/Homebrew/cask/lib/hbc/artifact/nested_container.rb index 68e4a552c..107640797 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/nested_container.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/nested_container.rb @@ -1,24 +1,28 @@  require "hbc/artifact/base" -class Hbc::Artifact::NestedContainer < Hbc::Artifact::Base -  def install_phase -    @cask.artifacts[:nested_container].each { |container| extract(container) } -  end +module Hbc +  module Artifact +    class NestedContainer < Base +      def install_phase +        @cask.artifacts[:nested_container].each { |container| extract(container) } +      end -  def uninstall_phase -    # no need to take action; is removed after extraction -  end +      def uninstall_phase +        # no need to take action; is removed after extraction +      end -  def extract(container_relative_path) -    source = @cask.staged_path.join(container_relative_path) -    container = Hbc::Container.for_path(source, @command) +      def extract(container_relative_path) +        source = @cask.staged_path.join(container_relative_path) +        container = Container.for_path(source, @command) -    unless container -      raise Hbc::CaskError, "Aw dang, could not identify nested container at '#{source}'" -    end +        unless container +          raise CaskError, "Aw dang, could not identify nested container at '#{source}'" +        end -    ohai "Extracting nested container #{source.basename}" -    container.new(@cask, source, @command).extract -    FileUtils.remove_entry_secure(source) +        ohai "Extracting nested container #{source.basename}" +        container.new(@cask, source, @command).extract +        FileUtils.remove_entry_secure(source) +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/pkg.rb b/Library/Homebrew/cask/lib/hbc/artifact/pkg.rb index fb27308d7..e590a9082 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/pkg.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/pkg.rb @@ -1,53 +1,57 @@  require "hbc/artifact/base" -class Hbc::Artifact::Pkg < Hbc::Artifact::Base -  attr_reader :pkg_relative_path +module Hbc +  module Artifact +    class Pkg < Base +      attr_reader :pkg_relative_path -  def self.artifact_dsl_key -    :pkg -  end +      def self.artifact_dsl_key +        :pkg +      end -  def load_pkg_description(pkg_description) -    @pkg_relative_path = pkg_description.shift -    @pkg_install_opts = pkg_description.shift -    begin -      if @pkg_install_opts.respond_to?(:keys) -        @pkg_install_opts.assert_valid_keys(:allow_untrusted) -      elsif @pkg_install_opts -        raise +      def load_pkg_description(pkg_description) +        @pkg_relative_path = pkg_description.shift +        @pkg_install_opts = pkg_description.shift +        begin +          if @pkg_install_opts.respond_to?(:keys) +            @pkg_install_opts.assert_valid_keys(:allow_untrusted) +          elsif @pkg_install_opts +            raise +          end +          raise if pkg_description.nil? +        rescue StandardError +          raise CaskInvalidError.new(@cask, "Bad pkg stanza") +        end        end -      raise if pkg_description.nil? -    rescue StandardError -      raise Hbc::CaskInvalidError.new(@cask, "Bad pkg stanza") -    end -  end -  def pkg_install_opts(opt) -    @pkg_install_opts[opt] if @pkg_install_opts.respond_to?(:keys) -  end +      def pkg_install_opts(opt) +        @pkg_install_opts[opt] if @pkg_install_opts.respond_to?(:keys) +      end -  def install_phase -    @cask.artifacts[:pkg].each { |pkg_description| run_installer(pkg_description) } -  end +      def install_phase +        @cask.artifacts[:pkg].each { |pkg_description| run_installer(pkg_description) } +      end -  def uninstall_phase -    # Do nothing. Must be handled explicitly by a separate :uninstall stanza. -  end +      def uninstall_phase +        # Do nothing. Must be handled explicitly by a separate :uninstall stanza. +      end -  def run_installer(pkg_description) -    load_pkg_description pkg_description -    ohai "Running installer for #{@cask}; your password may be necessary." -    ohai "Package installers may write to any location; options such as --appdir are ignored." -    source = @cask.staged_path.join(pkg_relative_path) -    unless source.exist? -      raise Hbc::CaskError, "pkg source file not found: '#{source}'" +      def run_installer(pkg_description) +        load_pkg_description pkg_description +        ohai "Running installer for #{@cask}; your password may be necessary." +        ohai "Package installers may write to any location; options such as --appdir are ignored." +        source = @cask.staged_path.join(pkg_relative_path) +        unless source.exist? +          raise CaskError, "pkg source file not found: '#{source}'" +        end +        args = [ +                 "-pkg",    source, +                 "-target", "/" +               ] +        args << "-verboseR" if Hbc.verbose +        args << "-allowUntrusted" if pkg_install_opts :allow_untrusted +        @command.run!("/usr/sbin/installer", sudo: true, args: args, print_stdout: true) +      end      end -    args = [ -             "-pkg",    source, -             "-target", "/" -           ] -    args << "-verboseR" if Hbc.verbose -    args << "-allowUntrusted" if pkg_install_opts :allow_untrusted -    @command.run!("/usr/sbin/installer", sudo: true, args: args, print_stdout: true)    end  end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/postflight_block.rb b/Library/Homebrew/cask/lib/hbc/artifact/postflight_block.rb index 92b21a83f..bfe218f95 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/postflight_block.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/postflight_block.rb @@ -1,4 +1,8 @@  require "hbc/artifact/abstract_flight_block" -class Hbc::Artifact::PostflightBlock < Hbc::Artifact::AbstractFlightBlock +module Hbc +  module Artifact +    class PostflightBlock < AbstractFlightBlock +    end +  end  end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/preflight_block.rb b/Library/Homebrew/cask/lib/hbc/artifact/preflight_block.rb index 772a88016..35142df47 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/preflight_block.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/preflight_block.rb @@ -1,4 +1,8 @@  require "hbc/artifact/abstract_flight_block" -class Hbc::Artifact::PreflightBlock < Hbc::Artifact::AbstractFlightBlock +module Hbc +  module Artifact +    class PreflightBlock < AbstractFlightBlock +    end +  end  end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/prefpane.rb b/Library/Homebrew/cask/lib/hbc/artifact/prefpane.rb index e45cc0b19..a44f8ae3a 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/prefpane.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/prefpane.rb @@ -1,7 +1,11 @@  require "hbc/artifact/moved" -class Hbc::Artifact::Prefpane < Hbc::Artifact::Moved -  def self.artifact_english_name -    "Preference Pane" +module Hbc +  module Artifact +    class Prefpane < Moved +      def self.artifact_english_name +        "Preference Pane" +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/qlplugin.rb b/Library/Homebrew/cask/lib/hbc/artifact/qlplugin.rb index 6702aa5ef..ee41de2fe 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/qlplugin.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/qlplugin.rb @@ -1,21 +1,25 @@  require "hbc/artifact/moved" -class Hbc::Artifact::Qlplugin < Hbc::Artifact::Moved -  def self.artifact_english_name -    "QuickLook Plugin" -  end +module Hbc +  module Artifact +    class Qlplugin < Moved +      def self.artifact_english_name +        "QuickLook Plugin" +      end -  def install_phase -    super -    reload_quicklook -  end +      def install_phase +        super +        reload_quicklook +      end -  def uninstall_phase -    super -    reload_quicklook -  end +      def uninstall_phase +        super +        reload_quicklook +      end -  def reload_quicklook -    @command.run!("/usr/bin/qlmanage", args: ["-r"]) +      def reload_quicklook +        @command.run!("/usr/bin/qlmanage", args: ["-r"]) +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/relocated.rb b/Library/Homebrew/cask/lib/hbc/artifact/relocated.rb index cd0054188..953045b32 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/relocated.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/relocated.rb @@ -1,53 +1,57 @@  require "hbc/artifact/base" -class Hbc::Artifact::Relocated < Hbc::Artifact::Base -  def summary -    { -      english_description: self.class.english_description, -      contents:            @cask.artifacts[self.class.artifact_dsl_key].map(&method(:summarize_artifact)).compact, -    } -  end - -  attr_reader :source, :target - -  def printable_target -    target.to_s.sub(%r{^#{ENV['HOME']}(#{File::SEPARATOR}|$)}, "~/") -  end - -  ALT_NAME_ATTRIBUTE = "com.apple.metadata:kMDItemAlternateNames".freeze - -  # Try to make the asset searchable under the target name.  Spotlight -  # respects this attribute for many filetypes, but ignores it for App -  # bundles. Alfred 2.2 respects it even for App bundles. -  def add_altname_metadata(file, altname) -    return if altname.casecmp(file.basename).zero? -    odebug "Adding #{ALT_NAME_ATTRIBUTE} metadata" -    altnames = @command.run("/usr/bin/xattr", -                            args:         ["-p", ALT_NAME_ATTRIBUTE, file.to_s], -                            print_stderr: false).stdout.sub(%r{\A\((.*)\)\Z}, '\1') -    odebug "Existing metadata is: '#{altnames}'" -    altnames.concat(", ") unless altnames.empty? -    altnames.concat(%Q{"#{altname}"}) -    altnames = "(#{altnames})" - -    # Some packges are shipped as u=rx (e.g. Bitcoin Core) -    @command.run!("/bin/chmod", args: ["--", "u=rwx", file.to_s, file.realpath.to_s]) - -    @command.run!("/usr/bin/xattr", -                  args:         ["-w", ALT_NAME_ATTRIBUTE, altnames, file.to_s], -                  print_stderr: false) -  end - -  def load_specification(artifact_spec) -    source_string, target_hash = artifact_spec -    raise Hbc::CaskInvalidError if source_string.nil? -    @source = @cask.staged_path.join(source_string) -    if target_hash -      raise Hbc::CaskInvalidError unless target_hash.respond_to?(:keys) -      target_hash.assert_valid_keys(:target) -      @target = Hbc.send(self.class.artifact_dirmethod).join(target_hash[:target]) -    else -      @target = Hbc.send(self.class.artifact_dirmethod).join(source.basename) +module Hbc +  module Artifact +    class Relocated < Base +      def summary +        { +          english_description: self.class.english_description, +          contents:            @cask.artifacts[self.class.artifact_dsl_key].map(&method(:summarize_artifact)).compact, +        } +      end + +      attr_reader :source, :target + +      def printable_target +        target.to_s.sub(%r{^#{ENV['HOME']}(#{File::SEPARATOR}|$)}, "~/") +      end + +      ALT_NAME_ATTRIBUTE = "com.apple.metadata:kMDItemAlternateNames".freeze + +      # Try to make the asset searchable under the target name.  Spotlight +      # respects this attribute for many filetypes, but ignores it for App +      # bundles. Alfred 2.2 respects it even for App bundles. +      def add_altname_metadata(file, altname) +        return if altname.casecmp(file.basename).zero? +        odebug "Adding #{ALT_NAME_ATTRIBUTE} metadata" +        altnames = @command.run("/usr/bin/xattr", +                                args:         ["-p", ALT_NAME_ATTRIBUTE, file.to_s], +                                print_stderr: false).stdout.sub(%r{\A\((.*)\)\Z}, '\1') +        odebug "Existing metadata is: '#{altnames}'" +        altnames.concat(", ") unless altnames.empty? +        altnames.concat(%Q{"#{altname}"}) +        altnames = "(#{altnames})" + +        # Some packges are shipped as u=rx (e.g. Bitcoin Core) +        @command.run!("/bin/chmod", args: ["--", "u=rwx", file.to_s, file.realpath.to_s]) + +        @command.run!("/usr/bin/xattr", +                      args:         ["-w", ALT_NAME_ATTRIBUTE, altnames, file.to_s], +                      print_stderr: false) +      end + +      def load_specification(artifact_spec) +        source_string, target_hash = artifact_spec +        raise CaskInvalidError if source_string.nil? +        @source = @cask.staged_path.join(source_string) +        if target_hash +          raise CaskInvalidError unless target_hash.respond_to?(:keys) +          target_hash.assert_valid_keys(:target) +          @target = Hbc.send(self.class.artifact_dirmethod).join(target_hash[:target]) +        else +          @target = Hbc.send(self.class.artifact_dirmethod).join(source.basename) +        end +      end      end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/screen_saver.rb b/Library/Homebrew/cask/lib/hbc/artifact/screen_saver.rb index bbd929152..4cdc6037c 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/screen_saver.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/screen_saver.rb @@ -1,4 +1,8 @@  require "hbc/artifact/moved" -class Hbc::Artifact::ScreenSaver < Hbc::Artifact::Moved +module Hbc +  module Artifact +    class ScreenSaver < Moved +    end +  end  end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/service.rb b/Library/Homebrew/cask/lib/hbc/artifact/service.rb index d5a00e4fe..1af93c533 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/service.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/service.rb @@ -1,4 +1,8 @@  require "hbc/artifact/moved" -class Hbc::Artifact::Service < Hbc::Artifact::Moved +module Hbc +  module Artifact +    class Service < Moved +    end +  end  end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/stage_only.rb b/Library/Homebrew/cask/lib/hbc/artifact/stage_only.rb index 7a48b19aa..594c5bef9 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/stage_only.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/stage_only.rb @@ -1,15 +1,19 @@  require "hbc/artifact/base" -class Hbc::Artifact::StageOnly < Hbc::Artifact::Base -  def self.artifact_dsl_key -    :stage_only -  end +module Hbc +  module Artifact +    class StageOnly < Base +      def self.artifact_dsl_key +        :stage_only +      end -  def install_phase -    # do nothing -  end +      def install_phase +        # do nothing +      end -  def uninstall_phase -    # do nothing +      def uninstall_phase +        # do nothing +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/suite.rb b/Library/Homebrew/cask/lib/hbc/artifact/suite.rb index cdfb757dd..35251f70c 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/suite.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/suite.rb @@ -1,11 +1,15 @@  require "hbc/artifact/moved" -class Hbc::Artifact::Suite < Hbc::Artifact::Moved -  def self.artifact_english_name -    "App Suite" -  end +module Hbc +  module Artifact +    class Suite < Moved +      def self.artifact_english_name +        "App Suite" +      end -  def self.artifact_dirmethod -    :appdir +      def self.artifact_dirmethod +        :appdir +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/symlinked.rb b/Library/Homebrew/cask/lib/hbc/artifact/symlinked.rb index 7432df577..3ab45cccc 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/symlinked.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/symlinked.rb @@ -1,65 +1,69 @@  require "hbc/artifact/relocated" -class Hbc::Artifact::Symlinked < Hbc::Artifact::Relocated -  def self.link_type_english_name -    "Symlink" -  end +module Hbc +  module Artifact +    class Symlinked < Relocated +      def self.link_type_english_name +        "Symlink" +      end -  def self.english_description -    "#{artifact_english_name} #{link_type_english_name}s" -  end +      def self.english_description +        "#{artifact_english_name} #{link_type_english_name}s" +      end -  def self.islink?(path) -    path.symlink? -  end +      def self.islink?(path) +        path.symlink? +      end -  def link(artifact_spec) -    load_specification artifact_spec -    return unless preflight_checks(source, target) -    ohai "#{self.class.link_type_english_name}ing #{self.class.artifact_english_name} '#{source.basename}' to '#{target}'" -    create_filesystem_link(source, target) -  end +      def link(artifact_spec) +        load_specification artifact_spec +        return unless preflight_checks(source, target) +        ohai "#{self.class.link_type_english_name}ing #{self.class.artifact_english_name} '#{source.basename}' to '#{target}'" +        create_filesystem_link(source, target) +      end -  def unlink(artifact_spec) -    load_specification artifact_spec -    return unless self.class.islink?(target) -    ohai "Removing #{self.class.artifact_english_name} #{self.class.link_type_english_name.downcase}: '#{target}'" -    target.delete -  end +      def unlink(artifact_spec) +        load_specification artifact_spec +        return unless self.class.islink?(target) +        ohai "Removing #{self.class.artifact_english_name} #{self.class.link_type_english_name.downcase}: '#{target}'" +        target.delete +      end -  def install_phase -    @cask.artifacts[self.class.artifact_dsl_key].each(&method(:link)) -  end +      def install_phase +        @cask.artifacts[self.class.artifact_dsl_key].each(&method(:link)) +      end -  def uninstall_phase -    @cask.artifacts[self.class.artifact_dsl_key].each(&method(:unlink)) -  end +      def uninstall_phase +        @cask.artifacts[self.class.artifact_dsl_key].each(&method(:unlink)) +      end -  def preflight_checks(source, target) -    if target.exist? && !self.class.islink?(target) -      ohai "It seems there is already #{self.class.artifact_english_article} #{self.class.artifact_english_name} at '#{target}'; not linking." -      return false -    end -    unless source.exist? -      raise Hbc::CaskError, "It seems the #{self.class.link_type_english_name.downcase} source is not there: '#{source}'" -    end -    true -  end +      def preflight_checks(source, target) +        if target.exist? && !self.class.islink?(target) +          ohai "It seems there is already #{self.class.artifact_english_article} #{self.class.artifact_english_name} at '#{target}'; not linking." +          return false +        end +        unless source.exist? +          raise CaskError, "It seems the #{self.class.link_type_english_name.downcase} source is not there: '#{source}'" +        end +        true +      end -  def create_filesystem_link(source, target) -    Pathname.new(target).dirname.mkpath -    @command.run!("/bin/ln", args: ["-hfs", "--", source, target]) -    add_altname_metadata source, target.basename.to_s -  end +      def create_filesystem_link(source, target) +        Pathname.new(target).dirname.mkpath +        @command.run!("/bin/ln", args: ["-hfs", "--", source, target]) +        add_altname_metadata source, target.basename.to_s +      end -  def summarize_artifact(artifact_spec) -    load_specification artifact_spec +      def summarize_artifact(artifact_spec) +        load_specification artifact_spec -    return unless self.class.islink?(target) +        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? +        link_description = "#{Tty.red}Broken Link#{Tty.reset}: " unless target.exist? +        target_readlink_abv = " (#{target.readlink.abv})" if target.readlink.exist? -    "#{link_description}#{printable_target} -> #{target.readlink}#{target_readlink_abv}" +        "#{link_description}#{printable_target} -> #{target.readlink}#{target_readlink_abv}" +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/uninstall.rb b/Library/Homebrew/cask/lib/hbc/artifact/uninstall.rb index 12010aeb8..8b5603064 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/uninstall.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/uninstall.rb @@ -1,4 +1,8 @@  require "hbc/artifact/uninstall_base" -class Hbc::Artifact::Uninstall < Hbc::Artifact::UninstallBase +module Hbc +  module Artifact +    class Uninstall < UninstallBase +    end +  end  end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/uninstall_base.rb b/Library/Homebrew/cask/lib/hbc/artifact/uninstall_base.rb index f92e09a89..63ffd18c9 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/uninstall_base.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/uninstall_base.rb @@ -2,248 +2,252 @@ require "pathname"  require "hbc/artifact/base" -class Hbc::Artifact::UninstallBase < Hbc::Artifact::Base -  # TODO: 500 is also hardcoded in cask/pkg.rb, but much of -  #       that logic is probably in the wrong location - -  PATH_ARG_SLICE_SIZE = 500 - -  ORDERED_DIRECTIVES = [ -                         :early_script, -                         :launchctl, -                         :quit, -                         :signal, -                         :login_item, -                         :kext, -                         :script, -                         :pkgutil, -                         :delete, -                         :trash, -                         :rmdir, -                       ].freeze - -  # TODO: these methods were consolidated here from separate -  #       sources and should be refactored for consistency - -  def self.expand_path_strings(path_strings) -    path_strings.map { |path_string| -      path_string.start_with?("~") ? Pathname.new(path_string).expand_path : Pathname.new(path_string) -    } -  end +module Hbc +  module Artifact +    class UninstallBase < Base +      # TODO: 500 is also hardcoded in cask/pkg.rb, but much of +      #       that logic is probably in the wrong location + +      PATH_ARG_SLICE_SIZE = 500 + +      ORDERED_DIRECTIVES = [ +                             :early_script, +                             :launchctl, +                             :quit, +                             :signal, +                             :login_item, +                             :kext, +                             :script, +                             :pkgutil, +                             :delete, +                             :trash, +                             :rmdir, +                           ].freeze + +      # TODO: these methods were consolidated here from separate +      #       sources and should be refactored for consistency + +      def self.expand_path_strings(path_strings) +        path_strings.map { |path_string| +          path_string.start_with?("~") ? Pathname.new(path_string).expand_path : Pathname.new(path_string) +        } +      end -  def self.remove_relative_path_strings(action, path_strings) -    relative = path_strings.map { |path_string| -      path_string if %r{/\.\.(?:/|\Z)}.match(path_string) || !%r{\A/}.match(path_string) -    }.compact -    relative.each do |path_string| -      opoo "Skipping #{action} for relative path #{path_string}" -    end -    path_strings - relative -  end +      def self.remove_relative_path_strings(action, path_strings) +        relative = path_strings.map { |path_string| +          path_string if %r{/\.\.(?:/|\Z)}.match(path_string) || !%r{\A/}.match(path_string) +        }.compact +        relative.each do |path_string| +          opoo "Skipping #{action} for relative path #{path_string}" +        end +        path_strings - relative +      end -  def self.remove_undeletable_path_strings(action, path_strings) -    undeletable = path_strings.map { |path_string| -      path_string if MacOS.undeletable?(Pathname.new(path_string)) -    }.compact -    undeletable.each do |path_string| -      opoo "Skipping #{action} for undeletable path #{path_string}" -    end -    path_strings - undeletable -  end +      def self.remove_undeletable_path_strings(action, path_strings) +        undeletable = path_strings.map { |path_string| +          path_string if MacOS.undeletable?(Pathname.new(path_string)) +        }.compact +        undeletable.each do |path_string| +          opoo "Skipping #{action} for undeletable path #{path_string}" +        end +        path_strings - undeletable +      end -  def install_phase -    odebug "Nothing to do. The uninstall artifact has no install phase." -  end +      def install_phase +        odebug "Nothing to do. The uninstall artifact has no install phase." +      end -  def uninstall_phase -    dispatch_uninstall_directives -  end +      def uninstall_phase +        dispatch_uninstall_directives +      end -  def dispatch_uninstall_directives(expand_tilde = true) -    directives_set = @cask.artifacts[stanza] -    ohai "Running #{stanza} process for #{@cask}; your password may be necessary" +      def dispatch_uninstall_directives(expand_tilde = true) +        directives_set = @cask.artifacts[stanza] +        ohai "Running #{stanza} process for #{@cask}; your password may be necessary" -    directives_set.each do |directives| -      warn_for_unknown_directives(directives) -    end +        directives_set.each do |directives| +          warn_for_unknown_directives(directives) +        end -    ORDERED_DIRECTIVES.each do |directive_sym| -      directives_set.select { |h| h.key?(directive_sym) }.each do |directives| -        args = [directives] -        args << expand_tilde if [:delete, :trash, :rmdir].include?(directive_sym) -        send("uninstall_#{directive_sym}", *args) +        ORDERED_DIRECTIVES.each do |directive_sym| +          directives_set.select { |h| h.key?(directive_sym) }.each do |directives| +            args = [directives] +            args << expand_tilde if [:delete, :trash, :rmdir].include?(directive_sym) +            send("uninstall_#{directive_sym}", *args) +          end +        end        end -    end -  end -  private +      private -  def stanza -    self.class.artifact_dsl_key -  end +      def stanza +        self.class.artifact_dsl_key +      end -  def warn_for_unknown_directives(directives) -    unknown_keys = directives.keys - ORDERED_DIRECTIVES -    return if unknown_keys.empty? -    opoo %Q{Unknown arguments to #{stanza} -- #{unknown_keys.inspect}. Running "brew update; brew cleanup; brew cask cleanup" will likely fix it.} -  end +      def warn_for_unknown_directives(directives) +        unknown_keys = directives.keys - ORDERED_DIRECTIVES +        return if unknown_keys.empty? +        opoo %Q{Unknown arguments to #{stanza} -- #{unknown_keys.inspect}. Running "brew update; brew cleanup; brew cask cleanup" will likely fix it.} +      end -  # Preserve prior functionality of script which runs first. Should rarely be needed. -  # :early_script should not delete files, better defer that to :script. -  # If Cask writers never need :early_script it may be removed in the future. -  def uninstall_early_script(directives) -    uninstall_script(directives, directive_name: :early_script) -  end +      # Preserve prior functionality of script which runs first. Should rarely be needed. +      # :early_script should not delete files, better defer that to :script. +      # If Cask writers never need :early_script it may be removed in the future. +      def uninstall_early_script(directives) +        uninstall_script(directives, directive_name: :early_script) +      end -  # :launchctl must come before :quit/:signal for cases where app would instantly re-launch -  def uninstall_launchctl(directives) -    Array(directives[:launchctl]).each do |service| -      ohai "Removing launchctl service #{service}" -      [false, true].each do |with_sudo| -        plist_status = @command.run("/bin/launchctl", args: ["list", service], sudo: with_sudo, print_stderr: false).stdout -        if plist_status =~ %r{^\{} -          @command.run!("/bin/launchctl", args: ["remove", service], sudo: with_sudo) -          sleep 1 +      # :launchctl must come before :quit/:signal for cases where app would instantly re-launch +      def uninstall_launchctl(directives) +        Array(directives[:launchctl]).each do |service| +          ohai "Removing launchctl service #{service}" +          [false, true].each do |with_sudo| +            plist_status = @command.run("/bin/launchctl", args: ["list", service], sudo: with_sudo, print_stderr: false).stdout +            if plist_status =~ %r{^\{} +              @command.run!("/bin/launchctl", args: ["remove", service], sudo: with_sudo) +              sleep 1 +            end +            paths = ["/Library/LaunchAgents/#{service}.plist", +                     "/Library/LaunchDaemons/#{service}.plist"] +            paths.each { |elt| elt.prepend(ENV["HOME"]) } unless with_sudo +            paths = paths.map { |elt| Pathname(elt) }.select(&:exist?) +            paths.each do |path| +              @command.run!("/bin/rm", args: ["-f", "--", path], sudo: with_sudo) +            end +            # undocumented and untested: pass a path to uninstall :launchctl +            next unless Pathname(service).exist? +            @command.run!("/bin/launchctl", args: ["unload", "-w", "--", service], sudo: with_sudo) +            @command.run!("/bin/rm",        args: ["-f", "--", service], sudo: with_sudo) +            sleep 1 +          end          end -        paths = ["/Library/LaunchAgents/#{service}.plist", -                 "/Library/LaunchDaemons/#{service}.plist"] -        paths.each { |elt| elt.prepend(ENV["HOME"]) } unless with_sudo -        paths = paths.map { |elt| Pathname(elt) }.select(&:exist?) -        paths.each do |path| -          @command.run!("/bin/rm", args: ["-f", "--", path], sudo: with_sudo) +      end + +      # :quit/:signal must come before :kext so the kext will not be in use by a running process +      def uninstall_quit(directives) +        Array(directives[:quit]).each do |id| +          ohai "Quitting application ID #{id}" +          num_running = count_running_processes(id) +          next unless num_running > 0 +          @command.run!("/usr/bin/osascript", args: ["-e", %Q{tell application id "#{id}" to quit}], sudo: true) +          sleep 3          end -        # undocumented and untested: pass a path to uninstall :launchctl -        next unless Pathname(service).exist? -        @command.run!("/bin/launchctl", args: ["unload", "-w", "--", service], sudo: with_sudo) -        @command.run!("/bin/rm",        args: ["-f", "--", service], sudo: with_sudo) -        sleep 1        end -    end -  end -  # :quit/:signal must come before :kext so the kext will not be in use by a running process -  def uninstall_quit(directives) -    Array(directives[:quit]).each do |id| -      ohai "Quitting application ID #{id}" -      num_running = count_running_processes(id) -      next unless num_running > 0 -      @command.run!("/usr/bin/osascript", args: ["-e", %Q{tell application id "#{id}" to quit}], sudo: true) -      sleep 3 -    end -  end +      # :signal should come after :quit so it can be used as a backup when :quit fails +      def uninstall_signal(directives) +        Array(directives[:signal]).flatten.each_slice(2) do |pair| +          raise CaskInvalidError.new(@cask, "Each #{stanza} :signal must have 2 elements.") unless pair.length == 2 +          signal, id = pair +          ohai "Signalling '#{signal}' to application ID '#{id}'" +          pids = get_unix_pids(id) +          next unless pids.any? +          # Note that unlike :quit, signals are sent from the current user (not +          # upgraded to the superuser).  This is a todo item for the future, but +          # there should be some additional thought/safety checks about that, as a +          # misapplied "kill" by root could bring down the system. The fact that we +          # learned the pid from AppleScript is already some degree of protection, +          # though indirect. +          odebug "Unix ids are #{pids.inspect} for processes with bundle identifier #{id}" +          Process.kill(signal, *pids) +          sleep 3 +        end +      end -  # :signal should come after :quit so it can be used as a backup when :quit fails -  def uninstall_signal(directives) -    Array(directives[:signal]).flatten.each_slice(2) do |pair| -      raise Hbc::CaskInvalidError.new(@cask, "Each #{stanza} :signal must have 2 elements.") unless pair.length == 2 -      signal, id = pair -      ohai "Signalling '#{signal}' to application ID '#{id}'" -      pids = get_unix_pids(id) -      next unless pids.any? -      # Note that unlike :quit, signals are sent from the current user (not -      # upgraded to the superuser).  This is a todo item for the future, but -      # there should be some additional thought/safety checks about that, as a -      # misapplied "kill" by root could bring down the system. The fact that we -      # learned the pid from AppleScript is already some degree of protection, -      # though indirect. -      odebug "Unix ids are #{pids.inspect} for processes with bundle identifier #{id}" -      Process.kill(signal, *pids) -      sleep 3 -    end -  end +      def count_running_processes(bundle_id) +        @command.run!("/usr/bin/osascript", +                      args: ["-e", %Q{tell application "System Events" to count processes whose bundle identifier is "#{bundle_id}"}], +                      sudo: true).stdout.to_i +      end -  def count_running_processes(bundle_id) -    @command.run!("/usr/bin/osascript", -                  args: ["-e", %Q{tell application "System Events" to count processes whose bundle identifier is "#{bundle_id}"}], -                  sudo: true).stdout.to_i -  end +      def get_unix_pids(bundle_id) +        pid_string = @command.run!("/usr/bin/osascript", +                                   args: ["-e", %Q{tell application "System Events" to get the unix id of every process whose bundle identifier is "#{bundle_id}"}], +                                   sudo: true).stdout.chomp +        return [] unless pid_string =~ %r{\A\d+(?:\s*,\s*\d+)*\Z} # sanity check +        pid_string.split(%r{\s*,\s*}).map(&:strip).map(&:to_i) +      end -  def get_unix_pids(bundle_id) -    pid_string = @command.run!("/usr/bin/osascript", -                               args: ["-e", %Q{tell application "System Events" to get the unix id of every process whose bundle identifier is "#{bundle_id}"}], -                               sudo: true).stdout.chomp -    return [] unless pid_string =~ %r{\A\d+(?:\s*,\s*\d+)*\Z} # sanity check -    pid_string.split(%r{\s*,\s*}).map(&:strip).map(&:to_i) -  end +      def uninstall_login_item(directives) +        Array(directives[:login_item]).each do |name| +          ohai "Removing login item #{name}" +          @command.run!("/usr/bin/osascript", +                        args: ["-e", %Q{tell application "System Events" to delete every login item whose name is "#{name}"}], +                        sudo: false) +          sleep 1 +        end +      end -  def uninstall_login_item(directives) -    Array(directives[:login_item]).each do |name| -      ohai "Removing login item #{name}" -      @command.run!("/usr/bin/osascript", -                    args: ["-e", %Q{tell application "System Events" to delete every login item whose name is "#{name}"}], -                    sudo: false) -      sleep 1 -    end -  end +      # :kext should be unloaded before attempting to delete the relevant file +      def uninstall_kext(directives) +        Array(directives[:kext]).each do |kext| +          ohai "Unloading kernel extension #{kext}" +          is_loaded = @command.run!("/usr/sbin/kextstat", args: ["-l", "-b", kext], sudo: true).stdout +          if is_loaded.length > 1 +            @command.run!("/sbin/kextunload", args: ["-b", kext], sudo: true) +            sleep 1 +          end +        end +      end -  # :kext should be unloaded before attempting to delete the relevant file -  def uninstall_kext(directives) -    Array(directives[:kext]).each do |kext| -      ohai "Unloading kernel extension #{kext}" -      is_loaded = @command.run!("/usr/sbin/kextstat", args: ["-l", "-b", kext], sudo: true).stdout -      if is_loaded.length > 1 -        @command.run!("/sbin/kextunload", args: ["-b", kext], sudo: true) +      # :script must come before :pkgutil, :delete, or :trash so that the script file is not already deleted +      def uninstall_script(directives, directive_name: :script) +        executable, script_arguments = self.class.read_script_arguments(directives, +                                                                        "uninstall", +                                                                        { must_succeed: true, sudo: true }, +                                                                        { print_stdout: true }, +                                                                        directive_name) +        ohai "Running uninstall script #{executable}" +        raise CaskInvalidError.new(@cask, "#{stanza} :#{directive_name} without :executable.") if executable.nil? +        executable_path = @cask.staged_path.join(executable) +        @command.run("/bin/chmod", args: ["--", "+x", executable_path]) if File.exist?(executable_path) +        @command.run(executable_path, script_arguments)          sleep 1        end -    end -  end - -  # :script must come before :pkgutil, :delete, or :trash so that the script file is not already deleted -  def uninstall_script(directives, directive_name: :script) -    executable, script_arguments = self.class.read_script_arguments(directives, -                                                                    "uninstall", -                                                                    { must_succeed: true, sudo: true }, -                                                                    { print_stdout: true }, -                                                                    directive_name) -    ohai "Running uninstall script #{executable}" -    raise Hbc::CaskInvalidError.new(@cask, "#{stanza} :#{directive_name} without :executable.") if executable.nil? -    executable_path = @cask.staged_path.join(executable) -    @command.run("/bin/chmod", args: ["--", "+x", executable_path]) if File.exist?(executable_path) -    @command.run(executable_path, script_arguments) -    sleep 1 -  end -  def uninstall_pkgutil(directives) -    ohai "Removing files from pkgutil Bill-of-Materials" -    Array(directives[:pkgutil]).each do |regexp| -      pkgs = Hbc::Pkg.all_matching(regexp, @command) -      pkgs.each(&:uninstall) -    end -  end +      def uninstall_pkgutil(directives) +        ohai "Removing files from pkgutil Bill-of-Materials" +        Array(directives[:pkgutil]).each do |regexp| +          pkgs = Hbc::Pkg.all_matching(regexp, @command) +          pkgs.each(&:uninstall) +        end +      end -  def uninstall_delete(directives, expand_tilde = true) -    Array(directives[:delete]).concat(Array(directives[:trash])).flatten.each_slice(PATH_ARG_SLICE_SIZE) do |path_slice| -      ohai "Removing files: #{path_slice.utf8_inspect}" -      path_slice = self.class.expand_path_strings(path_slice) if expand_tilde -      path_slice = self.class.remove_relative_path_strings(:delete, path_slice) -      path_slice = self.class.remove_undeletable_path_strings(:delete, path_slice) -      @command.run!("/bin/rm", args: path_slice.unshift("-rf", "--"), sudo: true) -    end -  end +      def uninstall_delete(directives, expand_tilde = true) +        Array(directives[:delete]).concat(Array(directives[:trash])).flatten.each_slice(PATH_ARG_SLICE_SIZE) do |path_slice| +          ohai "Removing files: #{path_slice.utf8_inspect}" +          path_slice = self.class.expand_path_strings(path_slice) if expand_tilde +          path_slice = self.class.remove_relative_path_strings(:delete, path_slice) +          path_slice = self.class.remove_undeletable_path_strings(:delete, path_slice) +          @command.run!("/bin/rm", args: path_slice.unshift("-rf", "--"), sudo: true) +        end +      end -  # :trash functionality is stubbed as a synonym for :delete -  # TODO: make :trash work differently, moving files to the Trash -  def uninstall_trash(directives, expand_tilde = true) -    uninstall_delete(directives, expand_tilde) -  end +      # :trash functionality is stubbed as a synonym for :delete +      # TODO: make :trash work differently, moving files to the Trash +      def uninstall_trash(directives, expand_tilde = true) +        uninstall_delete(directives, expand_tilde) +      end -  def uninstall_rmdir(directives, expand_tilde = true) -    Array(directives[:rmdir]).flatten.each do |directory| -      directory = self.class.expand_path_strings([directory]).first if expand_tilde -      directory = self.class.remove_relative_path_strings(:rmdir, [directory]).first -      directory = self.class.remove_undeletable_path_strings(:rmdir, [directory]).first -      next if directory.to_s.empty? -      ohai "Removing directory if empty: #{directory.to_s.utf8_inspect}" -      directory = Pathname.new(directory) -      next unless directory.exist? -      @command.run!("/bin/rm", -                    args:         ["-f", "--", directory.join(".DS_Store")], -                    sudo:         true, -                    print_stderr: false) -      @command.run("/bin/rmdir", -                   args:         ["--", directory], -                   sudo:         true, -                   print_stderr: false) +      def uninstall_rmdir(directives, expand_tilde = true) +        Array(directives[:rmdir]).flatten.each do |directory| +          directory = self.class.expand_path_strings([directory]).first if expand_tilde +          directory = self.class.remove_relative_path_strings(:rmdir, [directory]).first +          directory = self.class.remove_undeletable_path_strings(:rmdir, [directory]).first +          next if directory.to_s.empty? +          ohai "Removing directory if empty: #{directory.to_s.utf8_inspect}" +          directory = Pathname.new(directory) +          next unless directory.exist? +          @command.run!("/bin/rm", +                        args:         ["-f", "--", directory.join(".DS_Store")], +                        sudo:         true, +                        print_stderr: false) +          @command.run("/bin/rmdir", +                       args:         ["--", directory], +                       sudo:         true, +                       print_stderr: false) +        end +      end      end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/vst3_plugin.rb b/Library/Homebrew/cask/lib/hbc/artifact/vst3_plugin.rb index 243884435..056fffc2a 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/vst3_plugin.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/vst3_plugin.rb @@ -1,4 +1,8 @@  require "hbc/artifact/moved" -class Hbc::Artifact::Vst3Plugin < Hbc::Artifact::Moved +module Hbc +  module Artifact +    class Vst3Plugin < Moved +    end +  end  end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/vst_plugin.rb b/Library/Homebrew/cask/lib/hbc/artifact/vst_plugin.rb index 8d0546480..f38804635 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/vst_plugin.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/vst_plugin.rb @@ -1,4 +1,8 @@  require "hbc/artifact/moved" -class Hbc::Artifact::VstPlugin < Hbc::Artifact::Moved +module Hbc +  module Artifact +    class VstPlugin < Moved +    end +  end  end diff --git a/Library/Homebrew/cask/lib/hbc/artifact/zap.rb b/Library/Homebrew/cask/lib/hbc/artifact/zap.rb index 8bd8da63b..503ea35c4 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/zap.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/zap.rb @@ -1,16 +1,20 @@  require "hbc/artifact/uninstall_base" -class Hbc::Artifact::Zap < Hbc::Artifact::UninstallBase -  def install_phase -    odebug "Nothing to do. The zap artifact has no install phase." -  end +module Hbc +  module Artifact +    class Zap < UninstallBase +      def install_phase +        odebug "Nothing to do. The zap artifact has no install phase." +      end -  def uninstall_phase -    odebug "Nothing to do. The zap artifact has no uninstall phase." -  end +      def uninstall_phase +        odebug "Nothing to do. The zap artifact has no uninstall phase." +      end -  def zap_phase -    expand_tilde = true -    dispatch_uninstall_directives(expand_tilde) +      def zap_phase +        expand_tilde = true +        dispatch_uninstall_directives(expand_tilde) +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/audit.rb b/Library/Homebrew/cask/lib/hbc/audit.rb index 98f09ffa4..476f2aec0 100644 --- a/Library/Homebrew/cask/lib/hbc/audit.rb +++ b/Library/Homebrew/cask/lib/hbc/audit.rb @@ -2,215 +2,217 @@ require "hbc/checkable"  require "hbc/download"  require "digest" -class Hbc::Audit -  include Hbc::Checkable +module Hbc +  class Audit +    include Checkable -  attr_reader :cask, :download +    attr_reader :cask, :download -  def initialize(cask, download: false, check_token_conflicts: false, command: Hbc::SystemCommand) -    @cask = cask -    @download = download -    @check_token_conflicts = check_token_conflicts -    @command = command -  end +    def initialize(cask, download: false, check_token_conflicts: false, command: SystemCommand) +      @cask = cask +      @download = download +      @check_token_conflicts = check_token_conflicts +      @command = command +    end -  def check_token_conflicts? -    @check_token_conflicts -  end +    def check_token_conflicts? +      @check_token_conflicts +    end -  def run! -    check_required_stanzas -    check_version -    check_sha256 -    check_appcast -    check_url -    check_generic_artifacts -    check_token_conflicts -    check_download -    self -  rescue StandardError => e -    odebug "#{e.message}\n#{e.backtrace.join("\n")}" -    add_error "exception while auditing #{cask}: #{e.message}" -    self -  end +    def run! +      check_required_stanzas +      check_version +      check_sha256 +      check_appcast +      check_url +      check_generic_artifacts +      check_token_conflicts +      check_download +      self +    rescue StandardError => e +      odebug "#{e.message}\n#{e.backtrace.join("\n")}" +      add_error "exception while auditing #{cask}: #{e.message}" +      self +    end -  def success? -    !(errors? || warnings?) -  end +    def success? +      !(errors? || warnings?) +    end -  def summary_header -    "audit for #{cask}" -  end +    def summary_header +      "audit for #{cask}" +    end -  private +    private -  def check_required_stanzas -    odebug "Auditing required stanzas" -    %i{version sha256 url homepage}.each do |sym| -      add_error "a #{sym} stanza is required" unless cask.send(sym) +    def check_required_stanzas +      odebug "Auditing required stanzas" +      %i{version sha256 url homepage}.each do |sym| +        add_error "a #{sym} stanza is required" unless cask.send(sym) +      end +      add_error "a license stanza is required (:unknown is OK)" unless cask.license +      add_error "at least one name stanza is required" if cask.name.empty? +      # TODO: specific DSL knowledge should not be spread around in various files like this +      # TODO: nested_container should not still be a pseudo-artifact at this point +      installable_artifacts = cask.artifacts.reject { |k| [:uninstall, :zap, :nested_container].include?(k) } +      add_error "at least one activatable artifact stanza is required" if installable_artifacts.empty?      end -    add_error "a license stanza is required (:unknown is OK)" unless cask.license -    add_error "at least one name stanza is required" if cask.name.empty? -    # TODO: specific DSL knowledge should not be spread around in various files like this -    # TODO: nested_container should not still be a pseudo-artifact at this point -    installable_artifacts = cask.artifacts.reject { |k| [:uninstall, :zap, :nested_container].include?(k) } -    add_error "at least one activatable artifact stanza is required" if installable_artifacts.empty? -  end -  def check_version -    return unless cask.version -    check_no_string_version_latest -  end +    def check_version +      return unless cask.version +      check_no_string_version_latest +    end -  def check_no_string_version_latest -    odebug "Verifying version :latest does not appear as a string ('latest')" -    return unless cask.version.raw_version == "latest" -    add_error "you should use version :latest instead of version 'latest'" -  end +    def check_no_string_version_latest +      odebug "Verifying version :latest does not appear as a string ('latest')" +      return unless cask.version.raw_version == "latest" +      add_error "you should use version :latest instead of version 'latest'" +    end -  def check_sha256 -    return unless cask.sha256 -    check_sha256_no_check_if_latest -    check_sha256_actually_256 -    check_sha256_invalid -  end +    def check_sha256 +      return unless cask.sha256 +      check_sha256_no_check_if_latest +      check_sha256_actually_256 +      check_sha256_invalid +    end -  def check_sha256_no_check_if_latest -    odebug "Verifying sha256 :no_check with version :latest" -    return unless cask.version.latest? && cask.sha256 != :no_check -    add_error "you should use sha256 :no_check when version is :latest" -  end +    def check_sha256_no_check_if_latest +      odebug "Verifying sha256 :no_check with version :latest" +      return unless cask.version.latest? && cask.sha256 != :no_check +      add_error "you should use sha256 :no_check when version is :latest" +    end -  def check_sha256_actually_256(sha256: cask.sha256, stanza: "sha256") -    odebug "Verifying #{stanza} string is a legal SHA-256 digest" -    return unless sha256.is_a?(String) -    return if sha256.length == 64 && sha256[%r{^[0-9a-f]+$}i] -    add_error "#{stanza} string must be of 64 hexadecimal characters" -  end +    def check_sha256_actually_256(sha256: cask.sha256, stanza: "sha256") +      odebug "Verifying #{stanza} string is a legal SHA-256 digest" +      return unless sha256.is_a?(String) +      return if sha256.length == 64 && sha256[%r{^[0-9a-f]+$}i] +      add_error "#{stanza} string must be of 64 hexadecimal characters" +    end -  def check_sha256_invalid(sha256: cask.sha256, stanza: "sha256") -    odebug "Verifying #{stanza} is not a known invalid value" -    empty_sha256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" -    return unless sha256 == empty_sha256 -    add_error "cannot use the sha256 for an empty string in #{stanza}: #{empty_sha256}" -  end +    def check_sha256_invalid(sha256: cask.sha256, stanza: "sha256") +      odebug "Verifying #{stanza} is not a known invalid value" +      empty_sha256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" +      return unless sha256 == empty_sha256 +      add_error "cannot use the sha256 for an empty string in #{stanza}: #{empty_sha256}" +    end -  def check_appcast -    return unless cask.appcast -    odebug "Auditing appcast" -    check_appcast_has_checkpoint -    return unless cask.appcast.checkpoint -    check_sha256_actually_256(sha256: cask.appcast.checkpoint, stanza: "appcast :checkpoint") -    check_sha256_invalid(sha256: cask.appcast.checkpoint, stanza: "appcast :checkpoint") -    return unless download -    check_appcast_http_code -    check_appcast_checkpoint_accuracy -  end +    def check_appcast +      return unless cask.appcast +      odebug "Auditing appcast" +      check_appcast_has_checkpoint +      return unless cask.appcast.checkpoint +      check_sha256_actually_256(sha256: cask.appcast.checkpoint, stanza: "appcast :checkpoint") +      check_sha256_invalid(sha256: cask.appcast.checkpoint, stanza: "appcast :checkpoint") +      return unless download +      check_appcast_http_code +      check_appcast_checkpoint_accuracy +    end -  def check_appcast_has_checkpoint -    odebug "Verifying appcast has :checkpoint key" -    add_error "a checkpoint sha256 is required for appcast" unless cask.appcast.checkpoint -  end +    def check_appcast_has_checkpoint +      odebug "Verifying appcast has :checkpoint key" +      add_error "a checkpoint sha256 is required for appcast" unless cask.appcast.checkpoint +    end -  def check_appcast_http_code -    odebug "Verifying appcast returns 200 HTTP response code" -    result = @command.run("/usr/bin/curl", args: ["--compressed", "--location", "--user-agent", Hbc::URL::FAKE_USER_AGENT, "--output", "/dev/null", "--write-out", "%{http_code}", cask.appcast], print_stderr: false) -    if result.success? -      http_code = result.stdout.chomp -      add_warning "unexpected HTTP response code retrieving appcast: #{http_code}" unless http_code == "200" -    else -      add_warning "error retrieving appcast: #{result.stderr}" +    def check_appcast_http_code +      odebug "Verifying appcast returns 200 HTTP response code" +      result = @command.run("/usr/bin/curl", args: ["--compressed", "--location", "--user-agent", URL::FAKE_USER_AGENT, "--output", "/dev/null", "--write-out", "%{http_code}", cask.appcast], print_stderr: false) +      if result.success? +        http_code = result.stdout.chomp +        add_warning "unexpected HTTP response code retrieving appcast: #{http_code}" unless http_code == "200" +      else +        add_warning "error retrieving appcast: #{result.stderr}" +      end      end -  end -  def check_appcast_checkpoint_accuracy -    odebug "Verifying appcast checkpoint is accurate" -    result = @command.run("/usr/bin/curl", args: ["--compressed", "--location", "--user-agent", Hbc::URL::FAKE_USER_AGENT, cask.appcast], print_stderr: false) -    if result.success? -      processed_appcast_text = result.stdout.gsub(%r{<pubDate>[^<]*</pubDate>}, "") -      # This step is necessary to replicate running `sed` from the command line -      processed_appcast_text << "\n" unless processed_appcast_text.end_with?("\n") -      expected = cask.appcast.checkpoint -      actual = Digest::SHA2.hexdigest(processed_appcast_text) -      add_warning <<-EOS.undent unless expected == actual -        appcast checkpoint mismatch -        Expected: #{expected} -        Actual: #{actual} -      EOS -    else -      add_warning "error retrieving appcast: #{result.stderr}" +    def check_appcast_checkpoint_accuracy +      odebug "Verifying appcast checkpoint is accurate" +      result = @command.run("/usr/bin/curl", args: ["--compressed", "--location", "--user-agent", URL::FAKE_USER_AGENT, cask.appcast], print_stderr: false) +      if result.success? +        processed_appcast_text = result.stdout.gsub(%r{<pubDate>[^<]*</pubDate>}, "") +        # This step is necessary to replicate running `sed` from the command line +        processed_appcast_text << "\n" unless processed_appcast_text.end_with?("\n") +        expected = cask.appcast.checkpoint +        actual = Digest::SHA2.hexdigest(processed_appcast_text) +        add_warning <<-EOS.undent unless expected == actual +          appcast checkpoint mismatch +          Expected: #{expected} +          Actual: #{actual} +        EOS +      else +        add_warning "error retrieving appcast: #{result.stderr}" +      end      end -  end -  def check_url -    return unless cask.url -    check_download_url_format -  end +    def check_url +      return unless cask.url +      check_download_url_format +    end -  def check_download_url_format -    odebug "Auditing URL format" -    if bad_sourceforge_url? -      add_warning "SourceForge URL format incorrect. See https://github.com/caskroom/homebrew-cask/blob/master/doc/cask_language_reference/stanzas/url.md#sourceforgeosdn-urls" -    elsif bad_osdn_url? -      add_warning "OSDN URL format incorrect. See https://github.com/caskroom/homebrew-cask/blob/master/doc/cask_language_reference/stanzas/url.md#sourceforgeosdn-urls" +    def check_download_url_format +      odebug "Auditing URL format" +      if bad_sourceforge_url? +        add_warning "SourceForge URL format incorrect. See https://github.com/caskroom/homebrew-cask/blob/master/doc/cask_language_reference/stanzas/url.md#sourceforgeosdn-urls" +      elsif bad_osdn_url? +        add_warning "OSDN URL format incorrect. See https://github.com/caskroom/homebrew-cask/blob/master/doc/cask_language_reference/stanzas/url.md#sourceforgeosdn-urls" +      end      end -  end -  def bad_url_format?(regex, valid_formats_array) -    return false unless cask.url.to_s =~ regex -    valid_formats_array.none? { |format| cask.url.to_s =~ format } -  end +    def bad_url_format?(regex, valid_formats_array) +      return false unless cask.url.to_s =~ regex +      valid_formats_array.none? { |format| cask.url.to_s =~ format } +    end -  def bad_sourceforge_url? -    bad_url_format?(%r{sourceforge}, -                    [ -                      %r{\Ahttps://sourceforge\.net/projects/[^/]+/files/latest/download\Z}, -                      %r{\Ahttps://downloads\.sourceforge\.net/(?!(project|sourceforge)\/)}, -                      # special cases: cannot find canonical format URL -                      %r{\Ahttps?://brushviewer\.sourceforge\.net/brushviewql\.zip\Z}, -                      %r{\Ahttps?://doublecommand\.sourceforge\.net/files/}, -                      %r{\Ahttps?://excalibur\.sourceforge\.net/get\.php\?id=}, -                    ]) -  end +    def bad_sourceforge_url? +      bad_url_format?(%r{sourceforge}, +                      [ +                        %r{\Ahttps://sourceforge\.net/projects/[^/]+/files/latest/download\Z}, +                        %r{\Ahttps://downloads\.sourceforge\.net/(?!(project|sourceforge)\/)}, +                        # special cases: cannot find canonical format URL +                        %r{\Ahttps?://brushviewer\.sourceforge\.net/brushviewql\.zip\Z}, +                        %r{\Ahttps?://doublecommand\.sourceforge\.net/files/}, +                        %r{\Ahttps?://excalibur\.sourceforge\.net/get\.php\?id=}, +                      ]) +    end -  def bad_osdn_url? -    bad_url_format?(%r{osd}, [%r{\Ahttps?://([^/]+.)?dl\.osdn\.jp/}]) -  end +    def bad_osdn_url? +      bad_url_format?(%r{osd}, [%r{\Ahttps?://([^/]+.)?dl\.osdn\.jp/}]) +    end -  def check_generic_artifacts -    cask.artifacts[:artifact].each do |source, target_hash| -      unless target_hash.is_a?(Hash) && target_hash[:target] -        add_error "target required for generic artifact #{source}" -        next +    def check_generic_artifacts +      cask.artifacts[:artifact].each do |source, target_hash| +        unless target_hash.is_a?(Hash) && target_hash[:target] +          add_error "target required for generic artifact #{source}" +          next +        end +        add_error "target must be absolute path for generic artifact #{source}" unless Pathname.new(target_hash[:target]).absolute?        end -      add_error "target must be absolute path for generic artifact #{source}" unless Pathname.new(target_hash[:target]).absolute?      end -  end -  def check_token_conflicts -    return unless check_token_conflicts? -    return unless core_formula_names.include?(cask.token) -    add_warning "possible duplicate, cask token conflicts with Homebrew core formula: #{core_formula_url}" -  end +    def check_token_conflicts +      return unless check_token_conflicts? +      return unless core_formula_names.include?(cask.token) +      add_warning "possible duplicate, cask token conflicts with Homebrew core formula: #{core_formula_url}" +    end -  def core_tap -    @core_tap ||= CoreTap.instance -  end +    def core_tap +      @core_tap ||= CoreTap.instance +    end -  def core_formula_names -    core_tap.formula_names -  end +    def core_formula_names +      core_tap.formula_names +    end -  def core_formula_url -    "#{core_tap.default_remote}/blob/master/Formula/#{cask.token}.rb" -  end +    def core_formula_url +      "#{core_tap.default_remote}/blob/master/Formula/#{cask.token}.rb" +    end -  def check_download -    return unless download && cask.url -    odebug "Auditing download" -    downloaded_path = download.perform -    Hbc::Verify.all(cask, downloaded_path) -  rescue => e -    add_error "download not possible: #{e.message}" +    def check_download +      return unless download && cask.url +      odebug "Auditing download" +      downloaded_path = download.perform +      Verify.all(cask, downloaded_path) +    rescue => e +      add_error "download not possible: #{e.message}" +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/auditor.rb b/Library/Homebrew/cask/lib/hbc/auditor.rb index 89947c1aa..6b0c1c476 100644 --- a/Library/Homebrew/cask/lib/hbc/auditor.rb +++ b/Library/Homebrew/cask/lib/hbc/auditor.rb @@ -1,10 +1,12 @@ -class Hbc::Auditor -  def self.audit(cask, audit_download: false, check_token_conflicts: false) -    download = audit_download && Hbc::Download.new(cask) -    audit = Hbc::Audit.new(cask, download:              download, -                                 check_token_conflicts: check_token_conflicts) -    audit.run! -    puts audit.summary -    audit.success? +module Hbc +  class Auditor +    def self.audit(cask, audit_download: false, check_token_conflicts: false) +      download = audit_download && Download.new(cask) +      audit = Audit.new(cask, download:              download, +                              check_token_conflicts: check_token_conflicts) +      audit.run! +      puts audit.summary +      audit.success? +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/cache.rb b/Library/Homebrew/cask/lib/hbc/cache.rb index 9fc5fe0f3..db3ec536b 100644 --- a/Library/Homebrew/cask/lib/hbc/cache.rb +++ b/Library/Homebrew/cask/lib/hbc/cache.rb @@ -1,21 +1,23 @@ -module Hbc::Cache -  module_function +module Hbc +  module Cache +    module_function -  def ensure_cache_exists -    return if Hbc.cache.exist? -    odebug "Creating Cache at #{Hbc.cache}" -    Hbc.cache.mkpath -  end +    def ensure_cache_exists +      return if Hbc.cache.exist? -  def migrate_legacy_cache -    if Hbc.legacy_cache.exist? -      ohai "Migrating cached files to #{Hbc.cache}..." +      odebug "Creating Cache at #{Hbc.cache}" +      Hbc.cache.mkpath +    end +    def migrate_legacy_cache +      return unless Hbc.legacy_cache.exist? + +      ohai "Migrating cached files to #{Hbc.cache}..."        Hbc.legacy_cache.children.select(&:symlink?).each do |symlink|          file = symlink.readlink          new_name = file.basename -                       .sub(%r{\-((?:(\d|#{Hbc::DSL::Version::DIVIDER_REGEX})*\-\2*)*[^\-]+)$}x, +                       .sub(%r{\-((?:(\d|#{DSL::Version::DIVIDER_REGEX})*\-\2*)*[^\-]+)$}x,                              '--\1')          renamed_file = Hbc.cache.join(new_name) diff --git a/Library/Homebrew/cask/lib/hbc/cask.rb b/Library/Homebrew/cask/lib/hbc/cask.rb index fd13a6fe7..756b05b83 100644 --- a/Library/Homebrew/cask/lib/hbc/cask.rb +++ b/Library/Homebrew/cask/lib/hbc/cask.rb @@ -2,92 +2,95 @@ require "forwardable"  require "hbc/dsl" -class Hbc::Cask -  extend Forwardable +module Hbc +  class Cask +    extend Forwardable -  attr_reader :token, :sourcefile_path -  def initialize(token, sourcefile_path: nil, dsl: nil, &block) -    @token = token -    @sourcefile_path = sourcefile_path -    @dsl = dsl || Hbc::DSL.new(@token) -    @dsl.instance_eval(&block) if block_given? -  end - -  Hbc::DSL::DSL_METHODS.each do |method_name| -    define_method(method_name) { @dsl.send(method_name) } -  end +    attr_reader :token, :sourcefile_path +    def initialize(token, sourcefile_path: nil, dsl: nil, &block) +      @token = token +      @sourcefile_path = sourcefile_path +      @dsl = dsl || DSL.new(@token) +      @dsl.instance_eval(&block) if block_given? +    end -  METADATA_SUBDIR = ".metadata".freeze +    DSL::DSL_METHODS.each do |method_name| +      define_method(method_name) { @dsl.send(method_name) } +    end -  def metadata_master_container_path -    @metadata_master_container_path ||= caskroom_path.join(METADATA_SUBDIR) -  end +    METADATA_SUBDIR = ".metadata".freeze -  def metadata_versioned_container_path -    cask_version = version ? version : :unknown -    metadata_master_container_path.join(cask_version.to_s) -  end - -  def metadata_path(timestamp = :latest, create = false) -    return nil unless metadata_versioned_container_path.respond_to?(:join) -    if create && timestamp == :latest -      raise Hbc::CaskError, "Cannot create metadata path when timestamp is :latest" +    def metadata_master_container_path +      @metadata_master_container_path ||= caskroom_path.join(METADATA_SUBDIR)      end -    path = if timestamp == :latest -             Pathname.glob(metadata_versioned_container_path.join("*")).sort.last -           elsif timestamp == :now -             Hbc::Utils.nowstamp_metadata_path(metadata_versioned_container_path) -           else -             metadata_versioned_container_path.join(timestamp) -           end -    if create -      odebug "Creating metadata directory #{path}" -      FileUtils.mkdir_p path + +    def metadata_versioned_container_path +      cask_version = version ? version : :unknown +      metadata_master_container_path.join(cask_version.to_s)      end -    path -  end -  def metadata_subdir(leaf, timestamp = :latest, create = false) -    if create && timestamp == :latest -      raise Hbc::CaskError, "Cannot create metadata subdir when timestamp is :latest" +    def metadata_path(timestamp = :latest, create = false) +      return nil unless metadata_versioned_container_path.respond_to?(:join) +      if create && timestamp == :latest +        raise CaskError, "Cannot create metadata path when timestamp is :latest" +      end +      path = if timestamp == :latest +               Pathname.glob(metadata_versioned_container_path.join("*")).sort.last +             elsif timestamp == :now +               Utils.nowstamp_metadata_path(metadata_versioned_container_path) +             else +               metadata_versioned_container_path.join(timestamp) +             end +      if create +        odebug "Creating metadata directory #{path}" +        FileUtils.mkdir_p path +      end +      path      end -    unless leaf.respond_to?(:length) && !leaf.empty? -      raise Hbc::CaskError, "Cannot create metadata subdir for empty leaf" + +    def metadata_subdir(leaf, timestamp = :latest, create = false) +      if create && timestamp == :latest +        raise CaskError, "Cannot create metadata subdir when timestamp is :latest" +      end +      unless leaf.respond_to?(:length) && !leaf.empty? +        raise CaskError, "Cannot create metadata subdir for empty leaf" +      end +      parent = metadata_path(timestamp, create) +      return nil unless parent.respond_to?(:join) +      subdir = parent.join(leaf) +      if create +        odebug "Creating metadata subdirectory #{subdir}" +        FileUtils.mkdir_p subdir +      end +      subdir      end -    parent = metadata_path(timestamp, create) -    return nil unless parent.respond_to?(:join) -    subdir = parent.join(leaf) -    if create -      odebug "Creating metadata subdirectory #{subdir}" -      FileUtils.mkdir_p subdir + +    def timestamped_versions +      Pathname.glob(metadata_master_container_path.join("*", "*")) +              .map { |p| p.relative_path_from(metadata_master_container_path) } +              .sort_by(&:basename) # sort by timestamp +              .map(&:split)      end -    subdir -  end -  def timestamped_versions -    Pathname.glob(metadata_master_container_path.join("*", "*")) -            .map { |p| p.relative_path_from(metadata_master_container_path) } -            .sort_by(&:basename) # sort by timestamp -            .map(&:split) -  end +    def versions +      timestamped_versions.map(&:first) +                          .reverse +                          .uniq +                          .reverse +    end -  def versions -    timestamped_versions.map(&:first) -                        .reverse -                        .uniq -                        .reverse -  end +    def installed? +      !versions.empty? +    end -  def installed? -    !versions.empty? -  end +    def to_s +      @token +    end -  def to_s -    @token -  end +    def dumpcask +      return unless Hbc.respond_to?(:debug) +      return unless Hbc.debug -  def dumpcask -    if Hbc.respond_to?(:debug) && Hbc.debug        odebug "Cask instance dumps in YAML:"        odebug "Cask instance toplevel:", to_yaml        [ diff --git a/Library/Homebrew/cask/lib/hbc/cask_dependencies.rb b/Library/Homebrew/cask/lib/hbc/cask_dependencies.rb index 6cbfd05af..4b4f042d8 100644 --- a/Library/Homebrew/cask/lib/hbc/cask_dependencies.rb +++ b/Library/Homebrew/cask/lib/hbc/cask_dependencies.rb @@ -1,33 +1,35 @@  require "hbc/topological_hash" -class Hbc::CaskDependencies -  attr_reader :cask, :graph, :sorted +module Hbc +  class CaskDependencies +    attr_reader :cask, :graph, :sorted -  def initialize(cask) -    @cask = cask -    @graph = graph_dependencies -    @sorted = sort -  end +    def initialize(cask) +      @cask = cask +      @graph = graph_dependencies +      @sorted = sort +    end -  def graph_dependencies -    deps_in = ->(csk) { csk.depends_on ? csk.depends_on.cask || [] : [] } -    walk = lambda { |acc, deps| -      deps.each do |dep| -        next if acc.key?(dep) -        succs = deps_in.call Hbc.load(dep) -        acc[dep] = succs -        walk.call(acc, succs) -      end -      acc -    } +    def graph_dependencies +      deps_in = ->(csk) { csk.depends_on ? csk.depends_on.cask || [] : [] } +      walk = lambda { |acc, deps| +        deps.each do |dep| +          next if acc.key?(dep) +          succs = deps_in.call Hbc.load(dep) +          acc[dep] = succs +          walk.call(acc, succs) +        end +        acc +      } -    graphed = walk.call({}, @cask.depends_on.cask) -    Hbc::TopologicalHash[graphed] -  end +      graphed = walk.call({}, @cask.depends_on.cask) +      TopologicalHash[graphed] +    end -  def sort -    @graph.tsort -  rescue TSort::Cyclic -    raise Hbc::CaskCyclicCaskDependencyError, @cask.token +    def sort +      @graph.tsort +    rescue TSort::Cyclic +      raise CaskCyclicCaskDependencyError, @cask.token +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/caskroom.rb b/Library/Homebrew/cask/lib/hbc/caskroom.rb index 7d02f3fa4..583cac34a 100644 --- a/Library/Homebrew/cask/lib/hbc/caskroom.rb +++ b/Library/Homebrew/cask/lib/hbc/caskroom.rb @@ -1,18 +1,26 @@ -module Hbc::Caskroom -  module_function +module Hbc +  module Caskroom +    module_function + +    def migrate_caskroom_from_repo_to_prefix +      repo_caskroom = Hbc.homebrew_repository.join("Caskroom") +      return if Hbc.caskroom.exist? +      return unless repo_caskroom.directory? -  def migrate_caskroom_from_repo_to_prefix -    repo_caskroom = Hbc.homebrew_repository.join("Caskroom") -    if !Hbc.caskroom.exist? && repo_caskroom.directory?        ohai "Moving Caskroom from HOMEBREW_REPOSITORY to HOMEBREW_PREFIX" -      FileUtils.mv repo_caskroom, Hbc.caskroom + +      if Hbc.caskroom.parent.writable? +        FileUtils.mv repo_caskroom, Hbc.caskroom +      else +        opoo "#{Hbc.caskroom.parent} is not writable, sudo is needed to move the Caskroom." +        system "/usr/bin/sudo", "--", "/bin/mv", "--", repo_caskroom.to_s, Hbc.caskroom.parent.to_s +      end      end -  end -  def ensure_caskroom_exists -    unless Hbc.caskroom.exist? -      ohai "Creating Caskroom at #{Hbc.caskroom}" +    def ensure_caskroom_exists +      return if Hbc.caskroom.exist? +      ohai "Creating Caskroom at #{Hbc.caskroom}"        if Hbc.caskroom.parent.writable?          Hbc.caskroom.mkpath        else @@ -28,7 +36,7 @@ module Hbc::Caskroom          # sudo in system is rude.          system "/usr/bin/sudo", "--", "/bin/mkdir", "-p", "--", Hbc.caskroom          unless Hbc.caskroom.parent == toplevel_dir -          system "/usr/bin/sudo", "--", "/usr/sbin/chown", "-R", "--", "#{Hbc::Utils.current_user}:staff", Hbc.caskroom.parent.to_s +          system "/usr/bin/sudo", "--", "/usr/sbin/chown", "-R", "--", "#{Utils.current_user}:staff", Hbc.caskroom.parent.to_s          end        end      end diff --git a/Library/Homebrew/cask/lib/hbc/caveats.rb b/Library/Homebrew/cask/lib/hbc/caveats.rb index 04bbcf218..a85429151 100644 --- a/Library/Homebrew/cask/lib/hbc/caveats.rb +++ b/Library/Homebrew/cask/lib/hbc/caveats.rb @@ -1,12 +1,14 @@ -class Hbc::Caveats -  def initialize(block) -    @block = block -  end +module Hbc +  class Caveats +    def initialize(block) +      @block = block +    end -  def eval_and_print(cask) -    dsl = Hbc::DSL::Caveats.new(cask) -    retval = dsl.instance_eval(&@block) -    return if retval.nil? -    puts retval.to_s.sub(%r{[\r\n \t]*\Z}, "\n\n") +    def eval_and_print(cask) +      dsl = DSL::Caveats.new(cask) +      retval = dsl.instance_eval(&@block) +      return if retval.nil? +      puts retval.to_s.sub(%r{[\r\n \t]*\Z}, "\n\n") +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/checkable.rb b/Library/Homebrew/cask/lib/hbc/checkable.rb index 9c12f80ca..42c47ea78 100644 --- a/Library/Homebrew/cask/lib/hbc/checkable.rb +++ b/Library/Homebrew/cask/lib/hbc/checkable.rb @@ -1,51 +1,53 @@ -module Hbc::Checkable -  def errors -    Array(@errors) -  end +module Hbc +  module Checkable +    def errors +      Array(@errors) +    end -  def warnings -    Array(@warnings) -  end +    def warnings +      Array(@warnings) +    end -  def add_error(message) -    @errors ||= [] -    @errors << message -  end +    def add_error(message) +      @errors ||= [] +      @errors << message +    end -  def add_warning(message) -    @warnings ||= [] -    @warnings << message -  end +    def add_warning(message) +      @warnings ||= [] +      @warnings << message +    end -  def errors? -    Array(@errors).any? -  end +    def errors? +      Array(@errors).any? +    end -  def warnings? -    Array(@warnings).any? -  end +    def warnings? +      Array(@warnings).any? +    end -  def result -    if errors? -      "#{Tty.red}failed#{Tty.reset}" -    elsif warnings? -      "#{Tty.yellow}warning#{Tty.reset}" -    else -      "#{Tty.green}passed#{Tty.reset}" +    def result +      if errors? +        "#{Tty.red}failed#{Tty.reset}" +      elsif warnings? +        "#{Tty.yellow}warning#{Tty.reset}" +      else +        "#{Tty.green}passed#{Tty.reset}" +      end      end -  end -  def summary -    summary = ["#{summary_header}: #{result}"] +    def summary +      summary = ["#{summary_header}: #{result}"] -    errors.each do |error| -      summary << " #{Tty.red}-#{Tty.reset} #{error}" -    end +      errors.each do |error| +        summary << " #{Tty.red}-#{Tty.reset} #{error}" +      end -    warnings.each do |warning| -      summary << " #{Tty.yellow}-#{Tty.reset} #{warning}" -    end +      warnings.each do |warning| +        summary << " #{Tty.yellow}-#{Tty.reset} #{warning}" +      end -    summary.join("\n") +      summary.join("\n") +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/cli.rb b/Library/Homebrew/cask/lib/hbc/cli.rb index 1378176da..3f67e131d 100644 --- a/Library/Homebrew/cask/lib/hbc/cli.rb +++ b/Library/Homebrew/cask/lib/hbc/cli.rb @@ -1,5 +1,3 @@ -class Hbc::CLI; end -  require "optparse"  require "shellwords" @@ -28,248 +26,250 @@ require "hbc/cli/internal_dump"  require "hbc/cli/internal_help"  require "hbc/cli/internal_stanza" -class Hbc::CLI -  ALIASES = { -              "ls"       => "list", -              "homepage" => "home", -              "-S"       => "search",    # verb starting with "-" is questionable -              "up"       => "update", -              "instal"   => "install",   # gem does the same -              "rm"       => "uninstall", -              "remove"   => "uninstall", -              "abv"      => "info", -              "dr"       => "doctor", -              # aliases from Homebrew that we don't (yet) support -              # 'ln'          => 'link', -              # 'configure'   => 'diy', -              # '--repo'      => '--repository', -              # 'environment' => '--env', -              # '-c1'         => '--config', -            }.freeze +module Hbc +  class CLI +    ALIASES = { +                "ls"       => "list", +                "homepage" => "home", +                "-S"       => "search",    # verb starting with "-" is questionable +                "up"       => "update", +                "instal"   => "install",   # gem does the same +                "rm"       => "uninstall", +                "remove"   => "uninstall", +                "abv"      => "info", +                "dr"       => "doctor", +                # aliases from Homebrew that we don't (yet) support +                # 'ln'          => 'link', +                # 'configure'   => 'diy', +                # '--repo'      => '--repository', +                # 'environment' => '--env', +                # '-c1'         => '--config', +              }.freeze + +    OPTIONS = { +                "--caskroom="             => :caskroom=, +                "--appdir="               => :appdir=, +                "--colorpickerdir="       => :colorpickerdir=, +                "--prefpanedir="          => :prefpanedir=, +                "--qlplugindir="          => :qlplugindir=, +                "--fontdir="              => :fontdir=, +                "--servicedir="           => :servicedir=, +                "--input_methoddir="      => :input_methoddir=, +                "--internet_plugindir="   => :internet_plugindir=, +                "--audio_unit_plugindir=" => :audio_unit_plugindir=, +                "--vst_plugindir="        => :vst_plugindir=, +                "--vst3_plugindir="       => :vst3_plugindir=, +                "--screen_saverdir="      => :screen_saverdir=, +              }.freeze -  OPTIONS = { -              "--caskroom="             => :caskroom=, -              "--appdir="               => :appdir=, -              "--colorpickerdir="       => :colorpickerdir=, -              "--prefpanedir="          => :prefpanedir=, -              "--qlplugindir="          => :qlplugindir=, -              "--fontdir="              => :fontdir=, -              "--servicedir="           => :servicedir=, -              "--input_methoddir="      => :input_methoddir=, -              "--internet_plugindir="   => :internet_plugindir=, -              "--audio_unit_plugindir=" => :audio_unit_plugindir=, -              "--vst_plugindir="        => :vst_plugindir=, -              "--vst3_plugindir="       => :vst3_plugindir=, -              "--screen_saverdir="      => :screen_saverdir=, +    FLAGS = { +              "--no-binaries" => :no_binaries=, +              "--debug"       => :debug=, +              "--verbose"     => :verbose=, +              "--outdated"    => :cleanup_outdated=, +              "--help"        => :help=,              }.freeze -  FLAGS = { -            "--no-binaries" => :no_binaries=, -            "--debug"       => :debug=, -            "--verbose"     => :verbose=, -            "--outdated"    => :cleanup_outdated=, -            "--help"        => :help=, -          }.freeze +    def self.command_classes +      @command_classes ||= self.constants +                               .map(&method(:const_get)) +                               .select { |sym| sym.respond_to?(:run) } +    end -  def self.command_classes -    @command_classes ||= Hbc::CLI.constants -                                 .map(&Hbc::CLI.method(:const_get)) -                                 .select { |sym| sym.respond_to?(:run) } -  end +    def self.commands +      @commands ||= command_classes.map(&:command_name) +    end -  def self.commands -    @commands ||= command_classes.map(&:command_name) -  end +    def self.lookup_command(command_string) +      @lookup ||= Hash[commands.zip(command_classes)] +      command_string = ALIASES.fetch(command_string, command_string) +      @lookup.fetch(command_string, command_string) +    end -  def self.lookup_command(command_string) -    @lookup ||= Hash[commands.zip(command_classes)] -    command_string = ALIASES.fetch(command_string, command_string) -    @lookup.fetch(command_string, command_string) -  end +    # modified from Homebrew +    def self.require?(path) +      require path +      true # OK if already loaded +    rescue LoadError => e +      # HACK: :( because we should raise on syntax errors +      #       but not if the file doesn't exist. +      # TODO: make robust! +      raise unless e.to_s.include? path +    end -  # modified from Homebrew -  def self.require?(path) -    require path -    true # OK if already loaded -  rescue LoadError => e -    # HACK: :( because we should raise on syntax errors -    #       but not if the file doesn't exist. -    # TODO: make robust! -    raise unless e.to_s.include? path -  end +    def self.should_init?(command) +      (command.is_a? Class) && (command < CLI::Base) && command.needs_init? +    end -  def self.should_init?(command) -    (command.is_a? Class) && (command < Hbc::CLI::Base) && command.needs_init? -  end +    def self.run_command(command, *rest) +      if command.respond_to?(:run) +        # usual case: built-in command verb +        command.run(*rest) +      elsif require? Utils.which("brewcask-#{command}.rb").to_s +        # external command as Ruby library on PATH, Homebrew-style +      elsif command.to_s.include?("/") && require?(command.to_s) +        # external command as Ruby library with literal path, useful +        # for development and troubleshooting +        sym = Pathname.new(command.to_s).basename(".rb").to_s.capitalize +        klass = begin +                  self.const_get(sym) +                rescue NameError +                  nil +                end -  def self.run_command(command, *rest) -    if command.respond_to?(:run) -      # usual case: built-in command verb -      command.run(*rest) -    elsif require? Hbc::Utils.which("brewcask-#{command}.rb").to_s -      # external command as Ruby library on PATH, Homebrew-style -    elsif command.to_s.include?("/") && require?(command.to_s) -      # external command as Ruby library with literal path, useful -      # for development and troubleshooting -      sym = Pathname.new(command.to_s).basename(".rb").to_s.capitalize -      klass = begin -                Hbc::CLI.const_get(sym) -              rescue NameError -                nil -              end -      if klass.respond_to?(:run) -        # invoke "run" on a Ruby library which follows our coding conventions -        klass.run(*rest) +        if klass.respond_to?(:run) +          # invoke "run" on a Ruby library which follows our coding conventions +          # other Ruby libraries must do everything via "require" +          klass.run(*rest) +        end +      elsif Utils.which "brewcask-#{command}" +        # arbitrary external executable on PATH, Homebrew-style +        exec "brewcask-#{command}", *ARGV[1..-1] +      elsif Pathname.new(command.to_s).executable? && +            command.to_s.include?("/") && +            !command.to_s.match(%r{\.rb$}) +        # arbitrary external executable with literal path, useful +        # for development and troubleshooting +        exec command, *ARGV[1..-1]        else -        # other Ruby libraries must do everything via "require" +        # failure +        NullCommand.new(command).run        end -    elsif Hbc::Utils.which "brewcask-#{command}" -      # arbitrary external executable on PATH, Homebrew-style -      exec "brewcask-#{command}", *ARGV[1..-1] -    elsif Pathname.new(command.to_s).executable? && -          command.to_s.include?("/") && -          !command.to_s.match(%r{\.rb$}) -      # arbitrary external executable with literal path, useful -      # for development and troubleshooting -      exec command, *ARGV[1..-1] -    else -      # failure -      Hbc::CLI::NullCommand.new(command).run      end -  end -  def self.process(arguments) -    command_string, *rest = *arguments -    rest = process_options(rest) -    command = Hbc.help ? "help" : lookup_command(command_string) -    Hbc.default_tap.install unless Hbc.default_tap.installed? -    Hbc.init if should_init?(command) -    run_command(command, *rest) -  rescue Hbc::CaskError, Hbc::CaskSha256MismatchError => e -    msg = e.message -    msg << e.backtrace.join("\n") if Hbc.debug -    onoe msg -    exit 1 -  rescue StandardError, ScriptError, NoMemoryError => e -    msg = e.message -    msg << Hbc::Utils.error_message_with_suggestions -    msg << e.backtrace.join("\n") -    onoe msg -    exit 1 -  end - -  def self.nice_listing(cask_list) -    cask_taps = {} -    cask_list.each do |c| -      user, repo, token = c.split "/" -      repo.sub!(%r{^homebrew-}i, "") -      cask_taps[token] ||= [] -      cask_taps[token].push "#{user}/#{repo}" +    def self.process(arguments) +      command_string, *rest = *arguments +      rest = process_options(rest) +      command = Hbc.help ? "help" : lookup_command(command_string) +      Hbc.default_tap.install unless Hbc.default_tap.installed? +      Hbc.init if should_init?(command) +      run_command(command, *rest) +    rescue CaskError, CaskSha256MismatchError => e +      msg = e.message +      msg << e.backtrace.join("\n") if Hbc.debug +      onoe msg +      exit 1 +    rescue StandardError, ScriptError, NoMemoryError => e +      msg = e.message +      msg << Utils.error_message_with_suggestions +      msg << e.backtrace.join("\n") +      onoe msg +      exit 1      end -    list = [] -    cask_taps.each do |token, taps| -      if taps.length == 1 -        list.push token -      else -        taps.each { |r| list.push [r, token].join "/" } + +    def self.nice_listing(cask_list) +      cask_taps = {} +      cask_list.each do |c| +        user, repo, token = c.split "/" +        repo.sub!(%r{^homebrew-}i, "") +        cask_taps[token] ||= [] +        cask_taps[token].push "#{user}/#{repo}" +      end +      list = [] +      cask_taps.each do |token, taps| +        if taps.length == 1 +          list.push token +        else +          taps.each { |r| list.push [r, token].join "/" } +        end        end +      list.sort      end -    list.sort -  end -  def self.parser -    # If you modify these arguments, please update USAGE.md -    @parser ||= OptionParser.new do |opts| -      OPTIONS.each do |option, method| -        opts.on("#{option}" "PATH", Pathname) do |path| -          Hbc.public_send(method, path) +    def self.parser +      # If you modify these arguments, please update USAGE.md +      @parser ||= OptionParser.new do |opts| +        OPTIONS.each do |option, method| +          opts.on("#{option}" "PATH", Pathname) do |path| +            Hbc.public_send(method, path) +          end          end -      end -      opts.on("--binarydir=PATH") do -        opoo <<-EOS.undent -          Option --binarydir is obsolete! -          Homebrew-Cask now uses the same location as your Homebrew installation for executable links. -        EOS -      end +        opts.on("--binarydir=PATH") do +          opoo <<-EOS.undent +            Option --binarydir is obsolete! +            Homebrew-Cask now uses the same location as your Homebrew installation for executable links. +          EOS +        end -      FLAGS.each do |flag, method| -        opts.on(flag) do -          Hbc.public_send(method, true) +        FLAGS.each do |flag, method| +          opts.on(flag) do +            Hbc.public_send(method, true) +          end          end -      end -      opts.on("--version") do -        raise OptionParser::InvalidOption # override default handling of --version +        opts.on("--version") do +          raise OptionParser::InvalidOption # override default handling of --version +        end        end      end -  end -  def self.process_options(args) -    all_args = Shellwords.shellsplit(ENV["HOMEBREW_CASK_OPTS"] || "") + args -    remaining = [] -    until all_args.empty? -      begin -        head = all_args.shift -        remaining.concat(parser.parse([head])) -      rescue OptionParser::InvalidOption -        remaining << head -        retry -      rescue OptionParser::MissingArgument -        raise Hbc::CaskError, "The option '#{head}' requires an argument" -      rescue OptionParser::AmbiguousOption -        raise Hbc::CaskError, "There is more than one possible option that starts with '#{head}'" +    def self.process_options(args) +      all_args = Shellwords.shellsplit(ENV["HOMEBREW_CASK_OPTS"] || "") + args +      remaining = [] +      until all_args.empty? +        begin +          head = all_args.shift +          remaining.concat(parser.parse([head])) +        rescue OptionParser::InvalidOption +          remaining << head +          retry +        rescue OptionParser::MissingArgument +          raise CaskError, "The option '#{head}' requires an argument" +        rescue OptionParser::AmbiguousOption +          raise CaskError, "There is more than one possible option that starts with '#{head}'" +        end        end -    end -    # for compat with Homebrew, not certain if this is desirable -    Hbc.verbose = true if !ENV["VERBOSE"].nil? || !ENV["HOMEBREW_VERBOSE"].nil? +      # for compat with Homebrew, not certain if this is desirable +      Hbc.verbose = true if !ENV["VERBOSE"].nil? || !ENV["HOMEBREW_VERBOSE"].nil? -    remaining -  end - -  class NullCommand -    def initialize(attempted_verb) -      @attempted_verb = attempted_verb +      remaining      end -    def run(*args) -      if args.include?("--version") || @attempted_verb == "--version" -        puts Hbc.full_version -      else -        purpose -        usage -        unless @attempted_verb.to_s.strip.empty? || @attempted_verb == "help" -          raise Hbc::CaskError, "Unknown command: #{@attempted_verb}" +    class NullCommand +      def initialize(attempted_verb) +        @attempted_verb = attempted_verb +      end + +      def run(*args) +        if args.include?("--version") || @attempted_verb == "--version" +          puts Hbc.full_version +        else +          purpose +          usage +          unless @attempted_verb.to_s.strip.empty? || @attempted_verb == "help" +            raise CaskError, "Unknown command: #{@attempted_verb}" +          end          end        end -    end -    def purpose -      puts <<-EOS.undent -        brew-cask provides a friendly homebrew-style CLI workflow for the -        administration of macOS applications distributed as binaries. +      def purpose +        puts <<-EOS.undent +          brew-cask provides a friendly homebrew-style CLI workflow for the +          administration of macOS applications distributed as binaries. -      EOS -    end +        EOS +      end -    def usage -      max_command_len = Hbc::CLI.commands.map(&:length).max +      def usage +        max_command_len = CLI.commands.map(&:length).max -      puts "Commands:\n\n" -      Hbc::CLI.command_classes.each do |klass| -        next unless klass.visible -        puts "    #{klass.command_name.ljust(max_command_len)}  #{_help_for(klass)}" +        puts "Commands:\n\n" +        CLI.command_classes.each do |klass| +          next unless klass.visible +          puts "    #{klass.command_name.ljust(max_command_len)}  #{_help_for(klass)}" +        end +        puts %Q{\nSee also "man brew-cask"}        end -      puts %Q{\nSee also "man brew-cask"} -    end -    def help -      "" -    end +      def help +        "" +      end -    def _help_for(klass) -      klass.respond_to?(:help) ? klass.help : nil +      def _help_for(klass) +        klass.respond_to?(:help) ? klass.help : nil +      end      end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/cli/audit.rb b/Library/Homebrew/cask/lib/hbc/cli/audit.rb index 289547b44..a06f71c60 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/audit.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/audit.rb @@ -1,52 +1,56 @@ -class Hbc::CLI::Audit < Hbc::CLI::Base -  def self.help -    "verifies installability of Casks" -  end - -  def self.run(*args) -    failed_casks = new(args, Hbc::Auditor).run -    return if failed_casks.empty? -    raise Hbc::CaskError, "audit failed for casks: #{failed_casks.join(' ')}" -  end - -  def initialize(args, auditor) -    @args = args -    @auditor = auditor -  end - -  def run -    casks_to_audit.each_with_object([]) do |cask, failed| -      failed << cask unless audit(cask) +module Hbc +  class CLI +    class Audit < Base +      def self.help +        "verifies installability of Casks" +      end + +      def self.run(*args) +        failed_casks = new(args, Auditor).run +        return if failed_casks.empty? +        raise CaskError, "audit failed for casks: #{failed_casks.join(" ")}" +      end + +      def initialize(args, auditor) +        @args = args +        @auditor = auditor +      end + +      def run +        casks_to_audit.each_with_object([]) do |cask, failed| +          failed << cask unless audit(cask) +        end +      end + +      def audit(cask) +        odebug "Auditing Cask #{cask}" +        @auditor.audit(cask, audit_download:        audit_download?, +                             check_token_conflicts: check_token_conflicts?) +      end + +      def audit_download? +        @args.include?("--download") +      end + +      def check_token_conflicts? +        @args.include?("--token-conflicts") +      end + +      def casks_to_audit +        if cask_tokens.empty? +          Hbc.all +        else +          cask_tokens.map { |token| Hbc.load(token) } +        end +      end + +      def cask_tokens +        @cask_tokens ||= self.class.cask_tokens_from(@args) +      end + +      def self.needs_init? +        true +      end      end    end - -  def audit(cask) -    odebug "Auditing Cask #{cask}" -    @auditor.audit(cask, audit_download:        audit_download?, -                         check_token_conflicts: check_token_conflicts?) -  end - -  def audit_download? -    @args.include?("--download") -  end - -  def check_token_conflicts? -    @args.include?("--token-conflicts") -  end - -  def casks_to_audit -    if cask_tokens.empty? -      Hbc.all -    else -      cask_tokens.map { |token| Hbc.load(token) } -    end -  end - -  def cask_tokens -    @cask_tokens ||= self.class.cask_tokens_from(@args) -  end - -  def self.needs_init? -    true -  end  end diff --git a/Library/Homebrew/cask/lib/hbc/cli/base.rb b/Library/Homebrew/cask/lib/hbc/cli/base.rb index af03969af..6c706d537 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/base.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/base.rb @@ -1,21 +1,25 @@ -class Hbc::CLI::Base -  def self.command_name -    @command_name ||= name.sub(%r{^.*:}, "").gsub(%r{(.)([A-Z])}, '\1_\2').downcase -  end +module Hbc +  class CLI +    class Base +      def self.command_name +        @command_name ||= name.sub(%r{^.*:}, "").gsub(%r{(.)([A-Z])}, '\1_\2').downcase +      end -  def self.visible -    true -  end +      def self.visible +        true +      end -  def self.cask_tokens_from(args) -    args.reject { |a| a.empty? || a.chars.first == "-" } -  end +      def self.cask_tokens_from(args) +        args.reject { |a| a.empty? || a.chars.first == "-" } +      end -  def self.help -    "No help available for the #{command_name} command" -  end +      def self.help +        "No help available for the #{command_name} command" +      end -  def self.needs_init? -    false +      def self.needs_init? +        false +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/cli/cat.rb b/Library/Homebrew/cask/lib/hbc/cli/cat.rb index d6d545c3b..75f6c1e91 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/cat.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/cat.rb @@ -1,15 +1,19 @@ -class Hbc::CLI::Cat < Hbc::CLI::Base -  def self.run(*args) -    cask_tokens = cask_tokens_from(args) -    raise Hbc::CaskUnspecifiedError if cask_tokens.empty? -    # only respects the first argument -    cask_token = cask_tokens.first.sub(%r{\.rb$}i, "") -    cask_path = Hbc.path(cask_token) -    raise Hbc::CaskUnavailableError, cask_token.to_s unless cask_path.exist? -    puts File.open(cask_path, &:read) -  end +module Hbc +  class CLI +    class Cat < Base +      def self.run(*args) +        cask_tokens = cask_tokens_from(args) +        raise CaskUnspecifiedError if cask_tokens.empty? +        # only respects the first argument +        cask_token = cask_tokens.first.sub(%r{\.rb$}i, "") +        cask_path = Hbc.path(cask_token) +        raise CaskUnavailableError, cask_token.to_s unless cask_path.exist? +        puts File.open(cask_path, &:read) +      end -  def self.help -    "dump raw source of the given Cask to the standard output" +      def self.help +        "dump raw source of the given Cask to the standard output" +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/cli/cleanup.rb b/Library/Homebrew/cask/lib/hbc/cli/cleanup.rb index 4115d26fc..0296dc96d 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/cleanup.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/cleanup.rb @@ -1,108 +1,112 @@ -class Hbc::CLI::Cleanup < Hbc::CLI::Base -  OUTDATED_DAYS = 10 -  OUTDATED_TIMESTAMP = Time.now - (60 * 60 * 24 * OUTDATED_DAYS) - -  def self.help -    "cleans up cached downloads and tracker symlinks" -  end - -  def self.needs_init? -    true -  end +module Hbc +  class CLI +    class Cleanup < Base +      OUTDATED_DAYS = 10 +      OUTDATED_TIMESTAMP = Time.now - (60 * 60 * 24 * OUTDATED_DAYS) + +      def self.help +        "cleans up cached downloads and tracker symlinks" +      end -  def self.run(*args) -    if args.empty? -      default.cleanup! -    else -      default.cleanup(args) -    end -  end +      def self.needs_init? +        true +      end -  def self.default -    @default ||= new(Hbc.cache, Hbc.cleanup_outdated) -  end +      def self.run(*args) +        if args.empty? +          default.cleanup! +        else +          default.cleanup(args) +        end +      end -  attr_reader :cache_location, :outdated_only -  def initialize(cache_location, outdated_only) -    @cache_location = Pathname.new(cache_location) -    @outdated_only = outdated_only -  end +      def self.default +        @default ||= new(Hbc.cache, Hbc.cleanup_outdated) +      end -  def cleanup! -    remove_cache_files -  end +      attr_reader :cache_location, :outdated_only +      def initialize(cache_location, outdated_only) +        @cache_location = Pathname.new(cache_location) +        @outdated_only = outdated_only +      end -  def cleanup(tokens) -    remove_cache_files(*tokens) -  end +      def cleanup! +        remove_cache_files +      end -  def cache_files -    return [] unless cache_location.exist? -    cache_location.children -                  .map(&method(:Pathname)) -                  .reject(&method(:outdated?)) -  end +      def cleanup(tokens) +        remove_cache_files(*tokens) +      end -  def outdated?(file) -    outdated_only && file && file.stat.mtime > OUTDATED_TIMESTAMP -  end +      def cache_files +        return [] unless cache_location.exist? +        cache_location.children +                      .map(&method(:Pathname)) +                      .reject(&method(:outdated?)) +      end -  def incomplete?(file) -    file.extname == ".incomplete" -  end +      def outdated?(file) +        outdated_only && file && file.stat.mtime > OUTDATED_TIMESTAMP +      end -  def cache_incompletes -    cache_files.select(&method(:incomplete?)) -  end +      def incomplete?(file) +        file.extname == ".incomplete" +      end -  def cache_completes -    cache_files.reject(&method(:incomplete?)) -  end +      def cache_incompletes +        cache_files.select(&method(:incomplete?)) +      end -  def disk_cleanup_size -    Hbc::Utils.size_in_bytes(cache_files) -  end +      def cache_completes +        cache_files.reject(&method(:incomplete?)) +      end -  def remove_cache_files(*tokens) -    message = "Removing cached downloads" -    message.concat " for #{tokens.join(', ')}" unless tokens.empty? -    message.concat " older than #{OUTDATED_DAYS} days old" if outdated_only -    ohai message +      def disk_cleanup_size +        Utils.size_in_bytes(cache_files) +      end -    deletable_cache_files = if tokens.empty? -                              cache_files -                            else -                              start_withs = tokens.map { |token| "#{token}--" } +      def remove_cache_files(*tokens) +        message = "Removing cached downloads" +        message.concat " for #{tokens.join(", ")}" unless tokens.empty? +        message.concat " older than #{OUTDATED_DAYS} days old" if outdated_only +        ohai message -                              cache_files.select { |path| -                                path.basename.to_s.start_with?(*start_withs) -                              } -                            end +        deletable_cache_files = if tokens.empty? +                                  cache_files +                                else +                                  start_withs = tokens.map { |token| "#{token}--" } -    delete_paths(deletable_cache_files) -  end +                                  cache_files.select { |path| +                                    path.basename.to_s.start_with?(*start_withs) +                                  } +                                end -  def delete_paths(paths) -    cleanup_size = 0 -    processed_files = 0 -    paths.each do |item| -      next unless item.exist? -      processed_files += 1 -      if Hbc::Utils.file_locked?(item) -        puts "skipping: #{item} is locked" -        next +        delete_paths(deletable_cache_files)        end -      puts item -      item_size = File.size?(item) -      cleanup_size += item_size unless item_size.nil? -      item.unlink -    end -    if processed_files.zero? -      puts "Nothing to do" -    else -      disk_space = disk_usage_readable(cleanup_size) -      ohai "This operation has freed approximately #{disk_space} of disk space." +      def delete_paths(paths) +        cleanup_size = 0 +        processed_files = 0 +        paths.each do |item| +          next unless item.exist? +          processed_files += 1 +          if Utils.file_locked?(item) +            puts "skipping: #{item} is locked" +            next +          end +          puts item +          item_size = File.size?(item) +          cleanup_size += item_size unless item_size.nil? +          item.unlink +        end + +        if processed_files.zero? +          puts "Nothing to do" +        else +          disk_space = disk_usage_readable(cleanup_size) +          ohai "This operation has freed approximately #{disk_space} of disk space." +        end +      end      end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/cli/create.rb b/Library/Homebrew/cask/lib/hbc/cli/create.rb index 3c1ac76ed..14860942f 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/create.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/create.rb @@ -1,37 +1,41 @@ -class Hbc::CLI::Create < Hbc::CLI::Base -  def self.run(*args) -    cask_tokens = cask_tokens_from(args) -    raise Hbc::CaskUnspecifiedError if cask_tokens.empty? -    cask_token = cask_tokens.first.sub(%r{\.rb$}i, "") -    cask_path = Hbc.path(cask_token) -    odebug "Creating Cask #{cask_token}" +module Hbc +  class CLI +    class Create < Base +      def self.run(*args) +        cask_tokens = cask_tokens_from(args) +        raise CaskUnspecifiedError if cask_tokens.empty? +        cask_token = cask_tokens.first.sub(%r{\.rb$}i, "") +        cask_path = Hbc.path(cask_token) +        odebug "Creating Cask #{cask_token}" -    raise Hbc::CaskAlreadyCreatedError, cask_token if cask_path.exist? +        raise CaskAlreadyCreatedError, cask_token if cask_path.exist? -    File.open(cask_path, "w") do |f| -      f.write template(cask_token) -    end +        File.open(cask_path, "w") do |f| +          f.write template(cask_token) +        end -    exec_editor cask_path -  end +        exec_editor cask_path +      end -  def self.template(cask_token) -    <<-EOS.undent -      cask '#{cask_token}' do -        version '' -        sha256 '' +      def self.template(cask_token) +        <<-EOS.undent +          cask '#{cask_token}' do +            version '' +            sha256 '' -        url 'https://' -        name '' -        homepage '' -        license :unknown # TODO: change license and remove this comment; ':unknown' is a machine-generated placeholder +            url 'https://' +            name '' +            homepage '' +            license :unknown # TODO: change license and remove this comment; ':unknown' is a machine-generated placeholder -        app '' +            app '' +          end +        EOS        end -    EOS -  end -  def self.help -    "creates the given Cask and opens it in an editor" +      def self.help +        "creates the given Cask and opens it in an editor" +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/cli/doctor.rb b/Library/Homebrew/cask/lib/hbc/cli/doctor.rb index 2632bcaef..34f000b29 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/doctor.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/doctor.rb @@ -1,205 +1,209 @@ -class Hbc::CLI::Doctor < Hbc::CLI::Base -  def self.run -    ohai "macOS Release:", render_with_none_as_error(MacOS.full_version) -    ohai "Hardware Architecture:", render_with_none_as_error("#{Hardware::CPU.type}-#{Hardware::CPU.bits}") -    ohai "Ruby Version:", render_with_none_as_error("#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}") -    ohai "Ruby Path:", render_with_none_as_error(RbConfig.ruby) -    # TODO: consider removing most Homebrew constants from doctor output -    ohai "Homebrew Version:", render_with_none_as_error(homebrew_version) -    ohai "Homebrew Executable Path:", render_with_none_as_error(Hbc.homebrew_executable) -    ohai "Homebrew Cellar Path:", render_with_none_as_error(homebrew_cellar) -    ohai "Homebrew Repository Path:", render_with_none_as_error(homebrew_repository) -    ohai "Homebrew Origin:", render_with_none_as_error(homebrew_origin) -    ohai "Homebrew-Cask Version:", render_with_none_as_error(Hbc.full_version) -    ohai "Homebrew-Cask Install Location:", render_install_location -    ohai "Homebrew-Cask Staging Location:", render_staging_location(Hbc.caskroom) -    ohai "Homebrew-Cask Cached Downloads:", render_cached_downloads -    ohai "Homebrew-Cask Default Tap Path:", render_tap_paths(Hbc.default_tap.path) -    ohai "Homebrew-Cask Alternate Cask Taps:", render_tap_paths(alt_taps) -    ohai "Homebrew-Cask Default Tap Cask Count:", render_with_none_as_error(default_cask_count) -    ohai "Contents of $LOAD_PATH:", render_load_path($LOAD_PATH) -    ohai "Contents of $RUBYLIB Environment Variable:", render_env_var("RUBYLIB") -    ohai "Contents of $RUBYOPT Environment Variable:", render_env_var("RUBYOPT") -    ohai "Contents of $RUBYPATH Environment Variable:", render_env_var("RUBYPATH") -    ohai "Contents of $RBENV_VERSION Environment Variable:", render_env_var("RBENV_VERSION") -    ohai "Contents of $CHRUBY_VERSION Environment Variable:", render_env_var("CHRUBY_VERSION") -    ohai "Contents of $GEM_HOME Environment Variable:", render_env_var("GEM_HOME") -    ohai "Contents of $GEM_PATH Environment Variable:", render_env_var("GEM_PATH") -    ohai "Contents of $BUNDLE_PATH Environment Variable:", render_env_var("BUNDLE_PATH") -    ohai "Contents of $PATH Environment Variable:", render_env_var("PATH") -    ohai "Contents of $SHELL Environment Variable:", render_env_var("SHELL") -    ohai "Contents of Locale Environment Variables:", render_with_none(locale_variables) -    ohai "Running As Privileged User:", render_with_none_as_error(privileged_uid) -  end +module Hbc +  class CLI +    class Doctor < Base +      def self.run +        ohai "macOS Release:", render_with_none_as_error(MacOS.full_version) +        ohai "Hardware Architecture:", render_with_none_as_error("#{Hardware::CPU.type}-#{Hardware::CPU.bits}") +        ohai "Ruby Version:", render_with_none_as_error("#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}") +        ohai "Ruby Path:", render_with_none_as_error(RbConfig.ruby) +        # TODO: consider removing most Homebrew constants from doctor output +        ohai "Homebrew Version:", render_with_none_as_error(homebrew_version) +        ohai "Homebrew Executable Path:", render_with_none_as_error(Hbc.homebrew_executable) +        ohai "Homebrew Cellar Path:", render_with_none_as_error(homebrew_cellar) +        ohai "Homebrew Repository Path:", render_with_none_as_error(homebrew_repository) +        ohai "Homebrew Origin:", render_with_none_as_error(homebrew_origin) +        ohai "Homebrew-Cask Version:", render_with_none_as_error(Hbc.full_version) +        ohai "Homebrew-Cask Install Location:", render_install_location +        ohai "Homebrew-Cask Staging Location:", render_staging_location(Hbc.caskroom) +        ohai "Homebrew-Cask Cached Downloads:", render_cached_downloads +        ohai "Homebrew-Cask Default Tap Path:", render_tap_paths(Hbc.default_tap.path) +        ohai "Homebrew-Cask Alternate Cask Taps:", render_tap_paths(alt_taps) +        ohai "Homebrew-Cask Default Tap Cask Count:", render_with_none_as_error(default_cask_count) +        ohai "Contents of $LOAD_PATH:", render_load_path($LOAD_PATH) +        ohai "Contents of $RUBYLIB Environment Variable:", render_env_var("RUBYLIB") +        ohai "Contents of $RUBYOPT Environment Variable:", render_env_var("RUBYOPT") +        ohai "Contents of $RUBYPATH Environment Variable:", render_env_var("RUBYPATH") +        ohai "Contents of $RBENV_VERSION Environment Variable:", render_env_var("RBENV_VERSION") +        ohai "Contents of $CHRUBY_VERSION Environment Variable:", render_env_var("CHRUBY_VERSION") +        ohai "Contents of $GEM_HOME Environment Variable:", render_env_var("GEM_HOME") +        ohai "Contents of $GEM_PATH Environment Variable:", render_env_var("GEM_PATH") +        ohai "Contents of $BUNDLE_PATH Environment Variable:", render_env_var("BUNDLE_PATH") +        ohai "Contents of $PATH Environment Variable:", render_env_var("PATH") +        ohai "Contents of $SHELL Environment Variable:", render_env_var("SHELL") +        ohai "Contents of Locale Environment Variables:", render_with_none(locale_variables) +        ohai "Running As Privileged User:", render_with_none_as_error(privileged_uid) +      end -  def self.alt_taps -    Tap.select { |t| t.cask_dir && t != Hbc.default_tap } -       .map(&:path) -  end +      def self.alt_taps +        Tap.select { |t| t.cask_dir && t != Hbc.default_tap } +           .map(&:path) +      end -  def self.default_cask_count -    Hbc.default_tap.cask_files.count -  rescue StandardError -    "0 #{error_string "Error reading #{Hbc.default_tap.path}"}" -  end +      def self.default_cask_count +        Hbc.default_tap.cask_files.count +      rescue StandardError +        "0 #{error_string "Error reading #{Hbc.default_tap.path}"}" +      end -  def self.homebrew_origin -    homebrew_origin = notfound_string -    begin -      Dir.chdir(homebrew_repository) do -        homebrew_origin = Hbc::SystemCommand.run("/usr/bin/git", -                                                 args:         %w[config --get remote.origin.url], -                                                 print_stderr: false).stdout.strip -      end -      if homebrew_origin !~ %r{\S} -        homebrew_origin = "#{none_string} #{error_string}" -      elsif homebrew_origin !~ %r{(mxcl|Homebrew)/(home)?brew(\.git)?\Z} -        homebrew_origin.concat " #{error_string 'warning: nonstandard origin'}" -      end -    rescue StandardError -      homebrew_origin = error_string "Not Found - Error running git" -    end -    homebrew_origin -  end +      def self.homebrew_origin +        homebrew_origin = notfound_string +        begin +          Dir.chdir(homebrew_repository) do +            homebrew_origin = SystemCommand.run("/usr/bin/git", +                                                     args:         %w[config --get remote.origin.url], +                                                     print_stderr: false).stdout.strip +          end +          if homebrew_origin !~ %r{\S} +            homebrew_origin = "#{none_string} #{error_string}" +          elsif homebrew_origin !~ %r{(mxcl|Homebrew)/(home)?brew(\.git)?\Z} +            homebrew_origin.concat " #{error_string "warning: nonstandard origin"}" +          end +        rescue StandardError +          homebrew_origin = error_string "Not Found - Error running git" +        end +        homebrew_origin +      end -  def self.homebrew_repository -    homebrew_constants("repository") -  end +      def self.homebrew_repository +        homebrew_constants("repository") +      end -  def self.homebrew_cellar -    homebrew_constants("cellar") -  end +      def self.homebrew_cellar +        homebrew_constants("cellar") +      end -  def self.homebrew_version -    homebrew_constants("version") -  end +      def self.homebrew_version +        homebrew_constants("version") +      end -  def self.homebrew_taps -    @homebrew_taps ||= if homebrew_repository.respond_to?(:join) -                         homebrew_repository.join("Library", "Taps") -                       end -  end +      def self.homebrew_taps +        @homebrew_taps ||= if homebrew_repository.respond_to?(:join) +                             homebrew_repository.join("Library", "Taps") +                           end +      end -  def self.homebrew_constants(name) -    @homebrew_constants ||= {} -    return @homebrew_constants[name] if @homebrew_constants.key?(name) -    @homebrew_constants[name] = notfound_string -    begin -      @homebrew_constants[name] = Hbc::SystemCommand.run!(Hbc.homebrew_executable, -                                                          args:         ["--#{name}"], -                                                          print_stderr: false) -                                                    .stdout -                                                    .strip -      if @homebrew_constants[name] !~ %r{\S} -        @homebrew_constants[name] = "#{none_string} #{error_string}" -      end -      path = Pathname.new(@homebrew_constants[name]) -      @homebrew_constants[name] = path if path.exist? -    rescue StandardError -      @homebrew_constants[name] = error_string "Not Found - Error running brew" -    end -    @homebrew_constants[name] -  end +      def self.homebrew_constants(name) +        @homebrew_constants ||= {} +        return @homebrew_constants[name] if @homebrew_constants.key?(name) +        @homebrew_constants[name] = notfound_string +        begin +          @homebrew_constants[name] = SystemCommand.run!(Hbc.homebrew_executable, +                                                              args:         ["--#{name}"], +                                                              print_stderr: false) +                                                        .stdout +                                                        .strip +          if @homebrew_constants[name] !~ %r{\S} +            @homebrew_constants[name] = "#{none_string} #{error_string}" +          end +          path = Pathname.new(@homebrew_constants[name]) +          @homebrew_constants[name] = path if path.exist? +        rescue StandardError +          @homebrew_constants[name] = error_string "Not Found - Error running brew" +        end +        @homebrew_constants[name] +      end -  def self.locale_variables -    ENV.keys.grep(%r{^(?:LC_\S+|LANG|LANGUAGE)\Z}).collect { |v| %Q{#{v}="#{ENV[v]}"} }.sort.join("\n") -  end +      def self.locale_variables +        ENV.keys.grep(%r{^(?:LC_\S+|LANG|LANGUAGE)\Z}).collect { |v| %Q{#{v}="#{ENV[v]}"} }.sort.join("\n") +      end -  def self.privileged_uid -    Process.euid == 0 ? "Yes #{error_string 'warning: not recommended'}" : "No" -  rescue StandardError -    notfound_string -  end +      def self.privileged_uid +        Process.euid.zero? ? "Yes #{error_string "warning: not recommended"}" : "No" +      rescue StandardError +        notfound_string +      end -  def self.none_string -    "<NONE>" -  end +      def self.none_string +        "<NONE>" +      end -  def self.legacy_tap_pattern -    %r{phinze} -  end +      def self.legacy_tap_pattern +        %r{phinze} +      end -  def self.notfound_string -    "#{Tty.red}Not Found - Unknown Error#{Tty.reset}" -  end +      def self.notfound_string +        "#{Tty.red}Not Found - Unknown Error#{Tty.reset}" +      end -  def self.error_string(string = "Error") -    "#{Tty.red}(#{string})#{Tty.reset}" -  end +      def self.error_string(string = "Error") +        "#{Tty.red}(#{string})#{Tty.reset}" +      end -  def self.render_with_none(string) -    return string if !string.nil? && string.respond_to?(:to_s) && !string.to_s.empty? -    none_string -  end +      def self.render_with_none(string) +        return string if !string.nil? && string.respond_to?(:to_s) && !string.to_s.empty? +        none_string +      end -  def self.render_with_none_as_error(string) -    return string if !string.nil? && string.respond_to?(:to_s) && !string.to_s.empty? -    "#{none_string} #{error_string}" -  end +      def self.render_with_none_as_error(string) +        return string if !string.nil? && string.respond_to?(:to_s) && !string.to_s.empty? +        "#{none_string} #{error_string}" +      end -  def self.render_tap_paths(paths) -    paths = [paths] unless paths.respond_to?(:each) -    paths.collect do |dir| -      if dir.nil? || dir.to_s.empty? -        none_string -      elsif dir.to_s.match(legacy_tap_pattern) -        dir.to_s.concat(" #{error_string 'Warning: legacy tap path'}") -      else -        dir.to_s +      def self.render_tap_paths(paths) +        paths = [paths] unless paths.respond_to?(:each) +        paths.collect do |dir| +          if dir.nil? || dir.to_s.empty? +            none_string +          elsif dir.to_s.match(legacy_tap_pattern) +            dir.to_s.concat(" #{error_string "Warning: legacy tap path"}") +          else +            dir.to_s +          end +        end        end -    end -  end -  def self.render_env_var(var) -    if ENV.key?(var) -      %Q{#{var}="#{ENV[var]}"} -    else -      none_string -    end -  end +      def self.render_env_var(var) +        if ENV.key?(var) +          %Q{#{var}="#{ENV[var]}"} +        else +          none_string +        end +      end -  # This could be done by calling into Homebrew, but the situation -  # where "doctor" is needed is precisely the situation where such -  # things are less dependable. -  def self.render_install_location -    locations = Dir.glob(Pathname.new(homebrew_cellar).join("brew-cask", "*")).reverse -    if locations.empty? -      none_string -    else -      locations.collect do |l| -        "#{l} #{error_string 'error: legacy install. Run "brew uninstall --force brew-cask".'}" +      # This could be done by calling into Homebrew, but the situation +      # where "doctor" is needed is precisely the situation where such +      # things are less dependable. +      def self.render_install_location +        locations = Dir.glob(Pathname.new(homebrew_cellar).join("brew-cask", "*")).reverse +        if locations.empty? +          none_string +        else +          locations.collect do |l| +            "#{l} #{error_string 'error: legacy install. Run "brew uninstall --force brew-cask".'}" +          end +        end        end -    end -  end -  def self.render_staging_location(path) -    path = Pathname.new(path) -    if !path.exist? -      "#{path} #{error_string 'error: path does not exist'}}" -    elsif !path.writable? -      "#{path} #{error_string 'error: not writable by current user'}" -    else -      path -    end -  end +      def self.render_staging_location(path) +        path = Pathname.new(path) +        if !path.exist? +          "#{path} #{error_string "error: path does not exist"}}" +        elsif !path.writable? +          "#{path} #{error_string "error: not writable by current user"}" +        else +          path +        end +      end -  def self.render_load_path(paths) -    return "#{none_string} #{error_string}" if [*paths].empty? -    paths -  end +      def self.render_load_path(paths) +        return "#{none_string} #{error_string}" if [*paths].empty? +        paths +      end -  def self.render_cached_downloads -    cleanup = Hbc::CLI::Cleanup.default -    files = cleanup.cache_files -    count = files.count -    size = cleanup.disk_cleanup_size -    size_msg = "#{number_readable(count)} files, #{disk_usage_readable(size)}" -    warn_msg = error_string('warning: run "brew cask cleanup"') -    size_msg << " #{warn_msg}" if count > 0 -    [Hbc.cache, size_msg] -  end +      def self.render_cached_downloads +        cleanup = CLI::Cleanup.default +        files = cleanup.cache_files +        count = files.count +        size = cleanup.disk_cleanup_size +        size_msg = "#{number_readable(count)} files, #{disk_usage_readable(size)}" +        warn_msg = error_string('warning: run "brew cask cleanup"') +        size_msg << " #{warn_msg}" if count > 0 +        [Hbc.cache, size_msg] +      end -  def self.help -    "checks for configuration issues" +      def self.help +        "checks for configuration issues" +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/cli/edit.rb b/Library/Homebrew/cask/lib/hbc/cli/edit.rb index b2d4a9156..3090cf196 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/edit.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/edit.rb @@ -1,18 +1,22 @@ -class Hbc::CLI::Edit < Hbc::CLI::Base -  def self.run(*args) -    cask_tokens = cask_tokens_from(args) -    raise Hbc::CaskUnspecifiedError if cask_tokens.empty? -    # only respects the first argument -    cask_token = cask_tokens.first.sub(%r{\.rb$}i, "") -    cask_path = Hbc.path(cask_token) -    odebug "Opening editor for Cask #{cask_token}" -    unless cask_path.exist? -      raise Hbc::CaskUnavailableError, %Q{#{cask_token}, run "brew cask create #{cask_token}" to create a new Cask} -    end -    exec_editor cask_path -  end +module Hbc +  class CLI +    class Edit < Base +      def self.run(*args) +        cask_tokens = cask_tokens_from(args) +        raise CaskUnspecifiedError if cask_tokens.empty? +        # only respects the first argument +        cask_token = cask_tokens.first.sub(%r{\.rb$}i, "") +        cask_path = Hbc.path(cask_token) +        odebug "Opening editor for Cask #{cask_token}" +        unless cask_path.exist? +          raise CaskUnavailableError, %Q{#{cask_token}, run "brew cask create #{cask_token}" to create a new Cask} +        end +        exec_editor cask_path +      end -  def self.help -    "edits the given Cask" +      def self.help +        "edits the given Cask" +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/cli/fetch.rb b/Library/Homebrew/cask/lib/hbc/cli/fetch.rb index 647f2af2c..9b3d5099c 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/fetch.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/fetch.rb @@ -1,19 +1,23 @@ -class Hbc::CLI::Fetch < Hbc::CLI::Base -  def self.run(*args) -    cask_tokens = cask_tokens_from(args) -    raise Hbc::CaskUnspecifiedError if cask_tokens.empty? -    force = args.include? "--force" +module Hbc +  class CLI +    class Fetch < Base +      def self.run(*args) +        cask_tokens = cask_tokens_from(args) +        raise CaskUnspecifiedError if cask_tokens.empty? +        force = args.include? "--force" -    cask_tokens.each do |cask_token| -      ohai "Downloading external files for Cask #{cask_token}" -      cask = Hbc.load(cask_token) -      downloaded_path = Hbc::Download.new(cask, force: force).perform -      Hbc::Verify.all(cask, downloaded_path) -      ohai "Success! Downloaded to -> #{downloaded_path}" -    end -  end +        cask_tokens.each do |cask_token| +          ohai "Downloading external files for Cask #{cask_token}" +          cask = Hbc.load(cask_token) +          downloaded_path = Download.new(cask, force: force).perform +          Verify.all(cask, downloaded_path) +          ohai "Success! Downloaded to -> #{downloaded_path}" +        end +      end -  def self.help -    "downloads remote application files to local cache" +      def self.help +        "downloads remote application files to local cache" +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/cli/home.rb b/Library/Homebrew/cask/lib/hbc/cli/home.rb index 9c8c0a0e4..b35b08279 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/home.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/home.rb @@ -1,18 +1,22 @@ -class Hbc::CLI::Home < Hbc::CLI::Base -  def self.run(*cask_tokens) -    if cask_tokens.empty? -      odebug "Opening project homepage" -      system "/usr/bin/open", "--", "http://caskroom.io/" -    else -      cask_tokens.each do |cask_token| -        odebug "Opening homepage for Cask #{cask_token}" -        cask = Hbc.load(cask_token) -        system "/usr/bin/open", "--", cask.homepage +module Hbc +  class CLI +    class Home < Base +      def self.run(*cask_tokens) +        if cask_tokens.empty? +          odebug "Opening project homepage" +          system "/usr/bin/open", "--", "http://caskroom.io/" +        else +          cask_tokens.each do |cask_token| +            odebug "Opening homepage for Cask #{cask_token}" +            cask = Hbc.load(cask_token) +            system "/usr/bin/open", "--", cask.homepage +          end +        end        end -    end -  end -  def self.help -    "opens the homepage of the given Cask" +      def self.help +        "opens the homepage of the given Cask" +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/cli/info.rb b/Library/Homebrew/cask/lib/hbc/cli/info.rb index 76f2d1366..7fbdff3eb 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/info.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/info.rb @@ -1,65 +1,69 @@ -class Hbc::CLI::Info < Hbc::CLI::Base -  def self.run(*args) -    cask_tokens = cask_tokens_from(args) -    raise Hbc::CaskUnspecifiedError if cask_tokens.empty? -    cask_tokens.each do |cask_token| -      odebug "Getting info for Cask #{cask_token}" -      cask = Hbc.load(cask_token) +module Hbc +  class CLI +    class Info < Base +      def self.run(*args) +        cask_tokens = cask_tokens_from(args) +        raise CaskUnspecifiedError if cask_tokens.empty? +        cask_tokens.each do |cask_token| +          odebug "Getting info for Cask #{cask_token}" +          cask = Hbc.load(cask_token) -      info(cask) -    end -  end +          info(cask) +        end +      end -  def self.help -    "displays information about the given Cask" -  end +      def self.help +        "displays information about the given Cask" +      end -  def self.info(cask) -    puts "#{cask.token}: #{cask.version}" -    puts formatted_url(cask.homepage) if cask.homepage -    installation_info(cask) -    puts "From: #{formatted_url(github_info(cask))}" if github_info(cask) -    name_info(cask) -    artifact_info(cask) -    Hbc::Installer.print_caveats(cask) -  end +      def self.info(cask) +        puts "#{cask.token}: #{cask.version}" +        puts formatted_url(cask.homepage) if cask.homepage +        installation_info(cask) +        puts "From: #{formatted_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}" -  end +      def self.formatted_url(url) +        "#{Tty.em}#{url}#{Tty.reset}" +      end -  def self.installation_info(cask) -    if cask.installed? -      cask.versions.each do |version| -        versioned_staged_path = cask.caskroom_path.join(version) +      def self.installation_info(cask) +        if cask.installed? +          cask.versions.each do |version| +            versioned_staged_path = cask.caskroom_path.join(version) -        puts versioned_staged_path.to_s -          .concat(" (") -          .concat(versioned_staged_path.exist? ? versioned_staged_path.abv : "#{Tty.red}does not exist#{Tty.reset}") -          .concat(")") +            puts versioned_staged_path.to_s +              .concat(" (") +              .concat(versioned_staged_path.exist? ? versioned_staged_path.abv : "#{Tty.red}does not exist#{Tty.reset}") +              .concat(")") +          end +        else +          puts "Not installed" +        end        end -    else -      puts "Not installed" -    end -  end -  def self.name_info(cask) -    ohai cask.name.size > 1 ? "Names" : "Name" -    puts cask.name.empty? ? "#{Tty.red}None#{Tty.reset}" : cask.name -  end +      def self.name_info(cask) +        ohai cask.name.size > 1 ? "Names" : "Name" +        puts cask.name.empty? ? "#{Tty.red}None#{Tty.reset}" : cask.name +      end -  def self.github_info(cask) -    user, repo, token = Hbc::QualifiedToken.parse(Hbc.all_tokens.detect { |t| t.split("/").last == cask.token }) -    "#{Tap.fetch(user, repo).default_remote}/blob/master/Casks/#{token}.rb" -  end +      def self.github_info(cask) +        user, repo, token = QualifiedToken.parse(Hbc.all_tokens.detect { |t| t.split("/").last == cask.token }) +        "#{Tap.fetch(user, repo).default_remote}/blob/master/Casks/#{token}.rb" +      end -  def self.artifact_info(cask) -    ohai "Artifacts" -    Hbc::DSL::ORDINARY_ARTIFACT_TYPES.each do |type| -      next if cask.artifacts[type].empty? -      cask.artifacts[type].each do |artifact| -        activatable_item = type == :stage_only ? "<none>" : artifact.first -        puts "#{activatable_item} (#{type})" +      def self.artifact_info(cask) +        ohai "Artifacts" +        DSL::ORDINARY_ARTIFACT_TYPES.each do |type| +          next if cask.artifacts[type].empty? +          cask.artifacts[type].each do |artifact| +            activatable_item = type == :stage_only ? "<none>" : artifact.first +            puts "#{activatable_item} (#{type})" +          end +        end        end      end    end diff --git a/Library/Homebrew/cask/lib/hbc/cli/install.rb b/Library/Homebrew/cask/lib/hbc/cli/install.rb index 43eab9f3d..d7575344d 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/install.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/install.rb @@ -1,60 +1,63 @@ +module Hbc +  class CLI +    class Install < Base +      def self.run(*args) +        cask_tokens = cask_tokens_from(args) +        raise CaskUnspecifiedError if cask_tokens.empty? +        force = args.include? "--force" +        skip_cask_deps = args.include? "--skip-cask-deps" +        require_sha = args.include? "--require-sha" +        retval = install_casks cask_tokens, force, skip_cask_deps, require_sha +        # retval is ternary: true/false/nil -class Hbc::CLI::Install < Hbc::CLI::Base -  def self.run(*args) -    cask_tokens = cask_tokens_from(args) -    raise Hbc::CaskUnspecifiedError if cask_tokens.empty? -    force = args.include? "--force" -    skip_cask_deps = args.include? "--skip-cask-deps" -    require_sha = args.include? "--require-sha" -    retval = install_casks cask_tokens, force, skip_cask_deps, require_sha -    # retval is ternary: true/false/nil - -    raise Hbc::CaskError, "nothing to install" if retval.nil? -    raise Hbc::CaskError, "install incomplete" unless retval -  end +        raise CaskError, "nothing to install" if retval.nil? +        raise CaskError, "install incomplete" unless retval +      end -  def self.install_casks(cask_tokens, force, skip_cask_deps, require_sha) -    count = 0 -    cask_tokens.each do |cask_token| -      begin -        cask = Hbc.load(cask_token) -        Hbc::Installer.new(cask, -                           force:          force, -                           skip_cask_deps: skip_cask_deps, -                           require_sha:    require_sha).install -        count += 1 -      rescue Hbc::CaskAlreadyInstalledError => e -        opoo e.message -        count += 1 -      rescue Hbc::CaskAutoUpdatesError => e -        opoo e.message -        count += 1 -      rescue Hbc::CaskUnavailableError => e -        warn_unavailable_with_suggestion cask_token, e -      rescue Hbc::CaskNoShasumError => e -        opoo e.message -        count += 1 +      def self.install_casks(cask_tokens, force, skip_cask_deps, require_sha) +        count = 0 +        cask_tokens.each do |cask_token| +          begin +            cask = Hbc.load(cask_token) +            Installer.new(cask, +                               force:          force, +                               skip_cask_deps: skip_cask_deps, +                               require_sha:    require_sha).install +            count += 1 +          rescue CaskAlreadyInstalledError => e +            opoo e.message +            count += 1 +          rescue CaskAutoUpdatesError => e +            opoo e.message +            count += 1 +          rescue CaskUnavailableError => e +            warn_unavailable_with_suggestion cask_token, e +          rescue CaskNoShasumError => e +            opoo e.message +            count += 1 +          end +        end +        count.zero? ? nil : count == cask_tokens.length        end -    end -    count == 0 ? nil : count == cask_tokens.length -  end -  def self.warn_unavailable_with_suggestion(cask_token, e) -    exact_match, partial_matches = Hbc::CLI::Search.search(cask_token) -    errmsg = e.message -    if exact_match -      errmsg.concat(". Did you mean:\n#{exact_match}") -    elsif !partial_matches.empty? -      errmsg.concat(". Did you mean one of:\n#{puts_columns(partial_matches.take(20))}\n") -    end -    onoe errmsg -  end +      def self.warn_unavailable_with_suggestion(cask_token, e) +        exact_match, partial_matches = Search.search(cask_token) +        errmsg = e.message +        if exact_match +          errmsg.concat(". Did you mean:\n#{exact_match}") +        elsif !partial_matches.empty? +          errmsg.concat(". Did you mean one of:\n#{puts_columns(partial_matches.take(20))}\n") +        end +        onoe errmsg +      end -  def self.help -    "installs the given Cask" -  end +      def self.help +        "installs the given Cask" +      end -  def self.needs_init? -    true +      def self.needs_init? +        true +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_audit_modified_casks.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_audit_modified_casks.rb index f05dbe803..47258a7b2 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/internal_audit_modified_casks.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_audit_modified_casks.rb @@ -1,135 +1,139 @@ -class Hbc::CLI::InternalAuditModifiedCasks < Hbc::CLI::InternalUseBase -  RELEVANT_STANZAS = %i{version sha256 url appcast}.freeze +module Hbc +  class CLI +    class InternalAuditModifiedCasks < InternalUseBase +      RELEVANT_STANZAS = %i{version sha256 url appcast}.freeze + +      class << self +        def needs_init? +          true +        end + +        def run(*args) +          commit_range = commit_range(args) +          cleanup = args.any? { |a| a =~ %r{^-+c(leanup)?$}i } +          new(commit_range, cleanup: cleanup).run +        end + +        def commit_range(args) +          posargs = args.reject { |a| a.empty? || a.chars.first == "-" } +          odie usage unless posargs.size == 1 +          posargs.first +        end + +        def posargs(args) +          args.reject { |a| a.empty? || a.chars.first == "-" } +        end + +        def usage +          <<-EOS.undent +            Usage: brew cask _audit_modified_casks [options...] <commit range> + +            Given a range of Git commits, find any Casks that were modified and run `brew +            cask audit' on them. If the `url', `version', or `sha256' stanzas were modified, +            run with the `--download' flag to verify the hash. + +            Options: +              -c, --cleanup +                Remove all cached downloads. Use with care. +          EOS +        end +      end -  class << self -    def needs_init? -      true -    end +      def initialize(commit_range, cleanup: false) +        @commit_range = commit_range +        @cleanup = cleanup +      end -    def run(*args) -      commit_range = commit_range(args) -      cleanup = args.any? { |a| a =~ %r{^-+c(leanup)?$}i } -      new(commit_range, cleanup: cleanup).run -    end +      attr_reader :commit_range -    def commit_range(args) -      posargs = args.reject { |a| a.empty? || a.chars.first == "-" } -      odie usage unless posargs.size == 1 -      posargs.first -    end +      def cleanup? +        @cleanup +      end -    def posargs(args) -      args.reject { |a| a.empty? || a.chars.first == "-" } -    end +      def run +        at_exit do +          cleanup +        end + +        Dir.chdir git_root do +          modified_cask_files.zip(modified_casks).each do |cask_file, cask| +            audit(cask, cask_file) +          end +        end +        report_failures +      end -    def usage -      <<-EOS.undent -        Usage: brew cask _audit_modified_casks [options...] <commit range> +      def git_root +        @git_root ||= git("rev-parse", "--show-toplevel") +      end -        Given a range of Git commits, find any Casks that were modified and run `brew -        cask audit' on them. If the `url', `version', or `sha256' stanzas were modified, -        run with the `--download' flag to verify the hash. +      def modified_cask_files +        @modified_cask_files ||= git_filter_cask_files("AM") +      end -        Options: -          -c, --cleanup -            Remove all cached downloads. Use with care. -      EOS -    end -  end +      def added_cask_files +        @added_cask_files ||= git_filter_cask_files("A") +      end -  def initialize(commit_range, cleanup: false) -    @commit_range = commit_range -    @cleanup = cleanup -  end +      def git_filter_cask_files(filter) +        git("diff", "--name-only", "--diff-filter=#{filter}", commit_range, +            "--", Pathname.new(git_root).join("Casks", "*.rb").to_s).split("\n") +      end -  attr_reader :commit_range +      def modified_casks +        return @modified_casks if defined? @modified_casks +        @modified_casks = modified_cask_files.map { |f| Hbc.load(f) } +        if @modified_casks.any? +          num_modified = @modified_casks.size +          ohai "#{num_modified} modified #{pluralize("cask", num_modified)}: " \ +            "#{@modified_casks.join(" ")}" +        end +        @modified_casks +      end -  def cleanup? -    @cleanup -  end +      def audit(cask, cask_file) +        audit_download = audit_download?(cask, cask_file) +        check_token_conflicts = added_cask_files.include?(cask_file) +        success = Auditor.audit(cask, audit_download:        audit_download, +                                      check_token_conflicts: check_token_conflicts) +        failed_casks << cask unless success +      end -  def run -    at_exit do -      cleanup -    end +      def failed_casks +        @failed_casks ||= [] +      end -    Dir.chdir git_root do -      modified_cask_files.zip(modified_casks).each do |cask_file, cask| -        audit(cask, cask_file) +      def audit_download?(cask, cask_file) +        cask.sha256 != :no_check && relevant_stanza_modified?(cask_file)        end -    end -    report_failures -  end -  def git_root -    @git_root ||= git(*%w[rev-parse --show-toplevel]) -  end +      def relevant_stanza_modified?(cask_file) +        out = git("diff", commit_range, "--", cask_file) +        out =~ %r{^\+\s*(#{RELEVANT_STANZAS.join('|')})} +      end -  def modified_cask_files -    @modified_cask_files ||= git_filter_cask_files("AM") -  end +      def git(*args) +        odebug ["git", *args].join(" ") +        out, err, status = Open3.capture3("git", *args) +        return out.chomp if status.success? +        odie err.chomp +      end -  def added_cask_files -    @added_cask_files ||= git_filter_cask_files("A") -  end +      def report_failures +        return if failed_casks.empty? +        num_failed = failed_casks.size +        cask_pluralized = pluralize("cask", num_failed) +        odie "audit failed for #{num_failed} #{cask_pluralized}: " \ +          "#{failed_casks.join(" ")}" +      end -  def git_filter_cask_files(filter) -    git("diff", "--name-only", "--diff-filter=#{filter}", commit_range, -        "--", Pathname.new(git_root).join("Casks", "*.rb").to_s).split("\n") -  end +      def pluralize(str, num) +        num == 1 ?  str : "#{str}s" +      end -  def modified_casks -    return @modified_casks if defined? @modified_casks -    @modified_casks = modified_cask_files.map { |f| Hbc.load(f) } -    if @modified_casks.any? -      num_modified = @modified_casks.size -      ohai "#{num_modified} modified #{pluralize('cask', num_modified)}: " \ -        "#{@modified_casks.join(' ')}" +      def cleanup +        Cleanup.run if cleanup? +      end      end -    @modified_casks -  end - -  def audit(cask, cask_file) -    audit_download = audit_download?(cask, cask_file) -    check_token_conflicts = added_cask_files.include?(cask_file) -    success = Hbc::Auditor.audit(cask, audit_download:        audit_download, -                                       check_token_conflicts: check_token_conflicts) -    failed_casks << cask unless success -  end - -  def failed_casks -    @failed_casks ||= [] -  end - -  def audit_download?(cask, cask_file) -    cask.sha256 != :no_check && relevant_stanza_modified?(cask_file) -  end - -  def relevant_stanza_modified?(cask_file) -    out = git("diff", commit_range, "--", cask_file) -    out =~ %r{^\+\s*(#{RELEVANT_STANZAS.join('|')})} -  end - -  def git(*args) -    odebug ["git", *args].join(" ") -    out, err, status = Open3.capture3("git", *args) -    return out.chomp if status.success? -    odie err.chomp -  end - -  def report_failures -    return if failed_casks.empty? -    num_failed = failed_casks.size -    cask_pluralized = pluralize("cask", num_failed) -    odie "audit failed for #{num_failed} #{cask_pluralized}: " \ -      "#{failed_casks.join(' ')}" -  end - -  def pluralize(str, num) -    num == 1 ?  str : "#{str}s" -  end - -  def cleanup -    Hbc::CLI::Cleanup.run if cleanup?    end  end diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_checkurl.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_checkurl.rb index d53f420e2..77cf250b1 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/internal_checkurl.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_checkurl.rb @@ -1,15 +1,19 @@ -class Hbc::CLI::InternalCheckurl < Hbc::CLI::InternalUseBase -  def self.run(*args) -    casks_to_check = args.empty? ? Hbc.all : args.map { |arg| Hbc.load(arg) } -    casks_to_check.each do |cask| -      odebug "Checking URL for Cask #{cask}" -      checker = Hbc::UrlChecker.new(cask) -      checker.run -      puts checker.summary -    end -  end +module Hbc +  class CLI +    class InternalCheckurl < InternalUseBase +      def self.run(*args) +        casks_to_check = args.empty? ? Hbc.all : args.map { |arg| Hbc.load(arg) } +        casks_to_check.each do |cask| +          odebug "Checking URL for Cask #{cask}" +          checker = UrlChecker.new(cask) +          checker.run +          puts checker.summary +        end +      end -  def self.help -    "checks for bad Cask URLs" +      def self.help +        "checks for bad Cask URLs" +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_dump.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_dump.rb index d1cfe8d63..af1494e5f 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/internal_dump.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_dump.rb @@ -1,30 +1,34 @@ -class Hbc::CLI::InternalDump < Hbc::CLI::InternalUseBase -  def self.run(*arguments) -    cask_tokens = cask_tokens_from(arguments) -    raise Hbc::CaskUnspecifiedError if cask_tokens.empty? -    retval = dump_casks(*cask_tokens) -    # retval is ternary: true/false/nil +module Hbc +  class CLI +    class InternalDump < InternalUseBase +      def self.run(*arguments) +        cask_tokens = cask_tokens_from(arguments) +        raise CaskUnspecifiedError if cask_tokens.empty? +        retval = dump_casks(*cask_tokens) +        # retval is ternary: true/false/nil -    raise Hbc::CaskError, "nothing to dump" if retval.nil? -    raise Hbc::CaskError, "dump incomplete" unless retval -  end +        raise CaskError, "nothing to dump" if retval.nil? +        raise CaskError, "dump incomplete" unless retval +      end -  def self.dump_casks(*cask_tokens) -    Hbc.debug = true # Yuck. At the moment this is the only way to make dumps visible -    count = 0 -    cask_tokens.each do |cask_token| -      begin -        cask = Hbc.load(cask_token) -        count += 1 -        cask.dumpcask -      rescue StandardError => e -        opoo "#{cask_token} was not found or would not load: #{e}" +      def self.dump_casks(*cask_tokens) +        Hbc.debug = true # Yuck. At the moment this is the only way to make dumps visible +        count = 0 +        cask_tokens.each do |cask_token| +          begin +            cask = Hbc.load(cask_token) +            count += 1 +            cask.dumpcask +          rescue StandardError => e +            opoo "#{cask_token} was not found or would not load: #{e}" +          end +        end +        count.zero? ? nil : count == cask_tokens.length        end -    end -    count == 0 ? nil : count == cask_tokens.length -  end -  def self.help -    "Dump the given Cask in YAML format" +      def self.help +        "Dump the given Cask in YAML format" +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_help.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_help.rb index 81d7ee673..6c646cfd7 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/internal_help.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_help.rb @@ -1,19 +1,23 @@ -class Hbc::CLI::InternalHelp < Hbc::CLI::InternalUseBase -  def self.run(*_ignored) -    max_command_len = Hbc::CLI.commands.map(&:length).max -    puts "Unstable Internal-use Commands:\n\n" -    Hbc::CLI.command_classes.each do |klass| -      next if klass.visible -      puts "    #{klass.command_name.ljust(max_command_len)}  #{help_for(klass)}" -    end -    puts "\n" -  end +module Hbc +  class CLI +    class InternalHelp < InternalUseBase +      def self.run(*_ignored) +        max_command_len = CLI.commands.map(&:length).max +        puts "Unstable Internal-use Commands:\n\n" +        CLI.command_classes.each do |klass| +          next if klass.visible +          puts "    #{klass.command_name.ljust(max_command_len)}  #{help_for(klass)}" +        end +        puts "\n" +      end -  def self.help_for(klass) -    klass.respond_to?(:help) ? klass.help : nil -  end +      def self.help_for(klass) +        klass.respond_to?(:help) ? klass.help : nil +      end -  def self.help -    "Print help strings for unstable internal-use commands" +      def self.help +        "Print help strings for unstable internal-use commands" +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb index 651a9ae37..0265e34b7 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_stanza.rb @@ -1,127 +1,131 @@ -class Hbc::CLI::InternalStanza < Hbc::CLI::InternalUseBase -  # Syntax -  # -  #     brew cask _stanza <stanza_name> [ --table | --yaml | --inspect | --quiet ] [ <cask_token> ... ] -  # -  # If no tokens are given, then data for all Casks is returned. -  # -  # The pseudo-stanza "artifacts" is available. -  # -  # On failure, a blank line is returned on the standard output. -  # -  # Examples -  # -  #     brew cask _stanza appcast   --table -  #     brew cask _stanza app       --table alfred google-chrome adium voicemac logisim vagrant -  #     brew cask _stanza url       --table alfred google-chrome adium voicemac logisim vagrant -  #     brew cask _stanza version   --table alfred google-chrome adium voicemac logisim vagrant -  #     brew cask _stanza artifacts --table --inspect alfred google-chrome adium voicemac logisim vagrant -  #     brew cask _stanza artifacts --table --yaml    alfred google-chrome adium voicemac logisim vagrant -  # +module Hbc +  class CLI +    class InternalStanza < InternalUseBase +      # Syntax +      # +      #     brew cask _stanza <stanza_name> [ --table | --yaml | --inspect | --quiet ] [ <cask_token> ... ] +      # +      # If no tokens are given, then data for all Casks is returned. +      # +      # The pseudo-stanza "artifacts" is available. +      # +      # On failure, a blank line is returned on the standard output. +      # +      # Examples +      # +      #     brew cask _stanza appcast   --table +      #     brew cask _stanza app       --table alfred google-chrome adium voicemac logisim vagrant +      #     brew cask _stanza url       --table alfred google-chrome adium voicemac logisim vagrant +      #     brew cask _stanza version   --table alfred google-chrome adium voicemac logisim vagrant +      #     brew cask _stanza artifacts --table --inspect alfred google-chrome adium voicemac logisim vagrant +      #     brew cask _stanza artifacts --table --yaml    alfred google-chrome adium voicemac logisim vagrant +      # -  # TODO: this should be retrievable from Hbc::DSL -  ARTIFACTS = Set.new [ -                        :app, -                        :suite, -                        :artifact, -                        :prefpane, -                        :qlplugin, -                        :font, -                        :service, -                        :colorpicker, -                        :binary, -                        :input_method, -                        :internet_plugin, -                        :audio_unit_plugin, -                        :vst_plugin, -                        :vst3_plugin, -                        :screen_saver, -                        :pkg, -                        :installer, -                        :stage_only, -                        :nested_container, -                        :uninstall, -                        :postflight, -                        :uninstall_postflight, -                        :preflight, -                        :uninstall_postflight, -                      ] +      # TODO: this should be retrievable from Hbc::DSL +      ARTIFACTS = Set.new [ +                            :app, +                            :suite, +                            :artifact, +                            :prefpane, +                            :qlplugin, +                            :font, +                            :service, +                            :colorpicker, +                            :binary, +                            :input_method, +                            :internet_plugin, +                            :audio_unit_plugin, +                            :vst_plugin, +                            :vst3_plugin, +                            :screen_saver, +                            :pkg, +                            :installer, +                            :stage_only, +                            :nested_container, +                            :uninstall, +                            :postflight, +                            :uninstall_postflight, +                            :preflight, +                            :uninstall_postflight, +                          ] -  def self.run(*arguments) -    table = arguments.include? "--table" -    quiet = arguments.include? "--quiet" -    format = :to_yaml if arguments.include? "--yaml" -    format = :inspect if arguments.include? "--inspect" -    cask_tokens = arguments.reject { |arg| arg.chars.first == "-" } -    stanza = cask_tokens.shift.to_sym -    cask_tokens = Hbc.all_tokens if cask_tokens.empty? +      def self.run(*arguments) +        table = arguments.include? "--table" +        quiet = arguments.include? "--quiet" +        format = :to_yaml if arguments.include? "--yaml" +        format = :inspect if arguments.include? "--inspect" +        cask_tokens = arguments.reject { |arg| arg.chars.first == "-" } +        stanza = cask_tokens.shift.to_sym +        cask_tokens = Hbc.all_tokens if cask_tokens.empty? -    retval = print_stanzas(stanza, format, table, quiet, *cask_tokens) +        retval = print_stanzas(stanza, format, table, quiet, *cask_tokens) -    # retval is ternary: true/false/nil -    if retval.nil? -      exit 1 if quiet -      raise Hbc::CaskError, "nothing to print" -    elsif !retval -      exit 1 if quiet -      raise Hbc::CaskError, "print incomplete" -    end -  end +        # retval is ternary: true/false/nil +        if retval.nil? +          exit 1 if quiet +          raise CaskError, "nothing to print" +        elsif !retval +          exit 1 if quiet +          raise CaskError, "print incomplete" +        end +      end -  def self.print_stanzas(stanza, format = nil, table = nil, quiet = nil, *cask_tokens) -    count = 0 -    if ARTIFACTS.include?(stanza) -      artifact_name = stanza -      stanza = :artifacts -    end +      def self.print_stanzas(stanza, format = nil, table = nil, quiet = nil, *cask_tokens) +        count = 0 +        if ARTIFACTS.include?(stanza) +          artifact_name = stanza +          stanza = :artifacts +        end -    cask_tokens.each do |cask_token| -      print "#{cask_token}\t" if table +        cask_tokens.each do |cask_token| +          print "#{cask_token}\t" if table -      begin -        cask = Hbc.load(cask_token) -      rescue StandardError -        opoo "Cask '#{cask_token}' was not found" unless quiet -        puts "" -        next -      end +          begin +            cask = Hbc.load(cask_token) +          rescue StandardError +            opoo "Cask '#{cask_token}' was not found" unless quiet +            puts "" +            next +          end -      unless cask.respond_to?(stanza) -        opoo "no such stanza '#{stanza}' on Cask '#{cask_token}'" unless quiet -        puts "" -        next -      end +          unless cask.respond_to?(stanza) +            opoo "no such stanza '#{stanza}' on Cask '#{cask_token}'" unless quiet +            puts "" +            next +          end -      begin -        value = cask.send(stanza) -      rescue StandardError -        opoo "failure calling '#{stanza}' on Cask '#{cask_token}'" unless quiet -        puts "" -        next -      end +          begin +            value = cask.send(stanza) +          rescue StandardError +            opoo "failure calling '#{stanza}' on Cask '#{cask_token}'" unless quiet +            puts "" +            next +          end -      if artifact_name && !value.key?(artifact_name) -        opoo "no such stanza '#{artifact_name}' on Cask '#{cask_token}'" unless quiet -        puts "" -        next -      end +          if artifact_name && !value.key?(artifact_name) +            opoo "no such stanza '#{artifact_name}' on Cask '#{cask_token}'" unless quiet +            puts "" +            next +          end + +          value = value.fetch(artifact_name).to_a.flatten if artifact_name -      value = value.fetch(artifact_name).to_a.flatten if artifact_name +          if format +            puts value.send(format) +          elsif artifact_name || value.is_a?(Symbol) +            puts value.inspect +          else +            puts value.to_s +          end -      if format -        puts value.send(format) -      elsif artifact_name || value.is_a?(Symbol) -        puts value.inspect -      else -        puts value.to_s +          count += 1 +        end +        count.zero? ? nil : count == cask_tokens.length        end -      count += 1 +      def self.help +        "Extract and render a specific stanza for the given Casks" +      end      end -    count == 0 ? nil : count == cask_tokens.length -  end - -  def self.help -    "Extract and render a specific stanza for the given Casks"    end  end diff --git a/Library/Homebrew/cask/lib/hbc/cli/internal_use_base.rb b/Library/Homebrew/cask/lib/hbc/cli/internal_use_base.rb index 6a4359ea1..96b6eeaa8 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/internal_use_base.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/internal_use_base.rb @@ -1,9 +1,13 @@ -class Hbc::CLI::InternalUseBase < Hbc::CLI::Base -  def self.command_name -    super.sub(%r{^internal_}i, "_") -  end +module Hbc +  class CLI +    class InternalUseBase < Base +      def self.command_name +        super.sub(%r{^internal_}i, "_") +      end -  def self.visible -    false +      def self.visible +        false +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/cli/list.rb b/Library/Homebrew/cask/lib/hbc/cli/list.rb index 88907a797..3a993f8e6 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/list.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/list.rb @@ -1,86 +1,90 @@ -class Hbc::CLI::List < Hbc::CLI::Base -  def self.run(*arguments) -    @options = {} -    @options[:one] = true if arguments.delete("-1") -    @options[:versions] = true if arguments.delete("--versions") +module Hbc +  class CLI +    class List < Base +      def self.run(*arguments) +        @options = {} +        @options[:one] = true if arguments.delete("-1") +        @options[:versions] = true if arguments.delete("--versions") -    if arguments.delete("-l") -      @options[:one] = true -      opoo "Option -l is obsolete! Implying option -1." -    end +        if arguments.delete("-l") +          @options[:one] = true +          opoo "Option -l is obsolete! Implying option -1." +        end -    retval = arguments.any? ? list(*arguments) : list_installed -    # retval is ternary: true/false/nil -    if retval.nil? && !arguments.any? -      opoo "nothing to list" # special case: avoid exit code -    elsif retval.nil? -      raise Hbc::CaskError, "nothing to list" -    elsif !retval -      raise Hbc::CaskError, "listing incomplete" -    end -  end +        retval = arguments.any? ? list(*arguments) : list_installed +        # retval is ternary: true/false/nil +        if retval.nil? && !arguments.any? +          opoo "nothing to list" # special case: avoid exit code +        elsif retval.nil? +          raise CaskError, "nothing to list" +        elsif !retval +          raise CaskError, "listing incomplete" +        end +      end -  def self.list(*cask_tokens) -    count = 0 +      def self.list(*cask_tokens) +        count = 0 -    cask_tokens.each do |cask_token| -      odebug "Listing files for Cask #{cask_token}" -      begin -        cask = Hbc.load(cask_token) +        cask_tokens.each do |cask_token| +          odebug "Listing files for Cask #{cask_token}" +          begin +            cask = Hbc.load(cask_token) -        if cask.installed? -          if @options[:one] -            puts cask.token -          elsif @options[:versions] -            puts format_versioned(cask) -          else -            installed_caskfile = cask.metadata_master_container_path.join(*cask.timestamped_versions.last, "Casks", "#{cask_token}.rb") -            cask = Hbc.load(installed_caskfile) -            list_artifacts(cask) -          end +            if cask.installed? +              if @options[:one] +                puts cask.token +              elsif @options[:versions] +                puts format_versioned(cask) +              else +                installed_caskfile = cask.metadata_master_container_path.join(*cask.timestamped_versions.last, "Casks", "#{cask_token}.rb") +                cask = Hbc.load(installed_caskfile) +                list_artifacts(cask) +              end -          count += 1 -        else -          opoo "#{cask} is not installed" +              count += 1 +            else +              opoo "#{cask} is not installed" +            end +          rescue CaskUnavailableError => e +            onoe e +          end          end -      rescue Hbc::CaskUnavailableError => e -        onoe e -      end -    end -    count == 0 ? nil : count == cask_tokens.length -  end +        count.zero? ? nil : count == cask_tokens.length +      end -  def self.list_artifacts(cask) -    Hbc::Artifact.for_cask(cask).each do |artifact| -      summary = artifact.new(cask).summary -      ohai summary[:english_description], summary[:contents] unless summary.empty? -    end -  end +      def self.list_artifacts(cask) +        Artifact.for_cask(cask).each do |artifact| +          summary = artifact.new(cask).summary +          ohai summary[:english_description], summary[:contents] unless summary.empty? +        end +      end -  def self.list_installed -    installed_casks = Hbc.installed +      def self.list_installed +        installed_casks = Hbc.installed -    if @options[:one] -      puts installed_casks.map(&:to_s) -    elsif @options[:versions] -      puts installed_casks.map(&method(:format_versioned)) -    else -      puts_columns installed_casks.map(&:to_s) -    end +        if @options[:one] +          puts installed_casks.map(&:to_s) +        elsif @options[:versions] +          puts installed_casks.map(&method(:format_versioned)) +        else +          puts_columns installed_casks.map(&:to_s) +        end -    installed_casks.empty? ? nil : true -  end +        installed_casks.empty? ? nil : true +      end -  def self.format_versioned(cask) -    cask.to_s.concat(cask.versions.map(&:to_s).join(" ").prepend(" ")) -  end +      def self.format_versioned(cask) +        cask.to_s.concat(cask.versions.map(&:to_s).join(" ").prepend(" ")) +      end -  def self.help -    "with no args, lists installed Casks; given installed Casks, lists staged files" -  end +      def self.help +        "with no args, lists installed Casks; given installed Casks, lists staged files" +      end -  def self.needs_init? -    true +      def self.needs_init? +        true +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/cli/search.rb b/Library/Homebrew/cask/lib/hbc/cli/search.rb index 5c57ba43d..b671ea862 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/search.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/search.rb @@ -1,55 +1,59 @@ -class Hbc::CLI::Search < Hbc::CLI::Base -  def self.run(*arguments) -    render_results(*search(*arguments)) -  end +module Hbc +  class CLI +    class Search < Base +      def self.run(*arguments) +        render_results(*search(*arguments)) +      end -  def self.extract_regexp(string) -    if string =~ %r{^/(.*)/$} -      Regexp.last_match[1] -    else -      false -    end -  end +      def self.extract_regexp(string) +        if string =~ %r{^/(.*)/$} +          Regexp.last_match[1] +        else +          false +        end +      end -  def self.search(*arguments) -    exact_match = nil -    partial_matches = [] -    search_term = arguments.join(" ") -    search_regexp = extract_regexp arguments.first -    all_tokens = Hbc::CLI.nice_listing(Hbc.all_tokens) -    if search_regexp -      search_term = arguments.first -      partial_matches = all_tokens.grep(%r{#{search_regexp}}i) -    else -      simplified_tokens = all_tokens.map { |t| t.sub(%r{^.*\/}, "").gsub(%r{[^a-z0-9]+}i, "") } -      simplified_search_term = search_term.sub(%r{\.rb$}i, "").gsub(%r{[^a-z0-9]+}i, "") -      exact_match = simplified_tokens.grep(%r{^#{simplified_search_term}$}i) { |t| all_tokens[simplified_tokens.index(t)] }.first -      partial_matches = simplified_tokens.grep(%r{#{simplified_search_term}}i) { |t| all_tokens[simplified_tokens.index(t)] } -      partial_matches.delete(exact_match) -    end -    [exact_match, partial_matches, search_term] -  end +      def self.search(*arguments) +        exact_match = nil +        partial_matches = [] +        search_term = arguments.join(" ") +        search_regexp = extract_regexp arguments.first +        all_tokens = CLI.nice_listing(Hbc.all_tokens) +        if search_regexp +          search_term = arguments.first +          partial_matches = all_tokens.grep(%r{#{search_regexp}}i) +        else +          simplified_tokens = all_tokens.map { |t| t.sub(%r{^.*\/}, "").gsub(%r{[^a-z0-9]+}i, "") } +          simplified_search_term = search_term.sub(%r{\.rb$}i, "").gsub(%r{[^a-z0-9]+}i, "") +          exact_match = simplified_tokens.grep(%r{^#{simplified_search_term}$}i) { |t| all_tokens[simplified_tokens.index(t)] }.first +          partial_matches = simplified_tokens.grep(%r{#{simplified_search_term}}i) { |t| all_tokens[simplified_tokens.index(t)] } +          partial_matches.delete(exact_match) +        end +        [exact_match, partial_matches, search_term] +      end -  def self.render_results(exact_match, partial_matches, search_term) -    if !exact_match && partial_matches.empty? -      puts "No Cask found for \"#{search_term}\"." -      return -    end -    if exact_match -      ohai "Exact match" -      puts exact_match -    end -    unless partial_matches.empty? -      if extract_regexp search_term -        ohai "Regexp matches" -      else -        ohai "Partial matches" +      def self.render_results(exact_match, partial_matches, search_term) +        if !exact_match && partial_matches.empty? +          puts "No Cask found for \"#{search_term}\"." +          return +        end +        if exact_match +          ohai "Exact match" +          puts exact_match +        end +        unless partial_matches.empty? +          if extract_regexp search_term +            ohai "Regexp matches" +          else +            ohai "Partial matches" +          end +          puts_columns partial_matches +        end        end -      puts_columns partial_matches -    end -  end -  def self.help -    "searches all known Casks" +      def self.help +        "searches all known Casks" +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/cli/style.rb b/Library/Homebrew/cask/lib/hbc/cli/style.rb index 8793d2afd..638e25685 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/style.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/style.rb @@ -1,69 +1,73 @@  require "English" -class Hbc::CLI::Style < Hbc::CLI::Base -  def self.help -    "checks Cask style using RuboCop" -  end +module Hbc +  class CLI +    class Style < Base +      def self.help +        "checks Cask style using RuboCop" +      end -  def self.run(*args) -    retval = new(args).run -    raise Hbc::CaskError, "style check failed" unless retval -  end +      def self.run(*args) +        retval = new(args).run +        raise CaskError, "style check failed" unless retval +      end -  attr_reader :args -  def initialize(args) -    @args = args -  end +      attr_reader :args +      def initialize(args) +        @args = args +      end -  def run -    install_rubocop -    system "rubocop", *rubocop_args, "--", *cask_paths -    $CHILD_STATUS.success? -  end +      def run +        install_rubocop +        system "rubocop", *rubocop_args, "--", *cask_paths +        $CHILD_STATUS.success? +      end -  RUBOCOP_CASK_VERSION = "~> 0.8.3".freeze +      RUBOCOP_CASK_VERSION = "~> 0.8.3".freeze -  def install_rubocop -    Hbc::Utils.capture_stderr do -      begin -        Homebrew.install_gem_setup_path! "rubocop-cask", RUBOCOP_CASK_VERSION, "rubocop" -      rescue SystemExit -        raise Hbc::CaskError, $stderr.string.chomp.sub("#{Tty.red}Error#{Tty.reset}: ", "") +      def install_rubocop +        Utils.capture_stderr do +          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}: ", "") +          end +        end        end -    end -  end -  def cask_paths -    @cask_paths ||= if cask_tokens.empty? -                      Hbc.all_tapped_cask_dirs -                    elsif cask_tokens.any? { |file| File.exist?(file) } -                      cask_tokens -                    else -                      cask_tokens.map { |token| Hbc.path(token) } -                    end -  end +      def cask_paths +        @cask_paths ||= if cask_tokens.empty? +                          Hbc.all_tapped_cask_dirs +                        elsif cask_tokens.any? { |file| File.exist?(file) } +                          cask_tokens +                        else +                          cask_tokens.map { |token| Hbc.path(token) } +                        end +      end -  def cask_tokens -    @cask_tokens ||= self.class.cask_tokens_from(args) -  end +      def cask_tokens +        @cask_tokens ||= self.class.cask_tokens_from(args) +      end -  def rubocop_args -    fix? ? autocorrect_args : default_args -  end +      def rubocop_args +        fix? ? autocorrect_args : default_args +      end -  def default_args -    ["--format", "simple", "--force-exclusion", "--config", rubocop_config] -  end +      def default_args +        ["--format", "simple", "--force-exclusion", "--config", rubocop_config] +      end -  def autocorrect_args -    default_args + ["--auto-correct"] -  end +      def autocorrect_args +        default_args + ["--auto-correct"] +      end -  def rubocop_config -    Hbc.default_tap.cask_dir.join(".rubocop.yml") -  end +      def rubocop_config +        Hbc.default_tap.cask_dir.join(".rubocop.yml") +      end -  def fix? -    args.any? { |arg| arg =~ %r{--(fix|(auto-?)?correct)} } +      def fix? +        args.any? { |arg| arg =~ %r{--(fix|(auto-?)?correct)} } +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/cli/uninstall.rb b/Library/Homebrew/cask/lib/hbc/cli/uninstall.rb index ae15414b7..2bebb97b0 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/uninstall.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/uninstall.rb @@ -1,40 +1,44 @@ -class Hbc::CLI::Uninstall < Hbc::CLI::Base -  def self.run(*args) -    cask_tokens = cask_tokens_from(args) -    raise Hbc::CaskUnspecifiedError if cask_tokens.empty? -    force = args.include? "--force" +module Hbc +  class CLI +    class Uninstall < Base +      def self.run(*args) +        cask_tokens = cask_tokens_from(args) +        raise CaskUnspecifiedError if cask_tokens.empty? +        force = args.include? "--force" -    cask_tokens.each do |cask_token| -      odebug "Uninstalling Cask #{cask_token}" -      cask = Hbc.load(cask_token) +        cask_tokens.each do |cask_token| +          odebug "Uninstalling Cask #{cask_token}" +          cask = Hbc.load(cask_token) -      raise Hbc::CaskNotInstalledError, cask unless cask.installed? || force +          raise CaskNotInstalledError, cask unless cask.installed? || force -      latest_installed_version = cask.timestamped_versions.last +          latest_installed_version = cask.timestamped_versions.last -      unless latest_installed_version.nil? -        latest_installed_cask_file = cask.metadata_master_container_path -                                         .join(latest_installed_version.join(File::Separator), -                                               "Casks", "#{cask_token}.rb") +          unless latest_installed_version.nil? +            latest_installed_cask_file = cask.metadata_master_container_path +                                             .join(latest_installed_version.join(File::Separator), +                                                   "Casks", "#{cask_token}.rb") -        # use the same cask file that was used for installation, if possible -        cask = Hbc.load(latest_installed_cask_file) if latest_installed_cask_file.exist? -      end +            # use the same cask file that was used for installation, if possible +            cask = Hbc.load(latest_installed_cask_file) if latest_installed_cask_file.exist? +          end -      Hbc::Installer.new(cask, force: force).uninstall +          Installer.new(cask, force: force).uninstall -      next if (versions = cask.versions).empty? +          next if (versions = cask.versions).empty? -      single = versions.count == 1 +          single = versions.count == 1 -      puts <<-EOS.undent -        #{cask_token} #{versions.join(', ')} #{single ? 'is' : 'are'} still installed. -        Remove #{single ? 'it' : 'them all'} with `brew cask uninstall --force #{cask_token}`. -      EOS -    end -  end +          puts <<-EOS.undent +            #{cask_token} #{versions.join(", ")} #{single ? "is" : "are"} still installed. +            Remove #{single ? "it" : "them all"} with `brew cask uninstall --force #{cask_token}`. +          EOS +        end +      end -  def self.help -    "uninstalls the given Cask" +      def self.help +        "uninstalls the given Cask" +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/cli/update.rb b/Library/Homebrew/cask/lib/hbc/cli/update.rb index ceb947544..1d6ed2af5 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/update.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/update.rb @@ -1,16 +1,20 @@ -class Hbc::CLI::Update < Hbc::CLI::Base -  def self.run(*_ignored) -    result = Hbc::SystemCommand.run(Hbc.homebrew_executable, -                                    args: %w[update]) -    # TODO: separating stderr/stdout is undesirable here. -    #       Hbc::SystemCommand should have an option for plain -    #       unbuffered output. -    print result.stdout -    $stderr.print result.stderr -    exit result.exit_status -  end +module Hbc +  class CLI +    class Update < Base +      def self.run(*_ignored) +        result = SystemCommand.run(Hbc.homebrew_executable, +                                   args: %w[update]) +        # TODO: separating stderr/stdout is undesirable here. +        #       Hbc::SystemCommand should have an option for plain +        #       unbuffered output. +        print result.stdout +        $stderr.print result.stderr +        exit result.exit_status +      end -  def self.help -    "a synonym for 'brew update'" +      def self.help +        "a synonym for 'brew update'" +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/cli/zap.rb b/Library/Homebrew/cask/lib/hbc/cli/zap.rb index 081378330..2f9723858 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/zap.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/zap.rb @@ -1,15 +1,19 @@ -class Hbc::CLI::Zap < Hbc::CLI::Base -  def self.run(*args) -    cask_tokens = cask_tokens_from(args) -    raise Hbc::CaskUnspecifiedError if cask_tokens.empty? -    cask_tokens.each do |cask_token| -      odebug "Zapping Cask #{cask_token}" -      cask = Hbc.load(cask_token) -      Hbc::Installer.new(cask).zap -    end -  end +module Hbc +  class CLI +    class Zap < Base +      def self.run(*args) +        cask_tokens = cask_tokens_from(args) +        raise CaskUnspecifiedError if cask_tokens.empty? +        cask_tokens.each do |cask_token| +          odebug "Zapping Cask #{cask_token}" +          cask = Hbc.load(cask_token) +          Installer.new(cask).zap +        end +      end -  def self.help -    "zaps all files associated with the given Cask" +      def self.help +        "zaps all files associated with the given Cask" +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/container.rb b/Library/Homebrew/cask/lib/hbc/container.rb index e2b21a3ef..01dd10337 100644 --- a/Library/Homebrew/cask/lib/hbc/container.rb +++ b/Library/Homebrew/cask/lib/hbc/container.rb @@ -1,5 +1,3 @@ -class Hbc::Container; end -  require "hbc/container/base"  require "hbc/container/air"  require "hbc/container/bzip2" @@ -22,47 +20,49 @@ require "hbc/container/xip"  require "hbc/container/xz"  require "hbc/container/zip" -class Hbc::Container -  def self.autodetect_containers -    [ -      Hbc::Container::Pkg, -      Hbc::Container::Ttf, -      Hbc::Container::Otf, -      Hbc::Container::Air, -      Hbc::Container::Cab, -      Hbc::Container::Dmg, -      Hbc::Container::SevenZip, -      Hbc::Container::Sit, -      Hbc::Container::Rar, -      Hbc::Container::Zip, -      Hbc::Container::Xip,   # needs to be before xar as this is a cpio inside a gzip inside a xar -      Hbc::Container::Xar,   # need to be before tar as tar can also list xar -      Hbc::Container::Tar,   # or compressed tar (bzip2/gzip/lzma/xz) -      Hbc::Container::Bzip2, # pure bzip2 -      Hbc::Container::Gzip,  # pure gzip -      Hbc::Container::Lzma,  # pure lzma -      Hbc::Container::Xz,    # pure xz -    ] -    # for explicit use only (never autodetected): -    # Hbc::Container::Naked -    # Hbc::Container::GenericUnar -  end +module Hbc +  class Container +    def self.autodetect_containers +      [ +        Pkg, +        Ttf, +        Otf, +        Air, +        Cab, +        Dmg, +        SevenZip, +        Sit, +        Rar, +        Zip, +        Xip,   # needs to be before xar as this is a cpio inside a gzip inside a xar +        Xar,   # need to be before tar as tar can also list xar +        Tar,   # or compressed tar (bzip2/gzip/lzma/xz) +        Bzip2, # pure bzip2 +        Gzip,  # pure gzip +        Lzma,  # pure lzma +        Xz,    # pure xz +      ] +      # for explicit use only (never autodetected): +      # Hbc::Container::Naked +      # Hbc::Container::GenericUnar +    end -  def self.for_path(path, command) -    odebug "Determining which containers to use based on filetype" -    criteria = Hbc::Container::Criteria.new(path, command) -    autodetect_containers.find do |c| -      odebug "Checking container class #{c}" -      c.me?(criteria) +    def self.for_path(path, command) +      odebug "Determining which containers to use based on filetype" +      criteria = Criteria.new(path, command) +      autodetect_containers.find do |c| +        odebug "Checking container class #{c}" +        c.me?(criteria) +      end      end -  end -  def self.from_type(type) -    odebug "Determining which containers to use based on 'container :type'" -    begin -      Hbc::Container.const_get(type.to_s.split("_").map(&:capitalize).join) -    rescue NameError -      false +    def self.from_type(type) +      odebug "Determining which containers to use based on 'container :type'" +      begin +        self.const_get(type.to_s.split("_").map(&:capitalize).join) +      rescue NameError +        false +      end      end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/container/air.rb b/Library/Homebrew/cask/lib/hbc/container/air.rb index fc618db83..4b083e538 100644 --- a/Library/Homebrew/cask/lib/hbc/container/air.rb +++ b/Library/Homebrew/cask/lib/hbc/container/air.rb @@ -1,33 +1,37 @@  require "hbc/container/base" -class Hbc::Container::Air < Hbc::Container::Base -  INSTALLER_PATHNAME = -    Pathname("/Applications/Utilities/Adobe AIR Application Installer.app" \ -             "/Contents/MacOS/Adobe AIR Application Installer") - -  def self.me?(criteria) -    %w[.air].include?(criteria.path.extname) -  end - -  def self.installer_cmd -    return @installer_cmd ||= INSTALLER_PATHNAME if installer_exist? -    raise Hbc::CaskError, <<-EOS.undent -      Adobe AIR runtime not present, try installing it via - -          brew cask install adobe-air - -    EOS -  end - -  def self.installer_exist? -    INSTALLER_PATHNAME.exist? -  end - -  def extract -    install = @command.run(self.class.installer_cmd, -                           args: ["-silent", "-location", @cask.staged_path, Pathname.new(@path).realpath]) - -    return unless install.exit_status == 9 -    raise Hbc::CaskError, "Adobe AIR application #{@cask} already exists on the system, and cannot be reinstalled." +module Hbc +  class Container +    class Air < Base +      INSTALLER_PATHNAME = +        Pathname("/Applications/Utilities/Adobe AIR Application Installer.app" \ +                 "/Contents/MacOS/Adobe AIR Application Installer") + +      def self.me?(criteria) +        %w[.air].include?(criteria.path.extname) +      end + +      def self.installer_cmd +        return @installer_cmd ||= INSTALLER_PATHNAME if installer_exist? +        raise CaskError, <<-EOS.undent +          Adobe AIR runtime not present, try installing it via + +              brew cask install adobe-air + +        EOS +      end + +      def self.installer_exist? +        INSTALLER_PATHNAME.exist? +      end + +      def extract +        install = @command.run(self.class.installer_cmd, +                               args: ["-silent", "-location", @cask.staged_path, Pathname.new(@path).realpath]) + +        return unless install.exit_status == 9 +        raise CaskError, "Adobe AIR application #{@cask} already exists on the system, and cannot be reinstalled." +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/container/base.rb b/Library/Homebrew/cask/lib/hbc/container/base.rb index 42331df31..1f1c9ad9b 100644 --- a/Library/Homebrew/cask/lib/hbc/container/base.rb +++ b/Library/Homebrew/cask/lib/hbc/container/base.rb @@ -1,37 +1,41 @@ -class Hbc::Container::Base -  def initialize(cask, path, command, nested: false) -    @cask = cask -    @path = path -    @command = command -    @nested = nested -  end +module Hbc +  class Container +    class Base +      def initialize(cask, path, command, nested: false) +        @cask = cask +        @path = path +        @command = command +        @nested = nested +      end -  def extract_nested_inside(dir) -    children = Pathname.new(dir).children +      def extract_nested_inside(dir) +        children = Pathname.new(dir).children -    nested_container = children[0] +        nested_container = children[0] -    unless children.count == 1 && -           !nested_container.directory? && -           @cask.artifacts[:nested_container].empty? && -           extract_nested_container(nested_container) +        unless children.count == 1 && +               !nested_container.directory? && +               @cask.artifacts[:nested_container].empty? && +               extract_nested_container(nested_container) -      children.each do |src| -        dest = @cask.staged_path.join(src.basename) -        FileUtils.rm_r(dest) if dest.exist? -        FileUtils.mv(src, dest) +          children.each do |src| +            dest = @cask.staged_path.join(src.basename) +            FileUtils.rm_r(dest) if dest.exist? +            FileUtils.mv(src, dest) +          end +        end        end -    end -  end -  def extract_nested_container(source) -    container = Hbc::Container.for_path(source, @command) +      def extract_nested_container(source) +        container = Container.for_path(source, @command) -    return false unless container +        return false unless container -    ohai "Extracting nested container #{source.basename}" -    container.new(@cask, source, @command, nested: true).extract +        ohai "Extracting nested container #{source.basename}" +        container.new(@cask, source, @command, nested: true).extract -    true +        true +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/container/bzip2.rb b/Library/Homebrew/cask/lib/hbc/container/bzip2.rb index 617c68b32..81808071f 100644 --- a/Library/Homebrew/cask/lib/hbc/container/bzip2.rb +++ b/Library/Homebrew/cask/lib/hbc/container/bzip2.rb @@ -2,17 +2,21 @@ require "tmpdir"  require "hbc/container/base" -class Hbc::Container::Bzip2 < Hbc::Container::Base -  def self.me?(criteria) -    criteria.magic_number(%r{^BZh}n) -  end +module Hbc +  class Container +    class Bzip2 < Base +      def self.me?(criteria) +        criteria.magic_number(%r{^BZh}n) +      end -  def extract -    Dir.mktmpdir do |unpack_dir| -      @command.run!("/usr/bin/ditto",   args: ["--", @path, unpack_dir]) -      @command.run!("/usr/bin/bunzip2", args: ["--quiet", "--", Pathname.new(unpack_dir).join(@path.basename)]) +      def extract +        Dir.mktmpdir do |unpack_dir| +          @command.run!("/usr/bin/ditto",   args: ["--", @path, unpack_dir]) +          @command.run!("/usr/bin/bunzip2", args: ["--quiet", "--", Pathname.new(unpack_dir).join(@path.basename)]) -      extract_nested_inside(unpack_dir) +          extract_nested_inside(unpack_dir) +        end +      end      end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/container/cab.rb b/Library/Homebrew/cask/lib/hbc/container/cab.rb index 28000a5a3..d32b1b205 100644 --- a/Library/Homebrew/cask/lib/hbc/container/cab.rb +++ b/Library/Homebrew/cask/lib/hbc/container/cab.rb @@ -2,25 +2,29 @@ require "tmpdir"  require "hbc/container/base" -class Hbc::Container::Cab < Hbc::Container::Base -  def self.me?(criteria) -    cabextract = Hbc.homebrew_prefix.join("bin", "cabextract") +module Hbc +  class Container +    class Cab < Base +      def self.me?(criteria) +        cabextract = Hbc.homebrew_prefix.join("bin", "cabextract") -    criteria.magic_number(%r{^MSCF}n) && -      cabextract.exist? && -      criteria.command.run(cabextract, args: ["-t", "--", criteria.path.to_s]).stderr.empty? -  end +        criteria.magic_number(%r{^MSCF}n) && +          cabextract.exist? && +          criteria.command.run(cabextract, args: ["-t", "--", criteria.path.to_s]).stderr.empty? +      end -  def extract -    cabextract = Hbc.homebrew_prefix.join("bin", "cabextract") +      def extract +        cabextract = Hbc.homebrew_prefix.join("bin", "cabextract") -    unless cabextract.exist? -      raise Hbc::CaskError, "Expected to find cabextract executable. Cask '#{@cask}' must add: depends_on formula: 'cabextract'" -    end +        unless cabextract.exist? +          raise CaskError, "Expected to find cabextract executable. Cask '#{@cask}' must add: depends_on formula: 'cabextract'" +        end -    Dir.mktmpdir do |unpack_dir| -      @command.run!(cabextract, args: ["-d", unpack_dir, "--", @path]) -      @command.run!("/usr/bin/ditto", args: ["--", unpack_dir, @cask.staged_path]) +        Dir.mktmpdir do |unpack_dir| +          @command.run!(cabextract, args: ["-d", unpack_dir, "--", @path]) +          @command.run!("/usr/bin/ditto", args: ["--", unpack_dir, @cask.staged_path]) +        end +      end      end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/container/criteria.rb b/Library/Homebrew/cask/lib/hbc/container/criteria.rb index 2ebb9d6fa..207c5f3cd 100644 --- a/Library/Homebrew/cask/lib/hbc/container/criteria.rb +++ b/Library/Homebrew/cask/lib/hbc/container/criteria.rb @@ -1,18 +1,22 @@ -class Hbc::Container::Criteria -  attr_reader :path, :command +module Hbc +  class Container +    class Criteria +      attr_reader :path, :command -  def initialize(path, command) -    @path = path -    @command = command -  end +      def initialize(path, command) +        @path = path +        @command = command +      end -  def extension(regex) -    path.extname.sub(%r{^\.}, "") =~ Regexp.new(regex.source, regex.options | Regexp::IGNORECASE) -  end +      def extension(regex) +        path.extname.sub(%r{^\.}, "") =~ Regexp.new(regex.source, regex.options | Regexp::IGNORECASE) +      end -  def magic_number(regex) -    # 262: length of the longest regex (currently: Hbc::Container::Tar) -    @magic_number ||= File.open(@path, "rb") { |f| f.read(262) } -    @magic_number =~ regex +      def magic_number(regex) +        # 262: length of the longest regex (currently: Hbc::Container::Tar) +        @magic_number ||= File.open(@path, "rb") { |f| f.read(262) } +        @magic_number =~ regex +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/container/dmg.rb b/Library/Homebrew/cask/lib/hbc/container/dmg.rb index 7e4b9340d..d53c077cb 100644 --- a/Library/Homebrew/cask/lib/hbc/container/dmg.rb +++ b/Library/Homebrew/cask/lib/hbc/container/dmg.rb @@ -3,123 +3,127 @@ require "tempfile"  require "hbc/container/base" -class Hbc::Container::Dmg < Hbc::Container::Base -  def self.me?(criteria) -    !criteria.command.run("/usr/bin/hdiutil", -                          # realpath is a failsafe against unusual filenames -                          args:         ["imageinfo", Pathname.new(criteria.path).realpath], -                          print_stderr: false).stdout.empty? -  end +module Hbc +  class Container +    class Dmg < Base +      def self.me?(criteria) +        !criteria.command.run("/usr/bin/hdiutil", +                              # realpath is a failsafe against unusual filenames +                              args:         ["imageinfo", Pathname.new(criteria.path).realpath], +                              print_stderr: false).stdout.empty? +      end -  attr_reader :mounts -  def initialize(*args) -    super(*args) -    @mounts = [] -  end +      attr_reader :mounts +      def initialize(*args) +        super(*args) +        @mounts = [] +      end -  def extract -    mount! -    assert_mounts_found -    extract_mounts -  ensure -    eject! -  end +      def extract +        mount! +        assert_mounts_found +        extract_mounts +      ensure +        eject! +      end -  def mount! -    plist = @command.run!("/usr/bin/hdiutil", -                          # realpath is a failsafe against unusual filenames -                          args:  %w[mount -plist -nobrowse -readonly -noidme -mountrandom /tmp] + [Pathname.new(@path).realpath], -                          input: %w[y]) -                    .plist -    @mounts = mounts_from_plist(plist) -  end +      def mount! +        plist = @command.run!("/usr/bin/hdiutil", +                              # realpath is a failsafe against unusual filenames +                              args:  %w[mount -plist -nobrowse -readonly -noidme -mountrandom /tmp] + [Pathname.new(@path).realpath], +                              input: %w[y]) +                        .plist +        @mounts = mounts_from_plist(plist) +      end -  def eject! -    @mounts.each do |mount| -      # realpath is a failsafe against unusual filenames -      mountpath = Pathname.new(mount).realpath -      next unless mountpath.exist? - -      begin -        tries ||= 2 -        @command.run("/usr/sbin/diskutil", -                     args:         ["eject", mountpath], -                     print_stderr: false) - -        raise Hbc::CaskError, "Failed to eject #{mountpath}" if mountpath.exist? -      rescue Hbc::CaskError => e -        raise e if (tries -= 1).zero? -        sleep 1 -        retry +      def eject! +        @mounts.each do |mount| +          # realpath is a failsafe against unusual filenames +          mountpath = Pathname.new(mount).realpath +          next unless mountpath.exist? + +          begin +            tries ||= 2 +            @command.run("/usr/sbin/diskutil", +                         args:         ["eject", mountpath], +                         print_stderr: false) + +            raise CaskError, "Failed to eject #{mountpath}" if mountpath.exist? +          rescue CaskError => e +            raise e if (tries -= 1).zero? +            sleep 1 +            retry +          end +        end        end -    end -  end -  private +      private -  def extract_mounts -    @mounts.each(&method(:extract_mount)) -  end +      def extract_mounts +        @mounts.each(&method(:extract_mount)) +      end -  def extract_mount(mount) -    Tempfile.open(["", ".bom"]) do |bomfile| -      bomfile.close +      def extract_mount(mount) +        Tempfile.open(["", ".bom"]) do |bomfile| +          bomfile.close -      Tempfile.open(["", ".list"]) do |filelist| -        filelist.write(bom_filelist_from_path(mount)) -        filelist.close +          Tempfile.open(["", ".list"]) do |filelist| +            filelist.write(bom_filelist_from_path(mount)) +            filelist.close -        @command.run!("/usr/bin/mkbom", args: ["-s", "-i", filelist.path, "--", bomfile.path]) -        @command.run!("/usr/bin/ditto", args: ["--bom", bomfile.path, "--", mount, @cask.staged_path]) +            @command.run!("/usr/bin/mkbom", args: ["-s", "-i", filelist.path, "--", bomfile.path]) +            @command.run!("/usr/bin/ditto", args: ["--bom", bomfile.path, "--", mount, @cask.staged_path]) +          end +        end        end -    end -  end -  def bom_filelist_from_path(mount) -    Dir.chdir(mount) { -      Dir.glob("**/*", File::FNM_DOTMATCH).map { |path| -        next if skip_path?(Pathname(path)) -        path == "." ? path : path.prepend("./") -      }.compact.join("\n").concat("\n") -    } -  end +      def bom_filelist_from_path(mount) +        Dir.chdir(mount) { +          Dir.glob("**/*", File::FNM_DOTMATCH).map { |path| +            next if skip_path?(Pathname(path)) +            path == "." ? path : path.prepend("./") +          }.compact.join("\n").concat("\n") +        } +      end -  def skip_path?(path) -    dmg_metadata?(path) || system_dir_symlink?(path) -  end +      def skip_path?(path) +        dmg_metadata?(path) || system_dir_symlink?(path) +      end -  # unnecessary DMG metadata -  DMG_METADATA_FILES = %w[ -                         .background -                         .com.apple.timemachine.donotpresent -                         .DocumentRevisions-V100 -                         .DS_Store -                         .fseventsd -                         .MobileBackups -                         .Spotlight-V100 -                         .TemporaryItems -                         .Trashes -                         .VolumeIcon.icns -                       ].to_set.freeze - -  def dmg_metadata?(path) -    relative_root = path.sub(%r{/.*}, "") -    DMG_METADATA_FILES.include?(relative_root.basename.to_s) -  end +      # unnecessary DMG metadata +      DMG_METADATA_FILES = %w[ +                             .background +                             .com.apple.timemachine.donotpresent +                             .DocumentRevisions-V100 +                             .DS_Store +                             .fseventsd +                             .MobileBackups +                             .Spotlight-V100 +                             .TemporaryItems +                             .Trashes +                             .VolumeIcon.icns +                           ].to_set.freeze + +      def dmg_metadata?(path) +        relative_root = path.sub(%r{/.*}, "") +        DMG_METADATA_FILES.include?(relative_root.basename.to_s) +      end -  def system_dir_symlink?(path) -    # symlinks to system directories (commonly to /Applications) -    path.symlink? && MacOS.system_dir?(path.readlink) -  end +      def system_dir_symlink?(path) +        # symlinks to system directories (commonly to /Applications) +        path.symlink? && MacOS.system_dir?(path.readlink) +      end -  def mounts_from_plist(plist) -    return [] unless plist.respond_to?(:fetch) -    plist.fetch("system-entities", []).map { |entity| -      entity["mount-point"] -    }.compact -  end +      def mounts_from_plist(plist) +        return [] unless plist.respond_to?(:fetch) +        plist.fetch("system-entities", []).map { |entity| +          entity["mount-point"] +        }.compact +      end -  def assert_mounts_found -    raise Hbc::CaskError, "No mounts found in '#{@path}'; perhaps it is a bad DMG?" if @mounts.empty? +      def assert_mounts_found +        raise CaskError, "No mounts found in '#{@path}'; perhaps it is a bad DMG?" if @mounts.empty? +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/container/generic_unar.rb b/Library/Homebrew/cask/lib/hbc/container/generic_unar.rb index 1dcc0997a..32bbc8d15 100644 --- a/Library/Homebrew/cask/lib/hbc/container/generic_unar.rb +++ b/Library/Homebrew/cask/lib/hbc/container/generic_unar.rb @@ -2,25 +2,29 @@ require "tmpdir"  require "hbc/container/base" -class Hbc::Container::GenericUnar < Hbc::Container::Base -  def self.me?(criteria) -    lsar = Hbc.homebrew_prefix.join("bin", "lsar") -    lsar.exist? && -      criteria.command.run(lsar, -                           args:         ["-l", "-t", "--", criteria.path], -                           print_stderr: false).stdout.chomp.end_with?("passed, 0 failed.") -  end +module Hbc +  class Container +    class GenericUnar < Base +      def self.me?(criteria) +        lsar = Hbc.homebrew_prefix.join("bin", "lsar") +        lsar.exist? && +          criteria.command.run(lsar, +                               args:         ["-l", "-t", "--", criteria.path], +                               print_stderr: false).stdout.chomp.end_with?("passed, 0 failed.") +      end -  def extract -    unar = Hbc.homebrew_prefix.join("bin", "unar") +      def extract +        unar = Hbc.homebrew_prefix.join("bin", "unar") -    unless unar.exist? -      raise Hbc::CaskError, "Expected to find unar executable. Cask #{@cask} must add: depends_on formula: 'unar'" -    end +        unless unar.exist? +          raise CaskError, "Expected to find unar executable. Cask #{@cask} must add: depends_on formula: 'unar'" +        end -    Dir.mktmpdir do |unpack_dir| -      @command.run!(unar, args: ["-force-overwrite", "-quiet", "-no-directory", "-output-directory", unpack_dir, "--", @path]) -      @command.run!("/usr/bin/ditto", args: ["--", unpack_dir, @cask.staged_path]) +        Dir.mktmpdir do |unpack_dir| +          @command.run!(unar, args: ["-force-overwrite", "-quiet", "-no-directory", "-output-directory", unpack_dir, "--", @path]) +          @command.run!("/usr/bin/ditto", args: ["--", unpack_dir, @cask.staged_path]) +        end +      end      end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/container/gzip.rb b/Library/Homebrew/cask/lib/hbc/container/gzip.rb index 161578162..7e4722a7f 100644 --- a/Library/Homebrew/cask/lib/hbc/container/gzip.rb +++ b/Library/Homebrew/cask/lib/hbc/container/gzip.rb @@ -2,17 +2,21 @@ require "tmpdir"  require "hbc/container/base" -class Hbc::Container::Gzip < Hbc::Container::Base -  def self.me?(criteria) -    criteria.magic_number(%r{^\037\213}n) -  end +module Hbc +  class Container +    class Gzip < Base +      def self.me?(criteria) +        criteria.magic_number(%r{^\037\213}n) +      end -  def extract -    Dir.mktmpdir do |unpack_dir| -      @command.run!("/usr/bin/ditto",  args: ["--", @path, unpack_dir]) -      @command.run!("/usr/bin/gunzip", args: ["--quiet", "--name", "--", Pathname.new(unpack_dir).join(@path.basename)]) +      def extract +        Dir.mktmpdir do |unpack_dir| +          @command.run!("/usr/bin/ditto",  args: ["--", @path, unpack_dir]) +          @command.run!("/usr/bin/gunzip", args: ["--quiet", "--name", "--", Pathname.new(unpack_dir).join(@path.basename)]) -      extract_nested_inside(unpack_dir) +          extract_nested_inside(unpack_dir) +        end +      end      end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/container/lzma.rb b/Library/Homebrew/cask/lib/hbc/container/lzma.rb index e538b3779..a91132b55 100644 --- a/Library/Homebrew/cask/lib/hbc/container/lzma.rb +++ b/Library/Homebrew/cask/lib/hbc/container/lzma.rb @@ -2,22 +2,26 @@ require "tmpdir"  require "hbc/container/base" -class Hbc::Container::Lzma < Hbc::Container::Base -  def self.me?(criteria) -    criteria.magic_number(%r{^\]\000\000\200\000}n) -  end +module Hbc +  class Container +    class Lzma < Base +      def self.me?(criteria) +        criteria.magic_number(%r{^\]\000\000\200\000}n) +      end -  def extract -    unlzma = Hbc.homebrew_prefix.join("bin", "unlzma") +      def extract +        unlzma = Hbc.homebrew_prefix.join("bin", "unlzma") -    unless unlzma.exist? -      raise Hbc::CaskError, "Expected to find unlzma executable. Cask '#{@cask}' must add: depends_on formula: 'lzma'" -    end +        unless unlzma.exist? +          raise CaskError, "Expected to find unlzma executable. Cask '#{@cask}' must add: depends_on formula: 'lzma'" +        end -    Dir.mktmpdir do |unpack_dir| -      @command.run!("/usr/bin/ditto", args: ["--", @path, unpack_dir]) -      @command.run!(unlzma, args: ["-q", "--", Pathname(unpack_dir).join(@path.basename)]) -      @command.run!("/usr/bin/ditto", args: ["--", unpack_dir, @cask.staged_path]) +        Dir.mktmpdir do |unpack_dir| +          @command.run!("/usr/bin/ditto", args: ["--", @path, unpack_dir]) +          @command.run!(unlzma, args: ["-q", "--", Pathname(unpack_dir).join(@path.basename)]) +          @command.run!("/usr/bin/ditto", args: ["--", unpack_dir, @cask.staged_path]) +        end +      end      end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/container/naked.rb b/Library/Homebrew/cask/lib/hbc/container/naked.rb index 596f50789..375d62f7a 100644 --- a/Library/Homebrew/cask/lib/hbc/container/naked.rb +++ b/Library/Homebrew/cask/lib/hbc/container/naked.rb @@ -1,19 +1,23 @@  require "hbc/container/base" -class Hbc::Container::Naked < Hbc::Container::Base -  # Either inherit from this class and override with self.me?(criteria), -  # or use this class directly as "container type: :naked", -  # in which case self.me? is not called. -  def self.me?(*) -    false -  end +module Hbc +  class Container +    class Naked < Base +      # Either inherit from this class and override with self.me?(criteria), +      # or use this class directly as "container type: :naked", +      # in which case self.me? is not called. +      def self.me?(*) +        false +      end -  def extract -    @command.run!("/usr/bin/ditto", args: ["--", @path, @cask.staged_path.join(target_file)]) -  end +      def extract +        @command.run!("/usr/bin/ditto", args: ["--", @path, @cask.staged_path.join(target_file)]) +      end -  def target_file -    return @path.basename if @nested -    URI.decode(File.basename(@cask.url.path)) +      def target_file +        return @path.basename if @nested +        URI.decode(File.basename(@cask.url.path)) +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/container/otf.rb b/Library/Homebrew/cask/lib/hbc/container/otf.rb index f9a25e1ed..66222ad8d 100644 --- a/Library/Homebrew/cask/lib/hbc/container/otf.rb +++ b/Library/Homebrew/cask/lib/hbc/container/otf.rb @@ -1,7 +1,11 @@  require "hbc/container/naked" -class Hbc::Container::Otf < Hbc::Container::Naked -  def self.me?(criteria) -    criteria.magic_number(%r{^OTTO}n) +module Hbc +  class Container +    class Otf < Naked +      def self.me?(criteria) +        criteria.magic_number(%r{^OTTO}n) +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/container/pkg.rb b/Library/Homebrew/cask/lib/hbc/container/pkg.rb index 5d2282d0f..dfd62a863 100644 --- a/Library/Homebrew/cask/lib/hbc/container/pkg.rb +++ b/Library/Homebrew/cask/lib/hbc/container/pkg.rb @@ -1,9 +1,13 @@  require "hbc/container/naked" -class Hbc::Container::Pkg < Hbc::Container::Naked -  def self.me?(criteria) -    criteria.extension(%r{m?pkg$}) && -      (criteria.path.directory? || -       criteria.magic_number(%r{^xar!}n)) +module Hbc +  class Container +    class Pkg < Naked +      def self.me?(criteria) +        criteria.extension(%r{m?pkg$}) && +          (criteria.path.directory? || +           criteria.magic_number(%r{^xar!}n)) +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/container/rar.rb b/Library/Homebrew/cask/lib/hbc/container/rar.rb index 9c144006f..bcf225623 100644 --- a/Library/Homebrew/cask/lib/hbc/container/rar.rb +++ b/Library/Homebrew/cask/lib/hbc/container/rar.rb @@ -1,8 +1,12 @@  require "hbc/container/generic_unar" -class Hbc::Container::Rar < Hbc::Container::GenericUnar -  def self.me?(criteria) -    criteria.magic_number(%r{^Rar!}n) && -      super +module Hbc +  class Container +    class Rar < GenericUnar +      def self.me?(criteria) +        criteria.magic_number(%r{^Rar!}n) && +          super +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/container/seven_zip.rb b/Library/Homebrew/cask/lib/hbc/container/seven_zip.rb index f0d183064..7a144d532 100644 --- a/Library/Homebrew/cask/lib/hbc/container/seven_zip.rb +++ b/Library/Homebrew/cask/lib/hbc/container/seven_zip.rb @@ -1,9 +1,13 @@  require "hbc/container/generic_unar" -class Hbc::Container::SevenZip < Hbc::Container::GenericUnar -  def self.me?(criteria) -    # TODO: cover self-extracting archives -    criteria.magic_number(%r{^7z}n) && -      super +module Hbc +  class Container +    class SevenZip < GenericUnar +      def self.me?(criteria) +        # TODO: cover self-extracting archives +        criteria.magic_number(%r{^7z}n) && +          super +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/container/sit.rb b/Library/Homebrew/cask/lib/hbc/container/sit.rb index 155b93f3f..2d8849399 100644 --- a/Library/Homebrew/cask/lib/hbc/container/sit.rb +++ b/Library/Homebrew/cask/lib/hbc/container/sit.rb @@ -1,8 +1,12 @@  require "hbc/container/generic_unar" -class Hbc::Container::Sit < Hbc::Container::GenericUnar -  def self.me?(criteria) -    criteria.magic_number(%r{^StuffIt}n) && -      super +module Hbc +  class Container +    class Sit < GenericUnar +      def self.me?(criteria) +        criteria.magic_number(%r{^StuffIt}n) && +          super +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/container/tar.rb b/Library/Homebrew/cask/lib/hbc/container/tar.rb index 8bc7c5f64..df77e454d 100644 --- a/Library/Homebrew/cask/lib/hbc/container/tar.rb +++ b/Library/Homebrew/cask/lib/hbc/container/tar.rb @@ -2,17 +2,21 @@ require "tmpdir"  require "hbc/container/base" -class Hbc::Container::Tar < Hbc::Container::Base -  def self.me?(criteria) -    criteria.magic_number(%r{^.{257}ustar}n) || -      # or compressed tar (bzip2/gzip/lzma/xz) -      IO.popen(["/usr/bin/tar", "-t", "-f", criteria.path.to_s], err: "/dev/null") { |io| !io.read(1).nil? } -  end +module Hbc +  class Container +    class Tar < Base +      def self.me?(criteria) +        criteria.magic_number(%r{^.{257}ustar}n) || +          # or compressed tar (bzip2/gzip/lzma/xz) +          IO.popen(["/usr/bin/tar", "-t", "-f", criteria.path.to_s], err: "/dev/null") { |io| !io.read(1).nil? } +      end -  def extract -    Dir.mktmpdir do |unpack_dir| -      @command.run!("/usr/bin/tar", args: ["-x", "-f", @path, "-C", unpack_dir]) -      @command.run!("/usr/bin/ditto", args: ["--", unpack_dir, @cask.staged_path]) +      def extract +        Dir.mktmpdir do |unpack_dir| +          @command.run!("/usr/bin/tar", args: ["-x", "-f", @path, "-C", unpack_dir]) +          @command.run!("/usr/bin/ditto", args: ["--", unpack_dir, @cask.staged_path]) +        end +      end      end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/container/ttf.rb b/Library/Homebrew/cask/lib/hbc/container/ttf.rb index 8d787f360..62ca29b22 100644 --- a/Library/Homebrew/cask/lib/hbc/container/ttf.rb +++ b/Library/Homebrew/cask/lib/hbc/container/ttf.rb @@ -1,10 +1,14 @@  require "hbc/container/naked" -class Hbc::Container::Ttf < Hbc::Container::Naked -  def self.me?(criteria) -    # TrueType Font -    criteria.magic_number(%r{^\000\001\000\000\000}n) || -      # Truetype Font Collection -      criteria.magic_number(%r{^ttcf}n) +module Hbc +  class Container +    class Ttf < Naked +      def self.me?(criteria) +        # TrueType Font +        criteria.magic_number(%r{^\000\001\000\000\000}n) || +          # Truetype Font Collection +          criteria.magic_number(%r{^ttcf}n) +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/container/xar.rb b/Library/Homebrew/cask/lib/hbc/container/xar.rb index 5afc78bc5..228ab2343 100644 --- a/Library/Homebrew/cask/lib/hbc/container/xar.rb +++ b/Library/Homebrew/cask/lib/hbc/container/xar.rb @@ -2,15 +2,19 @@ require "tmpdir"  require "hbc/container/base" -class Hbc::Container::Xar < Hbc::Container::Base -  def self.me?(criteria) -    criteria.magic_number(%r{^xar!}n) -  end +module Hbc +  class Container +    class Xar < Base +      def self.me?(criteria) +        criteria.magic_number(%r{^xar!}n) +      end -  def extract -    Dir.mktmpdir do |unpack_dir| -      @command.run!("/usr/bin/xar", args: ["-x", "-f", @path, "-C", unpack_dir]) -      @command.run!("/usr/bin/ditto", args: ["--", unpack_dir, @cask.staged_path]) +      def extract +        Dir.mktmpdir do |unpack_dir| +          @command.run!("/usr/bin/xar", args: ["-x", "-f", @path, "-C", unpack_dir]) +          @command.run!("/usr/bin/ditto", args: ["--", unpack_dir, @cask.staged_path]) +        end +      end      end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/container/xip.rb b/Library/Homebrew/cask/lib/hbc/container/xip.rb index 579f28fe0..2d0f17e2e 100644 --- a/Library/Homebrew/cask/lib/hbc/container/xip.rb +++ b/Library/Homebrew/cask/lib/hbc/container/xip.rb @@ -1,24 +1,28 @@  require "tmpdir" -class Hbc::Container::Xip < Hbc::Container::Base -  def self.me?(criteria) -    criteria.magic_number(%r{^xar!}n) && -      IO.popen(["/usr/bin/xar", "-t", "-f", criteria.path.to_s], err: "/dev/null") { |io| io.read =~ %r{\AContent\nMetadata\n\Z} } -  end - -  def extract -    Dir.mktmpdir do |unpack_dir| -      begin -        ohai "Verifying signature for #{@path.basename}" -        @command.run!("/usr/sbin/pkgutil", args: ["--check-signature", @path]) -      rescue -        raise "Signature check failed." +module Hbc +  class Container +    class Xip < Base +      def self.me?(criteria) +        criteria.magic_number(%r{^xar!}n) && +          IO.popen(["/usr/bin/xar", "-t", "-f", criteria.path.to_s], err: "/dev/null") { |io| io.read =~ %r{\AContent\nMetadata\n\Z} }        end -      @command.run!("/usr/bin/xar", args: ["-x", "-f", @path, "Content", "-C", unpack_dir]) +      def extract +        Dir.mktmpdir do |unpack_dir| +          begin +            ohai "Verifying signature for #{@path.basename}" +            @command.run!("/usr/sbin/pkgutil", args: ["--check-signature", @path]) +          rescue +            raise "Signature check failed." +          end + +          @command.run!("/usr/bin/xar", args: ["-x", "-f", @path, "Content", "-C", unpack_dir]) -      Dir.chdir(@cask.staged_path) do -        @command.run!("/usr/bin/cpio", args: ["--quiet", "-i", "-I", Pathname(unpack_dir).join("Content")]) +          Dir.chdir(@cask.staged_path) do +            @command.run!("/usr/bin/cpio", args: ["--quiet", "-i", "-I", Pathname(unpack_dir).join("Content")]) +          end +        end        end      end    end diff --git a/Library/Homebrew/cask/lib/hbc/container/xz.rb b/Library/Homebrew/cask/lib/hbc/container/xz.rb index 228532943..831bef5aa 100644 --- a/Library/Homebrew/cask/lib/hbc/container/xz.rb +++ b/Library/Homebrew/cask/lib/hbc/container/xz.rb @@ -2,22 +2,26 @@ require "tmpdir"  require "hbc/container/base" -class Hbc::Container::Xz < Hbc::Container::Base -  def self.me?(criteria) -    criteria.magic_number(%r{^\xFD7zXZ\x00}n) -  end +module Hbc +  class Container +    class Xz < Base +      def self.me?(criteria) +        criteria.magic_number(%r{^\xFD7zXZ\x00}n) +      end -  def extract -    unxz = Hbc.homebrew_prefix.join("bin", "unxz") +      def extract +        unxz = Hbc.homebrew_prefix.join("bin", "unxz") -    unless unxz.exist? -      raise Hbc::CaskError, "Expected to find unxz executable. Cask '#{@cask}' must add: depends_on formula: 'xz'" -    end +        unless unxz.exist? +          raise CaskError, "Expected to find unxz executable. Cask '#{@cask}' must add: depends_on formula: 'xz'" +        end -    Dir.mktmpdir do |unpack_dir| -      @command.run!("/usr/bin/ditto", args: ["--", @path, unpack_dir]) -      @command.run!(unxz, args: ["-q", "--", Pathname(unpack_dir).join(@path.basename)]) -      @command.run!("/usr/bin/ditto", args: ["--", unpack_dir, @cask.staged_path]) +        Dir.mktmpdir do |unpack_dir| +          @command.run!("/usr/bin/ditto", args: ["--", @path, unpack_dir]) +          @command.run!(unxz, args: ["-q", "--", Pathname(unpack_dir).join(@path.basename)]) +          @command.run!("/usr/bin/ditto", args: ["--", unpack_dir, @cask.staged_path]) +        end +      end      end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/container/zip.rb b/Library/Homebrew/cask/lib/hbc/container/zip.rb index c6702fbb5..86e2d1bd6 100644 --- a/Library/Homebrew/cask/lib/hbc/container/zip.rb +++ b/Library/Homebrew/cask/lib/hbc/container/zip.rb @@ -1,15 +1,19 @@  require "hbc/container/base" -class Hbc::Container::Zip < Hbc::Container::Base -  def self.me?(criteria) -    criteria.magic_number(%r{^PK(\003\004|\005\006)}n) -  end +module Hbc +  class Container +    class Zip < Base +      def self.me?(criteria) +        criteria.magic_number(%r{^PK(\003\004|\005\006)}n) +      end -  def extract -    Dir.mktmpdir do |unpack_dir| -      @command.run!("/usr/bin/ditto", args: ["-x", "-k", "--", @path, unpack_dir]) +      def extract +        Dir.mktmpdir do |unpack_dir| +          @command.run!("/usr/bin/ditto", args: ["-x", "-k", "--", @path, unpack_dir]) -      extract_nested_inside(unpack_dir) +          extract_nested_inside(unpack_dir) +        end +      end      end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/download.rb b/Library/Homebrew/cask/lib/hbc/download.rb index 18dd7fe44..4166fc74d 100644 --- a/Library/Homebrew/cask/lib/hbc/download.rb +++ b/Library/Homebrew/cask/lib/hbc/download.rb @@ -1,43 +1,45 @@  require "fileutils"  require "hbc/verify" -class Hbc::Download -  attr_reader :cask - -  def initialize(cask, force: false) -    @cask = cask -    @force = force -  end - -  def perform -    clear_cache -    fetch -    downloaded_path -  end - -  private - -  attr_reader :force -  attr_accessor :downloaded_path - -  def downloader -    @downloader ||= case cask.url.using -                    when :svn -                      Hbc::SubversionDownloadStrategy.new(cask) -                    when :post -                      Hbc::CurlPostDownloadStrategy.new(cask) -                    else -                      Hbc::CurlDownloadStrategy.new(cask) -                    end -  end - -  def clear_cache -    downloader.clear_cache if force || cask.version.latest? -  end - -  def fetch -    self.downloaded_path = downloader.fetch -  rescue StandardError => e -    raise Hbc::CaskError, "Download failed on Cask '#{cask}' with message: #{e}" +module Hbc +  class Download +    attr_reader :cask + +    def initialize(cask, force: false) +      @cask = cask +      @force = force +    end + +    def perform +      clear_cache +      fetch +      downloaded_path +    end + +    private + +    attr_reader :force +    attr_accessor :downloaded_path + +    def downloader +      @downloader ||= case cask.url.using +                      when :svn +                        SubversionDownloadStrategy.new(cask) +                      when :post +                        CurlPostDownloadStrategy.new(cask) +                      else +                        CurlDownloadStrategy.new(cask) +                      end +    end + +    def clear_cache +      downloader.clear_cache if force || cask.version.latest? +    end + +    def fetch +      self.downloaded_path = downloader.fetch +    rescue StandardError => e +      raise CaskError, "Download failed on Cask '#{cask}' with message: #{e}" +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/download_strategy.rb b/Library/Homebrew/cask/lib/hbc/download_strategy.rb index 88ffb5050..400b9ffc8 100644 --- a/Library/Homebrew/cask/lib/hbc/download_strategy.rb +++ b/Library/Homebrew/cask/lib/hbc/download_strategy.rb @@ -6,327 +6,329 @@ require "cgi"  # * Our overridden fetch methods are expected to return  #   a value: the successfully downloaded file. -class Hbc::AbstractDownloadStrategy -  attr_reader :cask, :name, :url, :uri_object, :version - -  def initialize(cask, command = Hbc::SystemCommand) -    @cask       = cask -    @command    = command -    # TODO: this excess of attributes is a function of integrating -    #       with Homebrew's classes. Later we should be able to remove -    #       these in favor of @cask -    @name       = cask.token -    @url        = cask.url.to_s -    @uri_object = cask.url -    @version    = cask.version -  end +module Hbc +  class AbstractDownloadStrategy +    attr_reader :cask, :name, :url, :uri_object, :version + +    def initialize(cask, command = SystemCommand) +      @cask       = cask +      @command    = command +      # TODO: this excess of attributes is a function of integrating +      #       with Homebrew's classes. Later we should be able to remove +      #       these in favor of @cask +      @name       = cask.token +      @url        = cask.url.to_s +      @uri_object = cask.url +      @version    = cask.version +    end -  # All download strategies are expected to implement these methods -  def fetch; end +    # All download strategies are expected to implement these methods +    def fetch; end -  def cached_location; end +    def cached_location; end -  def clear_cache; end -end +    def clear_cache; end +  end -class Hbc::HbVCSDownloadStrategy < Hbc::AbstractDownloadStrategy -  REF_TYPES = [:branch, :revision, :revisions, :tag].freeze +  class HbVCSDownloadStrategy < AbstractDownloadStrategy +    REF_TYPES = [:branch, :revision, :revisions, :tag].freeze -  def initialize(cask, command = Hbc::SystemCommand) -    super -    @ref_type, @ref = extract_ref -    @clone = Hbc.cache.join(cache_filename) -  end +    def initialize(cask, command = SystemCommand) +      super +      @ref_type, @ref = extract_ref +      @clone = Hbc.cache.join(cache_filename) +    end -  def extract_ref -    key = REF_TYPES.find { |type| -      uri_object.respond_to?(type) && uri_object.send(type) -    } -    [key, key ? uri_object.send(key) : nil] -  end +    def extract_ref +      key = REF_TYPES.find { |type| +        uri_object.respond_to?(type) && uri_object.send(type) +      } +      [key, key ? uri_object.send(key) : nil] +    end -  def cache_filename -    "#{name}--#{cache_tag}" -  end +    def cache_filename +      "#{name}--#{cache_tag}" +    end -  def cache_tag -    "__UNKNOWN__" -  end +    def cache_tag +      "__UNKNOWN__" +    end -  def cached_location -    @clone -  end +    def cached_location +      @clone +    end -  def clear_cache -    cached_location.rmtree if cached_location.exist? +    def clear_cache +      cached_location.rmtree if cached_location.exist? +    end    end -end -class Hbc::CurlDownloadStrategy < Hbc::AbstractDownloadStrategy -  # TODO: should be part of url object -  def mirrors -    @mirrors ||= [] -  end +  class CurlDownloadStrategy < AbstractDownloadStrategy +    # TODO: should be part of url object +    def mirrors +      @mirrors ||= [] +    end -  def tarball_path -    @tarball_path ||= Hbc.cache.join("#{name}--#{version}#{ext}") -  end +    def tarball_path +      @tarball_path ||= Hbc.cache.join("#{name}--#{version}#{ext}") +    end -  def temporary_path -    @temporary_path ||= tarball_path.sub(%r{$}, ".incomplete") -  end +    def temporary_path +      @temporary_path ||= tarball_path.sub(%r{$}, ".incomplete") +    end -  def cached_location -    tarball_path -  end +    def cached_location +      tarball_path +    end -  def clear_cache -    [cached_location, temporary_path].each do |f| -      next unless f.exist? -      raise CurlDownloadStrategyError, "#{f} is in use by another process" if Hbc::Utils.file_locked?(f) -      f.unlink +    def clear_cache +      [cached_location, temporary_path].each do |f| +        next unless f.exist? +        raise CurlDownloadStrategyError, "#{f} is in use by another process" if Utils.file_locked?(f) +        f.unlink +      end      end -  end -  def downloaded_size -    temporary_path.size? || 0 -  end +    def downloaded_size +      temporary_path.size? || 0 +    end -  def _fetch -    odebug "Calling curl with args #{cask_curl_args.utf8_inspect}" -    curl(*cask_curl_args) -  end +    def _fetch +      odebug "Calling curl with args #{cask_curl_args.utf8_inspect}" +      curl(*cask_curl_args) +    end -  def fetch -    ohai "Downloading #{@url}" -    if tarball_path.exist? -      puts "Already downloaded: #{tarball_path}" -    else -      had_incomplete_download = temporary_path.exist? -      begin -        File.open(temporary_path, "w+") do |f| -          f.flock(File::LOCK_EX) -          _fetch -          f.flock(File::LOCK_UN) -        end -      rescue ErrorDuringExecution -        # 33 == range not supported -        # try wiping the incomplete download and retrying once -        if $CHILD_STATUS.exitstatus == 33 && had_incomplete_download -          ohai "Trying a full download" -          temporary_path.unlink -          had_incomplete_download = false -          retry +    def fetch +      ohai "Downloading #{@url}" +      if tarball_path.exist? +        puts "Already downloaded: #{tarball_path}" +      else +        had_incomplete_download = temporary_path.exist? +        begin +          File.open(temporary_path, "w+") do |f| +            f.flock(File::LOCK_EX) +            _fetch +            f.flock(File::LOCK_UN) +          end +        rescue ErrorDuringExecution +          # 33 == range not supported +          # try wiping the incomplete download and retrying once +          if $CHILD_STATUS.exitstatus == 33 && had_incomplete_download +            ohai "Trying a full download" +            temporary_path.unlink +            had_incomplete_download = false +            retry +          end + +          msg = @url +          msg.concat("\nThe incomplete download is cached at #{temporary_path}") if temporary_path.exist? +          raise CurlDownloadStrategyError, msg          end - -        msg = @url -        msg.concat("\nThe incomplete download is cached at #{temporary_path}") if temporary_path.exist? -        raise CurlDownloadStrategyError, msg +        ignore_interrupts { temporary_path.rename(tarball_path) }        end -      ignore_interrupts { temporary_path.rename(tarball_path) } -    end -    tarball_path -  rescue CurlDownloadStrategyError -    raise if mirrors.empty? -    puts "Trying a mirror..." -    @url = mirrors.shift -    retry -  end +      tarball_path +    rescue CurlDownloadStrategyError +      raise if mirrors.empty? +      puts "Trying a mirror..." +      @url = mirrors.shift +      retry +    end -  private +    private -  def cask_curl_args -    default_curl_args.tap do |args| -      args.concat(user_agent_args) -      args.concat(cookies_args) -      args.concat(referer_args) +    def cask_curl_args +      default_curl_args.tap do |args| +        args.concat(user_agent_args) +        args.concat(cookies_args) +        args.concat(referer_args) +      end      end -  end - -  def default_curl_args -    [url, "-C", downloaded_size, "-o", temporary_path] -  end -  def user_agent_args -    if uri_object.user_agent -      ["-A", uri_object.user_agent] -    else -      [] +    def default_curl_args +      [url, "-C", downloaded_size, "-o", temporary_path]      end -  end -  def cookies_args -    if uri_object.cookies -      [ -        "-b", -        # sort_by is for predictability between Ruby versions -        uri_object -          .cookies -          .sort_by(&:to_s) -          .map { |key, value| "#{CGI.escape(key.to_s)}=#{CGI.escape(value.to_s)}" } -          .join(";"), -      ] -    else -      [] +    def user_agent_args +      if uri_object.user_agent +        ["-A", uri_object.user_agent] +      else +        [] +      end      end -  end -  def referer_args -    if uri_object.referer -      ["-e", uri_object.referer] -    else -      [] +    def cookies_args +      if uri_object.cookies +        [ +          "-b", +          # sort_by is for predictability between Ruby versions +          uri_object +            .cookies +            .sort_by(&:to_s) +            .map { |key, value| "#{CGI.escape(key.to_s)}=#{CGI.escape(value.to_s)}" } +            .join(";"), +        ] +      else +        [] +      end      end -  end -  def ext -    Pathname.new(@url).extname -  end -end +    def referer_args +      if uri_object.referer +        ["-e", uri_object.referer] +      else +        [] +      end +    end -class Hbc::CurlPostDownloadStrategy < Hbc::CurlDownloadStrategy -  def cask_curl_args -    super -    default_curl_args.concat(post_args) +    def ext +      Pathname.new(@url).extname +    end    end -  def post_args -    if uri_object.data -      # sort_by is for predictability between Ruby versions -      uri_object -        .data -        .sort_by(&:to_s) -        .map { |key, value| ["-d", "#{CGI.escape(key.to_s)}=#{CGI.escape(value.to_s)}"] } -        .flatten -    else -      ["-X", "POST"] +  class CurlPostDownloadStrategy < CurlDownloadStrategy +    def cask_curl_args +      super +      default_curl_args.concat(post_args)      end -  end -end -class Hbc::SubversionDownloadStrategy < Hbc::HbVCSDownloadStrategy -  def cache_tag -    # TODO: pass versions as symbols, support :head here -    version == "head" ? "svn-HEAD" : "svn" +    def post_args +      if uri_object.data +        # sort_by is for predictability between Ruby versions +        uri_object +          .data +          .sort_by(&:to_s) +          .map { |key, value| ["-d", "#{CGI.escape(key.to_s)}=#{CGI.escape(value.to_s)}"] } +          .flatten +      else +        ["-X", "POST"] +      end +    end    end -  def repo_valid? -    @clone.join(".svn").directory? -  end +  class SubversionDownloadStrategy < HbVCSDownloadStrategy +    def cache_tag +      # TODO: pass versions as symbols, support :head here +      version == "head" ? "svn-HEAD" : "svn" +    end -  def repo_url -    `svn info '#{@clone}' 2>/dev/null`.strip[%r{^URL: (.+)$}, 1] -  end +    def repo_valid? +      @clone.join(".svn").directory? +    end -  # super does not provide checks for already-existing downloads -  def fetch -    if tarball_path.exist? -      puts "Already downloaded: #{tarball_path}" -    else -      @url = @url.sub(%r{^svn\+}, "") if @url =~ %r{^svn\+http://} -      ohai "Checking out #{@url}" +    def repo_url +      `svn info '#{@clone}' 2>/dev/null`.strip[%r{^URL: (.+)$}, 1] +    end -      clear_cache unless @url.chomp("/") == repo_url || quiet_system("svn", "switch", @url, @clone) +    # super does not provide checks for already-existing downloads +    def fetch +      if tarball_path.exist? +        puts "Already downloaded: #{tarball_path}" +      else +        @url = @url.sub(%r{^svn\+}, "") if @url =~ %r{^svn\+http://} +        ohai "Checking out #{@url}" -      if @clone.exist? && !repo_valid? -        puts "Removing invalid SVN repo from cache" -        clear_cache -      end +        clear_cache unless @url.chomp("/") == repo_url || quiet_system("svn", "switch", @url, @clone) -      case @ref_type -      when :revision -        fetch_repo @clone, @url, @ref -      when :revisions -        # nil is OK for main_revision, as fetch_repo will then get latest -        main_revision = @ref[:trunk] -        fetch_repo @clone, @url, main_revision, true +        if @clone.exist? && !repo_valid? +          puts "Removing invalid SVN repo from cache" +          clear_cache +        end -        fetch_externals do |external_name, external_url| -          fetch_repo @clone + external_name, external_url, @ref[external_name], true +        case @ref_type +        when :revision +          fetch_repo @clone, @url, @ref +        when :revisions +          # nil is OK for main_revision, as fetch_repo will then get latest +          main_revision = @ref[:trunk] +          fetch_repo @clone, @url, main_revision, true + +          fetch_externals do |external_name, external_url| +            fetch_repo @clone + external_name, external_url, @ref[external_name], true +          end +        else +          fetch_repo @clone, @url          end -      else -        fetch_repo @clone, @url +        compress        end -      compress +      tarball_path      end -    tarball_path -  end -  # This primary reason for redefining this method is the trust_cert -  # option, controllable from the Cask definition. We also force -  # consistent timestamps.  The rest of this method is similar to -  # Homebrew's, but translated to local idiom. -  def fetch_repo(target, url, revision = uri_object.revision, ignore_externals = false) -    # Use "svn up" when the repository already exists locally. -    # This saves on bandwidth and will have a similar effect to verifying the -    # cache as it will make any changes to get the right revision. -    svncommand = target.directory? ? "up" : "checkout" -    args = [svncommand] - -    # SVN shipped with XCode 3.1.4 can't force a checkout. -    args << "--force" unless MacOS.version == :leopard - -    # make timestamps consistent for checksumming -    args.concat(%w[--config-option config:miscellany:use-commit-times=yes]) - -    if uri_object.trust_cert -      args << "--trust-server-cert" -      args << "--non-interactive" -    end - -    args << url unless target.directory? -    args << target -    args << "-r" << revision if revision -    args << "--ignore-externals" if ignore_externals -    @command.run!("/usr/bin/svn", -                  args:         args, -                  print_stderr: false) -  end +    # This primary reason for redefining this method is the trust_cert +    # option, controllable from the Cask definition. We also force +    # consistent timestamps.  The rest of this method is similar to +    # Homebrew's, but translated to local idiom. +    def fetch_repo(target, url, revision = uri_object.revision, ignore_externals = false) +      # Use "svn up" when the repository already exists locally. +      # This saves on bandwidth and will have a similar effect to verifying the +      # cache as it will make any changes to get the right revision. +      svncommand = target.directory? ? "up" : "checkout" +      args = [svncommand] + +      # SVN shipped with XCode 3.1.4 can't force a checkout. +      args << "--force" unless MacOS.version == :leopard + +      # make timestamps consistent for checksumming +      args.concat(%w[--config-option config:miscellany:use-commit-times=yes]) + +      if uri_object.trust_cert +        args << "--trust-server-cert" +        args << "--non-interactive" +      end -  def tarball_path -    @tarball_path ||= cached_location.dirname.join(cached_location.basename.to_s + "-#{@cask.version}.tar") -  end +      args << url unless target.directory? +      args << target +      args << "-r" << revision if revision +      args << "--ignore-externals" if ignore_externals +      @command.run!("/usr/bin/svn", +                    args:         args, +                    print_stderr: false) +    end -  def shell_quote(str) -    # Oh god escaping shell args. -    # See http://notetoself.vrensk.com/2008/08/escaping-single-quotes-in-ruby-harder-than-expected/ -    str.gsub(%r{\\|'}) { |c| "\\#{c}" } -  end +    def tarball_path +      @tarball_path ||= cached_location.dirname.join(cached_location.basename.to_s + "-#{@cask.version}.tar") +    end -  def fetch_externals -    `svn propget svn:externals '#{shell_quote(@url)}'`.chomp.each_line do |line| -      name, url = line.split(%r{\s+}) -      yield name, url +    def shell_quote(str) +      # Oh god escaping shell args. +      # See http://notetoself.vrensk.com/2008/08/escaping-single-quotes-in-ruby-harder-than-expected/ +      str.gsub(%r{\\|'}) { |c| "\\#{c}" }      end -  end -  private - -  # TODO/UPDATE: the tar approach explained below is fragile -  # against challenges such as case-sensitive filesystems, -  # and must be re-implemented. -  # -  # Seems nutty: we "download" the contents into a tape archive. -  # Why? -  # * A single file is tractable to the rest of the Cask toolchain, -  # * An alternative would be to create a Directory container type. -  #   However, some type of file-serialization trick would still be -  #   needed in order to enable calculating a single checksum over -  #   a directory.  So, in that alternative implementation, the -  #   special cases would propagate outside this class, including -  #   the use of tar or equivalent. -  # * SubversionDownloadStrategy.cached_location is not versioned -  # * tarball_path provides a needed return value for our overridden -  #   fetch method. -  # * We can also take this private opportunity to strip files from -  #   the download which are protocol-specific. - -  def compress -    Dir.chdir(cached_location) do -      @command.run!("/usr/bin/tar", -                    args:         ['-s/^\.//', "--exclude", ".svn", "-cf", Pathname.new(tarball_path), "--", "."], -                    print_stderr: false) +    def fetch_externals +      `svn propget svn:externals '#{shell_quote(@url)}'`.chomp.each_line do |line| +        name, url = line.split(%r{\s+}) +        yield name, url +      end +    end + +    private + +    # TODO/UPDATE: the tar approach explained below is fragile +    # against challenges such as case-sensitive filesystems, +    # and must be re-implemented. +    # +    # Seems nutty: we "download" the contents into a tape archive. +    # Why? +    # * A single file is tractable to the rest of the Cask toolchain, +    # * An alternative would be to create a Directory container type. +    #   However, some type of file-serialization trick would still be +    #   needed in order to enable calculating a single checksum over +    #   a directory.  So, in that alternative implementation, the +    #   special cases would propagate outside this class, including +    #   the use of tar or equivalent. +    # * SubversionDownloadStrategy.cached_location is not versioned +    # * tarball_path provides a needed return value for our overridden +    #   fetch method. +    # * We can also take this private opportunity to strip files from +    #   the download which are protocol-specific. + +    def compress +      Dir.chdir(cached_location) do +        @command.run!("/usr/bin/tar", +                      args:         ['-s/^\.//', "--exclude", ".svn", "-cf", Pathname.new(tarball_path), "--", "."], +                      print_stderr: false) +      end +      clear_cache      end -    clear_cache    end  end diff --git a/Library/Homebrew/cask/lib/hbc/dsl.rb b/Library/Homebrew/cask/lib/hbc/dsl.rb index f39012542..83c0bf1fb 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl.rb @@ -1,7 +1,5 @@  require "set" -class Hbc::DSL; end -  require "hbc/dsl/appcast"  require "hbc/dsl/base"  require "hbc/dsl/caveats" @@ -18,266 +16,276 @@ require "hbc/dsl/uninstall_postflight"  require "hbc/dsl/uninstall_preflight"  require "hbc/dsl/version" -class Hbc::DSL -  ORDINARY_ARTIFACT_TYPES = [ -                              :app, -                              :artifact, -                              :audio_unit_plugin, -                              :binary, -                              :colorpicker, -                              :font, -                              :input_method, -                              :internet_plugin, -                              :pkg, -                              :prefpane, -                              :qlplugin, -                              :screen_saver, -                              :service, -                              :stage_only, -                              :suite, -                              :vst_plugin, -                              :vst3_plugin, -                            ].freeze - -  ACTIVATABLE_ARTIFACT_TYPES = ([:installer, *ORDINARY_ARTIFACT_TYPES] - [:stage_only]).freeze - -  SPECIAL_ARTIFACT_TYPES = [ -                             :uninstall, -                             :zap, +module Hbc +  class DSL +    ORDINARY_ARTIFACT_TYPES = [ +                                :app, +                                :artifact, +                                :audio_unit_plugin, +                                :binary, +                                :colorpicker, +                                :font, +                                :input_method, +                                :internet_plugin, +                                :pkg, +                                :prefpane, +                                :qlplugin, +                                :screen_saver, +                                :service, +                                :stage_only, +                                :suite, +                                :vst_plugin, +                                :vst3_plugin, +                              ].freeze + +    ACTIVATABLE_ARTIFACT_TYPES = ([:installer, *ORDINARY_ARTIFACT_TYPES] - [:stage_only]).freeze + +    SPECIAL_ARTIFACT_TYPES = [ +                               :uninstall, +                               :zap, +                             ].freeze + +    ARTIFACT_BLOCK_TYPES = [ +                             :preflight, +                             :postflight, +                             :uninstall_preflight, +                             :uninstall_postflight,                             ].freeze -  ARTIFACT_BLOCK_TYPES = [ -                           :preflight, -                           :postflight, -                           :uninstall_preflight, -                           :uninstall_postflight, -                         ].freeze - -  DSL_METHODS = Set.new [ -                          :accessibility_access, -                          :appcast, -                          :artifacts, -                          :auto_updates, -                          :caskroom_path, -                          :caveats, -                          :conflicts_with, -                          :container, -                          :depends_on, -                          :gpg, -                          :homepage, -                          :license, -                          :name, -                          :sha256, -                          :staged_path, -                          :url, -                          :version, -                          :appdir, -                          *ORDINARY_ARTIFACT_TYPES, -                          *ACTIVATABLE_ARTIFACT_TYPES, -                          *SPECIAL_ARTIFACT_TYPES, -                          *ARTIFACT_BLOCK_TYPES, -                        ].freeze - -  attr_reader :token -  def initialize(token) -    @token = token -  end - -  def name(*args) -    @name ||= [] -    return @name if args.empty? -    @name.concat(args.flatten) -  end +    DSL_METHODS = Set.new [ +                            :accessibility_access, +                            :appcast, +                            :artifacts, +                            :auto_updates, +                            :caskroom_path, +                            :caveats, +                            :conflicts_with, +                            :container, +                            :depends_on, +                            :gpg, +                            :homepage, +                            :license, +                            :name, +                            :sha256, +                            :staged_path, +                            :url, +                            :version, +                            :appdir, +                            *ORDINARY_ARTIFACT_TYPES, +                            *ACTIVATABLE_ARTIFACT_TYPES, +                            *SPECIAL_ARTIFACT_TYPES, +                            *ARTIFACT_BLOCK_TYPES, +                          ].freeze + +    attr_reader :token +    def initialize(token) +      @token = token +    end -  def assert_only_one_stanza_allowed(stanza, arg_given) -    return unless instance_variable_defined?("@#{stanza}") && arg_given -    raise Hbc::CaskInvalidError.new(token, "'#{stanza}' stanza may only appear once") -  end +    def name(*args) +      @name ||= [] +      return @name if args.empty? +      @name.concat(args.flatten) +    end -  def homepage(homepage = nil) -    assert_only_one_stanza_allowed :homepage, !homepage.nil? -    @homepage ||= homepage -  end +    def assert_only_one_stanza_allowed(stanza, arg_given) +      return unless instance_variable_defined?("@#{stanza}") && arg_given +      raise CaskInvalidError.new(token, "'#{stanza}' stanza may only appear once") +    end -  def url(*args, &block) -    url_given = !args.empty? || block_given? -    return @url unless url_given -    assert_only_one_stanza_allowed :url, url_given -    @url ||= begin -      Hbc::URL.from(*args, &block) -    rescue StandardError => e -      raise Hbc::CaskInvalidError.new(token, "'url' stanza failed with: #{e}") +    def homepage(homepage = nil) +      assert_only_one_stanza_allowed :homepage, !homepage.nil? +      @homepage ||= homepage      end -  end -  def appcast(*args) -    return @appcast if args.empty? -    assert_only_one_stanza_allowed :appcast, !args.empty? -    @appcast ||= begin -      Hbc::DSL::Appcast.new(*args) unless args.empty? -    rescue StandardError => e -      raise Hbc::CaskInvalidError.new(token, e) +    def url(*args, &block) +      url_given = !args.empty? || block_given? +      return @url unless url_given +      assert_only_one_stanza_allowed :url, url_given +      @url ||= begin +        URL.from(*args, &block) +      rescue StandardError => e +        raise CaskInvalidError.new(token, "'url' stanza failed with: #{e}") +      end      end -  end -  def gpg(*args) -    return @gpg if args.empty? -    assert_only_one_stanza_allowed :gpg, !args.empty? -    @gpg ||= begin -      Hbc::DSL::Gpg.new(*args) unless args.empty? -    rescue StandardError => e -      raise Hbc::CaskInvalidError.new(token, e) +    def appcast(*args) +      return @appcast if args.empty? +      assert_only_one_stanza_allowed :appcast, !args.empty? +      @appcast ||= begin +        DSL::Appcast.new(*args) unless args.empty? +      rescue StandardError => e +        raise CaskInvalidError.new(token, e) +      end      end -  end -  def container(*args) -    return @container if args.empty? -    # TODO: remove this constraint, and instead merge multiple container stanzas -    assert_only_one_stanza_allowed :container, !args.empty? -    @container ||= begin -      Hbc::DSL::Container.new(*args) unless args.empty? -    rescue StandardError => e -      raise Hbc::CaskInvalidError.new(token, e) +    def gpg(*args) +      return @gpg if args.empty? +      assert_only_one_stanza_allowed :gpg, !args.empty? +      @gpg ||= begin +        DSL::Gpg.new(*args) unless args.empty? +      rescue StandardError => e +        raise CaskInvalidError.new(token, e) +      end      end -    # TODO: remove this backward-compatibility section after removing nested_container -    if @container && @container.nested -      artifacts[:nested_container] << @container.nested + +    def container(*args) +      return @container if args.empty? +      # TODO: remove this constraint, and instead merge multiple container stanzas +      assert_only_one_stanza_allowed :container, !args.empty? +      @container ||= begin +        DSL::Container.new(*args) unless args.empty? +      rescue StandardError => e +        raise CaskInvalidError.new(token, e) +      end +      # TODO: remove this backward-compatibility section after removing nested_container +      if @container && @container.nested +        artifacts[:nested_container] << @container.nested +      end +      @container      end -    @container -  end -  SYMBOLIC_VERSIONS = Set.new [ -                                :latest, -                              ] +    SYMBOLIC_VERSIONS = Set.new [ +                                  :latest, +                                ] -  def version(arg = nil) -    return @version if arg.nil? -    assert_only_one_stanza_allowed :version, !arg.nil? -    raise Hbc::CaskInvalidError.new(token, "invalid 'version' value: '#{arg.inspect}'") if !arg.is_a?(String) && !SYMBOLIC_VERSIONS.include?(arg) -    @version ||= Hbc::DSL::Version.new(arg) -  end +    def version(arg = nil) +      return @version if arg.nil? +      assert_only_one_stanza_allowed :version, !arg.nil? +      raise CaskInvalidError.new(token, "invalid 'version' value: '#{arg.inspect}'") if !arg.is_a?(String) && !SYMBOLIC_VERSIONS.include?(arg) +      @version ||= DSL::Version.new(arg) +    end -  SYMBOLIC_SHA256S = Set.new [ -                               :no_check, -                             ] +    SYMBOLIC_SHA256S = Set.new [ +                                 :no_check, +                               ] -  def sha256(arg = nil) -    return @sha256 if arg.nil? -    assert_only_one_stanza_allowed :sha256, !arg.nil? -    raise Hbc::CaskInvalidError.new(token, "invalid 'sha256' value: '#{arg.inspect}'") if !arg.is_a?(String) && !SYMBOLIC_SHA256S.include?(arg) -    @sha256 ||= arg -  end +    def sha256(arg = nil) +      return @sha256 if arg.nil? +      assert_only_one_stanza_allowed :sha256, !arg.nil? +      raise CaskInvalidError.new(token, "invalid 'sha256' value: '#{arg.inspect}'") if !arg.is_a?(String) && !SYMBOLIC_SHA256S.include?(arg) +      @sha256 ||= arg +    end -  def license(arg = nil) -    return @license if arg.nil? -    assert_only_one_stanza_allowed :license, !arg.nil? -    @license ||= begin -      Hbc::DSL::License.new(arg) unless arg.nil? -    rescue StandardError => e -      raise Hbc::CaskInvalidError.new(token, e) +    def license(arg = nil) +      return @license if arg.nil? +      assert_only_one_stanza_allowed :license, !arg.nil? +      @license ||= begin +        DSL::License.new(arg) unless arg.nil? +      rescue StandardError => e +        raise CaskInvalidError.new(token, e) +      end      end -  end -  # depends_on uses a load method so that multiple stanzas can be merged -  def depends_on(*args) -    return @depends_on if args.empty? -    @depends_on ||= Hbc::DSL::DependsOn.new -    begin -      @depends_on.load(*args) unless args.empty? -    rescue RuntimeError => e -      raise Hbc::CaskInvalidError.new(token, e) +    # depends_on uses a load method so that multiple stanzas can be merged +    def depends_on(*args) +      return @depends_on if args.empty? +      @depends_on ||= DSL::DependsOn.new +      begin +        @depends_on.load(*args) unless args.empty? +      rescue RuntimeError => e +        raise CaskInvalidError.new(token, e) +      end +      @depends_on      end -    @depends_on -  end -  def conflicts_with(*args) -    return @conflicts_with if args.empty? -    # TODO: remove this constraint, and instead merge multiple conflicts_with stanzas -    assert_only_one_stanza_allowed :conflicts_with, !args.empty? -    @conflicts_with ||= begin -      Hbc::DSL::ConflictsWith.new(*args) unless args.empty? -    rescue StandardError => e -      raise Hbc::CaskInvalidError.new(token, e) +    def conflicts_with(*args) +      return @conflicts_with if args.empty? +      # TODO: remove this constraint, and instead merge multiple conflicts_with stanzas +      assert_only_one_stanza_allowed :conflicts_with, !args.empty? +      @conflicts_with ||= begin +        DSL::ConflictsWith.new(*args) unless args.empty? +      rescue StandardError => e +        raise CaskInvalidError.new(token, e) +      end      end -  end -  def artifacts -    @artifacts ||= Hash.new { |hash, key| hash[key] = Set.new } -  end +    def artifacts +      @artifacts ||= Hash.new { |hash, key| hash[key] = Set.new } +    end -  def caskroom_path -    @caskroom_path ||= Hbc.caskroom.join(token) -  end +    def caskroom_path +      @caskroom_path ||= Hbc.caskroom.join(token) +    end -  def staged_path -    return @staged_path if @staged_path -    cask_version = version || :unknown -    @staged_path = caskroom_path.join(cask_version.to_s) -  end +    def staged_path +      return @staged_path if @staged_path +      cask_version = version || :unknown +      @staged_path = caskroom_path.join(cask_version.to_s) +    end -  def caveats(*string, &block) -    @caveats ||= [] -    if block_given? -      @caveats << Hbc::Caveats.new(block) -    elsif string.any? -      @caveats << string.map { |s| s.to_s.sub(%r{[\r\n \t]*\Z}, "\n\n") } +    def caveats(*string, &block) +      @caveats ||= [] +      if block_given? +        @caveats << Hbc::Caveats.new(block) +      elsif string.any? +        @caveats << string.map { |s| s.to_s.sub(%r{[\r\n \t]*\Z}, "\n\n") } +      end +      @caveats      end -    @caveats -  end -  def accessibility_access(accessibility_access = nil) -    assert_only_one_stanza_allowed :accessibility_access, !accessibility_access.nil? -    @accessibility_access ||= accessibility_access -  end +    def accessibility_access(accessibility_access = nil) +      assert_only_one_stanza_allowed :accessibility_access, !accessibility_access.nil? +      @accessibility_access ||= accessibility_access +    end -  def auto_updates(auto_updates = nil) -    assert_only_one_stanza_allowed :auto_updates, !auto_updates.nil? -    @auto_updates ||= auto_updates -  end +    def auto_updates(auto_updates = nil) +      assert_only_one_stanza_allowed :auto_updates, !auto_updates.nil? +      @auto_updates ||= auto_updates +    end -  ORDINARY_ARTIFACT_TYPES.each do |type| -    define_method(type) do |*args| -      if type == :stage_only && args != [true] -        raise Hbc::CaskInvalidError.new(token, "'stage_only' takes a single argument: true") -      end -      artifacts[type] << args -      if artifacts.key?(:stage_only) && artifacts.keys.count > 1 && -         !(artifacts.keys & ACTIVATABLE_ARTIFACT_TYPES).empty? -        raise Hbc::CaskInvalidError.new(token, "'stage_only' must be the only activatable artifact") +    ORDINARY_ARTIFACT_TYPES.each do |type| +      define_method(type) do |*args| +        if type == :stage_only && args != [true] +          raise CaskInvalidError.new(token, "'stage_only' takes a single argument: true") +        end +        artifacts[type] << args +        if artifacts.key?(:stage_only) && artifacts.keys.count > 1 && +           !(artifacts.keys & ACTIVATABLE_ARTIFACT_TYPES).empty? +          raise CaskInvalidError.new(token, "'stage_only' must be the only activatable artifact") +        end        end      end -  end -  def installer(*args) -    return artifacts[:installer] if args.empty? -    artifacts[:installer] << Hbc::DSL::Installer.new(*args) -    raise "'stage_only' must be the only activatable artifact" if artifacts.key?(:stage_only) -  rescue StandardError => e -    raise Hbc::CaskInvalidError.new(token, e) -  end +    def installer(*args) +      return artifacts[:installer] if args.empty? +      artifacts[:installer] << DSL::Installer.new(*args) +      raise "'stage_only' must be the only activatable artifact" if artifacts.key?(:stage_only) +    rescue StandardError => e +      raise CaskInvalidError.new(token, e) +    end -  SPECIAL_ARTIFACT_TYPES.each do |type| -    define_method(type) do |*args| -      artifacts[type].merge(args) +    SPECIAL_ARTIFACT_TYPES.each do |type| +      define_method(type) do |*args| +        artifacts[type].merge(args) +      end      end -  end -  ARTIFACT_BLOCK_TYPES.each do |type| -    define_method(type) do |&block| -      artifacts[type] << block +    ARTIFACT_BLOCK_TYPES.each do |type| +      define_method(type) do |&block| +        artifacts[type] << block +      end      end -  end -  def method_missing(method, *) -    Hbc::Utils.method_missing_message(method, token) -    nil -  end +    def method_missing(method, *) +      if method +        Utils.method_missing_message(method, token) +        nil +      else +        super +      end +    end -  def appdir -    self.class.appdir -  end +    def respond_to_missing?(*) +      true +    end + +    def appdir +      self.class.appdir +    end -  def self.appdir -    Hbc.appdir.sub(%r{\/$}, "") +    def self.appdir +      Hbc.appdir.sub(%r{\/$}, "") +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb b/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb index b02616cfe..2f1245d3d 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/appcast.rb @@ -1,17 +1,21 @@ -class Hbc::DSL::Appcast -  attr_reader :parameters, :checkpoint +module Hbc +  class DSL +    class Appcast +      attr_reader :parameters, :checkpoint -  def initialize(uri, parameters = {}) -    @parameters     = parameters -    @uri            = Hbc::UnderscoreSupportingURI.parse(uri) -    @checkpoint     = @parameters[:checkpoint] -  end +      def initialize(uri, parameters = {}) +        @parameters     = parameters +        @uri            = UnderscoreSupportingURI.parse(uri) +        @checkpoint     = @parameters[:checkpoint] +      end -  def to_yaml -    [@uri, @parameters].to_yaml -  end +      def to_yaml +        [@uri, @parameters].to_yaml +      end -  def to_s -    @uri.to_s +      def to_s +        @uri.to_s +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/base.rb b/Library/Homebrew/cask/lib/hbc/dsl/base.rb index 4bf62014e..ccf93dae9 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/base.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/base.rb @@ -1,21 +1,33 @@ -class Hbc::DSL::Base -  extend Forwardable +module Hbc +  class DSL +    class Base +      extend Forwardable -  def initialize(cask, command = Hbc::SystemCommand) -    @cask = cask -    @command = command -  end +      def initialize(cask, command = SystemCommand) +        @cask = cask +        @command = command +      end -  def_delegators :@cask, :token, :version, :caskroom_path, :staged_path, :appdir +      def_delegators :@cask, :token, :version, :caskroom_path, :staged_path, :appdir -  def system_command(executable, options = {}) -    @command.run!(executable, options) -  end +      def system_command(executable, options = {}) +        @command.run!(executable, options) +      end + +      def method_missing(method, *) +        if method +          underscored_class = self.class.name.gsub(%r{([[:lower:]])([[:upper:]][[:lower:]])}, '\1_\2').downcase +          section = underscored_class.downcase.split("::").last +          Utils.method_missing_message(method, @cask.to_s, section) +          nil +        else +          super +        end +      end -  def method_missing(method, *) -    underscored_class = self.class.name.gsub(%r{([[:lower:]])([[:upper:]][[:lower:]])}, '\1_\2').downcase -    section = underscored_class.downcase.split("::").last -    Hbc::Utils.method_missing_message(method, @cask.to_s, section) -    nil +      def respond_to_missing?(*) +        true +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/caveats.rb b/Library/Homebrew/cask/lib/hbc/dsl/caveats.rb index d872f49cb..5efd7d562 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/caveats.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/caveats.rb @@ -5,108 +5,112 @@  # ( The return value of the last method in the block is also sent  #   to the output by the caller, but that feature is only for the  #   convenience of Cask authors. ) -class Hbc::DSL::Caveats < Hbc::DSL::Base -  def path_environment_variable(path) -    puts <<-EOS.undent -    To use #{@cask}, you may need to add the #{path} directory -    to your PATH environment variable, eg (for bash shell): +module Hbc +  class DSL +    class Caveats < Base +      def path_environment_variable(path) +        puts <<-EOS.undent +        To use #{@cask}, you may need to add the #{path} directory +        to your PATH environment variable, eg (for bash shell): -      export PATH=#{path}:"$PATH" +          export PATH=#{path}:"$PATH" -    EOS -  end +        EOS +      end -  def zsh_path_helper(path) -    puts <<-EOS.undent -    To use #{@cask}, zsh users may need to add the following line to their -    ~/.zprofile.  (Among other effects, #{path} will be added to the -    PATH environment variable): +      def zsh_path_helper(path) +        puts <<-EOS.undent +        To use #{@cask}, zsh users may need to add the following line to their +        ~/.zprofile.  (Among other effects, #{path} will be added to the +        PATH environment variable): -      eval `/usr/libexec/path_helper -s` +          eval `/usr/libexec/path_helper -s` -    EOS -  end +        EOS +      end -  def files_in_usr_local -    localpath = "/usr/local" -    return unless Hbc.homebrew_prefix.to_s.downcase.start_with?(localpath) -    puts <<-EOS.undent -      Cask #{@cask} installs files under "#{localpath}". The presence of such -      files can cause warnings when running "brew doctor", which is considered -      to be a bug in Homebrew-Cask. +      def files_in_usr_local +        localpath = "/usr/local" +        return unless Hbc.homebrew_prefix.to_s.downcase.start_with?(localpath) +        puts <<-EOS.undent +          Cask #{@cask} installs files under "#{localpath}". The presence of such +          files can cause warnings when running "brew doctor", which is considered +          to be a bug in Homebrew-Cask. -    EOS -  end +        EOS +      end -  def depends_on_java(java_version = "any") -    if java_version == "any" -      puts <<-EOS.undent -      #{@cask} requires Java. You can install the latest version with +      def depends_on_java(java_version = "any") +        if java_version == "any" +          puts <<-EOS.undent +          #{@cask} requires Java. You can install the latest version with -        brew cask install java +            brew cask install java -      EOS -    elsif java_version.include?("8") || java_version.include?("+") -      puts <<-EOS.undent -      #{@cask} requires Java #{java_version}. You can install the latest version with +          EOS +        elsif java_version.include?("8") || java_version.include?("+") +          puts <<-EOS.undent +          #{@cask} requires Java #{java_version}. You can install the latest version with -        brew cask install java +            brew cask install java -      EOS -    else -      puts <<-EOS.undent -      #{@cask} requires Java #{java_version}. You can install it with +          EOS +        else +          puts <<-EOS.undent +          #{@cask} requires Java #{java_version}. You can install it with -        brew cask install caskroom/versions/java#{java_version} +            brew cask install caskroom/versions/java#{java_version} -      EOS -    end -  end +          EOS +        end +      end -  def logout -    puts <<-EOS.undent -    You must log out and log back in for the installation of #{@cask} -    to take effect. +      def logout +        puts <<-EOS.undent +        You must log out and log back in for the installation of #{@cask} +        to take effect. -    EOS -  end +        EOS +      end -  def reboot -    puts <<-EOS.undent -    You must reboot for the installation of #{@cask} to take effect. +      def reboot +        puts <<-EOS.undent +        You must reboot for the installation of #{@cask} to take effect. -    EOS -  end +        EOS +      end -  def discontinued -    puts <<-EOS.undent -    #{@cask} has been officially discontinued upstream. -    It may stop working correctly (or at all) in recent versions of macOS. +      def discontinued +        puts <<-EOS.undent +        #{@cask} has been officially discontinued upstream. +        It may stop working correctly (or at all) in recent versions of macOS. -    EOS -  end +        EOS +      end -  def free_license(web_page) -    puts <<-EOS.undent -    The vendor offers a free license for #{@cask} at -      #{web_page} +      def free_license(web_page) +        puts <<-EOS.undent +        The vendor offers a free license for #{@cask} at +          #{web_page} -    EOS -  end +        EOS +      end -  def malware(radar_number) -    puts <<-EOS.undent -    #{@cask} has been reported to bundle malware. Like with any app, use at your own risk. +      def malware(radar_number) +        puts <<-EOS.undent +        #{@cask} has been reported to bundle malware. Like with any app, use at your own risk. -    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} +        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} -    If this report is accurate, please duplicate it at -      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 +        If this report is accurate, please duplicate it at +          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 -    EOS +        EOS +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/conflicts_with.rb b/Library/Homebrew/cask/lib/hbc/dsl/conflicts_with.rb index b2de2cd45..e121e5373 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/conflicts_with.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/conflicts_with.rb @@ -1,30 +1,34 @@ -class Hbc::DSL::ConflictsWith -  VALID_KEYS = Set.new [ -                         :formula, -                         :cask, -                         :macos, -                         :arch, -                         :x11, -                         :java, -                       ] +module Hbc +  class DSL +    class ConflictsWith +      VALID_KEYS = Set.new [ +                             :formula, +                             :cask, +                             :macos, +                             :arch, +                             :x11, +                             :java, +                           ] -  attr_accessor(*VALID_KEYS) -  attr_accessor :pairs +      attr_accessor(*VALID_KEYS) +      attr_accessor :pairs -  def initialize(pairs = {}) -    @pairs = pairs -    pairs.each do |key, value| -      raise "invalid conflicts_with key: '#{key.inspect}'" unless VALID_KEYS.include?(key) -      writer_method = "#{key}=".to_sym -      send(writer_method, value) -    end -  end +      def initialize(pairs = {}) +        @pairs = pairs +        pairs.each do |key, value| +          raise "invalid conflicts_with key: '#{key.inspect}'" unless VALID_KEYS.include?(key) +          writer_method = "#{key}=".to_sym +          send(writer_method, value) +        end +      end -  def to_yaml -    @pairs.to_yaml -  end +      def to_yaml +        @pairs.to_yaml +      end -  def to_s -    @pairs.inspect +      def to_s +        @pairs.inspect +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/container.rb b/Library/Homebrew/cask/lib/hbc/dsl/container.rb index 39f156668..56db31d97 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/container.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/container.rb @@ -1,26 +1,30 @@ -class Hbc::DSL::Container -  VALID_KEYS = Set.new [ -                         :type, -                         :nested, -                       ] +module Hbc +  class DSL +    class Container +      VALID_KEYS = Set.new [ +                             :type, +                             :nested, +                           ] -  attr_accessor(*VALID_KEYS) -  attr_accessor :pairs +      attr_accessor(*VALID_KEYS) +      attr_accessor :pairs -  def initialize(pairs = {}) -    @pairs = pairs -    pairs.each do |key, value| -      raise "invalid container key: '#{key.inspect}'" unless VALID_KEYS.include?(key) -      writer_method = "#{key}=".to_sym -      send(writer_method, value) -    end -  end +      def initialize(pairs = {}) +        @pairs = pairs +        pairs.each do |key, value| +          raise "invalid container key: '#{key.inspect}'" unless VALID_KEYS.include?(key) +          writer_method = "#{key}=".to_sym +          send(writer_method, value) +        end +      end -  def to_yaml -    @pairs.to_yaml -  end +      def to_yaml +        @pairs.to_yaml +      end -  def to_s -    @pairs.inspect +      def to_s +        @pairs.inspect +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/depends_on.rb b/Library/Homebrew/cask/lib/hbc/dsl/depends_on.rb index a7dba3643..0e80938b7 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/depends_on.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/depends_on.rb @@ -1,124 +1,128 @@  require "rubygems" -class Hbc::DSL::DependsOn -  VALID_KEYS = Set.new [ -                         :formula, -                         :cask, -                         :macos, -                         :arch, -                         :x11, -                         :java, -                       ].freeze +module Hbc +  class DSL +    class DependsOn +      VALID_KEYS = Set.new [ +                             :formula, +                             :cask, +                             :macos, +                             :arch, +                             :x11, +                             :java, +                           ].freeze -  VALID_ARCHES = { -                   intel:    { type: :intel, bits: [32, 64] }, -                   ppc:      { type: :ppc,   bits: [32, 64] }, -                   # specific -                   i386:     { type: :intel, bits: 32 }, -                   x86_64:   { type: :intel, bits: 64 }, -                   ppc_7400: { type: :ppc,   bits: 32 }, -                   ppc_64:   { type: :ppc,   bits: 64 }, -                 }.freeze +      VALID_ARCHES = { +                       intel:    { type: :intel, bits: [32, 64] }, +                       ppc:      { type: :ppc,   bits: [32, 64] }, +                       # specific +                       i386:     { type: :intel, bits: 32 }, +                       x86_64:   { type: :intel, bits: 64 }, +                       ppc_7400: { type: :ppc,   bits: 32 }, +                       ppc_64:   { type: :ppc,   bits: 64 }, +                     }.freeze -  # 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, -                  }.freeze +      # 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, +                      }.freeze -  attr_accessor :java -  attr_accessor :pairs -  attr_reader :arch, :cask, :formula, :macos, :x11 +      attr_accessor :java +      attr_accessor :pairs +      attr_reader :arch, :cask, :formula, :macos, :x11 -  def initialize -    @pairs ||= {} -  end +      def initialize +        @pairs ||= {} +      end -  def load(pairs = {}) -    pairs.each do |key, value| -      raise "invalid depends_on key: '#{key.inspect}'" unless VALID_KEYS.include?(key) -      writer_method = "#{key}=".to_sym -      @pairs[key] = send(writer_method, value) -    end -  end +      def load(pairs = {}) +        pairs.each do |key, value| +          raise "invalid depends_on key: '#{key.inspect}'" unless VALID_KEYS.include?(key) +          writer_method = "#{key}=".to_sym +          @pairs[key] = send(writer_method, value) +        end +      end -  def self.coerce_os_release(arg) -    @macos_symbols ||= MacOS::Version::SYMBOLS -    @inverted_macos_symbols ||= @macos_symbols.invert +      def self.coerce_os_release(arg) +        @macos_symbols ||= MacOS::Version::SYMBOLS +        @inverted_macos_symbols ||= @macos_symbols.invert -    begin -      if arg.is_a?(Symbol) -        Gem::Version.new(@macos_symbols.fetch(arg)) -      elsif arg =~ %r{^\s*:?([a-z]\S+)\s*$}i -        Gem::Version.new(@macos_symbols.fetch(Regexp.last_match[1].downcase.to_sym)) -      elsif @inverted_macos_symbols.key?(arg) -        Gem::Version.new(arg) -      else -        raise +        begin +          if arg.is_a?(Symbol) +            Gem::Version.new(@macos_symbols.fetch(arg)) +          elsif arg =~ %r{^\s*:?([a-z]\S+)\s*$}i +            Gem::Version.new(@macos_symbols.fetch(Regexp.last_match[1].downcase.to_sym)) +          elsif @inverted_macos_symbols.key?(arg) +            Gem::Version.new(arg) +          else +            raise +          end +        rescue StandardError +          raise "invalid 'depends_on macos' value: #{arg.inspect}" +        end        end -    rescue StandardError -      raise "invalid 'depends_on macos' value: #{arg.inspect}" -    end -  end -  def formula=(*arg) -    @formula ||= [] -    @formula.concat(Array(*arg)) -  end +      def formula=(*arg) +        @formula ||= [] +        @formula.concat(Array(*arg)) +      end -  def cask=(*arg) -    @cask ||= [] -    @cask.concat(Array(*arg)) -  end +      def cask=(*arg) +        @cask ||= [] +        @cask.concat(Array(*arg)) +      end -  def macos=(*arg) -    @macos ||= [] -    macos = if arg.count == 1 && arg.first =~ %r{^\s*(<|>|[=<>]=)\s*(\S+)\s*$} -              raise "'depends_on macos' comparison expressions cannot be combined" unless @macos.empty? -              operator = Regexp.last_match[1].to_sym -              release = self.class.coerce_os_release(Regexp.last_match[2]) -              [[operator, release]] -            else -              raise "'depends_on macos' comparison expressions cannot be combined" if @macos.first.is_a?(Symbol) -              Array(*arg).map { |elt| -                self.class.coerce_os_release(elt) -              }.sort -            end -    @macos.concat(macos) -  end +      def macos=(*arg) +        @macos ||= [] +        macos = if arg.count == 1 && arg.first =~ %r{^\s*(<|>|[=<>]=)\s*(\S+)\s*$} +                  raise "'depends_on macos' comparison expressions cannot be combined" unless @macos.empty? +                  operator = Regexp.last_match[1].to_sym +                  release = self.class.coerce_os_release(Regexp.last_match[2]) +                  [[operator, release]] +                else +                  raise "'depends_on macos' comparison expressions cannot be combined" if @macos.first.is_a?(Symbol) +                  Array(*arg).map { |elt| +                    self.class.coerce_os_release(elt) +                  }.sort +                end +        @macos.concat(macos) +      end -  def arch=(*arg) -    @arch ||= [] -    arches = Array(*arg).map { |elt| -      elt = elt.to_s.downcase.sub(%r{^:}, "").tr("-", "_").to_sym -      ARCH_SYNONYMS.key?(elt) ? ARCH_SYNONYMS[elt] : elt -    } -    invalid_arches = arches - VALID_ARCHES.keys -    raise "invalid 'depends_on arch' values: #{invalid_arches.inspect}" unless invalid_arches.empty? -    @arch.concat(arches.map { |arch| VALID_ARCHES[arch] }) -  end +      def arch=(*arg) +        @arch ||= [] +        arches = Array(*arg).map { |elt| +          elt = elt.to_s.downcase.sub(%r{^:}, "").tr("-", "_").to_sym +          ARCH_SYNONYMS.key?(elt) ? ARCH_SYNONYMS[elt] : elt +        } +        invalid_arches = arches - VALID_ARCHES.keys +        raise "invalid 'depends_on arch' values: #{invalid_arches.inspect}" unless invalid_arches.empty? +        @arch.concat(arches.map { |arch| VALID_ARCHES[arch] }) +      end -  def x11=(arg) -    raise "invalid 'depends_on x11' value: #{arg.inspect}" unless [true, false].include?(arg) -    @x11 = arg -  end +      def x11=(arg) +        raise "invalid 'depends_on x11' value: #{arg.inspect}" unless [true, false].include?(arg) +        @x11 = arg +      end -  def to_yaml -    @pairs.to_yaml -  end +      def to_yaml +        @pairs.to_yaml +      end -  def to_s -    @pairs.inspect +      def to_s +        @pairs.inspect +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/gpg.rb b/Library/Homebrew/cask/lib/hbc/dsl/gpg.rb index 9496a8c05..572ede227 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/gpg.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/gpg.rb @@ -1,43 +1,47 @@ -class Hbc::DSL::Gpg -  KEY_PARAMETERS = Set.new [ -                             :key_id, -                             :key_url, -                           ] +module Hbc +  class DSL +    class Gpg +      KEY_PARAMETERS = Set.new [ +                                 :key_id, +                                 :key_url, +                               ] -  VALID_PARAMETERS = Set.new [] -  VALID_PARAMETERS.merge KEY_PARAMETERS +      VALID_PARAMETERS = Set.new [] +      VALID_PARAMETERS.merge KEY_PARAMETERS -  attr_accessor(*VALID_PARAMETERS) -  attr_accessor :signature +      attr_accessor(*VALID_PARAMETERS) +      attr_accessor :signature -  def initialize(signature, parameters = {}) -    @parameters = parameters -    @signature = Hbc::UnderscoreSupportingURI.parse(signature) -    parameters.each do |hkey, hvalue| -      raise "invalid 'gpg' parameter: '#{hkey.inspect}'" unless VALID_PARAMETERS.include?(hkey) -      writer_method = "#{hkey}=".to_sym -      hvalue = Hbc::UnderscoreSupportingURI.parse(hvalue) if hkey == :key_url -      valid_id?(hvalue) if hkey == :key_id -      send(writer_method, hvalue) -    end -    return if KEY_PARAMETERS.intersection(parameters.keys).length == 1 -    raise "'gpg' stanza must include exactly one of: '#{KEY_PARAMETERS.to_a}'" -  end +      def initialize(signature, parameters = {}) +        @parameters = parameters +        @signature = UnderscoreSupportingURI.parse(signature) +        parameters.each do |hkey, hvalue| +          raise "invalid 'gpg' parameter: '#{hkey.inspect}'" unless VALID_PARAMETERS.include?(hkey) +          writer_method = "#{hkey}=".to_sym +          hvalue = UnderscoreSupportingURI.parse(hvalue) if hkey == :key_url +          valid_id?(hvalue) if hkey == :key_id +          send(writer_method, hvalue) +        end +        return if KEY_PARAMETERS.intersection(parameters.keys).length == 1 +        raise "'gpg' stanza must include exactly one of: '#{KEY_PARAMETERS.to_a}'" +      end -  def valid_id?(id) -    legal_lengths = Set.new [8, 16, 40] -    is_valid = id.is_a?(String) && legal_lengths.include?(id.length) && id[%r{^[0-9a-f]+$}i] -    raise "invalid ':key_id' value: '#{id.inspect}'" unless is_valid +      def valid_id?(id) +        legal_lengths = Set.new [8, 16, 40] +        is_valid = id.is_a?(String) && legal_lengths.include?(id.length) && id[%r{^[0-9a-f]+$}i] +        raise "invalid ':key_id' value: '#{id.inspect}'" unless is_valid -    is_valid -  end +        is_valid +      end -  def to_yaml -    # bug, :key_url value is not represented as an instance of Hbc::UnderscoreSupportingURI -    [@signature, @parameters].to_yaml -  end +      def to_yaml +        # bug, :key_url value is not represented as an instance of Hbc::UnderscoreSupportingURI +        [@signature, @parameters].to_yaml +      end -  def to_s -    @signature.to_s +      def to_s +        @signature.to_s +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/installer.rb b/Library/Homebrew/cask/lib/hbc/dsl/installer.rb index 74b4b3a91..92561c703 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/installer.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/installer.rb @@ -1,28 +1,32 @@ -class Hbc::DSL::Installer -  VALID_KEYS = Set.new [ -                         :manual, -                         :script, -                       ] +module Hbc +  class DSL +    class Installer +      VALID_KEYS = Set.new [ +                             :manual, +                             :script, +                           ] -  attr_accessor(*VALID_KEYS) +      attr_accessor(*VALID_KEYS) -  def initialize(*parameters) -    raise Hbc::CaskInvalidError.new(token, "'installer' stanza requires an argument") if parameters.empty? -    parameters = {}.merge(*parameters) -    if parameters.key?(:script) && !parameters[:script].respond_to?(:key?) -      if parameters.key?(:executable) -        raise Hbc::CaskInvalidError.new(token, "'installer' stanza gave arguments for both :script and :executable") +      def initialize(*parameters) +        raise CaskInvalidError.new(token, "'installer' stanza requires an argument") if parameters.empty? +        parameters = {}.merge(*parameters) +        if parameters.key?(:script) && !parameters[:script].respond_to?(:key?) +          if parameters.key?(:executable) +            raise CaskInvalidError.new(token, "'installer' stanza gave arguments for both :script and :executable") +          end +          parameters[:executable] = parameters[:script] +          parameters.delete(:script) +          parameters = { script: parameters } +        end +        unless parameters.keys.length == 1 +          raise "invalid 'installer' stanza: only one of #{VALID_KEYS.inspect} is permitted" +        end +        key = parameters.keys.first +        raise "invalid 'installer' stanza key: '#{key.inspect}'" unless VALID_KEYS.include?(key) +        writer_method = "#{key}=".to_sym +        send(writer_method, parameters[key])        end -      parameters[:executable] = parameters[:script] -      parameters.delete(:script) -      parameters = { script: parameters }      end -    unless parameters.keys.length == 1 -      raise "invalid 'installer' stanza: only one of #{VALID_KEYS.inspect} is permitted" -    end -    key = parameters.keys.first -    raise "invalid 'installer' stanza key: '#{key.inspect}'" unless VALID_KEYS.include?(key) -    writer_method = "#{key}=".to_sym -    send(writer_method, parameters[key])    end  end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/license.rb b/Library/Homebrew/cask/lib/hbc/dsl/license.rb index 5f607c268..affbc08f5 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/license.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/license.rb @@ -1,66 +1,70 @@ -class Hbc::DSL::License -  # a generic category can always be given as a license, so -  # category names should be given as both key and value -  VALID_LICENSES = { -                     # license         category -                     unknown:       :unknown, +module Hbc +  class DSL +    class License +      # a generic category can always be given as a license, so +      # category names should be given as both key and value +      VALID_LICENSES = { +                         # license         category +                         unknown:       :unknown, -                     other:         :other, +                         other:         :other, -                     closed:        :closed, -                     commercial:    :closed, -                     gratis:        :closed, -                     freemium:      :closed, +                         closed:        :closed, +                         commercial:    :closed, +                         gratis:        :closed, +                         freemium:      :closed, -                     oss:           :oss, -                     affero:        :oss, -                     apache:        :oss, -                     arphic:        :oss, -                     artistic:      :oss, -                     bsd:           :oss, -                     cc:            :oss, -                     eclipse:       :oss, -                     gpl:           :oss, -                     isc:           :oss, -                     lppl:          :oss, -                     ncsa:          :oss, -                     mit:           :oss, -                     mpl:           :oss, -                     ofl:           :oss, -                     public_domain: :oss, -                     ubuntu_font:   :oss, -                     x11:           :oss, -                   }.freeze +                         oss:           :oss, +                         affero:        :oss, +                         apache:        :oss, +                         arphic:        :oss, +                         artistic:      :oss, +                         bsd:           :oss, +                         cc:            :oss, +                         eclipse:       :oss, +                         gpl:           :oss, +                         isc:           :oss, +                         lppl:          :oss, +                         ncsa:          :oss, +                         mit:           :oss, +                         mpl:           :oss, +                         ofl:           :oss, +                         public_domain: :oss, +                         ubuntu_font:   :oss, +                         x11:           :oss, +                       }.freeze -  DEFAULT_LICENSE = :unknown -  DEFAULT_CATEGORY = VALID_LICENSES[DEFAULT_LICENSE] +      DEFAULT_LICENSE = :unknown +      DEFAULT_CATEGORY = VALID_LICENSES[DEFAULT_LICENSE] -  attr_reader :value +      attr_reader :value -  def self.check_constants -    categories = Set.new(VALID_LICENSES.values) -    categories.each do |cat| -      next if VALID_LICENSES.key?(cat) -      raise "license category is not a value: '#{@cat.inspect}'" -    end -  end +      def self.check_constants +        categories = Set.new(VALID_LICENSES.values) +        categories.each do |cat| +          next if VALID_LICENSES.key?(cat) +          raise "license category is not a value: '#{@cat.inspect}'" +        end +      end -  def self.category(license) -    VALID_LICENSES.fetch(license, DEFAULT_CATEGORY) -  end +      def self.category(license) +        VALID_LICENSES.fetch(license, DEFAULT_CATEGORY) +      end -  def initialize(arg) -    @value = arg -    @value = DEFAULT_LICENSE if @value.nil? -    return if VALID_LICENSES.key?(@value) -    raise "invalid license value: '#{@value.inspect}'" -  end +      def initialize(arg) +        @value = arg +        @value = DEFAULT_LICENSE if @value.nil? +        return if VALID_LICENSES.key?(@value) +        raise "invalid license value: '#{@value.inspect}'" +      end -  def category -    self.class.category(@value) -  end +      def category +        self.class.category(@value) +      end -  def to_s -    @value.inspect +      def to_s +        @value.inspect +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/postflight.rb b/Library/Homebrew/cask/lib/hbc/dsl/postflight.rb index 321c7e81a..1026f6de6 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/postflight.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/postflight.rb @@ -1,9 +1,13 @@  require "hbc/staged" -class Hbc::DSL::Postflight < Hbc::DSL::Base -  include Hbc::Staged +module Hbc +  class DSL +    class Postflight < Base +      include Staged -  def suppress_move_to_applications(options = {}) -    # TODO: Remove from all casks because it is no longer needed +      def suppress_move_to_applications(options = {}) +        # TODO: Remove from all casks because it is no longer needed +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/preflight.rb b/Library/Homebrew/cask/lib/hbc/dsl/preflight.rb index a0d53c69c..55a778706 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/preflight.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/preflight.rb @@ -1,3 +1,7 @@ -class Hbc::DSL::Preflight < Hbc::DSL::Base -  include Hbc::Staged +module Hbc +  class DSL +    class Preflight < Base +      include Staged +    end +  end  end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/stanza_proxy.rb b/Library/Homebrew/cask/lib/hbc/dsl/stanza_proxy.rb index 02c76fb27..b1a850c5a 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/stanza_proxy.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/stanza_proxy.rb @@ -1,37 +1,49 @@ -class Hbc::DSL::StanzaProxy -  attr_reader :type +module Hbc +  class DSL +    class StanzaProxy +      attr_reader :type -  def self.once(type) -    resolved = nil -    new(type) { resolved ||= yield } -  end +      def self.once(type) +        resolved = nil +        new(type) { resolved ||= yield } +      end -  def initialize(type, &resolver) -    @type = type -    @resolver = resolver -  end +      def initialize(type, &resolver) +        @type = type +        @resolver = resolver +      end -  def proxy? -    true -  end +      def proxy? +        true +      end -  def to_s -    @resolver.call.to_s -  end +      def to_s +        @resolver.call.to_s +      end -  # Serialization for dumpcask -  def encode_with(coder) -    coder["type"] = type -    coder["resolved"] = @resolver.call -  end +      # Serialization for dumpcask +      def encode_with(coder) +        coder["type"] = type +        coder["resolved"] = @resolver.call +      end -  def respond_to?(symbol, include_private = false) -    return true if %i{encode_with proxy? to_s type}.include?(symbol) -    return false if symbol == :to_ary -    @resolver.call.respond_to?(symbol, include_private) -  end +      def method_missing(method, *args) +        if method != :to_ary +          @resolver.call.send(method, *args) +        else +          super +        end +      end + +      def respond_to?(method, include_private = false) +        return true if %i{encode_with proxy? to_s type}.include?(method) +        return false if method == :to_ary +        @resolver.call.respond_to?(method, include_private) +      end -  def method_missing(symbol, *args) -    @resolver.call.send(symbol, *args) +      def respond_to_missing?(*) +        true +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/uninstall_postflight.rb b/Library/Homebrew/cask/lib/hbc/dsl/uninstall_postflight.rb index bd8777ca7..f481cc357 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/uninstall_postflight.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/uninstall_postflight.rb @@ -1,2 +1,6 @@ -class Hbc::DSL::UninstallPostflight < Hbc::DSL::Base +module Hbc +  class DSL +    class UninstallPostflight < Base +    end +  end  end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/uninstall_preflight.rb b/Library/Homebrew/cask/lib/hbc/dsl/uninstall_preflight.rb index 994151c25..36cdec12f 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/uninstall_preflight.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/uninstall_preflight.rb @@ -1,5 +1,9 @@  require "hbc/staged" -class Hbc::DSL::UninstallPreflight < Hbc::DSL::Base -  include Hbc::Staged +module Hbc +  class DSL +    class UninstallPreflight < Base +      include Staged +    end +  end  end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/version.rb b/Library/Homebrew/cask/lib/hbc/dsl/version.rb index e01e67ea2..d4697460a 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/version.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/version.rb @@ -1,111 +1,115 @@ -class Hbc::DSL::Version < ::String -  DIVIDERS = { -               "." => :dots, -               "-" => :hyphens, -               "_" => :underscores, -               "/" => :slashes, -             }.freeze - -  DIVIDER_REGEX = %r{(#{DIVIDERS.keys.map { |v| Regexp.quote(v) }.join('|')})} - -  MAJOR_MINOR_PATCH_REGEX = %r{^(\d+)(?:\.(\d+)(?:\.(\d+))?)?} - -  class << self -    private - -    def define_divider_methods(divider) -      define_divider_deletion_method(divider) -      define_divider_conversion_methods(divider) -    end +module Hbc +  class DSL +    class Version < ::String +      DIVIDERS = { +                   "." => :dots, +                   "-" => :hyphens, +                   "_" => :underscores, +                   "/" => :slashes, +                 }.freeze + +      DIVIDER_REGEX = %r{(#{DIVIDERS.keys.map { |v| Regexp.quote(v) }.join('|')})} + +      MAJOR_MINOR_PATCH_REGEX = %r{^(\d+)(?:\.(\d+)(?:\.(\d+))?)?} + +      class << self +        private + +        def define_divider_methods(divider) +          define_divider_deletion_method(divider) +          define_divider_conversion_methods(divider) +        end + +        def define_divider_deletion_method(divider) +          method_name = deletion_method_name(divider) +          define_method(method_name) do +            version { delete(divider) } +          end +        end + +        def deletion_method_name(divider) +          "no_#{DIVIDERS[divider]}" +        end + +        def define_divider_conversion_methods(left_divider) +          (DIVIDERS.keys - [left_divider]).each do |right_divider| +            define_divider_conversion_method(left_divider, right_divider) +          end +        end + +        def define_divider_conversion_method(left_divider, right_divider) +          method_name = conversion_method_name(left_divider, right_divider) +          define_method(method_name) do +            version { gsub(left_divider, right_divider) } +          end +        end + +        def conversion_method_name(left_divider, right_divider) +          "#{DIVIDERS[left_divider]}_to_#{DIVIDERS[right_divider]}" +        end +      end -    def define_divider_deletion_method(divider) -      method_name = deletion_method_name(divider) -      define_method(method_name) do -        version { delete(divider) } +      DIVIDERS.keys.each do |divider| +        define_divider_methods(divider)        end -    end -    def deletion_method_name(divider) -      "no_#{DIVIDERS[divider]}" -    end +      attr_reader :raw_version -    def define_divider_conversion_methods(left_divider) -      (DIVIDERS.keys - [left_divider]).each do |right_divider| -        define_divider_conversion_method(left_divider, right_divider) +      def initialize(raw_version) +        @raw_version = raw_version +        super(raw_version.to_s)        end -    end -    def define_divider_conversion_method(left_divider, right_divider) -      method_name = conversion_method_name(left_divider, right_divider) -      define_method(method_name) do -        version { gsub(left_divider, right_divider) } +      def latest? +        to_s == "latest"        end -    end -    def conversion_method_name(left_divider, right_divider) -      "#{DIVIDERS[left_divider]}_to_#{DIVIDERS[right_divider]}" -    end -  end - -  DIVIDERS.keys.each do |divider| -    define_divider_methods(divider) -  end - -  attr_reader :raw_version - -  def initialize(raw_version) -    @raw_version = raw_version -    super(raw_version.to_s) -  end - -  def latest? -    to_s == "latest" -  end - -  def major -    version { slice(MAJOR_MINOR_PATCH_REGEX, 1) } -  end +      def major +        version { slice(MAJOR_MINOR_PATCH_REGEX, 1) } +      end -  def minor -    version { slice(MAJOR_MINOR_PATCH_REGEX, 2) } -  end +      def minor +        version { slice(MAJOR_MINOR_PATCH_REGEX, 2) } +      end -  def patch -    version { slice(MAJOR_MINOR_PATCH_REGEX, 3) } -  end +      def patch +        version { slice(MAJOR_MINOR_PATCH_REGEX, 3) } +      end -  def major_minor -    version { [major, minor].reject(&:empty?).join(".") } -  end +      def major_minor +        version { [major, minor].reject(&:empty?).join(".") } +      end -  def major_minor_patch -    version { [major, minor, patch].reject(&:empty?).join(".") } -  end +      def major_minor_patch +        version { [major, minor, patch].reject(&:empty?).join(".") } +      end -  def before_comma -    version { split(",", 2)[0] } -  end +      def before_comma +        version { split(",", 2)[0] } +      end -  def after_comma -    version { split(",", 2)[1] } -  end +      def after_comma +        version { split(",", 2)[1] } +      end -  def before_colon -    version { split(":", 2)[0] } -  end +      def before_colon +        version { split(":", 2)[0] } +      end -  def after_colon -    version { split(":", 2)[1] } -  end +      def after_colon +        version { split(":", 2)[1] } +      end -  def no_dividers -    version { gsub(DIVIDER_REGEX, "") } -  end +      def no_dividers +        version { gsub(DIVIDER_REGEX, "") } +      end -  private +      private -  def version -    return self if empty? || latest? -    self.class.new(yield) +      def version +        return self if empty? || latest? +        self.class.new(yield) +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/exceptions.rb b/Library/Homebrew/cask/lib/hbc/exceptions.rb index 8813aaedf..f77106d92 100644 --- a/Library/Homebrew/cask/lib/hbc/exceptions.rb +++ b/Library/Homebrew/cask/lib/hbc/exceptions.rb @@ -1,146 +1,148 @@ -class Hbc::CaskError < RuntimeError; end +module Hbc +  class CaskError < RuntimeError; end -class Hbc::AbstractCaskErrorWithToken < Hbc::CaskError -  attr_reader :token +  class AbstractCaskErrorWithToken < CaskError +    attr_reader :token -  def initialize(token) -    @token = token +    def initialize(token) +      @token = token +    end    end -end -class Hbc::CaskNotInstalledError < Hbc::AbstractCaskErrorWithToken -  def to_s -    "#{token} is not installed" +  class CaskNotInstalledError < AbstractCaskErrorWithToken +    def to_s +      "#{token} is not installed" +    end    end -end -class Hbc::CaskUnavailableError < Hbc::AbstractCaskErrorWithToken -  def to_s -    "No available Cask for #{token}" +  class CaskUnavailableError < AbstractCaskErrorWithToken +    def to_s +      "No available Cask for #{token}" +    end    end -end -class Hbc::CaskAlreadyCreatedError < Hbc::AbstractCaskErrorWithToken -  def to_s -    %Q{A Cask for #{token} already exists. Run "brew cask cat #{token}" to see it.} +  class CaskAlreadyCreatedError < AbstractCaskErrorWithToken +    def to_s +      %Q{A Cask for #{token} already exists. Run "brew cask cat #{token}" to see it.} +    end    end -end -class Hbc::CaskAlreadyInstalledError < Hbc::AbstractCaskErrorWithToken -  def to_s -    %Q{A Cask for #{token} is already installed. Add the "--force" option to force re-install.} +  class CaskAlreadyInstalledError < AbstractCaskErrorWithToken +    def to_s +      %Q{A Cask for #{token} is already installed. Add the "--force" option to force re-install.} +    end    end -end -class Hbc::CaskAutoUpdatesError < Hbc::AbstractCaskErrorWithToken -  def to_s -    %Q{A Cask for #{token} is already installed and using auto-updates. Add the "--force" option to force re-install.} +  class CaskAutoUpdatesError < AbstractCaskErrorWithToken +    def to_s +      %Q{A Cask for #{token} is already installed and using auto-updates. Add the "--force" option to force re-install.} +    end    end -end -class Hbc::CaskCommandFailedError < Hbc::CaskError -  def initialize(cmd, stdout, stderr, status) -    @cmd = cmd -    @stdout = stdout -    @stderr = stderr -    @status = status -  end +  class CaskCommandFailedError < CaskError +    def initialize(cmd, stdout, stderr, status) +      @cmd = cmd +      @stdout = stdout +      @stderr = stderr +      @status = status +    end -  def to_s -    <<-EOS -Command failed to execute! +    def to_s +      <<-EOS +  Command failed to execute! -==> Failed command: -#{@cmd} +  ==> Failed command: +  #{@cmd} -==> Standard Output of failed command: -#{@stdout} +  ==> Standard Output of failed command: +  #{@stdout} -==> Standard Error of failed command: -#{@stderr} +  ==> Standard Error of failed command: +  #{@stderr} -==> Exit status of failed command: -#{@status.inspect} -    EOS +  ==> Exit status of failed command: +  #{@status.inspect} +      EOS +    end    end -end -class Hbc::CaskX11DependencyError < Hbc::AbstractCaskErrorWithToken -  def to_s -    <<-EOS.undent -      #{token} requires XQuartz/X11, which can be installed via homebrew-cask by +  class CaskX11DependencyError < AbstractCaskErrorWithToken +    def to_s +      <<-EOS.undent +        #{token} requires XQuartz/X11, which can be installed via homebrew-cask by -        brew cask install xquartz +          brew cask install xquartz -      or manually, by downloading the package from +        or manually, by downloading the package from -        https://www.xquartz.org/ -    EOS +          https://www.xquartz.org/ +      EOS +    end    end -end -class Hbc::CaskCyclicCaskDependencyError < Hbc::AbstractCaskErrorWithToken -  def to_s -    "Cask '#{token}' includes cyclic dependencies on other Casks and could not be installed." +  class CaskCyclicCaskDependencyError < AbstractCaskErrorWithToken +    def to_s +      "Cask '#{token}' includes cyclic dependencies on other Casks and could not be installed." +    end    end -end -class Hbc::CaskUnspecifiedError < Hbc::CaskError -  def to_s -    "This command requires a Cask token" +  class CaskUnspecifiedError < CaskError +    def to_s +      "This command requires a Cask token" +    end    end -end -class Hbc::CaskInvalidError < Hbc::AbstractCaskErrorWithToken -  attr_reader :submsg -  def initialize(token, *submsg) -    super(token) -    @submsg = submsg.join(" ") -  end +  class CaskInvalidError < AbstractCaskErrorWithToken +    attr_reader :submsg +    def initialize(token, *submsg) +      super(token) +      @submsg = submsg.join(" ") +    end -  def to_s -    "Cask '#{token}' definition is invalid" + (!submsg.empty? ? ": #{submsg}" : "") +    def to_s +      "Cask '#{token}' definition is invalid" + (!submsg.empty? ? ": #{submsg}" : "") +    end    end -end -class Hbc::CaskTokenDoesNotMatchError < Hbc::CaskInvalidError -  def initialize(token, header_token) -    super(token, "Bad header line: '#{header_token}' does not match file name") +  class CaskTokenDoesNotMatchError < CaskInvalidError +    def initialize(token, header_token) +      super(token, "Bad header line: '#{header_token}' does not match file name") +    end    end -end -class Hbc::CaskSha256MissingError < ArgumentError -end - -class Hbc::CaskSha256MismatchError < RuntimeError -  attr_reader :path, :expected, :actual -  def initialize(path, expected, actual) -    @path = path -    @expected = expected -    @actual = actual +  class CaskSha256MissingError < ArgumentError    end -  def to_s -    <<-EOS.undent -      sha256 mismatch -      Expected: #{expected} -      Actual: #{actual} -      File: #{path} -      To retry an incomplete download, remove the file above. -    EOS -  end -end +  class CaskSha256MismatchError < RuntimeError +    attr_reader :path, :expected, :actual +    def initialize(path, expected, actual) +      @path = path +      @expected = expected +      @actual = actual +    end -class Hbc::CaskNoShasumError < Hbc::CaskError -  attr_reader :token -  def initialize(token) -    @token = token +    def to_s +      <<-EOS.undent +        sha256 mismatch +        Expected: #{expected} +        Actual: #{actual} +        File: #{path} +        To retry an incomplete download, remove the file above. +      EOS +    end    end -  def to_s -    <<-EOS.undent -      Cask '#{token}' does not have a sha256 checksum defined and was not installed. -      This means you have the "--require-sha" option set, perhaps in your HOMEBREW_CASK_OPTS. -    EOS +  class CaskNoShasumError < CaskError +    attr_reader :token +    def initialize(token) +      @token = token +    end + +    def to_s +      <<-EOS.undent +        Cask '#{token}' does not have a sha256 checksum defined and was not installed. +        This means you have the "--require-sha" option set, perhaps in your HOMEBREW_CASK_OPTS. +      EOS +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/extend/hash.rb b/Library/Homebrew/cask/lib/hbc/extend/hash.rb index dc28cfb29..3a06ba3af 100644 --- a/Library/Homebrew/cask/lib/hbc/extend/hash.rb +++ b/Library/Homebrew/cask/lib/hbc/extend/hash.rb @@ -2,6 +2,6 @@ class Hash    def assert_valid_keys(*valid_keys)      unknown_keys = keys - valid_keys      return if unknown_keys.empty? -    raise Hbc::CaskError, %Q{Unknown keys: #{unknown_keys.inspect}. Running "#{UPDATE_CMD}" will likely fix it.} +    raise CaskError, %Q{Unknown keys: #{unknown_keys.inspect}. Running "#{UPDATE_CMD}" will likely fix it.}    end  end diff --git a/Library/Homebrew/cask/lib/hbc/fetcher.rb b/Library/Homebrew/cask/lib/hbc/fetcher.rb index 44a898ce0..6f58ca023 100644 --- a/Library/Homebrew/cask/lib/hbc/fetcher.rb +++ b/Library/Homebrew/cask/lib/hbc/fetcher.rb @@ -1,22 +1,24 @@  require "open3" -class Hbc::Fetcher -  TIMEOUT = 10 +module Hbc +  class Fetcher +    TIMEOUT = 10 -  def self.head(url) -    if url.to_s =~ %r{googlecode} -      googlecode_fake_head(url) -    else -      Hbc::SystemCommand.run("/usr/bin/curl", -                             args: ["--max-time", TIMEOUT, "--silent", "--location", "--head", url]).stdout +    def self.head(url) +      if url.to_s =~ %r{googlecode} +        googlecode_fake_head(url) +      else +        SystemCommand.run("/usr/bin/curl", +                          args: ["--max-time", TIMEOUT, "--silent", "--location", "--head", url]).stdout +      end      end -  end -  # google code does not properly respond to HTTP HEAD requests, like a jerk -  # this fakes a HEAD by doing a GET, taking the first 20 lines, then running away -  def self.googlecode_fake_head(url) -    command = "curl --max-time #{TIMEOUT} --verbose --location '#{url}' | head -n 20 > /dev/null" -    stderr = Open3.capture3(command)[1] -    stderr.split("\n").grep(%r{^< }).map { |line| line.sub(%r{^< }, "") }.join("\n") +    # google code does not properly respond to HTTP HEAD requests, like a jerk +    # this fakes a HEAD by doing a GET, taking the first 20 lines, then running away +    def self.googlecode_fake_head(url) +      command = "curl --max-time #{TIMEOUT} --verbose --location '#{url}' | head -n 20 > /dev/null" +      stderr = Open3.capture3(command)[1] +      stderr.split("\n").grep(%r{^< }).map { |line| line.sub(%r{^< }, "") }.join("\n") +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/installer.rb b/Library/Homebrew/cask/lib/hbc/installer.rb index 72a9b3077..f0cc0d1a9 100644 --- a/Library/Homebrew/cask/lib/hbc/installer.rb +++ b/Library/Homebrew/cask/lib/hbc/installer.rb @@ -4,142 +4,144 @@ require "hbc/cask_dependencies"  require "hbc/staged"  require "hbc/verify" -class Hbc::Installer -  # TODO: it is unwise for Hbc::Staged to be a module, when we are -  #       dealing with both staged and unstaged Casks here.  This should -  #       either be a class which is only sometimes instantiated, or there -  #       should be explicit checks on whether staged state is valid in -  #       every method. -  include Hbc::Staged -  include Hbc::Verify - -  attr_reader :force, :skip_cask_deps - -  PERSISTENT_METADATA_SUBDIRS = ["gpg"].freeze - -  def initialize(cask, command: Hbc::SystemCommand, force: false, skip_cask_deps: false, require_sha: false) -    @cask = cask -    @command = command -    @force = force -    @skip_cask_deps = skip_cask_deps -    @require_sha = require_sha -  end +module Hbc +  class Installer +    # TODO: it is unwise for Hbc::Staged to be a module, when we are +    #       dealing with both staged and unstaged Casks here. This should +    #       either be a class which is only sometimes instantiated, or there +    #       should be explicit checks on whether staged state is valid in +    #       every method. +    include Staged +    include Verify + +    attr_reader :force, :skip_cask_deps + +    PERSISTENT_METADATA_SUBDIRS = ["gpg"].freeze + +    def initialize(cask, command: SystemCommand, force: false, skip_cask_deps: false, require_sha: false) +      @cask = cask +      @command = command +      @force = force +      @skip_cask_deps = skip_cask_deps +      @require_sha = require_sha +    end -  def self.print_caveats(cask) -    odebug "Printing caveats" -    unless cask.caveats.empty? -      output = capture_output do -        cask.caveats.each do |caveat| -          if caveat.respond_to?(:eval_and_print) -            caveat.eval_and_print(cask) -          else -            puts caveat +    def self.print_caveats(cask) +      odebug "Printing caveats" +      unless cask.caveats.empty? +        output = capture_output do +          cask.caveats.each do |caveat| +            if caveat.respond_to?(:eval_and_print) +              caveat.eval_and_print(cask) +            else +              puts caveat +            end            end          end -      end -      unless output.empty? -        ohai "Caveats" -        puts output +        unless output.empty? +          ohai "Caveats" +          puts output +        end        end      end -  end - -  def self.capture_output(&block) -    old_stdout = $stdout -    $stdout = Buffer.new($stdout.tty?) -    block.call -    output = $stdout.string -    $stdout = old_stdout -    output -  end -  def install -    odebug "Hbc::Installer.install" - -    if @cask.installed? && @cask.auto_updates && !force -      raise Hbc::CaskAutoUpdatesError, @cask +    def self.capture_output(&block) +      old_stdout = $stdout +      $stdout = Buffer.new($stdout.tty?) +      block.call +      output = $stdout.string +      $stdout = old_stdout +      output      end -    raise Hbc::CaskAlreadyInstalledError, @cask if @cask.installed? && !force +    def install +      odebug "Hbc::Installer.install" + +      if @cask.installed? && @cask.auto_updates && !force +        raise CaskAutoUpdatesError, @cask +      end -    print_caveats +      raise CaskAlreadyInstalledError, @cask if @cask.installed? && !force + +      print_caveats + +      begin +        satisfy_dependencies +        verify_has_sha if @require_sha && !@force +        download +        verify +        extract_primary_container +        install_artifacts +        save_caskfile +        enable_accessibility_access +      rescue StandardError => e +        purge_versioned_files +        raise e +      end -    begin -      satisfy_dependencies -      verify_has_sha if @require_sha && !@force -      download -      verify -      extract_primary_container -      install_artifacts -      save_caskfile -      enable_accessibility_access -    rescue StandardError => e -      purge_versioned_files -      raise e +      puts summary      end -    puts summary -  end - -  def summary -    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} " -        end -    s << "#{@cask} was successfully installed!" -  end +    def summary +      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} " +          end +      s << "#{@cask} was successfully installed!" +    end -  def download -    odebug "Downloading" -    download = Hbc::Download.new(@cask, force: false) -    @downloaded_path = download.perform -    odebug "Downloaded to -> #{@downloaded_path}" -    @downloaded_path -  end +    def download +      odebug "Downloading" +      download = Download.new(@cask, force: false) +      @downloaded_path = download.perform +      odebug "Downloaded to -> #{@downloaded_path}" +      @downloaded_path +    end -  def verify_has_sha -    odebug "Checking cask has checksum" -    return unless @cask.sha256 == :no_check -    raise Hbc::CaskNoShasumError, @cask -  end +    def verify_has_sha +      odebug "Checking cask has checksum" +      return unless @cask.sha256 == :no_check +      raise CaskNoShasumError, @cask +    end -  def verify -    Hbc::Verify.all(@cask, @downloaded_path) -  end +    def verify +      Verify.all(@cask, @downloaded_path) +    end -  def extract_primary_container -    odebug "Extracting primary container" -    FileUtils.mkdir_p @cask.staged_path -    container = if @cask.container && @cask.container.type -                  Hbc::Container.from_type(@cask.container.type) -                else -                  Hbc::Container.for_path(@downloaded_path, @command) -                end -    unless container -      raise Hbc::CaskError, "Uh oh, could not figure out how to unpack '#{@downloaded_path}'" +    def extract_primary_container +      odebug "Extracting primary container" +      FileUtils.mkdir_p @cask.staged_path +      container = if @cask.container && @cask.container.type +                    Container.from_type(@cask.container.type) +                  else +                    Container.for_path(@downloaded_path, @command) +                  end +      unless container +        raise CaskError, "Uh oh, could not figure out how to unpack '#{@downloaded_path}'" +      end +      odebug "Using container class #{container} for #{@downloaded_path}" +      container.new(@cask, @downloaded_path, @command).extract      end -    odebug "Using container class #{container} for #{@downloaded_path}" -    container.new(@cask, @downloaded_path, @command).extract -  end -  def install_artifacts -    odebug "Installing artifacts" -    artifacts = Hbc::Artifact.for_cask(@cask) -    odebug "#{artifacts.length} artifact/s defined", artifacts -    artifacts.each do |artifact| -      odebug "Installing artifact of class #{artifact}" -      options = { command: @command, force: force } -      artifact.new(@cask, options).install_phase +    def install_artifacts +      odebug "Installing artifacts" +      artifacts = Artifact.for_cask(@cask) +      odebug "#{artifacts.length} artifact/s defined", artifacts +      artifacts.each do |artifact| +        odebug "Installing artifact of class #{artifact}" +        options = { command: @command, force: force } +        artifact.new(@cask, options).install_phase +      end      end -  end -  # TODO: move dependencies to a separate class -  #       dependencies should also apply for "brew cask stage" -  #       override dependencies with --force or perhaps --force-deps -  def satisfy_dependencies -    if @cask.depends_on +    # TODO: move dependencies to a separate class +    #       dependencies should also apply for "brew cask stage" +    #       override dependencies with --force or perhaps --force-deps +    def satisfy_dependencies +      return unless @cask.depends_on +        ohai "Satisfying dependencies"        macos_dependencies        arch_dependencies @@ -148,195 +150,200 @@ class Hbc::Installer        cask_dependencies unless skip_cask_deps        puts "complete"      end -  end -  def macos_dependencies -    return unless @cask.depends_on.macos -    if @cask.depends_on.macos.first.is_a?(Array) -      operator, release = @cask.depends_on.macos.first -      unless MacOS.version.send(operator, release) -        raise Hbc::CaskError, "Cask #{@cask} depends on macOS release #{operator} #{release}, but you are running release #{MacOS.version}." -      end -    elsif @cask.depends_on.macos.length > 1 -      unless @cask.depends_on.macos.include?(Gem::Version.new(MacOS.version.to_s)) -        raise Hbc::CaskError, "Cask #{@cask} depends on macOS release being one of [#{@cask.depends_on.macos.map(&:to_s).join(', ')}], but you are running release #{MacOS.version}." -      end -    else -      unless MacOS.version == @cask.depends_on.macos.first -        raise Hbc::CaskError, "Cask #{@cask} depends on macOS release #{@cask.depends_on.macos.first}, but you are running release #{MacOS.version}." +    def macos_dependencies +      return unless @cask.depends_on.macos +      if @cask.depends_on.macos.first.is_a?(Array) +        operator, release = @cask.depends_on.macos.first +        unless MacOS.version.send(operator, release) +          raise CaskError, "Cask #{@cask} depends on macOS release #{operator} #{release}, but you are running release #{MacOS.version}." +        end +      elsif @cask.depends_on.macos.length > 1 +        unless @cask.depends_on.macos.include?(Gem::Version.new(MacOS.version.to_s)) +          raise CaskError, "Cask #{@cask} depends on macOS release being one of [#{@cask.depends_on.macos.map(&:to_s).join(", ")}], but you are running release #{MacOS.version}." +        end +      else +        unless MacOS.version == @cask.depends_on.macos.first +          raise CaskError, "Cask #{@cask} depends on macOS release #{@cask.depends_on.macos.first}, but you are running release #{MacOS.version}." +        end        end      end -  end -  def arch_dependencies -    return if @cask.depends_on.arch.nil? -    @current_arch ||= { type: Hardware::CPU.type, bits: Hardware::CPU.bits } -    return if @cask.depends_on.arch.any? { |arch| -      arch[:type] == @current_arch[:type] && -      Array(arch[:bits]).include?(@current_arch[:bits]) -    } -    raise Hbc::CaskError, "Cask #{@cask} depends on hardware architecture being one of [#{@cask.depends_on.arch.map(&:to_s).join(', ')}], but you are running #{@current_arch}" -  end +    def arch_dependencies +      return if @cask.depends_on.arch.nil? +      @current_arch ||= { type: Hardware::CPU.type, bits: Hardware::CPU.bits } +      return if @cask.depends_on.arch.any? { |arch| +        arch[:type] == @current_arch[:type] && +        Array(arch[:bits]).include?(@current_arch[:bits]) +      } +      raise CaskError, "Cask #{@cask} depends on hardware architecture being one of [#{@cask.depends_on.arch.map(&:to_s).join(", ")}], but you are running #{@current_arch}" +    end -  def x11_dependencies -    return unless @cask.depends_on.x11 -    raise Hbc::CaskX11DependencyError, @cask.token if Hbc.x11_libpng.select(&:exist?).empty? -  end +    def x11_dependencies +      return unless @cask.depends_on.x11 +      raise CaskX11DependencyError, @cask.token if Hbc.x11_libpng.select(&:exist?).empty? +    end -  def formula_dependencies -    return unless @cask.depends_on.formula && !@cask.depends_on.formula.empty? -    ohai "Installing Formula dependencies from Homebrew" -    @cask.depends_on.formula.each do |dep_name| -      print "#{dep_name} ... " -      installed = @command.run(Hbc.homebrew_executable, -                               args:         ["list", "--versions", dep_name], -                               print_stderr: false).stdout.include?(dep_name) -      if installed -        puts "already installed" -      else -        @command.run!(Hbc.homebrew_executable, -                      args: ["install", dep_name]) -        puts "done" +    def formula_dependencies +      return unless @cask.depends_on.formula && !@cask.depends_on.formula.empty? +      ohai "Installing Formula dependencies from Homebrew" +      @cask.depends_on.formula.each do |dep_name| +        print "#{dep_name} ... " +        installed = @command.run(Hbc.homebrew_executable, +                                 args:         ["list", "--versions", dep_name], +                                 print_stderr: false).stdout.include?(dep_name) +        if installed +          puts "already installed" +        else +          @command.run!(Hbc.homebrew_executable, +                        args: ["install", dep_name]) +          puts "done" +        end        end      end -  end -  def cask_dependencies -    return unless @cask.depends_on.cask && !@cask.depends_on.cask.empty? -    ohai "Installing Cask dependencies: #{@cask.depends_on.cask.join(', ')}" -    deps = Hbc::CaskDependencies.new(@cask) -    deps.sorted.each do |dep_token| -      puts "#{dep_token} ..." -      dep = Hbc.load(dep_token) -      if dep.installed? -        puts "already installed" -      else -        Hbc::Installer.new(dep, force: false, skip_cask_deps: true).install -        puts "done" +    def cask_dependencies +      return unless @cask.depends_on.cask && !@cask.depends_on.cask.empty? +      ohai "Installing Cask dependencies: #{@cask.depends_on.cask.join(", ")}" +      deps = CaskDependencies.new(@cask) +      deps.sorted.each do |dep_token| +        puts "#{dep_token} ..." +        dep = Hbc.load(dep_token) +        if dep.installed? +          puts "already installed" +        else +          Installer.new(dep, force: false, skip_cask_deps: true).install +          puts "done" +        end        end      end -  end -  def print_caveats -    self.class.print_caveats(@cask) -  end +    def print_caveats +      self.class.print_caveats(@cask) +    end -  # TODO: logically could be in a separate class -  def enable_accessibility_access -    return unless @cask.accessibility_access -    ohai "Enabling accessibility access" -    if MacOS.version <= :mountain_lion -      @command.run!("/usr/bin/touch", -                    args: [Hbc.pre_mavericks_accessibility_dotfile], -                    sudo: true) -    elsif MacOS.version <= :yosemite -      @command.run!("/usr/bin/sqlite3", -                    args: [ -                            Hbc.tcc_db, -                            "INSERT OR REPLACE INTO access VALUES('kTCCServiceAccessibility','#{bundle_identifier}',0,1,1,NULL);", -                          ], -                    sudo: true) -    else -      @command.run!("/usr/bin/sqlite3", -                    args: [ -                            Hbc.tcc_db, -                            "INSERT OR REPLACE INTO access VALUES('kTCCServiceAccessibility','#{bundle_identifier}',0,1,1,NULL,NULL);", -                          ], -                    sudo: true) +    # TODO: logically could be in a separate class +    def enable_accessibility_access +      return unless @cask.accessibility_access +      ohai "Enabling accessibility access" +      if MacOS.version <= :mountain_lion +        @command.run!("/usr/bin/touch", +                      args: [Hbc.pre_mavericks_accessibility_dotfile], +                      sudo: true) +      elsif MacOS.version <= :yosemite +        @command.run!("/usr/bin/sqlite3", +                      args: [ +                              Hbc.tcc_db, +                              "INSERT OR REPLACE INTO access VALUES('kTCCServiceAccessibility','#{bundle_identifier}',0,1,1,NULL);", +                            ], +                      sudo: true) +      elsif MacOS.version <= :el_capitan +        @command.run!("/usr/bin/sqlite3", +                      args: [ +                              Hbc.tcc_db, +                              "INSERT OR REPLACE INTO access VALUES('kTCCServiceAccessibility','#{bundle_identifier}',0,1,1,NULL,NULL);", +                            ], +                      sudo: true) +      else +        opoo <<-EOS.undent +          Accessibility access cannot be enabled automatically on this version of macOS. +          See System Preferences to enable it manually. +        EOS +      end      end -  end -  def disable_accessibility_access -    return unless @cask.accessibility_access -    if MacOS.version >= :mavericks -      ohai "Disabling accessibility access" -      @command.run!("/usr/bin/sqlite3", -                    args: [ -                            Hbc.tcc_db, -                            "DELETE FROM access WHERE client='#{bundle_identifier}';", -                          ], -                    sudo: true) -    else -      opoo <<-EOS.undent -        Accessibility access was enabled for #{@cask}, but it is not safe to disable -        automatically on this version of macOS.  See System Preferences. -      EOS +    def disable_accessibility_access +      return unless @cask.accessibility_access +      if MacOS.version >= :mavericks && MacOS.version <= :el_capitan +        ohai "Disabling accessibility access" +        @command.run!("/usr/bin/sqlite3", +                      args: [ +                              Hbc.tcc_db, +                              "DELETE FROM access WHERE client='#{bundle_identifier}';", +                            ], +                      sudo: true) +      else +        opoo <<-EOS.undent +          Accessibility access cannot be disabled automatically on this version of macOS. +          See System Preferences to disable it manually. +        EOS +      end      end -  end -  def save_caskfile -    timestamp = :now -    create    = true -    savedir   = @cask.metadata_subdir("Casks", timestamp, create) -    if Dir.entries(savedir).size > 2 -      # should not happen -      raise Hbc::CaskAlreadyInstalledError, @cask unless force -      savedir.rmtree -      FileUtils.mkdir_p savedir +    def save_caskfile +      timestamp = :now +      create    = true +      savedir   = @cask.metadata_subdir("Casks", timestamp, create) +      if Dir.entries(savedir).size > 2 +        # should not happen +        raise CaskAlreadyInstalledError, @cask unless force +        savedir.rmtree +        FileUtils.mkdir_p savedir +      end +      FileUtils.copy(@cask.sourcefile_path, savedir) if @cask.sourcefile_path      end -    FileUtils.copy(@cask.sourcefile_path, savedir) if @cask.sourcefile_path -  end -  def uninstall -    odebug "Hbc::Installer.uninstall" -    disable_accessibility_access -    uninstall_artifacts -    purge_versioned_files -    purge_caskroom_path if force -  end +    def uninstall +      odebug "Hbc::Installer.uninstall" +      disable_accessibility_access +      uninstall_artifacts +      purge_versioned_files +      purge_caskroom_path if force +    end -  def uninstall_artifacts -    odebug "Un-installing artifacts" -    artifacts = Hbc::Artifact.for_cask(@cask) -    odebug "#{artifacts.length} artifact/s defined", artifacts -    artifacts.each do |artifact| -      odebug "Un-installing artifact of class #{artifact}" -      options = { command: @command, force: force } -      artifact.new(@cask, options).uninstall_phase +    def uninstall_artifacts +      odebug "Un-installing artifacts" +      artifacts = Artifact.for_cask(@cask) +      odebug "#{artifacts.length} artifact/s defined", artifacts +      artifacts.each do |artifact| +        odebug "Un-installing artifact of class #{artifact}" +        options = { command: @command, force: force } +        artifact.new(@cask, options).uninstall_phase +      end      end -  end -  def zap -    ohai %Q{Implied "brew cask uninstall #{@cask}"} -    uninstall_artifacts -    if Hbc::Artifact::Zap.me?(@cask) -      ohai "Dispatching zap stanza" -      Hbc::Artifact::Zap.new(@cask, command: @command).zap_phase -    else -      opoo "No zap stanza present for Cask '#{@cask}'" +    def zap +      ohai %Q{Implied "brew cask uninstall #{@cask}"} +      uninstall_artifacts +      if Artifact::Zap.me?(@cask) +        ohai "Dispatching zap stanza" +        Artifact::Zap.new(@cask, command: @command).zap_phase +      else +        opoo "No zap stanza present for Cask '#{@cask}'" +      end +      ohai "Removing all staged versions of Cask '#{@cask}'" +      purge_caskroom_path      end -    ohai "Removing all staged versions of Cask '#{@cask}'" -    purge_caskroom_path -  end -  def gain_permissions_remove(path) -    Hbc::Utils.gain_permissions_remove(path, command: @command) -  end +    def gain_permissions_remove(path) +      Utils.gain_permissions_remove(path, command: @command) +    end -  def purge_versioned_files -    odebug "Purging files for version #{@cask.version} of Cask #{@cask}" +    def purge_versioned_files +      odebug "Purging files for version #{@cask.version} of Cask #{@cask}" -    # versioned staged distribution -    gain_permissions_remove(@cask.staged_path) if !@cask.staged_path.nil? && @cask.staged_path.exist? +      # versioned staged distribution +      gain_permissions_remove(@cask.staged_path) if !@cask.staged_path.nil? && @cask.staged_path.exist? -    # Homebrew-Cask metadata -    if @cask.metadata_versioned_container_path.respond_to?(:children) && -       @cask.metadata_versioned_container_path.exist? -      @cask.metadata_versioned_container_path.children.each do |subdir| -        unless PERSISTENT_METADATA_SUBDIRS.include?(subdir.basename) -          gain_permissions_remove(subdir) +      # Homebrew-Cask metadata +      if @cask.metadata_versioned_container_path.respond_to?(:children) && +         @cask.metadata_versioned_container_path.exist? +        @cask.metadata_versioned_container_path.children.each do |subdir| +          unless PERSISTENT_METADATA_SUBDIRS.include?(subdir.basename) +            gain_permissions_remove(subdir) +          end          end        end -    end -    @cask.metadata_versioned_container_path.rmdir_if_possible -    @cask.metadata_master_container_path.rmdir_if_possible +      @cask.metadata_versioned_container_path.rmdir_if_possible +      @cask.metadata_master_container_path.rmdir_if_possible -    # toplevel staged distribution -    @cask.caskroom_path.rmdir_if_possible -  end +      # toplevel staged distribution +      @cask.caskroom_path.rmdir_if_possible +    end -  def purge_caskroom_path -    odebug "Purging all staged versions of Cask #{@cask}" -    gain_permissions_remove(@cask.caskroom_path) +    def purge_caskroom_path +      odebug "Purging all staged versions of Cask #{@cask}" +      gain_permissions_remove(@cask.caskroom_path) +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/locations.rb b/Library/Homebrew/cask/lib/hbc/locations.rb index 5e18ba8fe..32c95413c 100644 --- a/Library/Homebrew/cask/lib/hbc/locations.rb +++ b/Library/Homebrew/cask/lib/hbc/locations.rb @@ -1,196 +1,198 @@ -module Hbc::Locations -  def self.included(base) -    base.extend(ClassMethods) -  end - -  module ClassMethods -    def legacy_caskroom -      @legacy_caskroom ||= Pathname.new("/opt/homebrew-cask/Caskroom") +module Hbc +  module Locations +    def self.included(base) +      base.extend(ClassMethods)      end -    def default_caskroom -      @default_caskroom ||= homebrew_prefix.join("Caskroom") -    end +    module ClassMethods +      def legacy_caskroom +        @legacy_caskroom ||= Pathname.new("/opt/homebrew-cask/Caskroom") +      end -    def caskroom -      @caskroom ||= begin -        if Hbc::Utils.path_occupied?(legacy_caskroom) -          opoo <<-EOS.undent -            The default Caskroom location has moved to #{default_caskroom}. +      def default_caskroom +        @default_caskroom ||= homebrew_prefix.join("Caskroom") +      end -            Please migrate your Casks to the new location and delete #{legacy_caskroom}, -            or if you would like to keep your Caskroom at #{legacy_caskroom}, add the -            following to your HOMEBREW_CASK_OPTS: +      def caskroom +        @caskroom ||= begin +          if Utils.path_occupied?(legacy_caskroom) +            opoo <<-EOS.undent +              The default Caskroom location has moved to #{default_caskroom}. -              --caskroom=#{legacy_caskroom} +              Please migrate your Casks to the new location and delete #{legacy_caskroom}, +              or if you would like to keep your Caskroom at #{legacy_caskroom}, add the +              following to your HOMEBREW_CASK_OPTS: -            For more details on each of those options, see https://github.com/caskroom/homebrew-cask/issues/21913. -          EOS -          legacy_caskroom -        else -          default_caskroom +                --caskroom=#{legacy_caskroom} + +              For more details on each of those options, see https://github.com/caskroom/homebrew-cask/issues/21913. +            EOS +            legacy_caskroom +          else +            default_caskroom +          end          end        end -    end -    def caskroom=(caskroom) -      @caskroom = caskroom -    end +      def caskroom=(caskroom) +        @caskroom = caskroom +      end -    def legacy_cache -      @legacy_cache ||= homebrew_cache.join("Casks") -    end +      def legacy_cache +        @legacy_cache ||= homebrew_cache.join("Casks") +      end -    def cache -      @cache ||= homebrew_cache.join("Cask") -    end +      def cache +        @cache ||= homebrew_cache.join("Cask") +      end -    attr_writer :appdir +      attr_writer :appdir -    def appdir -      @appdir ||= Pathname.new("/Applications").expand_path -    end +      def appdir +        @appdir ||= Pathname.new("/Applications").expand_path +      end -    attr_writer :prefpanedir +      attr_writer :prefpanedir -    def prefpanedir -      @prefpanedir ||= Pathname.new("~/Library/PreferencePanes").expand_path -    end +      def prefpanedir +        @prefpanedir ||= Pathname.new("~/Library/PreferencePanes").expand_path +      end -    attr_writer :qlplugindir +      attr_writer :qlplugindir -    def qlplugindir -      @qlplugindir ||= Pathname.new("~/Library/QuickLook").expand_path -    end +      def qlplugindir +        @qlplugindir ||= Pathname.new("~/Library/QuickLook").expand_path +      end -    attr_writer :fontdir +      attr_writer :fontdir -    def fontdir -      @fontdir ||= Pathname.new("~/Library/Fonts").expand_path -    end +      def fontdir +        @fontdir ||= Pathname.new("~/Library/Fonts").expand_path +      end -    attr_writer :colorpickerdir +      attr_writer :colorpickerdir -    def colorpickerdir -      @colorpickerdir ||= Pathname.new("~/Library/ColorPickers").expand_path -    end +      def colorpickerdir +        @colorpickerdir ||= Pathname.new("~/Library/ColorPickers").expand_path +      end -    attr_writer :servicedir +      attr_writer :servicedir -    def servicedir -      @servicedir ||= Pathname.new("~/Library/Services").expand_path -    end +      def servicedir +        @servicedir ||= Pathname.new("~/Library/Services").expand_path +      end -    attr_writer :binarydir +      attr_writer :binarydir -    def binarydir -      @binarydir ||= homebrew_prefix.join("bin") -    end +      def binarydir +        @binarydir ||= homebrew_prefix.join("bin") +      end -    attr_writer :input_methoddir +      attr_writer :input_methoddir -    def input_methoddir -      @input_methoddir ||= Pathname.new("~/Library/Input Methods").expand_path -    end +      def input_methoddir +        @input_methoddir ||= Pathname.new("~/Library/Input Methods").expand_path +      end -    attr_writer :internet_plugindir +      attr_writer :internet_plugindir -    def internet_plugindir -      @internet_plugindir ||= Pathname.new("~/Library/Internet Plug-Ins").expand_path -    end +      def internet_plugindir +        @internet_plugindir ||= Pathname.new("~/Library/Internet Plug-Ins").expand_path +      end -    attr_writer :audio_unit_plugindir +      attr_writer :audio_unit_plugindir -    def audio_unit_plugindir -      @audio_unit_plugindir ||= Pathname.new("~/Library/Audio/Plug-Ins/Components").expand_path -    end +      def audio_unit_plugindir +        @audio_unit_plugindir ||= Pathname.new("~/Library/Audio/Plug-Ins/Components").expand_path +      end -    attr_writer :vst_plugindir +      attr_writer :vst_plugindir -    def vst_plugindir -      @vst_plugindir ||= Pathname.new("~/Library/Audio/Plug-Ins/VST").expand_path -    end +      def vst_plugindir +        @vst_plugindir ||= Pathname.new("~/Library/Audio/Plug-Ins/VST").expand_path +      end -    attr_writer :vst3_plugindir +      attr_writer :vst3_plugindir -    def vst3_plugindir -      @vst3_plugindir ||= Pathname.new("~/Library/Audio/Plug-Ins/VST3").expand_path -    end +      def vst3_plugindir +        @vst3_plugindir ||= Pathname.new("~/Library/Audio/Plug-Ins/VST3").expand_path +      end -    attr_writer :screen_saverdir +      attr_writer :screen_saverdir -    def screen_saverdir -      @screen_saverdir ||= Pathname.new("~/Library/Screen Savers").expand_path -    end +      def screen_saverdir +        @screen_saverdir ||= Pathname.new("~/Library/Screen Savers").expand_path +      end -    attr_writer :default_tap +      attr_writer :default_tap -    def default_tap -      @default_tap ||= Tap.fetch("caskroom", "homebrew-cask") -    end +      def default_tap +        @default_tap ||= Tap.fetch("caskroom", "homebrew-cask") +      end -    def path(query) -      query = query.sub(%r{\.rb$}i, "") -      token_with_tap = if query.include?("/") -                         query -                       else -                         all_tokens.detect do |tap_and_token| -                           tap_and_token.split("/")[2] == query +      def path(query) +        query = query.sub(%r{\.rb$}i, "") +        token_with_tap = if query.include?("/") +                           query +                         else +                           all_tokens.detect do |tap_and_token| +                             tap_and_token.split("/")[2] == query +                           end                           end -                       end -      if token_with_tap -        user, repo, token = token_with_tap.split("/") -        Tap.fetch(user, repo).cask_dir.join("#{token}.rb") -      else -        default_tap.cask_dir.join("#{query}.rb") +        if token_with_tap +          user, repo, token = token_with_tap.split("/") +          Tap.fetch(user, repo).cask_dir.join("#{token}.rb") +        else +          default_tap.cask_dir.join("#{query}.rb") +        end        end -    end -    def tcc_db -      @tcc_db ||= Pathname.new("/Library/Application Support/com.apple.TCC/TCC.db") -    end +      def tcc_db +        @tcc_db ||= Pathname.new("/Library/Application Support/com.apple.TCC/TCC.db") +      end -    def pre_mavericks_accessibility_dotfile -      @pre_mavericks_accessibility_dotfile ||= Pathname.new("/private/var/db/.AccessibilityAPIEnabled") -    end +      def pre_mavericks_accessibility_dotfile +        @pre_mavericks_accessibility_dotfile ||= Pathname.new("/private/var/db/.AccessibilityAPIEnabled") +      end -    def x11_executable -      @x11_executable ||= Pathname.new("/usr/X11/bin/X") -    end +      def x11_executable +        @x11_executable ||= Pathname.new("/usr/X11/bin/X") +      end -    def x11_libpng -      @x11_libpng ||= [Pathname.new("/opt/X11/lib/libpng.dylib"), Pathname.new("/usr/X11/lib/libpng.dylib")] -    end +      def x11_libpng +        @x11_libpng ||= [Pathname.new("/opt/X11/lib/libpng.dylib"), Pathname.new("/usr/X11/lib/libpng.dylib")] +      end -    def homebrew_cache -      @homebrew_cache ||= HOMEBREW_CACHE -    end +      def homebrew_cache +        @homebrew_cache ||= HOMEBREW_CACHE +      end -    def homebrew_cache=(path) -      @homebrew_cache = path ? Pathname.new(path) : path -    end +      def homebrew_cache=(path) +        @homebrew_cache = path ? Pathname.new(path) : path +      end -    def homebrew_executable -      @homebrew_executable ||= HOMEBREW_BREW_FILE -    end +      def homebrew_executable +        @homebrew_executable ||= HOMEBREW_BREW_FILE +      end -    def homebrew_prefix -      # where Homebrew links -      @homebrew_prefix ||= HOMEBREW_PREFIX -    end +      def homebrew_prefix +        # where Homebrew links +        @homebrew_prefix ||= HOMEBREW_PREFIX +      end -    def homebrew_prefix=(path) -      @homebrew_prefix = path ? Pathname.new(path) : path -    end +      def homebrew_prefix=(path) +        @homebrew_prefix = path ? Pathname.new(path) : path +      end -    def homebrew_repository -      # where Homebrew's .git dir is found -      @homebrew_repository ||= HOMEBREW_REPOSITORY -    end +      def homebrew_repository +        # where Homebrew's .git dir is found +        @homebrew_repository ||= HOMEBREW_REPOSITORY +      end -    def homebrew_repository=(path) -      @homebrew_repository = path ? Pathname.new(path) : path +      def homebrew_repository=(path) +        @homebrew_repository = path ? Pathname.new(path) : path +      end      end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/macos.rb b/Library/Homebrew/cask/lib/hbc/macos.rb index 5e25c657e..fb15be108 100644 --- a/Library/Homebrew/cask/lib/hbc/macos.rb +++ b/Library/Homebrew/cask/lib/hbc/macos.rb @@ -2,377 +2,377 @@ require "set"  require "os/mac/version" -module OS::Mac -  SYSTEM_DIRS = [ -                  "/", -                  "/Applications", -                  "/Applications/Utilities", -                  "/Incompatible Software", -                  "/Library", -                  "/Library/Application Support", -                  "/Library/Audio", -                  "/Library/Caches", -                  "/Library/ColorPickers", -                  "/Library/ColorSync", -                  "/Library/Components", -                  "/Library/Compositions", -                  "/Library/Contextual Menu Items", -                  "/Library/CoreMediaIO", -                  "/Library/Desktop Pictures", -                  "/Library/Developer", -                  "/Library/Dictionaries", -                  "/Library/DirectoryServices", -                  "/Library/Documentation", -                  "/Library/Extensions", -                  "/Library/Filesystems", -                  "/Library/Fonts", -                  "/Library/Frameworks", -                  "/Library/Graphics", -                  "/Library/Image Capture", -                  "/Library/Input Methods", -                  "/Library/Internet Plug-Ins", -                  "/Library/Java", -                  "/Library/Keyboard Layouts", -                  "/Library/Keychains", -                  "/Library/LaunchAgents", -                  "/Library/LaunchDaemons", -                  "/Library/Logs", -                  "/Library/Messages", -                  "/Library/Modem Scripts", -                  "/Library/OpenDirectory", -                  "/Library/PDF Services", -                  "/Library/Perl", -                  "/Library/PreferencePanes", -                  "/Library/Preferences", -                  "/Library/Printers", -                  "/Library/PrivilegedHelperTools", -                  "/Library/Python", -                  "/Library/QuickLook", -                  "/Library/QuickTime", -                  "/Library/Receipts", -                  "/Library/Ruby", -                  "/Library/Sandbox", -                  "/Library/Screen Savers", -                  "/Library/ScriptingAdditions", -                  "/Library/Scripts", -                  "/Library/Security", -                  "/Library/Speech", -                  "/Library/Spelling", -                  "/Library/Spotlight", -                  "/Library/StartupItems", -                  "/Library/SystemProfiler", -                  "/Library/Updates", -                  "/Library/User Pictures", -                  "/Library/Video", -                  "/Library/WebServer", -                  "/Library/Widgets", -                  "/Library/iTunes", -                  "/Network", -                  "/System", -                  "/System/Library", -                  "/System/Library/Accessibility", -                  "/System/Library/Accounts", -                  "/System/Library/Address Book Plug-Ins", -                  "/System/Library/Assistant", -                  "/System/Library/Automator", -                  "/System/Library/BridgeSupport", -                  "/System/Library/Caches", -                  "/System/Library/ColorPickers", -                  "/System/Library/ColorSync", -                  "/System/Library/Colors", -                  "/System/Library/Components", -                  "/System/Library/Compositions", -                  "/System/Library/CoreServices", -                  "/System/Library/DTDs", -                  "/System/Library/DirectoryServices", -                  "/System/Library/Displays", -                  "/System/Library/Extensions", -                  "/System/Library/Filesystems", -                  "/System/Library/Filters", -                  "/System/Library/Fonts", -                  "/System/Library/Frameworks", -                  "/System/Library/Graphics", -                  "/System/Library/IdentityServices", -                  "/System/Library/Image Capture", -                  "/System/Library/Input Methods", -                  "/System/Library/InternetAccounts", -                  "/System/Library/Java", -                  "/System/Library/KerberosPlugins", -                  "/System/Library/Keyboard Layouts", -                  "/System/Library/Keychains", -                  "/System/Library/LaunchAgents", -                  "/System/Library/LaunchDaemons", -                  "/System/Library/LinguisticData", -                  "/System/Library/LocationBundles", -                  "/System/Library/LoginPlugins", -                  "/System/Library/Messages", -                  "/System/Library/Metadata", -                  "/System/Library/MonitorPanels", -                  "/System/Library/OpenDirectory", -                  "/System/Library/OpenSSL", -                  "/System/Library/Password Server Filters", -                  "/System/Library/PerformanceMetrics", -                  "/System/Library/Perl", -                  "/System/Library/PreferencePanes", -                  "/System/Library/Printers", -                  "/System/Library/PrivateFrameworks", -                  "/System/Library/QuickLook", -                  "/System/Library/QuickTime", -                  "/System/Library/QuickTimeJava", -                  "/System/Library/Recents", -                  "/System/Library/SDKSettingsPlist", -                  "/System/Library/Sandbox", -                  "/System/Library/Screen Savers", -                  "/System/Library/ScreenReader", -                  "/System/Library/ScriptingAdditions", -                  "/System/Library/ScriptingDefinitions", -                  "/System/Library/Security", -                  "/System/Library/Services", -                  "/System/Library/Sounds", -                  "/System/Library/Speech", -                  "/System/Library/Spelling", -                  "/System/Library/Spotlight", -                  "/System/Library/StartupItems", -                  "/System/Library/SyncServices", -                  "/System/Library/SystemConfiguration", -                  "/System/Library/SystemProfiler", -                  "/System/Library/Tcl", -                  "/System/Library/TextEncodings", -                  "/System/Library/User Template", -                  "/System/Library/UserEventPlugins", -                  "/System/Library/Video", -                  "/System/Library/WidgetResources", -                  "/User Information", -                  "/Users", -                  "/Volumes", -                  "/bin", -                  "/boot", -                  "/cores", -                  "/dev", -                  "/etc", -                  "/etc/X11", -                  "/etc/opt", -                  "/etc/sgml", -                  "/etc/xml", -                  "/home", -                  "/libexec", -                  "/lost+found", -                  "/media", -                  "/mnt", -                  "/net", -                  "/opt", -                  "/private", -                  "/private/etc", -                  "/private/tftpboot", -                  "/private/tmp", -                  "/private/var", -                  "/proc", -                  "/root", -                  "/sbin", -                  "/srv", -                  "/tmp", -                  "/usr", -                  "/usr/X11R6", -                  "/usr/bin", -                  "/usr/etc", -                  "/usr/include", -                  "/usr/lib", -                  "/usr/libexec", -                  "/usr/local", -                  "/usr/local/Cellar", -                  "/usr/local/Frameworks", -                  "/usr/local/Library", -                  "/usr/local/bin", -                  "/usr/local/etc", -                  "/usr/local/include", -                  "/usr/local/lib", -                  "/usr/local/libexec", -                  "/usr/local/opt", -                  "/usr/local/share", -                  "/usr/local/share/man", -                  "/usr/local/share/man/man1", -                  "/usr/local/share/man/man2", -                  "/usr/local/share/man/man3", -                  "/usr/local/share/man/man4", -                  "/usr/local/share/man/man5", -                  "/usr/local/share/man/man6", -                  "/usr/local/share/man/man7", -                  "/usr/local/share/man/man8", -                  "/usr/local/share/man/man9", -                  "/usr/local/share/man/mann", -                  "/usr/local/var", -                  "/usr/local/var/lib", -                  "/usr/local/var/lock", -                  "/usr/local/var/run", -                  "/usr/sbin", -                  "/usr/share", -                  "/usr/share/man", -                  "/usr/share/man/man1", -                  "/usr/share/man/man2", -                  "/usr/share/man/man3", -                  "/usr/share/man/man4", -                  "/usr/share/man/man5", -                  "/usr/share/man/man6", -                  "/usr/share/man/man7", -                  "/usr/share/man/man8", -                  "/usr/share/man/man9", -                  "/usr/share/man/mann", -                  "/usr/src", -                  "/var", -                  "/var/cache", -                  "/var/lib", -                  "/var/lock", -                  "/var/log", -                  "/var/mail", -                  "/var/run", -                  "/var/spool", -                  "/var/spool/mail", -                  "/var/tmp", -                ] -                .map(&method(:Pathname)) -                .to_set -                .freeze +module OS +  module Mac +    SYSTEM_DIRS = [ +                    "/", +                    "/Applications", +                    "/Applications/Utilities", +                    "/Incompatible Software", +                    "/Library", +                    "/Library/Application Support", +                    "/Library/Audio", +                    "/Library/Caches", +                    "/Library/ColorPickers", +                    "/Library/ColorSync", +                    "/Library/Components", +                    "/Library/Compositions", +                    "/Library/Contextual Menu Items", +                    "/Library/CoreMediaIO", +                    "/Library/Desktop Pictures", +                    "/Library/Developer", +                    "/Library/Dictionaries", +                    "/Library/DirectoryServices", +                    "/Library/Documentation", +                    "/Library/Extensions", +                    "/Library/Filesystems", +                    "/Library/Fonts", +                    "/Library/Frameworks", +                    "/Library/Graphics", +                    "/Library/Image Capture", +                    "/Library/Input Methods", +                    "/Library/Internet Plug-Ins", +                    "/Library/Java", +                    "/Library/Keyboard Layouts", +                    "/Library/Keychains", +                    "/Library/LaunchAgents", +                    "/Library/LaunchDaemons", +                    "/Library/Logs", +                    "/Library/Messages", +                    "/Library/Modem Scripts", +                    "/Library/OpenDirectory", +                    "/Library/PDF Services", +                    "/Library/Perl", +                    "/Library/PreferencePanes", +                    "/Library/Preferences", +                    "/Library/Printers", +                    "/Library/PrivilegedHelperTools", +                    "/Library/Python", +                    "/Library/QuickLook", +                    "/Library/QuickTime", +                    "/Library/Receipts", +                    "/Library/Ruby", +                    "/Library/Sandbox", +                    "/Library/Screen Savers", +                    "/Library/ScriptingAdditions", +                    "/Library/Scripts", +                    "/Library/Security", +                    "/Library/Speech", +                    "/Library/Spelling", +                    "/Library/Spotlight", +                    "/Library/StartupItems", +                    "/Library/SystemProfiler", +                    "/Library/Updates", +                    "/Library/User Pictures", +                    "/Library/Video", +                    "/Library/WebServer", +                    "/Library/Widgets", +                    "/Library/iTunes", +                    "/Network", +                    "/System", +                    "/System/Library", +                    "/System/Library/Accessibility", +                    "/System/Library/Accounts", +                    "/System/Library/Address Book Plug-Ins", +                    "/System/Library/Assistant", +                    "/System/Library/Automator", +                    "/System/Library/BridgeSupport", +                    "/System/Library/Caches", +                    "/System/Library/ColorPickers", +                    "/System/Library/ColorSync", +                    "/System/Library/Colors", +                    "/System/Library/Components", +                    "/System/Library/Compositions", +                    "/System/Library/CoreServices", +                    "/System/Library/DTDs", +                    "/System/Library/DirectoryServices", +                    "/System/Library/Displays", +                    "/System/Library/Extensions", +                    "/System/Library/Filesystems", +                    "/System/Library/Filters", +                    "/System/Library/Fonts", +                    "/System/Library/Frameworks", +                    "/System/Library/Graphics", +                    "/System/Library/IdentityServices", +                    "/System/Library/Image Capture", +                    "/System/Library/Input Methods", +                    "/System/Library/InternetAccounts", +                    "/System/Library/Java", +                    "/System/Library/KerberosPlugins", +                    "/System/Library/Keyboard Layouts", +                    "/System/Library/Keychains", +                    "/System/Library/LaunchAgents", +                    "/System/Library/LaunchDaemons", +                    "/System/Library/LinguisticData", +                    "/System/Library/LocationBundles", +                    "/System/Library/LoginPlugins", +                    "/System/Library/Messages", +                    "/System/Library/Metadata", +                    "/System/Library/MonitorPanels", +                    "/System/Library/OpenDirectory", +                    "/System/Library/OpenSSL", +                    "/System/Library/Password Server Filters", +                    "/System/Library/PerformanceMetrics", +                    "/System/Library/Perl", +                    "/System/Library/PreferencePanes", +                    "/System/Library/Printers", +                    "/System/Library/PrivateFrameworks", +                    "/System/Library/QuickLook", +                    "/System/Library/QuickTime", +                    "/System/Library/QuickTimeJava", +                    "/System/Library/Recents", +                    "/System/Library/SDKSettingsPlist", +                    "/System/Library/Sandbox", +                    "/System/Library/Screen Savers", +                    "/System/Library/ScreenReader", +                    "/System/Library/ScriptingAdditions", +                    "/System/Library/ScriptingDefinitions", +                    "/System/Library/Security", +                    "/System/Library/Services", +                    "/System/Library/Sounds", +                    "/System/Library/Speech", +                    "/System/Library/Spelling", +                    "/System/Library/Spotlight", +                    "/System/Library/StartupItems", +                    "/System/Library/SyncServices", +                    "/System/Library/SystemConfiguration", +                    "/System/Library/SystemProfiler", +                    "/System/Library/Tcl", +                    "/System/Library/TextEncodings", +                    "/System/Library/User Template", +                    "/System/Library/UserEventPlugins", +                    "/System/Library/Video", +                    "/System/Library/WidgetResources", +                    "/User Information", +                    "/Users", +                    "/Volumes", +                    "/bin", +                    "/boot", +                    "/cores", +                    "/dev", +                    "/etc", +                    "/etc/X11", +                    "/etc/opt", +                    "/etc/sgml", +                    "/etc/xml", +                    "/home", +                    "/libexec", +                    "/lost+found", +                    "/media", +                    "/mnt", +                    "/net", +                    "/opt", +                    "/private", +                    "/private/etc", +                    "/private/tftpboot", +                    "/private/tmp", +                    "/private/var", +                    "/proc", +                    "/root", +                    "/sbin", +                    "/srv", +                    "/tmp", +                    "/usr", +                    "/usr/X11R6", +                    "/usr/bin", +                    "/usr/etc", +                    "/usr/include", +                    "/usr/lib", +                    "/usr/libexec", +                    "/usr/local", +                    "/usr/local/Cellar", +                    "/usr/local/Frameworks", +                    "/usr/local/Library", +                    "/usr/local/bin", +                    "/usr/local/etc", +                    "/usr/local/include", +                    "/usr/local/lib", +                    "/usr/local/libexec", +                    "/usr/local/opt", +                    "/usr/local/share", +                    "/usr/local/share/man", +                    "/usr/local/share/man/man1", +                    "/usr/local/share/man/man2", +                    "/usr/local/share/man/man3", +                    "/usr/local/share/man/man4", +                    "/usr/local/share/man/man5", +                    "/usr/local/share/man/man6", +                    "/usr/local/share/man/man7", +                    "/usr/local/share/man/man8", +                    "/usr/local/share/man/man9", +                    "/usr/local/share/man/mann", +                    "/usr/local/var", +                    "/usr/local/var/lib", +                    "/usr/local/var/lock", +                    "/usr/local/var/run", +                    "/usr/sbin", +                    "/usr/share", +                    "/usr/share/man", +                    "/usr/share/man/man1", +                    "/usr/share/man/man2", +                    "/usr/share/man/man3", +                    "/usr/share/man/man4", +                    "/usr/share/man/man5", +                    "/usr/share/man/man6", +                    "/usr/share/man/man7", +                    "/usr/share/man/man8", +                    "/usr/share/man/man9", +                    "/usr/share/man/mann", +                    "/usr/src", +                    "/var", +                    "/var/cache", +                    "/var/lib", +                    "/var/lock", +                    "/var/log", +                    "/var/mail", +                    "/var/run", +                    "/var/spool", +                    "/var/spool/mail", +                    "/var/tmp", +                  ] +                  .map(&method(:Pathname)) +                  .to_set +                  .freeze -  # TODO: There should be a way to specify a containing -  #       directory under which nothing can be deleted. -  UNDELETABLE_DIRS = [ -                       "~/", -                       "~/Applications", -                       "~/Desktop", -                       "~/Documents", -                       "~/Downloads", -                       "~/Mail", -                       "~/Movies", -                       "~/Music", -                       "~/Music/iTunes", -                       "~/Music/iTunes/iTunes Music", -                       "~/Music/iTunes/Album Artwork", -                       "~/News", -                       "~/Pictures", -                       "~/Pictures/Desktops", -                       "~/Pictures/Photo Booth", -                       "~/Pictures/iChat Icons", -                       "~/Pictures/iPhoto Library", -                       "~/Public", -                       "~/Sites", -                       "~/Library", -                       "~/Library/.localized", -                       "~/Library/Accessibility", -                       "~/Library/Accounts", -                       "~/Library/Address Book Plug-Ins", -                       "~/Library/Application Scripts", -                       "~/Library/Application Support", -                       "~/Library/Application Support/Apple", -                       "~/Library/Application Support/com.apple.AssistiveControl", -                       "~/Library/Application Support/com.apple.QuickLook", -                       "~/Library/Application Support/com.apple.TCC", -                       "~/Library/Assistants", -                       "~/Library/Audio", -                       "~/Library/Automator", -                       "~/Library/Autosave Information", -                       "~/Library/Caches", -                       "~/Library/Calendars", -                       "~/Library/ColorPickers", -                       "~/Library/ColorSync", -                       "~/Library/Colors", -                       "~/Library/Components", -                       "~/Library/Compositions", -                       "~/Library/Containers", -                       "~/Library/Contextual Menu Items", -                       "~/Library/Cookies", -                       "~/Library/DTDs", -                       "~/Library/Desktop Pictures", -                       "~/Library/Developer", -                       "~/Library/Dictionaries", -                       "~/Library/DirectoryServices", -                       "~/Library/Displays", -                       "~/Library/Documentation", -                       "~/Library/Extensions", -                       "~/Library/Favorites", -                       "~/Library/FileSync", -                       "~/Library/Filesystems", -                       "~/Library/Filters", -                       "~/Library/FontCollections", -                       "~/Library/Fonts", -                       "~/Library/Frameworks", -                       "~/Library/GameKit", -                       "~/Library/Graphics", -                       "~/Library/Group Containers", -                       "~/Library/Icons", -                       "~/Library/IdentityServices", -                       "~/Library/Image Capture", -                       "~/Library/Images", -                       "~/Library/Input Methods", -                       "~/Library/Internet Plug-Ins", -                       "~/Library/InternetAccounts", -                       "~/Library/iTunes", -                       "~/Library/KeyBindings", -                       "~/Library/Keyboard Layouts", -                       "~/Library/Keychains", -                       "~/Library/LaunchAgents", -                       "~/Library/LaunchDaemons", -                       "~/Library/LocationBundles", -                       "~/Library/LoginPlugins", -                       "~/Library/Logs", -                       "~/Library/Mail", -                       "~/Library/Mail Downloads", -                       "~/Library/Messages", -                       "~/Library/Metadata", -                       "~/Library/Mobile Documents", -                       "~/Library/MonitorPanels", -                       "~/Library/OpenDirectory", -                       "~/Library/PDF Services", -                       "~/Library/PhonePlugins", -                       "~/Library/Phones", -                       "~/Library/PreferencePanes", -                       "~/Library/Preferences", -                       "~/Library/Printers", -                       "~/Library/PrivateFrameworks", -                       "~/Library/PubSub", -                       "~/Library/QuickLook", -                       "~/Library/QuickTime", -                       "~/Library/Receipts", -                       "~/Library/Recent Servers", -                       "~/Library/Recents", -                       "~/Library/Safari", -                       "~/Library/Saved Application State", -                       "~/Library/Screen Savers", -                       "~/Library/ScreenReader", -                       "~/Library/ScriptingAdditions", -                       "~/Library/ScriptingDefinitions", -                       "~/Library/Scripts", -                       "~/Library/Security", -                       "~/Library/Services", -                       "~/Library/Sounds", -                       "~/Library/Speech", -                       "~/Library/Spelling", -                       "~/Library/Spotlight", -                       "~/Library/StartupItems", -                       "~/Library/StickiesDatabase", -                       "~/Library/Sync Services", -                       "~/Library/SyncServices", -                       "~/Library/SyncedPreferences", -                       "~/Library/TextEncodings", -                       "~/Library/User Pictures", -                       "~/Library/Video", -                       "~/Library/Voices", -                       "~/Library/WebKit", -                       "~/Library/WidgetResources", -                       "~/Library/Widgets", -                       "~/Library/Workflows", -                     ] -                     .map { |x| Pathname(x.sub(%r{^~(?=(/|$))}, Dir.home)).expand_path } -                     .to_set -                     .union(SYSTEM_DIRS) -                     .freeze +    # TODO: There should be a way to specify a containing +    #       directory under which nothing can be deleted. +    UNDELETABLE_DIRS = [ +                         "~/", +                         "~/Applications", +                         "~/Desktop", +                         "~/Documents", +                         "~/Downloads", +                         "~/Mail", +                         "~/Movies", +                         "~/Music", +                         "~/Music/iTunes", +                         "~/Music/iTunes/iTunes Music", +                         "~/Music/iTunes/Album Artwork", +                         "~/News", +                         "~/Pictures", +                         "~/Pictures/Desktops", +                         "~/Pictures/Photo Booth", +                         "~/Pictures/iChat Icons", +                         "~/Pictures/iPhoto Library", +                         "~/Public", +                         "~/Sites", +                         "~/Library", +                         "~/Library/.localized", +                         "~/Library/Accessibility", +                         "~/Library/Accounts", +                         "~/Library/Address Book Plug-Ins", +                         "~/Library/Application Scripts", +                         "~/Library/Application Support", +                         "~/Library/Application Support/Apple", +                         "~/Library/Application Support/com.apple.AssistiveControl", +                         "~/Library/Application Support/com.apple.QuickLook", +                         "~/Library/Application Support/com.apple.TCC", +                         "~/Library/Assistants", +                         "~/Library/Audio", +                         "~/Library/Automator", +                         "~/Library/Autosave Information", +                         "~/Library/Caches", +                         "~/Library/Calendars", +                         "~/Library/ColorPickers", +                         "~/Library/ColorSync", +                         "~/Library/Colors", +                         "~/Library/Components", +                         "~/Library/Compositions", +                         "~/Library/Containers", +                         "~/Library/Contextual Menu Items", +                         "~/Library/Cookies", +                         "~/Library/DTDs", +                         "~/Library/Desktop Pictures", +                         "~/Library/Developer", +                         "~/Library/Dictionaries", +                         "~/Library/DirectoryServices", +                         "~/Library/Displays", +                         "~/Library/Documentation", +                         "~/Library/Extensions", +                         "~/Library/Favorites", +                         "~/Library/FileSync", +                         "~/Library/Filesystems", +                         "~/Library/Filters", +                         "~/Library/FontCollections", +                         "~/Library/Fonts", +                         "~/Library/Frameworks", +                         "~/Library/GameKit", +                         "~/Library/Graphics", +                         "~/Library/Group Containers", +                         "~/Library/Icons", +                         "~/Library/IdentityServices", +                         "~/Library/Image Capture", +                         "~/Library/Images", +                         "~/Library/Input Methods", +                         "~/Library/Internet Plug-Ins", +                         "~/Library/InternetAccounts", +                         "~/Library/iTunes", +                         "~/Library/KeyBindings", +                         "~/Library/Keyboard Layouts", +                         "~/Library/Keychains", +                         "~/Library/LaunchAgents", +                         "~/Library/LaunchDaemons", +                         "~/Library/LocationBundles", +                         "~/Library/LoginPlugins", +                         "~/Library/Logs", +                         "~/Library/Mail", +                         "~/Library/Mail Downloads", +                         "~/Library/Messages", +                         "~/Library/Metadata", +                         "~/Library/Mobile Documents", +                         "~/Library/MonitorPanels", +                         "~/Library/OpenDirectory", +                         "~/Library/PDF Services", +                         "~/Library/PhonePlugins", +                         "~/Library/Phones", +                         "~/Library/PreferencePanes", +                         "~/Library/Preferences", +                         "~/Library/Printers", +                         "~/Library/PrivateFrameworks", +                         "~/Library/PubSub", +                         "~/Library/QuickLook", +                         "~/Library/QuickTime", +                         "~/Library/Receipts", +                         "~/Library/Recent Servers", +                         "~/Library/Recents", +                         "~/Library/Safari", +                         "~/Library/Saved Application State", +                         "~/Library/Screen Savers", +                         "~/Library/ScreenReader", +                         "~/Library/ScriptingAdditions", +                         "~/Library/ScriptingDefinitions", +                         "~/Library/Scripts", +                         "~/Library/Security", +                         "~/Library/Services", +                         "~/Library/Sounds", +                         "~/Library/Speech", +                         "~/Library/Spelling", +                         "~/Library/Spotlight", +                         "~/Library/StartupItems", +                         "~/Library/StickiesDatabase", +                         "~/Library/Sync Services", +                         "~/Library/SyncServices", +                         "~/Library/SyncedPreferences", +                         "~/Library/TextEncodings", +                         "~/Library/User Pictures", +                         "~/Library/Video", +                         "~/Library/Voices", +                         "~/Library/WebKit", +                         "~/Library/WidgetResources", +                         "~/Library/Widgets", +                         "~/Library/Workflows", +                       ] +                       .map { |x| Pathname(x.sub(%r{^~(?=(/|$))}, Dir.home)).expand_path } +                       .to_set +                       .union(SYSTEM_DIRS) +                       .freeze -  def system_dir?(dir) -    SYSTEM_DIRS.include?(Pathname.new(dir).expand_path) -  end +    def system_dir?(dir) +      SYSTEM_DIRS.include?(Pathname.new(dir).expand_path) +    end -  def undeletable?(dir) -    UNDELETABLE_DIRS.include?(Pathname.new(dir).expand_path) +    def undeletable?(dir) +      UNDELETABLE_DIRS.include?(Pathname.new(dir).expand_path) +    end    end - -  alias release version  end diff --git a/Library/Homebrew/cask/lib/hbc/options.rb b/Library/Homebrew/cask/lib/hbc/options.rb index c0e3e2ed0..e9ba54ff6 100644 --- a/Library/Homebrew/cask/lib/hbc/options.rb +++ b/Library/Homebrew/cask/lib/hbc/options.rb @@ -1,37 +1,39 @@ -module Hbc::Options -  def self.included(base) -    base.extend(ClassMethods) -  end +module Hbc +  module Options +    def self.included(base) +      base.extend(ClassMethods) +    end -  module ClassMethods -    attr_writer :no_binaries +    module ClassMethods +      attr_writer :no_binaries -    def no_binaries -      @no_binaries ||= false -    end +      def no_binaries +        @no_binaries ||= false +      end -    attr_writer :debug +      attr_writer :debug -    def debug -      @debug ||= false -    end +      def debug +        @debug ||= false +      end -    attr_writer :verbose +      attr_writer :verbose -    def verbose -      @verbose ||= false -    end +      def verbose +        @verbose ||= false +      end -    attr_writer :cleanup_outdated +      attr_writer :cleanup_outdated -    def cleanup_outdated -      @cleanup_outdated ||= false -    end +      def cleanup_outdated +        @cleanup_outdated ||= false +      end -    attr_writer :help +      attr_writer :help -    def help -      @help ||= false +      def help +        @help ||= false +      end      end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/pkg.rb b/Library/Homebrew/cask/lib/hbc/pkg.rb index 6f8d28c24..7f187c9de 100644 --- a/Library/Homebrew/cask/lib/hbc/pkg.rb +++ b/Library/Homebrew/cask/lib/hbc/pkg.rb @@ -1,113 +1,115 @@ -class Hbc::Pkg -  def self.all_matching(regexp, command) -    command.run("/usr/sbin/pkgutil", args: ["--pkgs=#{regexp}"]).stdout.split("\n").map { |package_id| -      new(package_id.chomp, command) -    } -  end +module Hbc +  class Pkg +    def self.all_matching(regexp, command) +      command.run("/usr/sbin/pkgutil", args: ["--pkgs=#{regexp}"]).stdout.split("\n").map { |package_id| +        new(package_id.chomp, command) +      } +    end -  attr_reader :package_id +    attr_reader :package_id -  def initialize(package_id, command = Hbc::SystemCommand) -    @package_id = package_id -    @command = command -  end +    def initialize(package_id, command = SystemCommand) +      @package_id = package_id +      @command = command +    end -  def uninstall -    odebug "Deleting pkg files" -    pkgutil_bom_files.each_slice(500) do |file_slice| -      @command.run("/bin/rm", args: file_slice.unshift("-f", "--"), sudo: true) -    end -    odebug "Deleting pkg symlinks and special files" -    pkgutil_bom_specials.each_slice(500) do |file_slice| -      @command.run("/bin/rm", args: file_slice.unshift("-f", "--"), sudo: true) -    end -    odebug "Deleting pkg directories" -    _deepest_path_first(pkgutil_bom_dirs).each do |dir| -      next unless dir.exist? && !MacOS.undeletable?(dir) -      _with_full_permissions(dir) do -        _clean_broken_symlinks(dir) -        _clean_ds_store(dir) -        _rmdir(dir) +    def uninstall +      odebug "Deleting pkg files" +      pkgutil_bom_files.each_slice(500) do |file_slice| +        @command.run("/bin/rm", args: file_slice.unshift("-f", "--"), sudo: true) +      end +      odebug "Deleting pkg symlinks and special files" +      pkgutil_bom_specials.each_slice(500) do |file_slice| +        @command.run("/bin/rm", args: file_slice.unshift("-f", "--"), sudo: true)        end +      odebug "Deleting pkg directories" +      _deepest_path_first(pkgutil_bom_dirs).each do |dir| +        next unless dir.exist? && !MacOS.undeletable?(dir) +        _with_full_permissions(dir) do +          _clean_broken_symlinks(dir) +          _clean_ds_store(dir) +          _rmdir(dir) +        end +      end +      forget      end -    forget -  end -  def forget -    odebug "Unregistering pkg receipt (aka forgetting)" -    @command.run!("/usr/sbin/pkgutil", args: ["--forget", package_id], sudo: true) -  end +    def forget +      odebug "Unregistering pkg receipt (aka forgetting)" +      @command.run!("/usr/sbin/pkgutil", args: ["--forget", package_id], sudo: true) +    end -  def pkgutil_bom(*type) -    @command.run!("/usr/sbin/pkgutil", args: [*type, "--files", package_id].compact) -            .stdout -            .split("\n") -            .map { |path| root.join(path) } -  end +    def pkgutil_bom(*type) +      @command.run!("/usr/sbin/pkgutil", args: [*type, "--files", package_id].compact) +              .stdout +              .split("\n") +              .map { |path| root.join(path) } +    end -  def pkgutil_bom_files -    @pkgutil_bom_files ||= pkgutil_bom("--only-files") -  end +    def pkgutil_bom_files +      @pkgutil_bom_files ||= pkgutil_bom("--only-files") +    end -  def pkgutil_bom_dirs -    @pkgutil_bom_dirs ||= pkgutil_bom("--only-dirs") -  end +    def pkgutil_bom_dirs +      @pkgutil_bom_dirs ||= pkgutil_bom("--only-dirs") +    end -  def pkgutil_bom_all -    @pkgutil_bom_all ||= pkgutil_bom -  end +    def pkgutil_bom_all +      @pkgutil_bom_all ||= pkgutil_bom +    end -  def pkgutil_bom_specials -    pkgutil_bom_all - pkgutil_bom_files - pkgutil_bom_dirs -  end +    def pkgutil_bom_specials +      pkgutil_bom_all - pkgutil_bom_files - pkgutil_bom_dirs +    end -  def root -    @root ||= Pathname(info.fetch("volume")).join(info.fetch("install-location")) -  end +    def root +      @root ||= Pathname(info.fetch("volume")).join(info.fetch("install-location")) +    end -  def info -    @command.run!("/usr/sbin/pkgutil", args: ["--pkg-info-plist", package_id]) -            .plist -  end +    def info +      @command.run!("/usr/sbin/pkgutil", args: ["--pkg-info-plist", package_id]) +              .plist +    end -  def _rmdir(path) -    @command.run!("/bin/rmdir", args: ["--", path], sudo: true) if path.children.empty? -  end +    def _rmdir(path) +      @command.run!("/bin/rmdir", args: ["--", path], sudo: true) if path.children.empty? +    end -  def _with_full_permissions(path) -    original_mode = (path.stat.mode % 0o1000).to_s(8) -    # TODO: similarly read and restore macOS flags (cf man chflags) -    @command.run!("/bin/chmod", args: ["--", "777", path], sudo: true) -    yield -  ensure -    if path.exist? # block may have removed dir -      @command.run!("/bin/chmod", args: ["--", original_mode, path], sudo: true) +    def _with_full_permissions(path) +      original_mode = (path.stat.mode % 0o1000).to_s(8) +      # TODO: similarly read and restore macOS flags (cf man chflags) +      @command.run!("/bin/chmod", args: ["--", "777", path], sudo: true) +      yield +    ensure +      if path.exist? # block may have removed dir +        @command.run!("/bin/chmod", args: ["--", original_mode, path], sudo: true) +      end      end -  end -  def _deepest_path_first(paths) -    paths.sort do |path_a, path_b| -      path_b.to_s.split("/").count <=> path_a.to_s.split("/").count +    def _deepest_path_first(paths) +      paths.sort do |path_a, path_b| +        path_b.to_s.split("/").count <=> path_a.to_s.split("/").count +      end      end -  end -  # Some pkgs leave broken symlinks hanging around; we clean them out before -  # attempting to rmdir to prevent extra cruft from lying around after -  # uninstall -  def _clean_broken_symlinks(dir) -    dir.children.each do |child| -      if _broken_symlink?(child) -        @command.run!("/bin/rm", args: ["--", child], sudo: true) +    # Some pkgs leave broken symlinks hanging around; we clean them out before +    # attempting to rmdir to prevent extra cruft from lying around after +    # uninstall +    def _clean_broken_symlinks(dir) +      dir.children.each do |child| +        if _broken_symlink?(child) +          @command.run!("/bin/rm", args: ["--", child], sudo: true) +        end        end      end -  end -  def _clean_ds_store(dir) -    ds_store = dir.join(".DS_Store") -    @command.run!("/bin/rm", args: ["--", ds_store], sudo: true) if ds_store.exist? -  end +    def _clean_ds_store(dir) +      ds_store = dir.join(".DS_Store") +      @command.run!("/bin/rm", args: ["--", ds_store], sudo: true) if ds_store.exist? +    end -  def _broken_symlink?(path) -    path.symlink? && !path.exist? +    def _broken_symlink?(path) +      path.symlink? && !path.exist? +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/qualified_token.rb b/Library/Homebrew/cask/lib/hbc/qualified_token.rb index 635e1cb3d..ccfe08b45 100644 --- a/Library/Homebrew/cask/lib/hbc/qualified_token.rb +++ b/Library/Homebrew/cask/lib/hbc/qualified_token.rb @@ -1,37 +1,39 @@ -module Hbc::QualifiedToken -  REPO_PREFIX = "homebrew-".freeze +module Hbc +  module QualifiedToken +    REPO_PREFIX = "homebrew-".freeze -  # per https://github.com/Homebrew/homebrew/blob/4c7bc9ec3bca729c898ee347b6135ba692ee0274/Library/Homebrew/cmd/tap.rb#L121 -  USER_REGEX = %r{[a-z_\-]+} +    # per https://github.com/Homebrew/homebrew/blob/4c7bc9ec3bca729c898ee347b6135ba692ee0274/Library/Homebrew/cmd/tap.rb#L121 +    USER_REGEX = %r{[a-z_\-]+} -  # per https://github.com/Homebrew/homebrew/blob/4c7bc9ec3bca729c898ee347b6135ba692ee0274/Library/Homebrew/cmd/tap.rb#L121 -  REPO_REGEX = %r{(?:#{REPO_PREFIX})?\w+} +    # per https://github.com/Homebrew/homebrew/blob/4c7bc9ec3bca729c898ee347b6135ba692ee0274/Library/Homebrew/cmd/tap.rb#L121 +    REPO_REGEX = %r{(?:#{REPO_PREFIX})?\w+} -  # per https://github.com/caskroom/homebrew-cask/blob/master/CONTRIBUTING.md#generating-a-token-for-the-cask -  TOKEN_REGEX = %r{[a-z0-9\-]+} +    # per https://github.com/caskroom/homebrew-cask/blob/master/CONTRIBUTING.md#generating-a-token-for-the-cask +    TOKEN_REGEX = %r{[a-z0-9\-]+} -  TAP_REGEX = %r{#{USER_REGEX}[/\-]#{REPO_REGEX}} +    TAP_REGEX = %r{#{USER_REGEX}[/\-]#{REPO_REGEX}} -  QUALIFIED_TOKEN_REGEX ||= %r{#{TAP_REGEX}/#{TOKEN_REGEX}} +    QUALIFIED_TOKEN_REGEX ||= %r{#{TAP_REGEX}/#{TOKEN_REGEX}} -  def self.parse(arg) -    return nil unless arg.is_a?(String) && arg.downcase =~ %r{^#{QUALIFIED_TOKEN_REGEX}$} -    path_elements = arg.downcase.split("/") -    if path_elements.count == 2 -      # eg phinze-cask/google-chrome. -      # Not certain this form is needed, but it was supported in the past. -      token = path_elements[1] -      dash_elements = path_elements[0].split("-") -      repo = dash_elements.pop -      dash_elements.pop if dash_elements.count > 1 && dash_elements[-1] + "-" == REPO_PREFIX -      user = dash_elements.join("-") -    else -      # eg caskroom/cask/google-chrome -      # per https://github.com/Homebrew/homebrew/wiki/brew-tap -      user, repo, token = path_elements +    def self.parse(arg) +      return nil unless arg.is_a?(String) && arg.downcase =~ %r{^#{QUALIFIED_TOKEN_REGEX}$} +      path_elements = arg.downcase.split("/") +      if path_elements.count == 2 +        # eg phinze-cask/google-chrome. +        # Not certain this form is needed, but it was supported in the past. +        token = path_elements[1] +        dash_elements = path_elements[0].split("-") +        repo = dash_elements.pop +        dash_elements.pop if dash_elements.count > 1 && dash_elements[-1] + "-" == REPO_PREFIX +        user = dash_elements.join("-") +      else +        # eg caskroom/cask/google-chrome +        # per https://github.com/Homebrew/homebrew/wiki/brew-tap +        user, repo, token = path_elements +      end +      repo.sub!(%r{^#{REPO_PREFIX}}, "") +      odebug "[user, repo, token] might be [#{user}, #{repo}, #{token}]" +      [user, repo, token]      end -    repo.sub!(%r{^#{REPO_PREFIX}}, "") -    odebug "[user, repo, token] might be [#{user}, #{repo}, #{token}]" -    [user, repo, token]    end  end diff --git a/Library/Homebrew/cask/lib/hbc/scopes.rb b/Library/Homebrew/cask/lib/hbc/scopes.rb index 431c3ff47..8520028c9 100644 --- a/Library/Homebrew/cask/lib/hbc/scopes.rb +++ b/Library/Homebrew/cask/lib/hbc/scopes.rb @@ -1,45 +1,47 @@ -module Hbc::Scopes -  def self.included(base) -    base.extend(ClassMethods) -  end - -  module ClassMethods -    def all -      @all_casks ||= {} -      all_tokens.map { |t| @all_casks[t] ||= load(t) } +module Hbc +  module Scopes +    def self.included(base) +      base.extend(ClassMethods)      end -    def all_tapped_cask_dirs -      Tap.map(&:cask_dir).compact -    end +    module ClassMethods +      def all +        @all_casks ||= {} +        all_tokens.map { |t| @all_casks[t] ||= load(t) } +      end -    def all_tokens -      Tap.map { |t| -        t.cask_files.map { |p| -          "#{t.name}/#{File.basename(p, ".rb")}" -        } -      }.flatten -    end +      def all_tapped_cask_dirs +        Tap.map(&:cask_dir).compact +      end -    def installed -      # Hbc.load has some DWIM which is slow.  Optimize here -      # by spoon-feeding Hbc.load fully-qualified paths. -      # TODO: speed up Hbc::Source::Tapped (main perf drag is calling Hbc.all_tokens repeatedly) -      # TODO: ability to specify expected source when calling Hbc.load (minor perf benefit) -      Pathname.glob(caskroom.join("*")) -              .map { |caskroom_path| -                token = caskroom_path.basename.to_s +      def all_tokens +        Tap.map { |t| +          t.cask_files.map { |p| +            "#{t.name}/#{File.basename(p, ".rb")}" +          } +        }.flatten +      end -                path_to_cask = all_tapped_cask_dirs.find { |tap_dir| -                  tap_dir.join("#{token}.rb").exist? -                } +      def installed +        # Hbc.load has some DWIM which is slow.  Optimize here +        # by spoon-feeding Hbc.load fully-qualified paths. +        # TODO: speed up Hbc::Source::Tapped (main perf drag is calling Hbc.all_tokens repeatedly) +        # TODO: ability to specify expected source when calling Hbc.load (minor perf benefit) +        Pathname.glob(caskroom.join("*")) +                .map { |caskroom_path| +                  token = caskroom_path.basename.to_s + +                  path_to_cask = all_tapped_cask_dirs.find { |tap_dir| +                    tap_dir.join("#{token}.rb").exist? +                  } -                if path_to_cask -                  Hbc.load(path_to_cask.join("#{token}.rb")) -                else -                  Hbc.load(token) -                end -              } +                  if path_to_cask +                    Hbc.load(path_to_cask.join("#{token}.rb")) +                  else +                    Hbc.load(token) +                  end +                } +      end      end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/source.rb b/Library/Homebrew/cask/lib/hbc/source.rb index af298108a..b4d105894 100644 --- a/Library/Homebrew/cask/lib/hbc/source.rb +++ b/Library/Homebrew/cask/lib/hbc/source.rb @@ -1,5 +1,3 @@ -module Hbc::Source; end -  require "hbc/source/gone"  require "hbc/source/path_slash_required"  require "hbc/source/path_slash_optional" @@ -8,30 +6,32 @@ require "hbc/source/untapped_qualified"  require "hbc/source/tapped"  require "hbc/source/uri" -module Hbc::Source -  def self.sources -    [ -      Hbc::Source::URI, -      Hbc::Source::PathSlashRequired, -      Hbc::Source::TappedQualified, -      Hbc::Source::UntappedQualified, -      Hbc::Source::Tapped, -      Hbc::Source::PathSlashOptional, -      Hbc::Source::Gone, -    ] -  end +module Hbc +  module Source +    def self.sources +      [ +        URI, +        PathSlashRequired, +        TappedQualified, +        UntappedQualified, +        Tapped, +        PathSlashOptional, +        Gone, +      ] +    end -  def self.for_query(query) -    odebug "Translating '#{query}' into a valid Cask source" -    raise Hbc::CaskUnavailableError, query if query.to_s =~ %r{^\s*$} -    source = sources.find { |s| -      odebug "Testing source class #{s}" -      s.me?(query) -    } -    raise Hbc::CaskUnavailableError, query unless source -    odebug "Success! Using source class #{source}" -    resolved_cask_source = source.new(query) -    odebug "Resolved Cask URI or file source to '#{resolved_cask_source}'" -    resolved_cask_source +    def self.for_query(query) +      odebug "Translating '#{query}' into a valid Cask source" +      raise CaskUnavailableError, query if query.to_s =~ %r{^\s*$} +      source = sources.find { |s| +        odebug "Testing source class #{s}" +        s.me?(query) +      } +      raise CaskUnavailableError, query unless source +      odebug "Success! Using source class #{source}" +      resolved_cask_source = source.new(query) +      odebug "Resolved Cask URI or file source to '#{resolved_cask_source}'" +      resolved_cask_source +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/source/gone.rb b/Library/Homebrew/cask/lib/hbc/source/gone.rb index 2b9f2b5f2..1c744d0db 100644 --- a/Library/Homebrew/cask/lib/hbc/source/gone.rb +++ b/Library/Homebrew/cask/lib/hbc/source/gone.rb @@ -1,19 +1,23 @@ -class Hbc::Source::Gone -  def self.me?(query) -    Hbc::WithoutSource.new(query).installed? -  end +module Hbc +  module Source +    class Gone +      def self.me?(query) +        WithoutSource.new(query).installed? +      end -  attr_reader :query +      attr_reader :query -  def initialize(query) -    @query = query -  end +      def initialize(query) +        @query = query +      end -  def load -    Hbc::WithoutSource.new(query) -  end +      def load +        WithoutSource.new(query) +      end -  def to_s -    "" +      def to_s +        "" +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/source/path_base.rb b/Library/Homebrew/cask/lib/hbc/source/path_base.rb index bd85ab425..5725380ec 100644 --- a/Library/Homebrew/cask/lib/hbc/source/path_base.rb +++ b/Library/Homebrew/cask/lib/hbc/source/path_base.rb @@ -1,69 +1,73 @@  require "rubygems" -class Hbc::Source::PathBase -  # derived classes must define method self.me? +module Hbc +  module Source +    class PathBase +      # derived classes must define method self.me? -  def self.path_for_query(query) -    query_string = query.to_s -    Pathname.new(query_string.end_with?(".rb") ? query_string : query_string + ".rb") -  end +      def self.path_for_query(query) +        query_string = query.to_s +        Pathname.new(query_string.end_with?(".rb") ? query_string : query_string + ".rb") +      end -  attr_reader :path +      attr_reader :path -  def initialize(path) -    @path = Pathname(path).expand_path -  end +      def initialize(path) +        @path = Pathname(path).expand_path +      end -  def load -    raise Hbc::CaskError, "File '#{path}' does not exist"      unless path.exist? -    raise Hbc::CaskError, "File '#{path}' is not readable"     unless path.readable? -    raise Hbc::CaskError, "File '#{path}' is not a plain file" unless path.file? -    load_cask -  end +      def load +        raise CaskError, "File '#{path}' does not exist"      unless path.exist? +        raise CaskError, "File '#{path}' is not readable"     unless path.readable? +        raise CaskError, "File '#{path}' is not a plain file" unless path.file? +        load_cask +      end -  def to_s -    # stringify to fully-resolved location -    path.to_s -  end +      def to_s +        # stringify to fully-resolved location +        path.to_s +      end -  private +      private -  def load_cask -    instance_eval(cask_contents, __FILE__, __LINE__) -  rescue Hbc::CaskError, StandardError, ScriptError => e -    # bug: e.message.concat doesn't work with Hbc::CaskError exceptions -    raise e, e.message.concat(" while loading '#{path}'") -  end +      def load_cask +        instance_eval(cask_contents, __FILE__, __LINE__) +      rescue CaskError, StandardError, ScriptError => e +        # bug: e.message.concat doesn't work with CaskError exceptions +        raise e, e.message.concat(" while loading '#{path}'") +      end -  def cask_contents -    File.open(path, "rb") do |handle| -      contents = handle.read -      if defined?(Encoding) -        contents.force_encoding("UTF-8") -      else -        contents +      def cask_contents +        File.open(path, "rb") do |handle| +          contents = handle.read +          if defined?(Encoding) +            contents.force_encoding("UTF-8") +          else +            contents +          end +        end        end -    end -  end -  def cask(header_token, &block) -    build_cask(Hbc::Cask, header_token, &block) -  end +      def cask(header_token, &block) +        build_cask(Cask, header_token, &block) +      end -  def test_cask(header_token, &block) -    build_cask(Hbc::TestCask, header_token, &block) -  end +      def test_cask(header_token, &block) +        build_cask(TestCask, header_token, &block) +      end -  def build_cask(cask_class, header_token, &block) -    if header_token.is_a?(Hash) -      # Cask file is using old `cask :v1 => 'token'` syntax -      header_token = header_token.values.first -    end -    raise Hbc::CaskTokenDoesNotMatchError.new(cask_token, header_token) unless cask_token == header_token -    cask_class.new(cask_token, sourcefile_path: path, &block) -  end +      def build_cask(cask_class, header_token, &block) +        if header_token.is_a?(Hash) +          # Cask file is using old `cask :v1 => 'token'` syntax +          header_token = header_token.values.first +        end +        raise CaskTokenDoesNotMatchError.new(cask_token, header_token) unless cask_token == header_token +        cask_class.new(cask_token, sourcefile_path: path, &block) +      end -  def cask_token -    path.basename.to_s.sub(%r{\.rb}, "") +      def cask_token +        path.basename.to_s.sub(%r{\.rb}, "") +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/source/path_slash_optional.rb b/Library/Homebrew/cask/lib/hbc/source/path_slash_optional.rb index fb34c481a..d96a41130 100644 --- a/Library/Homebrew/cask/lib/hbc/source/path_slash_optional.rb +++ b/Library/Homebrew/cask/lib/hbc/source/path_slash_optional.rb @@ -1,8 +1,12 @@  require "hbc/source/path_base" -class Hbc::Source::PathSlashOptional < Hbc::Source::PathBase -  def self.me?(query) -    path = path_for_query(query) -    path.exist? +module Hbc +  module Source +    class PathSlashOptional < PathBase +      def self.me?(query) +        path = path_for_query(query) +        path.exist? +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/source/path_slash_required.rb b/Library/Homebrew/cask/lib/hbc/source/path_slash_required.rb index 0c533a8a5..2753b1710 100644 --- a/Library/Homebrew/cask/lib/hbc/source/path_slash_required.rb +++ b/Library/Homebrew/cask/lib/hbc/source/path_slash_required.rb @@ -1,8 +1,12 @@  require "hbc/source/path_base" -class Hbc::Source::PathSlashRequired < Hbc::Source::PathBase -  def self.me?(query) -    path = path_for_query(query) -    path.to_s.include?("/") && path.exist? +module Hbc +  module Source +    class PathSlashRequired < PathBase +      def self.me?(query) +        path = path_for_query(query) +        path.to_s.include?("/") && path.exist? +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/source/tapped.rb b/Library/Homebrew/cask/lib/hbc/source/tapped.rb index da9366840..6716e3a35 100644 --- a/Library/Homebrew/cask/lib/hbc/source/tapped.rb +++ b/Library/Homebrew/cask/lib/hbc/source/tapped.rb @@ -1,35 +1,39 @@ -class Hbc::Source::Tapped -  def self.me?(query) -    path_for_query(query).exist? -  end +module Hbc +  module Source +    class Tapped +      def self.me?(query) +        path_for_query(query).exist? +      end -  def self.path_for_query(query) -    # Repeating Hbc.all_tokens is very slow for operations such as -    # brew cask list, but memoizing the value might cause breakage -    # elsewhere, given that installation and tap status is permitted -    # to change during the course of an invocation. -    token_with_tap = Hbc.all_tokens.find { |t| t.split("/").last == query.sub(%r{\.rb$}i, "") } -    if token_with_tap -      user, repo, token = token_with_tap.split("/") -      Tap.fetch(user, repo).cask_dir.join("#{token}.rb") -    else -      Hbc.default_tap.cask_dir.join(query.sub(%r{(\.rb)?$}i, ".rb")) -    end -  end +      def self.path_for_query(query) +        # Repeating Hbc.all_tokens is very slow for operations such as +        # brew cask list, but memoizing the value might cause breakage +        # elsewhere, given that installation and tap status is permitted +        # to change during the course of an invocation. +        token_with_tap = Hbc.all_tokens.find { |t| t.split("/").last == query.sub(%r{\.rb$}i, "") } +        if token_with_tap +          user, repo, token = token_with_tap.split("/") +          Tap.fetch(user, repo).cask_dir.join("#{token}.rb") +        else +          Hbc.default_tap.cask_dir.join(query.sub(%r{(\.rb)?$}i, ".rb")) +        end +      end -  attr_reader :token +      attr_reader :token -  def initialize(token) -    @token = token -  end +      def initialize(token) +        @token = token +      end -  def load -    path = self.class.path_for_query(token) -    Hbc::Source::PathSlashOptional.new(path).load -  end +      def load +        path = self.class.path_for_query(token) +        PathSlashOptional.new(path).load +      end -  def to_s -    # stringify to fully-resolved location -    self.class.path_for_query(token).expand_path.to_s +      def to_s +        # stringify to fully-resolved location +        self.class.path_for_query(token).expand_path.to_s +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/source/tapped_qualified.rb b/Library/Homebrew/cask/lib/hbc/source/tapped_qualified.rb index 1da013db2..52191f279 100644 --- a/Library/Homebrew/cask/lib/hbc/source/tapped_qualified.rb +++ b/Library/Homebrew/cask/lib/hbc/source/tapped_qualified.rb @@ -1,22 +1,26 @@  require "hbc/source/tapped" -class Hbc::Source::TappedQualified < Hbc::Source::Tapped -  def self.me?(query) -    return if (tap = tap_for_query(query)).nil? +module Hbc +  module Source +    class TappedQualified < Tapped +      def self.me?(query) +        return if (tap = tap_for_query(query)).nil? -    tap.installed? && path_for_query(query).exist? -  end +        tap.installed? && path_for_query(query).exist? +      end -  def self.tap_for_query(query) -    qualified_token = Hbc::QualifiedToken.parse(query) -    return if qualified_token.nil? +      def self.tap_for_query(query) +        qualified_token = QualifiedToken.parse(query) +        return if qualified_token.nil? -    user, repo, token = qualified_token -    Tap.fetch(user, repo) -  end +        user, repo = qualified_token[0..1] +        Tap.fetch(user, repo) +      end -  def self.path_for_query(query) -    user, repo, token = Hbc::QualifiedToken.parse(query) -    Tap.fetch(user, repo).cask_dir.join(token.sub(%r{(\.rb)?$}i, ".rb")) +      def self.path_for_query(query) +        user, repo, token = QualifiedToken.parse(query) +        Tap.fetch(user, repo).cask_dir.join(token.sub(%r{(\.rb)?$}i, ".rb")) +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/source/untapped_qualified.rb b/Library/Homebrew/cask/lib/hbc/source/untapped_qualified.rb index 7188d34ce..6041605d8 100644 --- a/Library/Homebrew/cask/lib/hbc/source/untapped_qualified.rb +++ b/Library/Homebrew/cask/lib/hbc/source/untapped_qualified.rb @@ -1,10 +1,14 @@  require "hbc/source/tapped_qualified" -class Hbc::Source::UntappedQualified < Hbc::Source::TappedQualified -  def self.me?(query) -    return if (tap = tap_for_query(query)).nil? +module Hbc +  module Source +    class UntappedQualified < TappedQualified +      def self.me?(query) +        return if (tap = tap_for_query(query)).nil? -    tap.install -    tap.installed? && path_for_query(query).exist? +        tap.install +        tap.installed? && path_for_query(query).exist? +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/source/uri.rb b/Library/Homebrew/cask/lib/hbc/source/uri.rb index 99bc50688..09fab4bd0 100644 --- a/Library/Homebrew/cask/lib/hbc/source/uri.rb +++ b/Library/Homebrew/cask/lib/hbc/source/uri.rb @@ -1,28 +1,32 @@ -class Hbc::Source::URI -  def self.me?(query) -    !(query.to_s =~ URI.regexp).nil? -  end +module Hbc +  module Source +    class URI +      def self.me?(query) +        !(query.to_s =~ ::URI.regexp).nil? +      end -  attr_reader :uri +      attr_reader :uri -  def initialize(uri) -    @uri = uri -  end +      def initialize(uri) +        @uri = uri +      end -  def load -    Hbc.cache.mkpath -    path = Hbc.cache.join(File.basename(uri)) -    ohai "Downloading #{uri}" -    odebug "Download target -> #{path}" -    begin -      curl(uri, "-o", path.to_s) -    rescue ErrorDuringExecution -      raise Hbc::CaskUnavailableError, uri -    end -    Hbc::Source::PathSlashOptional.new(path).load -  end +      def load +        Hbc.cache.mkpath +        path = Hbc.cache.join(File.basename(uri)) +        ohai "Downloading #{uri}" +        odebug "Download target -> #{path}" +        begin +          curl(uri, "-o", path.to_s) +        rescue ErrorDuringExecution +          raise CaskUnavailableError, uri +        end +        PathSlashOptional.new(path).load +      end -  def to_s -    uri.to_s +      def to_s +        uri.to_s +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/staged.rb b/Library/Homebrew/cask/lib/hbc/staged.rb index 7e2c93541..dcc05ef5d 100644 --- a/Library/Homebrew/cask/lib/hbc/staged.rb +++ b/Library/Homebrew/cask/lib/hbc/staged.rb @@ -1,48 +1,50 @@ -module Hbc::Staged -  def info_plist_file(index = 0) -    index =  0 if index == :first -    index =  1 if index == :second -    index = -1 if index == :last -    Hbc.appdir.join(@cask.artifacts[:app].to_a.at(index).first, "Contents", "Info.plist") -  end - -  def plist_exec(cmd) -    @command.run!("/usr/libexec/PlistBuddy", args: ["-c", cmd, info_plist_file]) -  end - -  def plist_set(key, value) -    plist_exec("Set #{key} #{value}") -  rescue StandardError => e -    raise Hbc::CaskError, "#{@cask.token}: 'plist_set' failed with: #{e}" -  end - -  def bundle_identifier -    plist_exec("Print CFBundleIdentifier").stdout.chomp -  rescue StandardError => e -    raise Hbc::CaskError, "#{@cask.token}: 'bundle_identifier' failed with: #{e}" -  end - -  def set_permissions(paths, permissions_str) -    full_paths = remove_nonexistent(paths) -    return if full_paths.empty? -    @command.run!("/bin/chmod", args: ["-R", "--", permissions_str] + full_paths, -                                sudo: true) -  end - -  def set_ownership(paths, user: current_user, group: "staff") -    full_paths = remove_nonexistent(paths) -    return if full_paths.empty? -    @command.run!("/usr/sbin/chown", args: ["-R", "--", "#{user}:#{group}"] + full_paths, -                                     sudo: true) -  end - -  def current_user -    Hbc::Utils.current_user -  end - -  private - -  def remove_nonexistent(paths) -    Array(paths).map { |p| Pathname(p).expand_path }.select(&:exist?) +module Hbc +  module Staged +    def info_plist_file(index = 0) +      index =  0 if index == :first +      index =  1 if index == :second +      index = -1 if index == :last +      Hbc.appdir.join(@cask.artifacts[:app].to_a.at(index).first, "Contents", "Info.plist") +    end + +    def plist_exec(cmd) +      @command.run!("/usr/libexec/PlistBuddy", args: ["-c", cmd, info_plist_file]) +    end + +    def plist_set(key, value) +      plist_exec("Set #{key} #{value}") +    rescue StandardError => e +      raise CaskError, "#{@cask.token}: 'plist_set' failed with: #{e}" +    end + +    def bundle_identifier +      plist_exec("Print CFBundleIdentifier").stdout.chomp +    rescue StandardError => e +      raise CaskError, "#{@cask.token}: 'bundle_identifier' failed with: #{e}" +    end + +    def set_permissions(paths, permissions_str) +      full_paths = remove_nonexistent(paths) +      return if full_paths.empty? +      @command.run!("/bin/chmod", args: ["-R", "--", permissions_str] + full_paths, +                                  sudo: true) +    end + +    def set_ownership(paths, user: current_user, group: "staff") +      full_paths = remove_nonexistent(paths) +      return if full_paths.empty? +      @command.run!("/usr/sbin/chown", args: ["-R", "--", "#{user}:#{group}"] + full_paths, +                                       sudo: true) +    end + +    def current_user +      Utils.current_user +    end + +    private + +    def remove_nonexistent(paths) +      Array(paths).map { |p| Pathname(p).expand_path }.select(&:exist?) +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/system_command.rb b/Library/Homebrew/cask/lib/hbc/system_command.rb index bb8d91504..160aadff9 100644 --- a/Library/Homebrew/cask/lib/hbc/system_command.rb +++ b/Library/Homebrew/cask/lib/hbc/system_command.rb @@ -1,173 +1,179 @@  require "open3"  require "shellwords" -class Hbc::SystemCommand -  attr_reader :command +module Hbc +  class SystemCommand +    attr_reader :command -  def self.run(executable, options = {}) -    new(executable, options).run! -  end +    def self.run(executable, options = {}) +      new(executable, options).run! +    end -  def self.run!(command, options = {}) -    run(command, options.merge(must_succeed: true)) -  end +    def self.run!(command, options = {}) +      run(command, options.merge(must_succeed: true)) +    end -  def run! -    @processed_output = { stdout: "", stderr: "" } -    odebug "Executing: #{expanded_command.utf8_inspect}" - -    each_output_line do |type, line| -      case type -      when :stdout -        processed_output[:stdout] << line -        ohai line.chomp if options[:print_stdout] -      when :stderr -        processed_output[:stderr] << line -        ohai line.chomp if options[:print_stderr] +    def run! +      @processed_output = { stdout: "", stderr: "" } +      odebug "Executing: #{expanded_command.utf8_inspect}" + +      each_output_line do |type, line| +        case type +        when :stdout +          processed_output[:stdout] << line +          ohai line.chomp if options[:print_stdout] +        when :stderr +          processed_output[:stderr] << line +          ohai line.chomp if options[:print_stderr] +        end        end -    end -    assert_success if options[:must_succeed] -    result -  end +      assert_success if options[:must_succeed] +      result +    end -  def initialize(executable, options) -    @executable = executable -    @options = options -    process_options! -  end +    def initialize(executable, options) +      @executable = executable +      @options = options +      process_options! +    end -  private - -  attr_reader :executable, :options, :processed_output, :processed_status - -  def process_options! -    options.assert_valid_keys :input, :print_stdout, :print_stderr, :args, :must_succeed, :sudo, :bsexec -    sudo_prefix = %w[/usr/bin/sudo -E --] -    bsexec_prefix = ["/bin/launchctl", "bsexec", options[:bsexec] == :startup ? "/" : options[:bsexec]] -    @command = [executable] -    options[:print_stderr] = true    unless options.key?(:print_stderr) -    @command.unshift(*bsexec_prefix) if  options[:bsexec] -    @command.unshift(*sudo_prefix)   if  options[:sudo] -    @command.concat(options[:args])  if  options.key?(:args) && !options[:args].empty? -    @command[0] = Shellwords.shellescape(@command[0]) if @command.size == 1 -    nil -  end +    private + +    attr_reader :executable, :options, :processed_output, :processed_status + +    def process_options! +      options.assert_valid_keys :input, :print_stdout, :print_stderr, :args, :must_succeed, :sudo, :bsexec +      sudo_prefix = %w[/usr/bin/sudo -E --] +      bsexec_prefix = ["/bin/launchctl", "bsexec", options[:bsexec] == :startup ? "/" : options[:bsexec]] +      @command = [executable] +      options[:print_stderr] = true    unless options.key?(:print_stderr) +      @command.unshift(*bsexec_prefix) if  options[:bsexec] +      @command.unshift(*sudo_prefix)   if  options[:sudo] +      @command.concat(options[:args])  if  options.key?(:args) && !options[:args].empty? +      @command[0] = Shellwords.shellescape(@command[0]) if @command.size == 1 +      nil +    end -  def assert_success -    return if processed_status && processed_status.success? -    raise Hbc::CaskCommandFailedError.new(command.utf8_inspect, processed_output[:stdout], processed_output[:stderr], processed_status) -  end +    def assert_success +      return if processed_status && processed_status.success? +      raise CaskCommandFailedError.new(command.utf8_inspect, processed_output[:stdout], processed_output[:stderr], processed_status) +    end -  def expanded_command -    @expanded_command ||= command.map { |arg| -      if arg.respond_to?(:to_path) -        File.absolute_path(arg) -      else -        String(arg) -      end -    } -  end +    def expanded_command +      @expanded_command ||= command.map { |arg| +        if arg.respond_to?(:to_path) +          File.absolute_path(arg) +        else +          String(arg) +        end +      } +    end -  def each_output_line(&b) -    raw_stdin, raw_stdout, raw_stderr, raw_wait_thr = -      Open3.popen3(*expanded_command) +    def each_output_line(&b) +      raw_stdin, raw_stdout, raw_stderr, raw_wait_thr = +        Open3.popen3(*expanded_command) -    write_input_to(raw_stdin) if options[:input] -    raw_stdin.close_write -    each_line_from [raw_stdout, raw_stderr], &b +      write_input_to(raw_stdin) if options[:input] +      raw_stdin.close_write +      each_line_from [raw_stdout, raw_stderr], &b -    @processed_status = raw_wait_thr.value -  end +      @processed_status = raw_wait_thr.value +    end -  def write_input_to(raw_stdin) -    Array(options[:input]).each { |line| raw_stdin.puts line } -  end +    def write_input_to(raw_stdin) +      Array(options[:input]).each { |line| raw_stdin.puts line } +    end -  def each_line_from(sources) -    loop do -      readable_sources = IO.select(sources)[0] -      readable_sources.delete_if(&:eof?).first(1).each do |source| -        type = (source == sources[0] ? :stdout : :stderr) -        begin -          yield(type, source.readline_nonblock || "") -        rescue IO::WaitReadable, EOFError -          next +    def each_line_from(sources) +      loop do +        readable_sources = IO.select(sources)[0] +        readable_sources.delete_if(&:eof?).first(1).each do |source| +          type = (source == sources[0] ? :stdout : :stderr) +          begin +            yield(type, source.readline_nonblock || "") +          rescue IO::WaitReadable, EOFError +            next +          end          end +        break if readable_sources.empty?        end -      break if readable_sources.empty? +      sources.each(&:close_read)      end -    sources.each(&:close_read) -  end -  def result -    Hbc::SystemCommand::Result.new(command, -                                   processed_output[:stdout], -                                   processed_output[:stderr], -                                   processed_status.exitstatus) +    def result +      Result.new(command, +                 processed_output[:stdout], +                 processed_output[:stderr], +                 processed_status.exitstatus) +    end    end  end -class Hbc::SystemCommand::Result -  attr_accessor :command, :stdout, :stderr, :exit_status +module Hbc +  class SystemCommand +    class Result +      attr_accessor :command, :stdout, :stderr, :exit_status -  def initialize(command, stdout, stderr, exit_status) -    @command     = command -    @stdout      = stdout -    @stderr      = stderr -    @exit_status = exit_status -  end +      def initialize(command, stdout, stderr, exit_status) +        @command     = command +        @stdout      = stdout +        @stderr      = stderr +        @exit_status = exit_status +      end -  def plist -    @plist ||= self.class._parse_plist(@command, @stdout.dup) -  end +      def plist +        @plist ||= self.class._parse_plist(@command, @stdout.dup) +      end -  def success? -    @exit_status == 0 -  end +      def success? +        @exit_status.zero? +      end -  def merged_output -    @merged_output ||= @stdout + @stderr -  end +      def merged_output +        @merged_output ||= @stdout + @stderr +      end -  def to_s -    @stdout -  end +      def to_s +        @stdout +      end -  def self._warn_plist_garbage(command, garbage) -    return true unless garbage =~ %r{\S} -    external = File.basename(command.first) -    lines = garbage.strip.split("\n") -    opoo "Non-XML stdout from #{external}:" -    $stderr.puts lines.map { |l| "    #{l}" } -  end +      def self._warn_plist_garbage(command, garbage) +        return true unless garbage =~ %r{\S} +        external = File.basename(command.first) +        lines = garbage.strip.split("\n") +        opoo "Non-XML stdout from #{external}:" +        $stderr.puts lines.map { |l| "    #{l}" } +      end -  def self._parse_plist(command, output) -    raise Hbc::CaskError, "Empty plist input" unless output =~ %r{\S} -    output.sub!(%r{\A(.*?)(<\?\s*xml)}m, '\2') -    _warn_plist_garbage(command, Regexp.last_match[1]) if Hbc.debug -    output.sub!(%r{(<\s*/\s*plist\s*>)(.*?)\Z}m, '\1') -    _warn_plist_garbage(command, Regexp.last_match[2]) -    xml = Plist.parse_xml(output) -    unless xml.respond_to?(:keys) && !xml.keys.empty? -      raise Hbc::CaskError, <<-EOS -Empty result parsing plist output from command. -  command was: -  #{command.utf8_inspect} -  output we attempted to parse: -  #{output} -      EOS +      def self._parse_plist(command, output) +        raise CaskError, "Empty plist input" unless output =~ %r{\S} +        output.sub!(%r{\A(.*?)(<\?\s*xml)}m, '\2') +        _warn_plist_garbage(command, Regexp.last_match[1]) if Hbc.debug +        output.sub!(%r{(<\s*/\s*plist\s*>)(.*?)\Z}m, '\1') +        _warn_plist_garbage(command, Regexp.last_match[2]) +        xml = Plist.parse_xml(output) +        unless xml.respond_to?(:keys) && !xml.keys.empty? +          raise CaskError, <<-EOS +    Empty result parsing plist output from command. +      command was: +      #{command.utf8_inspect} +      output we attempted to parse: +      #{output} +          EOS +        end +        xml +      rescue Plist::ParseError => e +        raise CaskError, <<-EOS +    Error parsing plist output from command. +      command was: +      #{command.utf8_inspect} +      error was: +      #{e} +      output we attempted to parse: +      #{output} +        EOS +      end      end -    xml -  rescue Plist::ParseError => e -    raise Hbc::CaskError, <<-EOS -Error parsing plist output from command. -  command was: -  #{command.utf8_inspect} -  error was: -  #{e} -  output we attempted to parse: -  #{output} -    EOS    end  end diff --git a/Library/Homebrew/cask/lib/hbc/topological_hash.rb b/Library/Homebrew/cask/lib/hbc/topological_hash.rb index bbad1bb4d..2e484a28d 100644 --- a/Library/Homebrew/cask/lib/hbc/topological_hash.rb +++ b/Library/Homebrew/cask/lib/hbc/topological_hash.rb @@ -1,12 +1,14 @@  require "tsort"  # a basic topologically sortable hashmap -class Hbc::TopologicalHash < Hash -  include TSort +module Hbc +  class TopologicalHash < Hash +    include TSort -  alias tsort_each_node each_key +    alias tsort_each_node each_key -  def tsort_each_child(node, &block) -    fetch(node).each(&block) +    def tsort_each_child(node, &block) +      fetch(node).each(&block) +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/underscore_supporting_uri.rb b/Library/Homebrew/cask/lib/hbc/underscore_supporting_uri.rb index 34bfea387..8f8f66f43 100644 --- a/Library/Homebrew/cask/lib/hbc/underscore_supporting_uri.rb +++ b/Library/Homebrew/cask/lib/hbc/underscore_supporting_uri.rb @@ -1,26 +1,28 @@  require "uri" -module Hbc::UnderscoreSupportingURI -  def self.parse(maybe_uri) -    return nil if maybe_uri.nil? -    URI.parse(maybe_uri) -  rescue URI::InvalidURIError => e -    scheme, host, path = simple_parse(maybe_uri) -    raise e unless path && host.include?("_") -    URI.parse(without_host_underscores(scheme, host, path)).tap do |uri| -      uri.instance_variable_set("@host", host) +module Hbc +  module UnderscoreSupportingURI +    def self.parse(maybe_uri) +      return nil if maybe_uri.nil? +      URI.parse(maybe_uri) +    rescue URI::InvalidURIError => e +      scheme, host, path = simple_parse(maybe_uri) +      raise e unless path && host.include?("_") +      URI.parse(without_host_underscores(scheme, host, path)).tap do |uri| +        uri.instance_variable_set("@host", host) +      end      end -  end -  def self.simple_parse(maybe_uri) -    scheme, host_and_path = maybe_uri.split("://") -    host, path = host_and_path.split("/", 2) -    [scheme, host, path] -  rescue StandardError -    nil -  end +    def self.simple_parse(maybe_uri) +      scheme, host_and_path = maybe_uri.split("://") +      host, path = host_and_path.split("/", 2) +      [scheme, host, path] +    rescue StandardError +      nil +    end -  def self.without_host_underscores(scheme, host, path) -    ["#{scheme}:/", host.tr("_", "-"), path].join("/") +    def self.without_host_underscores(scheme, host, path) +      ["#{scheme}:/", host.tr("_", "-"), path].join("/") +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/url.rb b/Library/Homebrew/cask/lib/hbc/url.rb index 5f763ca8a..c09aaa061 100644 --- a/Library/Homebrew/cask/lib/hbc/url.rb +++ b/Library/Homebrew/cask/lib/hbc/url.rb @@ -1,37 +1,39 @@  require "forwardable" -class Hbc::URL -  FAKE_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10) http://caskroom.io".freeze +module Hbc +  class URL +    FAKE_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10) http://caskroom.io".freeze -  attr_reader :using, :revision, :trust_cert, :uri, :cookies, :referer, :data +    attr_reader :using, :revision, :trust_cert, :uri, :cookies, :referer, :data -  extend Forwardable -  def_delegators :uri, :path, :scheme, :to_s +    extend Forwardable +    def_delegators :uri, :path, :scheme, :to_s -  def self.from(*args, &block) -    if block_given? -      Hbc::DSL::StanzaProxy.once(self) { new(*block.call) } -    else -      new(*args) +    def self.from(*args, &block) +      if block_given? +        Hbc::DSL::StanzaProxy.once(self) { new(*block.call) } +      else +        new(*args) +      end      end -  end -  def initialize(uri, options = {}) -    @uri        = Hbc::UnderscoreSupportingURI.parse(uri) -    @user_agent = options[:user_agent] -    @cookies    = options[:cookies] -    @referer    = options[:referer] -    @using      = options[:using] -    @revision   = options[:revision] -    @trust_cert = options[:trust_cert] -    @data       = options[:data] -  end +    def initialize(uri, options = {}) +      @uri        = Hbc::UnderscoreSupportingURI.parse(uri) +      @user_agent = options[:user_agent] +      @cookies    = options[:cookies] +      @referer    = options[:referer] +      @using      = options[:using] +      @revision   = options[:revision] +      @trust_cert = options[:trust_cert] +      @data       = options[:data] +    end -  def user_agent -    if @user_agent == :fake -      FAKE_USER_AGENT -    else -      @user_agent +    def user_agent +      if @user_agent == :fake +        FAKE_USER_AGENT +      else +        @user_agent +      end      end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/url_checker.rb b/Library/Homebrew/cask/lib/hbc/url_checker.rb index 8737903df..4dc1f136a 100644 --- a/Library/Homebrew/cask/lib/hbc/url_checker.rb +++ b/Library/Homebrew/cask/lib/hbc/url_checker.rb @@ -1,75 +1,77 @@  require "hbc/checkable" -class Hbc::UrlChecker -  attr_accessor :cask, :response_status, :headers +module Hbc +  class UrlChecker +    attr_accessor :cask, :response_status, :headers -  include Hbc::Checkable +    include Checkable -  def initialize(cask, fetcher = Hbc::Fetcher) -    @cask = cask -    @fetcher = fetcher -    @headers = {} -  end +    def initialize(cask, fetcher = Fetcher) +      @cask = cask +      @fetcher = fetcher +      @headers = {} +    end -  def summary_header -    "url check result for #{cask}" -  end +    def summary_header +      "url check result for #{cask}" +    end -  def run -    _get_data_from_request -    return if errors? -    _check_response_status -  end +    def run +      _get_data_from_request +      return if errors? +      _check_response_status +    end -  HTTP_RESPONSES = [ -                     "HTTP/1.0 200 OK", -                     "HTTP/1.1 200 OK", -                     "HTTP/1.1 302 Found", -                   ].freeze +    HTTP_RESPONSES = [ +                       "HTTP/1.0 200 OK", +                       "HTTP/1.1 200 OK", +                       "HTTP/1.1 302 Found", +                     ].freeze -  OK_RESPONSES = { -                   "http"  => HTTP_RESPONSES, -                   "https" => HTTP_RESPONSES, -                   "ftp"   => ["OK"], -                 }.freeze +    OK_RESPONSES = { +                     "http"  => HTTP_RESPONSES, +                     "https" => HTTP_RESPONSES, +                     "ftp"   => ["OK"], +                   }.freeze -  def _check_response_status -    ok = OK_RESPONSES[cask.url.scheme] -    return if ok.include?(@response_status) -    add_error "unexpected http response, expecting #{ok.map(&:utf8_inspect).join(' or ')}, got #{@response_status.utf8_inspect}" -  end +    def _check_response_status +      ok = OK_RESPONSES[cask.url.scheme] +      return if ok.include?(@response_status) +      add_error "unexpected http response, expecting #{ok.map(&:utf8_inspect).join(" or ")}, got #{@response_status.utf8_inspect}" +    end -  def _get_data_from_request -    response = @fetcher.head(cask.url) +    def _get_data_from_request +      response = @fetcher.head(cask.url) -    if response.empty? -      add_error "timeout while requesting #{cask.url}" -      return -    end +      if response.empty? +        add_error "timeout while requesting #{cask.url}" +        return +      end -    response_lines = response.split("\n").map(&:chomp) +      response_lines = response.split("\n").map(&:chomp) -    case cask.url.scheme -    when "http", "https" then -      @response_status = response_lines.grep(%r{^HTTP}).last -      if @response_status.respond_to?(:strip) -        @response_status.strip! -        unless response_lines.index(@response_status).nil? -          http_headers = response_lines[(response_lines.index(@response_status) + 1)..-1] -          http_headers.each do |line| -            header_name, header_value = line.split(": ") -            @headers[header_name] = header_value +      case cask.url.scheme +      when "http", "https" then +        @response_status = response_lines.grep(%r{^HTTP}).last +        if @response_status.respond_to?(:strip) +          @response_status.strip! +          unless response_lines.index(@response_status).nil? +            http_headers = response_lines[(response_lines.index(@response_status) + 1)..-1] +            http_headers.each do |line| +              header_name, header_value = line.split(": ") +              @headers[header_name] = header_value +            end            end          end +      when "ftp" then +        @response_status = "OK" +        response_lines.each do |line| +          header_name, header_value = line.split(": ") +          @headers[header_name] = header_value +        end +      else +        add_error "unknown scheme for #{cask.url}"        end -    when "ftp" then -      @response_status = "OK" -      response_lines.each do |line| -        header_name, header_value = line.split(": ") -        @headers[header_name] = header_value -      end -    else -      add_error "unknown scheme for #{cask.url}"      end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/utils.rb b/Library/Homebrew/cask/lib/hbc/utils.rb index 599127523..9159544a6 100644 --- a/Library/Homebrew/cask/lib/hbc/utils.rb +++ b/Library/Homebrew/cask/lib/hbc/utils.rb @@ -1,5 +1,3 @@ -module Hbc::Utils; end -  require "yaml"  require "open3"  require "stringio" @@ -32,165 +30,168 @@ end  # global methods  def odebug(title, *sput) -  if Hbc.respond_to?(:debug) && 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 sput unless sput.empty? +  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 sput unless sput.empty?  end -module Hbc::Utils -  def self.which(cmd, path = ENV["PATH"]) -    unless File.basename(cmd) == cmd.to_s -      # cmd contains a directory element +module Hbc +  module Utils +    def self.which(cmd, path = ENV["PATH"]) +      unless File.basename(cmd) == cmd.to_s +        # cmd contains a directory element +        cmd_pn = Pathname(cmd) +        return nil unless cmd_pn.absolute? +        return resolve_executable(cmd_pn) +      end +      path.split(File::PATH_SEPARATOR).each do |elt| +        fq_cmd = Pathname(elt).expand_path.join(cmd) +        resolved = resolve_executable fq_cmd +        return resolved if resolved +      end +      nil +    end + +    def self.resolve_executable(cmd)        cmd_pn = Pathname(cmd) -      return nil unless cmd_pn.absolute? -      return resolve_executable(cmd_pn) +      return nil unless cmd_pn.exist? +      return nil unless cmd_pn.executable? +      begin +        cmd_pn = Pathname(cmd_pn.realpath) +      rescue RuntimeError +        return nil +      end +      return nil unless cmd_pn.file? +      cmd_pn      end -    path.split(File::PATH_SEPARATOR).each do |elt| -      fq_cmd = Pathname(elt).expand_path.join(cmd) -      resolved = resolve_executable fq_cmd -      return resolved if resolved + +    def self.gain_permissions_remove(path, command: SystemCommand) +      if path.respond_to?(:rmtree) && path.exist? +        gain_permissions(path, ["-R"], command, &:rmtree) +      elsif File.symlink?(path) +        gain_permissions(path, ["-h"], command, &FileUtils.method(:rm_f)) +      end      end -    nil -  end -  def self.resolve_executable(cmd) -    cmd_pn = Pathname(cmd) -    return nil unless cmd_pn.exist? -    return nil unless cmd_pn.executable? -    begin -      cmd_pn = Pathname(cmd_pn.realpath) -    rescue RuntimeError -      return nil +    def self.gain_permissions(path, command_args, command) +      tried_permissions = false +      tried_ownership = false +      begin +        yield path +      rescue StandardError +        # in case of permissions problems +        unless tried_permissions +          # TODO: Better handling for the case where path is a symlink. +          #       The -h and -R flags cannot be combined, and behavior is +          #       dependent on whether the file argument has a trailing +          #       slash.  This should do the right thing, but is fragile. +          command.run("/usr/bin/chflags", +                      must_succeed: false, +                      args:         command_args + ["--", "000", path]) +          command.run("/bin/chmod", +                      must_succeed: false, +                      args:         command_args + ["--", "u+rwx", path]) +          command.run("/bin/chmod", +                      must_succeed: false, +                      args:         command_args + ["-N", path]) +          tried_permissions = true +          retry # rmtree +        end +        unless tried_ownership +          # in case of ownership problems +          # TODO: Further examine files to see if ownership is the problem +          #       before using sudo+chown +          ohai "Using sudo to gain ownership of path '#{path}'" +          command.run("/usr/sbin/chown", +                      args: command_args + ["--", current_user, path], +                      sudo: true) +          tried_ownership = true +          # retry chflags/chmod after chown +          tried_permissions = false +          retry # rmtree +        end +      end      end -    return nil unless cmd_pn.file? -    cmd_pn -  end -  def self.gain_permissions_remove(path, command: Hbc::SystemCommand) -    if path.respond_to?(:rmtree) && path.exist? -      gain_permissions(path, ["-R"], command, &:rmtree) -    elsif File.symlink?(path) -      gain_permissions(path, ["-h"], command, &FileUtils.method(:rm_f)) +    def self.current_user +      Etc.getpwuid(Process.euid).name      end -  end -  def self.gain_permissions(path, command_args, command) -    tried_permissions = false -    tried_ownership = false -    begin -      yield path -    rescue StandardError -      # in case of permissions problems -      unless tried_permissions -        # TODO: Better handling for the case where path is a symlink. -        #       The -h and -R flags cannot be combined, and behavior is -        #       dependent on whether the file argument has a trailing -        #       slash.  This should do the right thing, but is fragile. -        command.run("/usr/bin/chflags", -                    must_succeed: false, -                    args:         command_args + ["--", "000", path]) -        command.run("/bin/chmod", -                    must_succeed: false, -                    args:         command_args + ["--", "u+rwx", path]) -        command.run("/bin/chmod", -                    must_succeed: false, -                    args:         command_args + ["-N", path]) -        tried_permissions = true -        retry # rmtree +    # paths that "look" descendant (textually) will still +    # return false unless both the given paths exist +    def self.file_is_descendant(file, dir) +      file = Pathname.new(file) +      dir  = Pathname.new(dir) +      return false unless file.exist? && dir.exist? +      unless dir.directory? +        onoe "Argument must be a directory: '#{dir}'" +        return false        end -      unless tried_ownership -        # in case of ownership problems -        # TODO: Further examine files to see if ownership is the problem -        #       before using sudo+chown -        ohai "Using sudo to gain ownership of path '#{path}'" -        command.run("/usr/sbin/chown", -                    args: command_args + ["--", current_user, path], -                    sudo: true) -        tried_ownership = true -        # retry chflags/chmod after chown -        tried_permissions = false -        retry # rmtree +      unless file.absolute? && dir.absolute? +        onoe "Both arguments must be absolute: '#{file}', '#{dir}'" +        return false        end +      while file.parent != file +        return true if File.identical?(file, dir) +        file = file.parent +      end +      false      end -  end -  def self.current_user -    Etc.getpwuid(Process.euid).name -  end - -  # paths that "look" descendant (textually) will still -  # return false unless both the given paths exist -  def self.file_is_descendant(file, dir) -    file = Pathname.new(file) -    dir  = Pathname.new(dir) -    return false unless file.exist? && dir.exist? -    unless dir.directory? -      onoe "Argument must be a directory: '#{dir}'" -      return false -    end -    unless file.absolute? && dir.absolute? -      onoe "Both arguments must be absolute: '#{file}', '#{dir}'" -      return false -    end -    while file.parent != file -      return true if File.identical?(file, dir) -      file = file.parent +    def self.path_occupied?(path) +      File.exist?(path) || File.symlink?(path)      end -    false -  end - -  def self.path_occupied?(path) -    File.exist?(path) || File.symlink?(path) -  end -  def self.error_message_with_suggestions -    <<-EOS.undent -      Most likely, this means you have an outdated version of Homebrew-Cask. Please run: +    def self.error_message_with_suggestions +      <<-EOS.undent +        Most likely, this means you have an outdated version of Homebrew-Cask. Please run: -          #{Tty.green}#{UPDATE_CMD} +            #{Tty.green}#{UPDATE_CMD} -      #{Tty.reset}If this doesn’t fix the problem, please report this bug: +        #{Tty.reset}If this doesn’t fix the problem, please report this bug: -          #{Tty.em}#{ISSUES_URL}#{Tty.reset} +            #{Tty.em}#{ISSUES_URL}#{Tty.reset} -    EOS -  end +      EOS +    end -  def self.method_missing_message(method, token, section = nil) -    poo = [] -    poo << "Unexpected method '#{method}' called" -    poo << "during #{section}" if section -    poo << "on Cask #{token}." +    def self.method_missing_message(method, token, section = nil) +      poo = [] +      poo << "Unexpected method '#{method}' called" +      poo << "during #{section}" if section +      poo << "on Cask #{token}." -    opoo(poo.join(" ") + "\n" + error_message_with_suggestions) -  end +      opoo(poo.join(" ") + "\n" + error_message_with_suggestions) +    end -  def self.nowstamp_metadata_path(container_path) -    @timenow ||= Time.now.gmtime -    if container_path.respond_to?(:join) -      precision = 3 -      timestamp = @timenow.strftime("%Y%m%d%H%M%S") -      fraction = format("%.#{precision}f", @timenow.to_f - @timenow.to_i)[1..-1] -      timestamp.concat(fraction) -      container_path.join(timestamp) +    def self.nowstamp_metadata_path(container_path) +      @timenow ||= Time.now.gmtime +      if container_path.respond_to?(:join) +        precision = 3 +        timestamp = @timenow.strftime("%Y%m%d%H%M%S") +        fraction = format("%.#{precision}f", @timenow.to_f - @timenow.to_i)[1..-1] +        timestamp.concat(fraction) +        container_path.join(timestamp) +      end      end -  end -  def self.size_in_bytes(files) -    Array(files).reduce(0) { |a, e| a + (File.size?(e) || 0) } -  end +    def self.size_in_bytes(files) +      Array(files).reduce(0) { |a, e| a + (File.size?(e) || 0) } +    end -  def self.capture_stderr -    previous_stderr = $stderr -    $stderr = StringIO.new -    yield -    $stderr.string -  ensure -    $stderr = previous_stderr +    def self.capture_stderr +      previous_stderr = $stderr +      $stderr = StringIO.new +      yield +      $stderr.string +    ensure +      $stderr = previous_stderr +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/utils/file.rb b/Library/Homebrew/cask/lib/hbc/utils/file.rb index 967c6834f..6b80f33ce 100644 --- a/Library/Homebrew/cask/lib/hbc/utils/file.rb +++ b/Library/Homebrew/cask/lib/hbc/utils/file.rb @@ -1,12 +1,14 @@ -module Hbc::Utils -  module_function +module Hbc +  module Utils +    module_function -  def file_locked?(file) -    unlocked = File.open(file).flock(File::LOCK_EX | File::LOCK_NB) -    # revert lock if file was unlocked before check -    File.open(file).flock(File::LOCK_UN) if unlocked -    !unlocked -  rescue -    true +    def file_locked?(file) +      unlocked = File.open(file).flock(File::LOCK_EX | File::LOCK_NB) +      # revert lock if file was unlocked before check +      File.open(file).flock(File::LOCK_UN) if unlocked +      !unlocked +    rescue +      true +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/verify.rb b/Library/Homebrew/cask/lib/hbc/verify.rb index d3c2713e7..dbf3d0e88 100644 --- a/Library/Homebrew/cask/lib/hbc/verify.rb +++ b/Library/Homebrew/cask/lib/hbc/verify.rb @@ -1,33 +1,33 @@ -module Hbc::Verify; end -  require "hbc/verify/checksum"  require "hbc/verify/gpg" -module Hbc::Verify -  module_function +module Hbc +  module Verify +    module_function -  def verifications -    [ -      Hbc::Verify::Checksum -      # TODO: Hbc::Verify::Gpg -    ] -  end +    def verifications +      [ +        Hbc::Verify::Checksum +        # TODO: Hbc::Verify::Gpg +      ] +    end -  def all(cask, downloaded_path) -    odebug "Verifying download" -    verifications = for_cask(cask) -    odebug "#{verifications.size} verifications defined", verifications -    verifications.each do |verification| -      odebug "Running verification of class #{verification}" -      verification.new(cask, downloaded_path).verify +    def all(cask, downloaded_path) +      odebug "Verifying download" +      verifications = for_cask(cask) +      odebug "#{verifications.size} verifications defined", verifications +      verifications.each do |verification| +        odebug "Running verification of class #{verification}" +        verification.new(cask, downloaded_path).verify +      end      end -  end -  def for_cask(cask) -    odebug "Determining which verifications to run for Cask #{cask}" -    verifications.select do |verification| -      odebug "Checking for verification class #{verification}" -      verification.me?(cask) +    def for_cask(cask) +      odebug "Determining which verifications to run for Cask #{cask}" +      verifications.select do |verification| +        odebug "Checking for verification class #{verification}" +        verification.me?(cask) +      end      end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/verify/checksum.rb b/Library/Homebrew/cask/lib/hbc/verify/checksum.rb index 3af6f1667..d079a4446 100644 --- a/Library/Homebrew/cask/lib/hbc/verify/checksum.rb +++ b/Library/Homebrew/cask/lib/hbc/verify/checksum.rb @@ -1,43 +1,47 @@  require "digest" -class Hbc::Verify::Checksum -  def self.me?(cask) -    return true unless cask.sha256 == :no_check -    ohai "No checksum defined for Cask #{cask}, skipping verification" -    false -  end - -  attr_reader :cask, :downloaded_path - -  def initialize(cask, downloaded_path) -    @cask = cask -    @downloaded_path = downloaded_path -  end - -  def verify -    return unless self.class.me?(cask) -    ohai "Verifying checksum for Cask #{cask}" -    verify_checksum -  end - -  private - -  def expected -    @expected ||= cask.sha256 -  end - -  def computed -    @computed ||= Digest::SHA2.file(downloaded_path).hexdigest -  end - -  def verify_checksum -    raise Hbc::CaskSha256MissingError, "sha256 required: sha256 '#{computed}'" if expected.nil? || expected.empty? - -    if expected == computed -      odebug "SHA256 checksums match" -    else -      ohai 'Note: running "brew update" may fix sha256 checksum errors' -      raise Hbc::CaskSha256MismatchError.new(downloaded_path, expected, computed) +module Hbc +  module Verify +    class Checksum +      def self.me?(cask) +        return true unless cask.sha256 == :no_check +        ohai "No checksum defined for Cask #{cask}, skipping verification" +        false +      end + +      attr_reader :cask, :downloaded_path + +      def initialize(cask, downloaded_path) +        @cask = cask +        @downloaded_path = downloaded_path +      end + +      def verify +        return unless self.class.me?(cask) +        ohai "Verifying checksum for Cask #{cask}" +        verify_checksum +      end + +      private + +      def expected +        @expected ||= cask.sha256 +      end + +      def computed +        @computed ||= Digest::SHA2.file(downloaded_path).hexdigest +      end + +      def verify_checksum +        raise CaskSha256MissingError, "sha256 required: sha256 '#{computed}'" if expected.nil? || expected.empty? + +        if expected == computed +          odebug "SHA256 checksums match" +        else +          ohai 'Note: running "brew update" may fix sha256 checksum errors' +          raise CaskSha256MismatchError.new(downloaded_path, expected, computed) +        end +      end      end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/verify/gpg.rb b/Library/Homebrew/cask/lib/hbc/verify/gpg.rb index 6190f67d1..6eb5fc23b 100644 --- a/Library/Homebrew/cask/lib/hbc/verify/gpg.rb +++ b/Library/Homebrew/cask/lib/hbc/verify/gpg.rb @@ -1,60 +1,64 @@ -class Hbc::Verify::Gpg -  def self.me?(cask) -    cask.gpg -  end +module Hbc +  module Verify +    class Gpg +      def self.me?(cask) +        cask.gpg +      end -  attr_reader :cask, :downloaded_path +      attr_reader :cask, :downloaded_path -  def initialize(cask, downloaded_path, command = Hbc::SystemCommand) -    @command = command -    @cask = cask -    @downloaded_path = downloaded_path -  end +      def initialize(cask, downloaded_path, command = Hbc::SystemCommand) +        @command = command +        @cask = cask +        @downloaded_path = downloaded_path +      end -  def available? -    return @available unless @available.nil? -    @available = self.class.me?(cask) && installed? -  end +      def available? +        return @available unless @available.nil? +        @available = self.class.me?(cask) && installed? +      end -  def installed? -    cmd = @command.run("/usr/bin/type", -                       args: ["-p", "gpg"]) +      def installed? +        cmd = @command.run("/usr/bin/type", +                           args: ["-p", "gpg"]) -    # if `gpg` is found, return its absolute path -    cmd.success? ? cmd.stdout : false -  end +        # if `gpg` is found, return its absolute path +        cmd.success? ? cmd.stdout : false +      end -  def fetch_sig(force = false) -    unversioned_cask = cask.version.is_a?(Symbol) -    cached = cask.metadata_subdir("gpg") unless unversioned_cask +      def fetch_sig(force = false) +        unversioned_cask = cask.version.is_a?(Symbol) +        cached = cask.metadata_subdir("gpg") unless unversioned_cask -    meta_dir = cached || cask.metadata_subdir("gpg", :now, true) -    sig_path = meta_dir.join("signature.asc") +        meta_dir = cached || cask.metadata_subdir("gpg", :now, true) +        sig_path = meta_dir.join("signature.asc") -    curl(cask.gpg.signature, "-o", sig_path.to_s) unless cached || force +        curl(cask.gpg.signature, "-o", sig_path.to_s) unless cached || force -    sig_path -  end +        sig_path +      end -  def import_key -    args = if cask.gpg.key_id -             ["--recv-keys", cask.gpg.key_id] -           elsif cask.gpg.key_url -             ["--fetch-key", cask.gpg.key_url.to_s] -           end +      def import_key +        args = if cask.gpg.key_id +                 ["--recv-keys", cask.gpg.key_id] +               elsif cask.gpg.key_url +                 ["--fetch-key", cask.gpg.key_url.to_s] +               end -    @command.run!("gpg", args: args) -  end +        @command.run!("gpg", args: args) +      end -  def verify -    return unless available? -    import_key -    sig = fetch_sig +      def verify +        return unless available? +        import_key +        sig = fetch_sig -    ohai "Verifying GPG signature for #{cask}" +        ohai "Verifying GPG signature for #{cask}" -    @command.run!("gpg", -                  args:         ["--verify", sig, downloaded_path], -                  print_stdout: true) +        @command.run!("gpg", +                      args:         ["--verify", sig, downloaded_path], +                      print_stdout: true) +      end +    end    end  end diff --git a/Library/Homebrew/cask/lib/hbc/without_source.rb b/Library/Homebrew/cask/lib/hbc/without_source.rb index 6ed826e41..69131d5c7 100644 --- a/Library/Homebrew/cask/lib/hbc/without_source.rb +++ b/Library/Homebrew/cask/lib/hbc/without_source.rb @@ -1,15 +1,17 @@ -class Hbc::WithoutSource < Hbc::Cask -  # Override from `Hbc::DSL` because we don't have a cask source file to work -  # with, so we don't know the cask's `version`. -  def staged_path -    (caskroom_path.children - [metadata_master_container_path]).first -  end +module Hbc +  class WithoutSource < Cask +    # Override from `Hbc::DSL` because we don't have a cask source file to work +    # with, so we don't know the cask's `version`. +    def staged_path +      (caskroom_path.children - [metadata_master_container_path]).first +    end -  def to_s -    "#{token} (!)" -  end +    def to_s +      "#{token} (!)" +    end -  def installed? -    caskroom_path.exist? +    def installed? +      caskroom_path.exist? +    end    end  end  | 
