From 6fb271526700cbe44869ed9089a59766ecdd689d Mon Sep 17 00:00:00 2001 From: Luka Vandervelden Date: Fri, 16 Aug 2019 14:55:25 +0200 Subject: [PATCH] Improved error reporting a bit. --- src/context.cr | 1 + src/exception.cr | 32 +++++++++++++++++++++ src/instructions.cr | 3 +- src/main.cr | 35 +++++++++++++++-------- src/recipe.cr | 70 +++++++++++++++++++++++---------------------- 5 files changed, 94 insertions(+), 47 deletions(-) create mode 100644 src/exception.cr diff --git a/src/context.cr b/src/context.cr index 8d7b79a..c92da2e 100644 --- a/src/context.cr +++ b/src/context.cr @@ -1,3 +1,4 @@ +require "./exception.cr" require "./config.cr" diff --git a/src/exception.cr b/src/exception.cr new file mode 100644 index 0000000..1cee050 --- /dev/null +++ b/src/exception.cr @@ -0,0 +1,32 @@ + +class Package::Exception < Exception + getter recipe : Recipe + def initialize(@recipe, message : String) + super message + end +end + +class Package::DownloadError < Package::Exception + getter url : URI + def initialize(recipe : Recipe, @url) + super recipe, "Downloading one of the sources failed." + end +end + +class Package::ExtractionError < Package::Exception + getter url : URI + def initialize(recipe : Recipe, @url) + super recipe, "Extracting one of the sources failed." + end +end + +class Package::BuildError < Package::Exception +end + +class Package::PackagingError < Package::Exception + getter package : Package + def initialize(recipe : Recipe, @package) + super recipe, "Assembling a package failed." + end +end + diff --git a/src/instructions.cr b/src/instructions.cr index bfff1b7..08c6e10 100644 --- a/src/instructions.cr +++ b/src/instructions.cr @@ -19,7 +19,8 @@ end class Package::Instructions class Set < Array(String) - def initialize(@phase : String) + getter phase : String + def initialize(@phase) super() end # FIXME: def execute diff --git a/src/main.cr b/src/main.cr index 4209434..2adde48 100644 --- a/src/main.cr +++ b/src/main.cr @@ -74,20 +74,31 @@ end # FIXME: Now we need to build their respective deptrees and to deduplicate # the list of recipes. -recipes.each do |recipe| - puts " >> #{recipe.name}".colorize :white +begin + latest_build_dir = "" + recipes.each do |recipe| + latest_build_dir = recipe.building_directory - raise "oh no, download failed" unless recipe.download + puts " >> #{recipe.name}".colorize :white - if download_only - exit 0 + recipe.download + + next if download_only + + recipe.extract + + recipe.build + recipe.package + + recipe.clean unless do_not_clean end - - raise "oh no, extraction failed" unless recipe.extract - - raise "oh no, build failed" unless recipe.build - raise "oh no, packaging failed" unless recipe.package - - recipe.clean unless do_not_clean +rescue e : Package::Exception + STDERR.puts "!! #{e.message}".colorize(:red).bright + STDERR.puts "!! You may want to inspect the build directory at #{latest_build_dir}" + exit 1 +rescue e + STDERR.puts "!! An unexpected error occured:".colorize(:red).bright + STDERR.puts e + exit 1 end diff --git a/src/recipe.cr b/src/recipe.cr index 78f1180..8264a9b 100644 --- a/src/recipe.cr +++ b/src/recipe.cr @@ -1,4 +1,3 @@ - require "uuid" require "uri" require "file_utils" @@ -9,6 +8,7 @@ require "./context.cr" require "./package.cr" require "./instructions.cr" require "./sources.cr" +require "./exception.cr" # 🤔 class URI @@ -184,28 +184,32 @@ class Package::Recipe @dirname || "#{name}-#{version}" end - def download : Bool - sources - .compact_map do |url| - unless File.exists? url.basename - @context.run @context.sources_directory, "wget", [ url.to_s, "-O", url.basename ] - end + def download + sources.each do |url| + unless File.exists? url.basename + status = @context.run @context.sources_directory, "wget", [ url.to_s, "-O", url.basename ] + + raise DownloadError.new self, url unless status.success? end - .map(&.success?) - .reduce(true) { |a, b| a && b } + end end - def extract : Bool + def extract Dir.mkdir_p building_directory - sources - .map do |url| - basename = url.basename + sources.each do |url| + basename = url.basename - @context.run building_directory, "bsdtar", [ "xvf", @context.sources_directory + "/" + url.basename ] - end - .map(&.success?) - .reduce true { |a, b| a && b } + status = @context.run( + building_directory, + "bsdtar", [ + "xvf", + @context.sources_directory + "/" + url.basename + ] + ) + + raise ExtractionError.new self, url unless status.success? + end end # TODO: @@ -215,9 +219,7 @@ class Package::Recipe # - Be careful about return values, flee from everything if something # goes somehow wrong. # - Make things thread-safe. (those ENV[]= calls are definitely not) - def build : Bool - success = true - + def build Dir.mkdir_p fake_root_directory ENV["PKG"] = fake_root_directory @@ -227,7 +229,7 @@ class Package::Recipe instructions.to_a.each do |instruction| if instruction.run(@context, self).failed? - success = false + raise BuildError.new self, "Building (#{instruction.phase} phase) failed." break end end @@ -236,11 +238,11 @@ class Package::Recipe ENV["PKG"] = nil - success = false if Dir.children(fake_root_directory).size == 0 + if Dir.children(fake_root_directory).size == 0 + raise BuildError.new self, "No file was installed in the fake root." + end - do_splits if success - - success + do_splits end private def do_splits @@ -295,18 +297,18 @@ class Package::Recipe # TODO: # - Errors management. Stop at first failure? # - Splits. This should be done between #build and #package. - def package : Bool + def package # This tries to build them all and stops at the first failure # (failures are currently reported by Context#package) - (@packages + auto_splits) - .find do |package| - if package.automatic && ! File.exists? package.fake_root_directory - next - end - - ! @context.package package + (@packages + auto_splits).each do |package| + if package.automatic && ! File.exists? package.fake_root_directory + next end - .== nil + + unless @context.package package + raise PackagingError.new self, package + end + end end def clean