diff --git a/lib/fpm/cookery/lifecycle_hooks.rb b/lib/fpm/cookery/lifecycle_hooks.rb index 09b9d009..6dca171b 100644 --- a/lib/fpm/cookery/lifecycle_hooks.rb +++ b/lib/fpm/cookery/lifecycle_hooks.rb @@ -6,6 +6,18 @@ module LifecycleHooks def run_lifecycle_hook(hook_name, *args) Log.debug("Run lifecycle hook: #{hook_name} (args: #{args.inspect})") self.__send__(hook_name, *args) + + # Backward compatibility for users of deprecated lifecycle hooks + case hook_name + when :before_package_file_create + unless self.__send__(:before_package_create, args[1]) == :UNUSED + Log.deprecated("Switch from \"before_package_create\" lifecycle hook to \"before_package_file_create\"") + end + when :after_package_file_create + unless self.__send__(:after_package_create, args[1]) == :UNUSED + Log.deprecated("Switch from \"after_package_create\" lifecycle hook to \"after_package_file_create\"") + end + end end def before_dependency_installation @@ -39,12 +51,24 @@ def before_install def after_install end + # Gets a the output filename and the FPM::Package object as argument. + def before_package_file_create(filename, package) + end + + # Gets a the output filename and the FPM::Package object as argument. + def after_package_file_create(filename, package) + end + # Gets a FPM::Package object as argument. + # @deprecated Use #after_package_file_create. def before_package_create(package) + :UNUSED end # Gets a FPM::Package object as argument. + # @deprecated Use #after_package_file_create. def after_package_create(package) + :UNUSED end end end diff --git a/lib/fpm/cookery/package/version.rb b/lib/fpm/cookery/package/version.rb index d7638b78..efb7cf4f 100644 --- a/lib/fpm/cookery/package/version.rb +++ b/lib/fpm/cookery/package/version.rb @@ -1,3 +1,6 @@ +require 'fpm/cookery/exceptions' +require 'fpm/cookery/log' + module FPM module Cookery module Package @@ -28,6 +31,21 @@ def initialize(recipe, target, config) @config = config @revision = recipe.revision @version, @epoch = split_version(@recipe.version) + + if !@epoch.nil? and !recipe.epoch.nil? + # If the epoch is defined in the version string and set in the + # epoch field, we don't know what to choose. + message = "The \"epoch\" is defined in the recipe's version (#{@recipe.version}) AND epoch (#{@recipe.epoch}) fields" + Log.error message + raise Error::Misconfiguration, message + end + + # The epoch in the version string has precedence over the #epoch + # attribute in the recipe. (backward compatibility) + @epoch = recipe.epoch if @epoch.nil? + + # Ensure that epoch is always a string + @epoch = @epoch.to_s unless @epoch.nil? end def vendor diff --git a/lib/fpm/cookery/packager.rb b/lib/fpm/cookery/packager.rb index 070ff8aa..ade5d460 100644 --- a/lib/fpm/cookery/packager.rb +++ b/lib/fpm/cookery/packager.rb @@ -213,18 +213,19 @@ def build_package(recipe, config) output = input.convert(output_class) - recipe.run_lifecycle_hook(:before_package_create, output) + output_filename = output.to_s(recipe.package_name_format) + recipe.run_lifecycle_hook(:before_package_file_create, output_filename, output) begin - output.output(output.to_s) - recipe.run_lifecycle_hook(:after_package_create, output) + output.output(output_filename) + recipe.run_lifecycle_hook(:after_package_file_create, output_filename, output) rescue FPM::Package::FileAlreadyExists - Log.info "Removing existing package file: #{output.to_s}" - FileUtils.rm_f(output.to_s) + Log.info "Removing existing package file: #{output_filename}" + FileUtils.rm_f(output_filename) retry ensure input.cleanup if input output.cleanup if output - Log.info "Created package: #{File.join(Dir.pwd, output.to_s)}" + Log.info "Created package: #{File.join(Dir.pwd, output_filename)}" end end end diff --git a/lib/fpm/cookery/recipe.rb b/lib/fpm/cookery/recipe.rb index 0dd13b65..14827541 100644 --- a/lib/fpm/cookery/recipe.rb +++ b/lib/fpm/cookery/recipe.rb @@ -34,7 +34,8 @@ class BaseRecipe :revision, :section, :sha1, :sha256, :sha512, :spec, :vendor, :version, :pre_install, :post_install, :pre_uninstall, :post_uninstall, :license, :omnibus_package, :omnibus_dir, :chain_package, - :default_prefix, :docker, :docker_image, :dockerfile + :default_prefix, :docker, :docker_image, :dockerfile, + :package_name_format, :epoch attr_rw_list :build_depends, :config_files, :conflicts, :depends, :exclude, :patches, :provides, :replaces, :omnibus_recipes, diff --git a/recipes/facter/recipe.rb b/recipes/facter/recipe.rb index 898a51f2..317f770d 100644 --- a/recipes/facter/recipe.rb +++ b/recipes/facter/recipe.rb @@ -1,4 +1,7 @@ class FacterRubyGem < FPM::Cookery::RubyGemRecipe name 'facter' version '1.6.16' + epoch 2 + + package_name_format 'NAME_EPOCH:FULLVERSION_ARCH.EXTENSION' end diff --git a/spec/lifecycle_hooks_spec.rb b/spec/lifecycle_hooks_spec.rb new file mode 100644 index 00000000..70976d36 --- /dev/null +++ b/spec/lifecycle_hooks_spec.rb @@ -0,0 +1,40 @@ +require 'spec_helper' +require 'fpm/cookery/lifecycle_hooks' + +describe 'LifecycleHooks' do + let(:object) do + Class.new do + attr_accessor :canary + + include FPM::Cookery::LifecycleHooks + + def before_package_create(package) + self.canary = package + end + + def after_package_create(package) + self.canary = package + end + end.new + end + + let(:canary) { Object.new } + + describe 'backward compatibility' do + describe 'Running :before_package_file_create hook' do + it 'calls the deprecated :before_package_create hook' do + object.run_lifecycle_hook(:before_package_file_create, 'filename', canary) + + expect(object.canary).to eq(canary) + end + end + + describe 'Running :after_package_file_create hook' do + it 'calls the deprecated :after_package_create hook' do + object.run_lifecycle_hook(:after_package_file_create, 'filename', canary) + + expect(object.canary).to eq(canary) + end + end + end +end diff --git a/spec/package_version_spec.rb b/spec/package_version_spec.rb index c01510ff..f1f0dfbe 100644 --- a/spec/package_version_spec.rb +++ b/spec/package_version_spec.rb @@ -85,6 +85,24 @@ expect(version.epoch).to eq(nil) end end + + context 'with epoch set in recipe' do + it 'returns the recipe epoch' do + recipe.version = '1.2.3' + recipe.epoch = 2 + + expect(version.epoch).to eq('2') # Must be a string + end + end + + context 'with epoch set in recipe version and epoch' do + it 'raises an Misconfiguration error' do + recipe.version = '3:1.2.3' + recipe.epoch = 2 + + expect { version.epoch }.to raise_error(FPM::Cookery::Error::Misconfiguration) + end + end end describe '#to_s' do