lib/autobuild/importer.rb in autobuild-1.10.0.rc13 vs lib/autobuild/importer.rb in autobuild-1.10.0.rc14

- old
+ new

@@ -148,10 +148,11 @@ @options = options.dup @options[:retry_count] = Integer(@options[:retry_count] || 0) @repository_id = options[:repository_id] || "#{self.class.name}:#{object_id}" @interactive = options[:interactive] @source_id = options[:source_id] || @repository_id + @post_hooks = Array.new end # Returns a string that identifies the remote repository uniquely # # This can be used to check whether two importers are pointing to the same @@ -234,24 +235,81 @@ if retry_count <= self.retry_count retry_count end end + # A list of hooks that are called after a successful checkout or update + # + # They are added either at the instance level with {#add_post_hook} or + # globally for all importers of a given type with {Importer.add_post_hook} + attr_reader :post_hooks + + # Define a post-import hook for all instances of this class + # + # @yieldparam [Importer] importer the importer that finished + # @yieldparam [Package] package the package we're acting on + # @see Importer#add_post_hook + def self.add_post_hook(&hook) + @post_hooks ||= Array.new + @post_hooks << hook + end + + # Enumerate the post-import hooks defined for all instances of this class + def self.each_post_hook(&hook) + (@post_hooks || Array.new).each(&hook) + end + + # @api private + # + # Call the post-import hooks added with {#add_post_hook} + def execute_post_hooks(package) + self.class.each_post_hook do |hook| + hook.call(self, package) + end + each_post_hook.each do |block| + block.call(self, package) + end + end + + # Add a block that should be called when the import has successfully + # finished + # + # @yieldparam [Importer] importer the importer that finished + # @yieldparam [Package] package the package we're acting on + # @see Importer.add_post_hook + def add_post_hook(&hook) + post_hooks << hook + end + + # Enumerate the post-import hooks for this importer + def each_post_hook(&hook) + return enum_for(__method__) if !block_given? + + self.class.each_post_hook(&hook) + post_hooks.each(&hook) + end + def perform_update(package,only_local=false) cur_patches = currently_applied_patches(package) needed_patches = self.patches if cur_patches.map(&:last) != needed_patches.map(&:last) patch(package, []) end + last_error = nil retry_count = 0 package.progress_start "updating %s" begin update(package,only_local) + execute_post_hooks(package) rescue Interrupt - raise + if last_error + raise last_error + else raise + end rescue ::Exception => original_error + last_error = original_error # If the package is patched, it might be that the update # failed because we needed to unpatch first. Try it out # # This assumes that importing data with conflict will # make the import fail, but not make the patch @@ -286,16 +344,21 @@ rescue Autobuild::Exception => e fallback(e, package, :import, package) end def perform_checkout(package, options = Hash.new) + last_error = nil package.progress_start "checking out %s", :done_message => 'checked out %s' do retry_count = 0 begin checkout(package, options) + execute_post_hooks(package) rescue Interrupt - raise + if last_error then raise last_error + else raise + end rescue ::Exception => original_error + last_error = original_error retry_count = update_retry_count(original_error, retry_count) if !retry_count raise end package.message "checkout of %s failed, deleting the source directory #{package.importdir} and retrying (#{retry_count}/#{self.retry_count})"