Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

edge case handleing #18621

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Library/Homebrew/api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ def self.fetch(endpoint)
cache[endpoint] = JSON.parse(output.stdout, freeze: true)
rescue JSON::ParserError
raise ArgumentError, "Invalid JSON file: #{Tty.underline}#{api_url}#{Tty.reset}"
rescue => e
raise "An error occurred while fetching the API response: #{e.message}"
end

sig {
Expand Down Expand Up @@ -104,6 +106,8 @@ def self.fetch_json_api_file(endpoint, target: HOMEBREW_CACHE_API/endpoint,
odie "Cannot download non-corrupt #{url}!" if retry_count > Homebrew::EnvConfig.curl_retries.to_i

retry
rescue => e
raise "An error occurred while fetching the JSON API file: #{e.message}"
end

if endpoint.end_with?(".jws.json")
Expand Down
3 changes: 3 additions & 0 deletions Library/Homebrew/build.rb
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,9 @@ def install
end
end
end
rescue => e
onoe "An error occurred during the installation of #{formula.full_name}: #{e.message}"
raise
end
end

Expand Down
4 changes: 4 additions & 0 deletions Library/Homebrew/cask_dependent.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ class Requirement < ::Requirement
attr_reader :cask

def initialize(cask)
raise ArgumentError, "Cask cannot be nil" if cask.nil?

@cask = cask
end

Expand All @@ -27,6 +29,8 @@ def full_name
end

def runtime_dependencies
raise "Cask is not installed" unless @cask.installed?

deps.flat_map { |dep| [dep, *dep.to_formula.runtime_dependencies] }.uniq
end

Expand Down
8 changes: 8 additions & 0 deletions Library/Homebrew/cmd/deps.rb
Original file line number Diff line number Diff line change
Expand Up @@ -226,10 +226,18 @@ def deps_for_dependent(dependency, recursive: false)
end

deps + reqs.to_a
rescue => e
onoe "Error processing dependency: #{dependency.name}"
onoe e.message
[]
end

def deps_for_dependents(dependents, recursive: false, &block)
dependents.map { |d| deps_for_dependent(d, recursive:) }.reduce(&block)
rescue => e
onoe "Error processing dependents"
onoe e.message
[]
end

def check_head_spec(dependents)
Expand Down
20 changes: 20 additions & 0 deletions Library/Homebrew/debrew.rb
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,30 @@ def self.debug(exception)
puts "When you exit this shell, you will return to the menu."
interactive_shell
end

menu.choice(:log) do
puts "Logging exception details to a file."
log_exception_details(exception)
end

menu.choice(:retry) do
puts "Retrying the operation."
return :retry
end
end
end
ensure
mu_unlock
end
end

def self.log_exception_details(exception)
File.open("debrew_exception.log", "a") do |file|
file.puts "Exception: #{exception.class.name}"
file.puts "Message: #{exception.message}"
file.puts "Backtrace:"
exception.backtrace.each { |line| file.puts line }
file.puts "-" * 40
end
end
end
6 changes: 6 additions & 0 deletions Library/Homebrew/dependency.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ def installed?(minimum_version: nil, minimum_revision: nil)
else
installed_version.version > minimum_version
end
rescue => e
raise "Error checking if dependency is installed: #{e.message}"
end

def satisfied?(inherited_options = [], minimum_version: nil, minimum_revision: nil)
Expand Down Expand Up @@ -139,6 +141,10 @@ def expand(dependent, deps = dependent.deps, cache_key: nil, &block)
deps.each do |dep|
next if dependent.name == dep.name

if @expand_stack.include?(dep.name)
raise "Circular dependency detected: #{dependent.name} -> #{dep.name}"
end

case action(dependent, dep, &block)
when :prune
next
Expand Down
4 changes: 4 additions & 0 deletions Library/Homebrew/dependency_collector.rb
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ def parse_spec(spec, tags)
spec
when Class
parse_class_spec(spec, tags)
else
raise ArgumentError, "Unsupported dependency specification: #{spec.inspect}"
end
end

Expand Down Expand Up @@ -218,6 +220,8 @@ def parse_url_spec(url, tags)
when ".lz" then Dependency.new("lzip", [*tags, :implicit])
when ".rar" then Dependency.new("libarchive", [*tags, :implicit])
when ".7z" then Dependency.new("p7zip", [*tags, :implicit])
else
raise ArgumentError, "Unsupported URL extension: #{File.extname(url)}"
end
end
end
Expand Down
21 changes: 21 additions & 0 deletions Library/Homebrew/exceptions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -791,3 +791,24 @@ def initialize(strongly_connected_components)
EOS
end
end

# Raised when a dependency is missing.
class MissingDependencyError < RuntimeError
def initialize(dependency)
super "Missing dependency: #{dependency}"
end
end

# Raised when a circular dependency is detected.
class CircularDependencyError < RuntimeError
def initialize(dependency)
super "Circular dependency detected: #{dependency}"
end
end

# Raised when a dependency installation fails.
class DependencyInstallationError < RuntimeError
def initialize(dependency, reason)
super "Failed to install dependency #{dependency}: #{reason}"
end
end
26 changes: 26 additions & 0 deletions Library/Homebrew/formula_assertions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,31 @@ def pipe_output(cmd, input = nil, result = nil)
puts output if verbose?
raise
end

# Asserts that the given block raises an exception of the specified type.
#
# @api public
sig { params(exception: T.class_of(Exception), message: T.nilable(String)).void }
def assert_raises(exception, message = nil, &block)
raised = false
begin
block.call
rescue exception
raised = true
end
assert raised, message || "Expected #{exception} to be raised"
end

# Asserts that the given block does not raise any exceptions.
#
# @api public
sig { params(message: T.nilable(String)).void }
def assert_nothing_raised(message = nil, &block)
begin
block.call
rescue Exception => e
flunk message || "Expected no exceptions, but raised #{e.class}: #{e.message}"
end
end
end
end
8 changes: 7 additions & 1 deletion Library/Homebrew/formula_auditor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ def audit_file
[versioned_aliases, valid_main_alias_names, valid_other_alias_names].each do |array|
array.map! { |a| "#{formula.tap}/#{a}" }
end

end

valid_versioned_aliases = versioned_aliases & valid_main_alias_names
Expand Down Expand Up @@ -985,7 +986,12 @@ def audit
next if only_audits&.exclude?(name)
next if except_audits&.include?(name)

send(audit_method_name)
begin
send(audit_method_name)
rescue => e
problem "Error during audit: #{e.message}"
next
end
end
end

Expand Down
5 changes: 4 additions & 1 deletion Library/Homebrew/formula_installer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,7 @@ def install
if pour_bottle?
begin
pour
rescue Exception # rubocop:disable Lint/RescueException
rescue Exception => e # rubocop:disable Lint/RescueException
# any exceptions must leave us with nothing installed
ignore_interrupts do
begin
Expand Down Expand Up @@ -530,6 +530,9 @@ def install
opoo "Nothing was installed to #{formula.prefix}" unless formula.latest_version_installed?
end_time = Time.now
Homebrew.messages.package_installed(formula.name, end_time - start_time)
rescue Exception => e # rubocop:disable Lint/RescueException
onoe "An error occurred during the installation of #{formula.full_name}: #{e.message}"
raise
end

sig { void }
Expand Down
Loading