From 3b4ee58c491f164c2751c1c0f941568c35fb0ac6 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Mon, 26 Jun 2017 07:30:28 +0200 Subject: Refactor using `Forwardable` and `DelegateClass`. --- Library/Homebrew/cask/lib/hbc/artifact/base.rb | 10 +++------- Library/Homebrew/cask/lib/hbc/cask.rb | 2 -- Library/Homebrew/cask/lib/hbc/checkable.rb | 14 ++++++-------- Library/Homebrew/cask/lib/hbc/installer.rb | 19 +++---------------- Library/Homebrew/cask/lib/hbc/url.rb | 2 -- Library/Homebrew/cask/lib/hbc/utils.rb | 8 ++++---- 6 files changed, 16 insertions(+), 39 deletions(-) (limited to 'Library/Homebrew/cask') diff --git a/Library/Homebrew/cask/lib/hbc/artifact/base.rb b/Library/Homebrew/cask/lib/hbc/artifact/base.rb index 2d9330b13..ae15552a4 100644 --- a/Library/Homebrew/cask/lib/hbc/artifact/base.rb +++ b/Library/Homebrew/cask/lib/hbc/artifact/base.rb @@ -1,6 +1,8 @@ module Hbc module Artifact class Base + extend Predicable + def self.artifact_name @artifact_name ||= name.sub(/^.*:/, "").gsub(/(.)([A-Z])/, '\1_\2').downcase end @@ -65,13 +67,7 @@ module Hbc {} end - def verbose? - @verbose - end - - def force? - @force - end + attr_predicate :force?, :verbose? def initialize(cask, command: SystemCommand, force: false, verbose: false) @cask = cask diff --git a/Library/Homebrew/cask/lib/hbc/cask.rb b/Library/Homebrew/cask/lib/hbc/cask.rb index e1cdb5dea..4a410f4c7 100644 --- a/Library/Homebrew/cask/lib/hbc/cask.rb +++ b/Library/Homebrew/cask/lib/hbc/cask.rb @@ -1,5 +1,3 @@ -require "forwardable" - require "hbc/dsl" require "hbc/metadata" diff --git a/Library/Homebrew/cask/lib/hbc/checkable.rb b/Library/Homebrew/cask/lib/hbc/checkable.rb index 03f052629..604dd3f89 100644 --- a/Library/Homebrew/cask/lib/hbc/checkable.rb +++ b/Library/Homebrew/cask/lib/hbc/checkable.rb @@ -1,29 +1,27 @@ module Hbc module Checkable def errors - Array(@errors) + @errors ||= [] end def warnings - Array(@warnings) + @warnings ||= [] end def add_error(message) - @errors ||= [] - @errors << message + errors << message end def add_warning(message) - @warnings ||= [] - @warnings << message + warnings << message end def errors? - Array(@errors).any? + errors.any? end def warnings? - Array(@warnings).any? + warnings.any? end def result diff --git a/Library/Homebrew/cask/lib/hbc/installer.rb b/Library/Homebrew/cask/lib/hbc/installer.rb index aa6d600f7..0477cbd22 100644 --- a/Library/Homebrew/cask/lib/hbc/installer.rb +++ b/Library/Homebrew/cask/lib/hbc/installer.rb @@ -6,6 +6,7 @@ require "hbc/verify" module Hbc class Installer + extend Predicable # 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 @@ -27,21 +28,7 @@ module Hbc @reinstall = false end - def skip_cask_deps? - @skip_cask_deps - end - - def force? - @force - end - - def binaries? - @binaries - end - - def verbose? - @verbose - end + attr_predicate :binaries?, :force?, :skip_cask_deps?, :require_sha?, :verbose? def self.print_caveats(cask) odebug "Printing caveats" @@ -75,7 +62,7 @@ module Hbc odebug "Hbc::Installer#fetch" satisfy_dependencies - verify_has_sha if @require_sha && !force? + verify_has_sha if require_sha? && !force? download verify end diff --git a/Library/Homebrew/cask/lib/hbc/url.rb b/Library/Homebrew/cask/lib/hbc/url.rb index 07b41fb80..15da2ced2 100644 --- a/Library/Homebrew/cask/lib/hbc/url.rb +++ b/Library/Homebrew/cask/lib/hbc/url.rb @@ -1,5 +1,3 @@ -require "forwardable" - module Hbc class URL FAKE_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10) https://caskroom.github.io".freeze diff --git a/Library/Homebrew/cask/lib/hbc/utils.rb b/Library/Homebrew/cask/lib/hbc/utils.rb index 59e85aaeb..f23ce059c 100644 --- a/Library/Homebrew/cask/lib/hbc/utils.rb +++ b/Library/Homebrew/cask/lib/hbc/utils.rb @@ -14,14 +14,14 @@ class Object end class Buffer < StringIO + extend Predicable + + attr_predicate :tty? + def initialize(tty = false) super() @tty = tty end - - def tty? - @tty - end end # global methods -- cgit v1.2.3 From 2703646b1008e8fc0a922e4677d9b2aadcea4b4d Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Tue, 27 Jun 2017 11:55:23 +0200 Subject: Remove `utf8_inspect` method. --- Library/Homebrew/cask/lib/hbc/download_strategy.rb | 2 +- Library/Homebrew/cask/lib/hbc/system_command.rb | 6 +++--- Library/Homebrew/cask/lib/hbc/url_checker.rb | 2 +- Library/Homebrew/cask/lib/hbc/utils.rb | 9 --------- 4 files changed, 5 insertions(+), 14 deletions(-) (limited to 'Library/Homebrew/cask') diff --git a/Library/Homebrew/cask/lib/hbc/download_strategy.rb b/Library/Homebrew/cask/lib/hbc/download_strategy.rb index 5b32b4840..28ae704ee 100644 --- a/Library/Homebrew/cask/lib/hbc/download_strategy.rb +++ b/Library/Homebrew/cask/lib/hbc/download_strategy.rb @@ -100,7 +100,7 @@ module Hbc end def _fetch - odebug "Calling curl with args #{cask_curl_args.utf8_inspect}" + odebug "Calling curl with args #{cask_curl_args}" curl(*cask_curl_args) end diff --git a/Library/Homebrew/cask/lib/hbc/system_command.rb b/Library/Homebrew/cask/lib/hbc/system_command.rb index 6414a9e80..901617b71 100644 --- a/Library/Homebrew/cask/lib/hbc/system_command.rb +++ b/Library/Homebrew/cask/lib/hbc/system_command.rb @@ -20,7 +20,7 @@ module Hbc def run! @processed_output = { stdout: "", stderr: "" } - odebug "Executing: #{expanded_command.utf8_inspect}" + odebug "Executing: #{expanded_command}" each_output_line do |type, line| case type @@ -62,7 +62,7 @@ module Hbc def assert_success return if processed_status && processed_status.success? - raise CaskCommandFailedError.new(command.utf8_inspect, processed_output[:stdout], processed_output[:stderr], processed_status) + raise CaskCommandFailedError.new(command, processed_output[:stdout], processed_output[:stderr], processed_status) end def expanded_command @@ -162,7 +162,7 @@ module Hbc raise CaskError, <<-EOS Empty result parsing plist output from command. command was: - #{command.utf8_inspect} + #{command} output we attempted to parse: #{output} EOS diff --git a/Library/Homebrew/cask/lib/hbc/url_checker.rb b/Library/Homebrew/cask/lib/hbc/url_checker.rb index 60a15ca2f..7076b13c5 100644 --- a/Library/Homebrew/cask/lib/hbc/url_checker.rb +++ b/Library/Homebrew/cask/lib/hbc/url_checker.rb @@ -38,7 +38,7 @@ module Hbc 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}" + add_error "unexpected http response, expecting #{ok.map(&:to_s).join(" or ")}, got #{@response_status}" end def _get_data_from_request diff --git a/Library/Homebrew/cask/lib/hbc/utils.rb b/Library/Homebrew/cask/lib/hbc/utils.rb index f23ce059c..22f826e74 100644 --- a/Library/Homebrew/cask/lib/hbc/utils.rb +++ b/Library/Homebrew/cask/lib/hbc/utils.rb @@ -4,15 +4,6 @@ require "stringio" BUG_REPORTS_URL = "https://github.com/caskroom/homebrew-cask#reporting-bugs".freeze -# monkeypatch Object - not a great idea -class Object - def utf8_inspect - return inspect unless defined?(Encoding) - return map(&:utf8_inspect) if respond_to?(:map) - inspect.force_encoding("UTF-8").sub(/\A"(.*)"\Z/, '\1') - end -end - class Buffer < StringIO extend Predicable -- cgit v1.2.3 From 96271aaa89c47cf4f0ff10e8e9a165c1ac2cdb73 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 28 Jun 2017 09:25:14 +0200 Subject: Use `attr_reader` in `CaskLoader`. --- Library/Homebrew/cask/lib/hbc/cask_loader.rb | 43 +++++++++++++++------------- 1 file changed, 23 insertions(+), 20 deletions(-) (limited to 'Library/Homebrew/cask') diff --git a/Library/Homebrew/cask/lib/hbc/cask_loader.rb b/Library/Homebrew/cask/lib/hbc/cask_loader.rb index 43fd9080d..8cd010ef6 100644 --- a/Library/Homebrew/cask/lib/hbc/cask_loader.rb +++ b/Library/Homebrew/cask/lib/hbc/cask_loader.rb @@ -1,12 +1,14 @@ module Hbc module CaskLoader class FromContentLoader + attr_reader :content + def initialize(content) @content = content end def load - instance_eval(@content.force_encoding("UTF-8"), __FILE__, __LINE__) + instance_eval(content.force_encoding("UTF-8"), __FILE__, __LINE__) end private @@ -18,25 +20,25 @@ module Hbc class FromPathLoader < FromContentLoader def self.can_load?(ref) - path = Pathname.new(ref) + path = Pathname(ref) path.extname == ".rb" && path.expand_path.exist? end attr_reader :token, :path def initialize(path) - path = Pathname.new(path).expand_path + path = Pathname(path).expand_path @token = path.basename(".rb").to_s @path = path end def load - raise CaskUnavailableError.new(@token, "'#{@path}' does not exist.") unless @path.exist? - raise CaskUnavailableError.new(@token, "'#{@path}' is not readable.") unless @path.readable? - raise CaskUnavailableError.new(@token, "'#{@path}' is not a file.") unless @path.file? + raise CaskUnavailableError.new(token, "'#{path}' does not exist.") unless path.exist? + raise CaskUnavailableError.new(token, "'#{path}' is not readable.") unless path.readable? + raise CaskUnavailableError.new(token, "'#{path}' is not a file.") unless path.file? - @content = IO.read(@path) + @content = IO.read(path) super end @@ -44,11 +46,11 @@ module Hbc private def cask(header_token, &block) - if @token != header_token - raise CaskTokenMismatchError.new(@token, header_token) + if token != header_token + raise CaskTokenMismatchError.new(token, header_token) end - Cask.new(header_token, sourcefile_path: @path, &block) + Cask.new(header_token, sourcefile_path: path, &block) end end @@ -65,14 +67,13 @@ module Hbc end def load - Hbc.cache.mkpath - FileUtils.rm_f @path + path.dirname.mkpath begin - ohai "Downloading #{@url}." - curl @url, "-o", @path + ohai "Downloading #{url}." + curl url, "-o", path rescue ErrorDuringExecution - raise CaskUnavailableError.new(@token, "Failed to download #{Formatter.url(@url)}.") + raise CaskUnavailableError.new(token, "Failed to download #{Formatter.url(url)}.") end super @@ -84,15 +85,17 @@ module Hbc ref.to_s.match?(HOMEBREW_TAP_CASK_REGEX) end + attr_reader :tap + def initialize(tapped_name) - user, repo, token = tapped_name.split("/", 3).map(&:downcase) + user, repo, token = tapped_name.split("/", 3) @tap = Tap.fetch(user, repo) super @tap.cask_dir/"#{token}.rb" end def load - @tap.install unless @tap.installed? + tap.install unless tap.installed? super end @@ -104,12 +107,12 @@ module Hbc end def initialize(ref) - @token = File.basename(ref, ".rb") - super CaskLoader.default_path(@token) + token = File.basename(ref, ".rb") + super CaskLoader.default_path(token) end def load - raise CaskUnavailableError.new(@token, "No Cask with this name exists.") + raise CaskUnavailableError.new(token, "No Cask with this name exists.") end end -- cgit v1.2.3 From 6a1fa87191bfef31ff1b2d47d3ebf281398a210f Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 28 Jun 2017 17:53:59 +0200 Subject: Refactor Formula/Cask dependencies. --- Library/Homebrew/cask/lib/hbc/cask.rb | 9 +++ Library/Homebrew/cask/lib/hbc/cask_dependencies.rb | 37 ++++++------ Library/Homebrew/cask/lib/hbc/dsl.rb | 4 +- Library/Homebrew/cask/lib/hbc/dsl/depends_on.rb | 4 +- Library/Homebrew/cask/lib/hbc/exceptions.rb | 12 +++- Library/Homebrew/cask/lib/hbc/installer.rb | 67 +++++++++++++--------- 6 files changed, 82 insertions(+), 51 deletions(-) (limited to 'Library/Homebrew/cask') diff --git a/Library/Homebrew/cask/lib/hbc/cask.rb b/Library/Homebrew/cask/lib/hbc/cask.rb index 4a410f4c7..672d18954 100644 --- a/Library/Homebrew/cask/lib/hbc/cask.rb +++ b/Library/Homebrew/cask/lib/hbc/cask.rb @@ -71,6 +71,15 @@ module Hbc @token end + def hash + token.hash + end + + def eql?(other) + token == other.token + end + alias == eql? + def dumpcask 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 8bba5df8e..0edda074e 100644 --- a/Library/Homebrew/cask/lib/hbc/cask_dependencies.rb +++ b/Library/Homebrew/cask/lib/hbc/cask_dependencies.rb @@ -1,35 +1,36 @@ +require "delegate" + require "hbc/topological_hash" module Hbc - class CaskDependencies - attr_reader :cask, :graph, :sorted + class CaskDependencies < DelegateClass(Array) + attr_reader :cask, :graph def initialize(cask) @cask = cask @graph = graph_dependencies - @sorted = sort + super(sort) end - def graph_dependencies - deps_in = ->(csk) { csk.depends_on ? csk.depends_on.cask || [] : [] } - walk = lambda do |acc, deps| - deps.each do |dep| - next if acc.key?(dep) - succs = deps_in.call CaskLoader.load(dep) - acc[dep] = succs - walk.call(acc, succs) - end - acc - end + private - graphed = walk.call({}, @cask.depends_on.cask) - TopologicalHash[graphed] + def graph_dependencies(cask = self.cask, acc = TopologicalHash.new) + return acc if acc.key?(cask) + deps = cask.depends_on.cask.map(&CaskLoader.public_method(:load)) + acc[cask] = deps + deps.each do |dep| + graph_dependencies(dep, acc) + end + acc end def sort - @graph.tsort + raise CaskSelfReferencingDependencyError, cask.token if graph[cask].include?(cask) + graph.tsort - [cask] rescue TSort::Cyclic - raise CaskCyclicCaskDependencyError, @cask.token + strongly_connected_components = graph.strongly_connected_components.sort_by(&:count) + cyclic_dependencies = strongly_connected_components.last - [cask] + raise CaskCyclicDependencyError.new(cask.token, cyclic_dependencies.join(", ")) end end end diff --git a/Library/Homebrew/cask/lib/hbc/dsl.rb b/Library/Homebrew/cask/lib/hbc/dsl.rb index 92245e8fb..112ceb943 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl.rb @@ -211,10 +211,10 @@ module Hbc # 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 + return @depends_on if args.empty? begin - @depends_on.load(*args) unless args.empty? + @depends_on.load(*args) rescue RuntimeError => e raise CaskInvalidError.new(token, e) end diff --git a/Library/Homebrew/cask/lib/hbc/dsl/depends_on.rb b/Library/Homebrew/cask/lib/hbc/dsl/depends_on.rb index a8c1a1b73..bdef4239a 100644 --- a/Library/Homebrew/cask/lib/hbc/dsl/depends_on.rb +++ b/Library/Homebrew/cask/lib/hbc/dsl/depends_on.rb @@ -24,6 +24,8 @@ module Hbc def initialize @pairs ||= {} + @cask ||= [] + @formula ||= [] end def load(pairs = {}) @@ -53,12 +55,10 @@ module Hbc end def formula=(*args) - @formula ||= [] @formula.concat(args) end def cask=(*args) - @cask ||= [] @cask.concat(args) end diff --git a/Library/Homebrew/cask/lib/hbc/exceptions.rb b/Library/Homebrew/cask/lib/hbc/exceptions.rb index d9e1b07db..1a246be65 100644 --- a/Library/Homebrew/cask/lib/hbc/exceptions.rb +++ b/Library/Homebrew/cask/lib/hbc/exceptions.rb @@ -77,9 +77,15 @@ module Hbc end end - class CaskCyclicCaskDependencyError < AbstractCaskErrorWithToken + class CaskCyclicDependencyError < AbstractCaskErrorWithToken def to_s - "Cask '#{token}' includes cyclic dependencies on other Casks and could not be installed." + "Cask '#{token}' includes cyclic dependencies on other Casks" << (reason.empty? ? "." : ": #{reason}") + end + end + + class CaskSelfReferencingDependencyError < CaskCyclicDependencyError + def to_s + "Cask '#{token}' depends on itself." end end @@ -91,7 +97,7 @@ module Hbc class CaskInvalidError < AbstractCaskErrorWithToken def to_s - "Cask '#{token}' definition is invalid" << (reason.empty? ? ".": ": #{reason}") + "Cask '#{token}' definition is invalid" << (reason.empty? ? "." : ": #{reason}") end end diff --git a/Library/Homebrew/cask/lib/hbc/installer.rb b/Library/Homebrew/cask/lib/hbc/installer.rb index 0477cbd22..252205a3b 100644 --- a/Library/Homebrew/cask/lib/hbc/installer.rb +++ b/Library/Homebrew/cask/lib/hbc/installer.rb @@ -1,5 +1,7 @@ require "rubygems" +require "formula_installer" + require "hbc/cask_dependencies" require "hbc/staged" require "hbc/verify" @@ -197,7 +199,6 @@ module Hbc x11_dependencies formula_dependencies cask_dependencies unless skip_cask_deps? - puts "complete" end def macos_dependencies @@ -234,36 +235,50 @@ module Hbc 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(HOMEBREW_BREW_FILE, - args: ["list", "--versions", dep_name], - print_stderr: false).stdout.include?(dep_name) - if installed - puts "already installed" - else - @command.run!(HOMEBREW_BREW_FILE, - args: ["install", dep_name]) - puts "done" + formulae = @cask.depends_on.formula.map { |f| Formula[f] } + return if formulae.empty? + + if formulae.all?(&:any_version_installed?) + puts "All Formula dependencies satisfied." + return + end + + not_installed = formulae.reject(&:any_version_installed?) + + ohai "Installing Formula dependencies: #{not_installed.map(&:to_s).join(", ")}" + not_installed.each do |formula| + begin + old_argv = ARGV.dup + ARGV.replace([]) + FormulaInstaller.new(formula).tap do |fi| + fi.installed_as_dependency = true + fi.installed_on_request = false + fi.show_header = true + fi.verbose = verbose? + fi.prelude + fi.install + fi.finish + end + ensure + ARGV.replace(old_argv) 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 = CaskDependencies.new(@cask) - deps.sorted.each do |dep_token| - puts "#{dep_token} ..." - dep = CaskLoader.load(dep_token) - if dep.installed? - puts "already installed" - else - Installer.new(dep, binaries: binaries?, verbose: verbose?, skip_cask_deps: true, force: false).install - puts "done" - end + return if @cask.depends_on.cask.empty? + casks = CaskDependencies.new(@cask) + + if casks.all?(&:installed?) + puts "All Cask dependencies satisfied." + return + end + + not_installed = casks.reject(&:installed?) + + ohai "Installing Cask dependencies: #{not_installed.map(&:to_s).join(", ")}" + not_installed.each do |cask| + Installer.new(cask, binaries: binaries?, verbose: verbose?, skip_cask_deps: true, force: false).install end end -- cgit v1.2.3