fpm-cookery 0.15.0 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/.travis.yml +10 -0
  2. data/CHANGELOG.md +8 -0
  3. data/bin/fpm-cook +1 -1
  4. data/fpm-cookery.gemspec +2 -1
  5. data/lib/fpm/cookery/chain_packager.rb +58 -0
  6. data/lib/fpm/cookery/cli.rb +93 -104
  7. data/lib/fpm/cookery/config.rb +86 -0
  8. data/lib/fpm/cookery/dependency_inspector.rb +7 -3
  9. data/lib/fpm/cookery/exceptions.rb +11 -0
  10. data/lib/fpm/cookery/facts.rb +1 -0
  11. data/lib/fpm/cookery/log.rb +1 -1
  12. data/lib/fpm/cookery/package/dir.rb +11 -35
  13. data/lib/fpm/cookery/package/gem.rb +25 -0
  14. data/lib/fpm/cookery/package/maintainer.rb +39 -0
  15. data/lib/fpm/cookery/package/package.rb +100 -0
  16. data/lib/fpm/cookery/package/version.rb +48 -0
  17. data/lib/fpm/cookery/packager.rb +65 -97
  18. data/lib/fpm/cookery/path.rb +4 -0
  19. data/lib/fpm/cookery/recipe.rb +59 -19
  20. data/lib/fpm/cookery/shellout.rb +35 -0
  21. data/lib/fpm/cookery/source_handler/curl.rb +12 -2
  22. data/lib/fpm/cookery/version.rb +1 -1
  23. data/recipes/arr-pm/recipe.rb +4 -0
  24. data/recipes/backports/recipe.rb +4 -0
  25. data/recipes/cabin/recipe.rb +4 -0
  26. data/recipes/clamp/recipe.rb +4 -0
  27. data/recipes/facter/recipe.rb +4 -0
  28. data/recipes/fpm-cookery-gem/addressable.rb +4 -0
  29. data/recipes/fpm-cookery-gem/arr-pm.rb +4 -0
  30. data/recipes/fpm-cookery-gem/backports.rb +4 -0
  31. data/recipes/fpm-cookery-gem/cabin.rb +4 -0
  32. data/recipes/fpm-cookery-gem/childprocess.rb +7 -0
  33. data/recipes/fpm-cookery-gem/clamp.rb +4 -0
  34. data/recipes/fpm-cookery-gem/facter.rb +4 -0
  35. data/recipes/fpm-cookery-gem/ffi.rb +4 -0
  36. data/recipes/fpm-cookery-gem/fpm.rb +7 -0
  37. data/recipes/fpm-cookery-gem/ftw.rb +7 -0
  38. data/recipes/fpm-cookery-gem/hiera.rb +7 -0
  39. data/recipes/fpm-cookery-gem/http_parser.rb.rb +4 -0
  40. data/recipes/fpm-cookery-gem/json.rb +4 -0
  41. data/recipes/fpm-cookery-gem/json_pure.rb +4 -0
  42. data/recipes/fpm-cookery-gem/puppet.rb +7 -0
  43. data/recipes/fpm-cookery-gem/recipe.rb +7 -0
  44. data/recipes/fpm-cookery-gem/rgen.rb +4 -0
  45. data/recipes/fpm-cookery/recipe.rb +1 -1
  46. data/recipes/fpm-cookery/ruby.rb +20 -10
  47. data/recipes/fpm/recipe.rb +4 -0
  48. data/recipes/json/recipe.rb +4 -0
  49. data/recipes/open4/recipe.rb +4 -0
  50. data/spec/config_spec.rb +167 -0
  51. data/spec/facts_spec.rb +7 -0
  52. data/spec/fixtures/test-config-1.yml +2 -0
  53. data/spec/package_maintainer_spec.rb +79 -0
  54. data/spec/package_spec.rb +182 -0
  55. data/spec/package_version_spec.rb +119 -0
  56. data/spec/recipe_spec.rb +18 -0
  57. data/spec/spec_helper.rb +1 -0
  58. metadata +61 -6
@@ -0,0 +1,11 @@
1
+ module FPM
2
+ module Cookery
3
+ class Error < StandardError
4
+ MethodNotImplemented = Class.new(self)
5
+
6
+ class InvalidConfigKey < self
7
+ attr_accessor :invalid_keys
8
+ end
9
+ end
10
+ end
11
+ end
@@ -19,6 +19,7 @@ module FPM
19
19
  @target ||= case platform
20
20
  when :centos, :redhat, :fedora then :rpm
21
21
  when :debian, :ubuntu then :deb
22
+ when :darwin then :osxpkg
22
23
  end
23
24
  end
24
25
 
@@ -10,7 +10,7 @@ module FPM
10
10
 
11
11
  @channel = ::Cabin::Channel.get
12
12
  @channel.subscribe(self)
13
- @channel.level = :debug
13
+ @channel.level = :info
14
14
 
15
15
  class << self
16
16
  def enable_debug(value = true)
@@ -1,49 +1,25 @@
1
1
  require 'fpm/package/dir'
2
- require 'delegate'
2
+ require 'fpm/cookery/package/package'
3
3
 
4
4
  module FPM
5
5
  module Cookery
6
6
  module Package
7
- class Dir < SimpleDelegator
8
- def initialize(recipe, config = {})
9
- super(FPM::Package::Dir.new)
10
-
11
- self.name = recipe.name
12
- self.url = recipe.homepage || recipe.source
13
- self.category = recipe.section || 'optional'
14
- self.description = recipe.description.strip if recipe.description
15
- self.architecture = recipe.arch.to_s if recipe.arch
16
-
17
- self.dependencies += recipe.depends
18
- self.conflicts += recipe.conflicts
19
- self.provides += recipe.provides
20
- self.replaces += recipe.replaces
21
- self.config_files += recipe.config_files
22
-
23
- attributes[:prefix] = '/'
24
- attributes[:chdir] = recipe.destdir.to_s
25
- attributes[:deb_compression] = 'gzip'
26
- attributes[:deb_user] = 'root'
27
- attributes[:deb_group] = 'root'
28
- attributes[:rpm_compression] = 'gzip'
29
- attributes[:rpm_digest] = 'md5'
30
- attributes[:rpm_user] = 'root'
31
- attributes[:rpm_group] = 'root'
32
- attributes[:rpm_defattrfile] = '-'
33
- attributes[:rpm_defattrdir] = '-'
7
+ class Dir < FPM::Cookery::Package::Package
8
+ def fpm_object
9
+ FPM::Package::Dir.new
10
+ end
34
11
 
35
- # TODO replace remove_excluded_files() in packager with this.
36
- attributes[:excludes] = []
12
+ def package_setup
13
+ fpm.attributes[:prefix] = '/'
14
+ fpm.attributes[:chdir] = recipe.destdir.to_s
15
+ end
37
16
 
17
+ def package_input
38
18
  inputs = config.fetch(:input, nil) || '.'
39
19
 
40
20
  Array(inputs).each do |path|
41
- input(path)
21
+ fpm.input(path)
42
22
  end
43
-
44
- # The call to input() overwrites the license and vendor attributes.
45
- # XXX Needs to be fixed in fpm/package/dir.rb.
46
- self.license = recipe.license if recipe.license
47
23
  end
48
24
  end
49
25
  end
@@ -0,0 +1,25 @@
1
+ require 'fpm/package/gem'
2
+ require 'fpm/cookery/package/package'
3
+
4
+ module FPM
5
+ module Cookery
6
+ module Package
7
+ class Gem < FPM::Cookery::Package::Package
8
+ def fpm_object
9
+ FPM::Package::Gem.new
10
+ end
11
+
12
+ def package_setup
13
+ fpm.version = recipe.version
14
+
15
+ fpm.attributes[:gem_fix_name?] = true
16
+ fpm.attributes[:gem_fix_dependencies?] = true
17
+ end
18
+
19
+ def package_input
20
+ fpm.input(recipe.name)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,39 @@
1
+ require 'fpm/cookery/shellout'
2
+
3
+ module FPM
4
+ module Cookery
5
+ module Package
6
+ class Maintainer < Struct.new(:recipe, :config)
7
+ def maintainer
8
+ config_maintainer || recipe_maintainer || git_maintainer
9
+ end
10
+
11
+ def to_s
12
+ maintainer
13
+ end
14
+ alias_method :to_str, :to_s
15
+
16
+ private
17
+
18
+ def config_maintainer
19
+ config[:maintainer]
20
+ end
21
+
22
+ def recipe_maintainer
23
+ recipe.maintainer
24
+ end
25
+
26
+ def git_maintainer
27
+ username = git_config('user.name')
28
+ useremail = git_config('user.email')
29
+
30
+ username && useremail ? "#{username} <#{useremail}>" : nil
31
+ end
32
+
33
+ def git_config(key)
34
+ FPM::Cookery::Shellout.git_config_get(key)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,100 @@
1
+ require 'fpm/cookery/exceptions'
2
+
3
+ module FPM
4
+ module Cookery
5
+ module Package
6
+ class Package
7
+ attr_reader :recipe, :config, :fpm
8
+
9
+ def initialize(recipe, config = {})
10
+ @recipe = recipe
11
+ @config = config
12
+ @fpm = fpm_object
13
+
14
+ @fpm.name = recipe.name
15
+ @fpm.url = recipe.homepage
16
+ @fpm.category = recipe.section || 'optional'
17
+ @fpm.description = recipe.description.strip if recipe.description
18
+ @fpm.architecture = recipe.arch.to_s if recipe.arch
19
+
20
+ @fpm.dependencies += recipe.depends
21
+ @fpm.conflicts += recipe.conflicts
22
+ @fpm.provides += recipe.provides
23
+ @fpm.replaces += recipe.replaces
24
+ @fpm.config_files += recipe.config_files
25
+
26
+ @fpm.attributes[:deb_compression] = 'gzip'
27
+ @fpm.attributes[:deb_user] = 'root'
28
+ @fpm.attributes[:deb_group] = 'root'
29
+ @fpm.attributes[:rpm_compression] = 'gzip'
30
+ @fpm.attributes[:rpm_digest] = 'md5'
31
+ @fpm.attributes[:rpm_user] = 'root'
32
+ @fpm.attributes[:rpm_group] = 'root'
33
+ @fpm.attributes[:rpm_defattrfile] = '-'
34
+ @fpm.attributes[:rpm_defattrdir] = '-'
35
+
36
+ # TODO replace remove_excluded_files() in packager with this.
37
+ @fpm.attributes[:excludes] = []
38
+
39
+ # Package type specific code should be called in package_setup.
40
+ package_setup
41
+
42
+ # The input for the FPM package will be set here.
43
+ package_input
44
+
45
+ # The call to input() overwrites the license and vendor attributes.
46
+ # XXX Needs to be fixed in fpm/package/dir.rb.
47
+ fpm.license = recipe.license if recipe.license
48
+ end
49
+
50
+ def fpm_object
51
+ # Has to be overwritten in a subclass.
52
+ raise Error::MethodNotImplemented, "The #fpm_object method has not been implemented in #{self.class}"
53
+ end
54
+
55
+ def package_setup
56
+ # Can be overwritten in a subclass.
57
+ end
58
+
59
+ def package_input
60
+ # Has to be overwritten in a subclass.
61
+ raise Error::MethodNotImplemented, "The #package_input method has not been implemented in #{self.class}"
62
+ end
63
+
64
+ def convert(output_class)
65
+ fpm.convert(output_class)
66
+ end
67
+
68
+ def cleanup
69
+ fpm.cleanup
70
+ end
71
+
72
+ def add_script(type, content)
73
+ case type.to_sym
74
+ when :pre_install
75
+ fpm.scripts[:before_install] = content
76
+ when :post_install
77
+ fpm.scripts[:after_install] = content
78
+ when :pre_uninstall
79
+ fpm.scripts[:before_remove] = content
80
+ when :post_uninstall
81
+ fpm.scripts[:after_remove] = content
82
+ end
83
+ end
84
+
85
+ # XXX should go away and set in initializer
86
+ def version=(value)
87
+ fpm.version = value
88
+ end
89
+
90
+ def maintainer=(value)
91
+ fpm.maintainer = value
92
+ end
93
+
94
+ def vendor=(value)
95
+ fpm.vendor = value
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,48 @@
1
+ module FPM
2
+ module Cookery
3
+ module Package
4
+ class Version
5
+ VENDOR_DELIMITER = {
6
+ :deb => '+',
7
+ :rpm => '.',
8
+ :default => '-'
9
+ }
10
+
11
+ attr_reader :version, :epoch, :revision
12
+
13
+ def initialize(recipe, target, config)
14
+ @recipe = recipe
15
+ @target = target
16
+ @config = config
17
+ @revision = recipe.revision
18
+ @version, @epoch = split_version(@recipe.version)
19
+ end
20
+
21
+ def vendor
22
+ @config[:vendor] || @recipe.vendor
23
+ end
24
+
25
+ def vendor_delimiter
26
+ VENDOR_DELIMITER[@target.to_sym] || VENDOR_DELIMITER[:default]
27
+ end
28
+
29
+ def to_s
30
+ if vendor
31
+ "#{version}#{vendor_delimiter}#{vendor}#{revision}"
32
+ else
33
+ "#{version}-#{revision}"
34
+ end
35
+ end
36
+ alias_method :to_str, :to_s
37
+
38
+ private
39
+
40
+ def split_version(version)
41
+ epoch, version = version.split(':', 2)
42
+
43
+ version.nil? ? [epoch, nil] : [version, epoch]
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -6,6 +6,8 @@ require 'fpm/cookery/source_integrity_check'
6
6
  require 'fpm/cookery/path'
7
7
  require 'fpm/cookery/log'
8
8
  require 'fpm/cookery/package/dir'
9
+ require 'fpm/cookery/package/version'
10
+ require 'fpm/cookery/package/maintainer'
9
11
  require 'fpm'
10
12
 
11
13
  module FPM
@@ -62,66 +64,68 @@ module FPM
62
64
 
63
65
  recipe.installing = false
64
66
 
65
- source = recipe.source_handler
67
+ if defined? recipe.source_handler()
68
+ source = recipe.source_handler
66
69
 
67
- recipe.cachedir.mkdir
68
- Dir.chdir(recipe.cachedir) do
69
- Log.info "Fetching source: #{source.source_url}"
70
- source.fetch
70
+ recipe.cachedir.mkdir
71
+ Dir.chdir(recipe.cachedir) do
72
+ Log.info "Fetching source: #{source.source_url}"
73
+ source.fetch
71
74
 
72
- if source.checksum?
73
- SourceIntegrityCheck.new(recipe).tap do |check|
74
- if check.checksum_missing?
75
- Log.warn 'Recipe does not provide a checksum. (sha256, sha1 or md5)'
76
- Log.puts <<-__WARN
75
+ if source.checksum?
76
+ SourceIntegrityCheck.new(recipe).tap do |check|
77
+ if check.checksum_missing?
78
+ Log.warn 'Recipe does not provide a checksum. (sha256, sha1 or md5)'
79
+ Log.puts <<-__WARN
77
80
  Digest: #{check.digest}
78
81
  Checksum: #{check.checksum_actual}
79
82
  Filename: #{check.filename}
80
83
 
81
- __WARN
82
- elsif check.error?
83
- Log.error 'Integrity check failed!'
84
- Log.puts <<-__ERROR
84
+ __WARN
85
+ elsif check.error?
86
+ Log.error 'Integrity check failed!'
87
+ Log.puts <<-__ERROR
85
88
  Digest: #{check.digest}
86
89
  Checksum expected: #{check.checksum_expected}
87
90
  Checksum actual: #{check.checksum_actual}
88
91
  Filename: #{check.filename}
89
92
 
90
- __ERROR
91
- exit 1
92
- end
93
- end
94
- end
95
- end
93
+ __ERROR
94
+ exit 1
95
+ end #end checksum missing
96
+ end #end check
97
+ end #end checksum
98
+ end #end chdir cachedir
96
99
 
97
- recipe.builddir.mkdir
98
- Dir.chdir(recipe.builddir) do
99
- extracted_source = source.extract
100
+ recipe.builddir.mkdir
101
+ Dir.chdir(recipe.builddir) do
102
+ extracted_source = source.extract
100
103
 
101
- Dir.chdir(extracted_source) do
102
- #Source::Patches.new(recipe.patches).apply!
104
+ Dir.chdir(extracted_source) do
105
+ #Source::Patches.new(recipe.patches).apply!
103
106
 
104
- build_cookie = build_cookie_name(package_name)
107
+ build_cookie = build_cookie_name(package_name)
105
108
 
106
- if File.exists?(build_cookie)
107
- Log.info 'Skipping build (`fpm-cook clean` to rebuild)'
108
- else
109
- Log.info "Building in #{File.expand_path(extracted_source, recipe.builddir)}"
110
- recipe.build and FileUtils.touch(build_cookie)
111
- end
109
+ if File.exists?(build_cookie)
110
+ Log.info 'Skipping build (`fpm-cook clean` to rebuild)'
111
+ else
112
+ Log.info "Building in #{File.expand_path(extracted_source, recipe.builddir)}"
113
+ recipe.build and FileUtils.touch(build_cookie)
114
+ end
112
115
 
113
- FileUtils.rm_rf(recipe.destdir) unless keep_destdir?
114
- recipe.destdir.mkdir unless File.exists?(recipe.destdir)
116
+ FileUtils.rm_rf(recipe.destdir) unless keep_destdir?
117
+ recipe.destdir.mkdir unless File.exists?(recipe.destdir)
115
118
 
116
- begin
117
- recipe.installing = true
118
- Log.info "Installing into #{recipe.destdir}"
119
- recipe.install
120
- ensure
121
- recipe.installing = false
122
- end
123
- end
124
- end
119
+ begin
120
+ recipe.installing = true
121
+ Log.info "Installing into #{recipe.destdir}"
122
+ recipe.install
123
+ ensure
124
+ recipe.installing = false
125
+ end
126
+ end #end chdir extracted_source
127
+ end #end chdir builddir
128
+ end #end defined source_handler
125
129
 
126
130
  if skip_package?
127
131
  Log.info "Package building disabled"
@@ -140,37 +144,15 @@ module FPM
140
144
  def build_package(recipe, config)
141
145
  recipe.pkgdir.mkdir
142
146
  Dir.chdir(recipe.pkgdir) do
143
- epoch, ver = recipe.version.split(':', 2)
144
- if ver.nil?
145
- ver, epoch = epoch, nil
146
- end
147
-
148
- # Build a version including vendor and revision.
149
- vendor = config[:vendor] || recipe.vendor
150
- vendor_rev = "#{vendor}#{recipe.revision}"
151
- case @target
152
- when "deb"
153
- vendor_delimiter = "+"
154
- when "rpm"
155
- vendor_delimiter = "."
156
- else
157
- vendor_delimiter = "-"
158
- end
159
- version = [ver, vendor_rev].join(vendor_delimiter)
160
-
161
- maintainer = recipe.maintainer || begin
162
- username = git_config('user.name')
163
- useremail = git_config('user.email')
164
-
165
- username && useremail ? "#{username} <#{useremail}>" : nil
166
- end
147
+ version = FPM::Cookery::Package::Version.new(recipe, @target, config)
148
+ maintainer = FPM::Cookery::Package::Maintainer.new(recipe, config)
167
149
 
168
- input = FPM::Cookery::Package::Dir.new(recipe, :input => config[:input])
150
+ input = recipe.input(config)
169
151
 
170
- input.version = version
171
- input.maintainer = maintainer
172
- input.vendor = vendor if vendor
173
- input.epoch = epoch if epoch
152
+ input.version = version.to_s
153
+ input.maintainer = maintainer.to_s
154
+ input.vendor = version.vendor if version.vendor
155
+ input.epoch = version.epoch if version.epoch
174
156
 
175
157
  add_scripts(recipe, input)
176
158
  remove_excluded_files(recipe)
@@ -195,16 +177,9 @@ module FPM
195
177
 
196
178
  def add_scripts(recipe, input)
197
179
  error = false
180
+ scripts = [:pre_install, :post_install, :pre_uninstall, :post_uninstall]
198
181
 
199
- # Map script names to fpm method names.
200
- script_map = {
201
- 'pre_install' => :before_install,
202
- 'post_install' => :after_install,
203
- 'pre_uninstall' => :before_remove,
204
- 'post_uninstall' => :after_remove
205
- }
206
-
207
- script_map.each do |script, fpm_script|
182
+ scripts.each do |script|
208
183
  unless recipe.send(script).nil?
209
184
  script_file = FPM::Cookery::Path.new(recipe.send(script))
210
185
 
@@ -215,7 +190,7 @@ module FPM
215
190
  end
216
191
 
217
192
  if File.exists?(script_file)
218
- input.scripts[fpm_script] = File.read(script_file.to_s)
193
+ input.add_script(script, File.read(script_file.to_s))
219
194
  else
220
195
  Log.error "#{script} script '#{script_file}' is missing"
221
196
  error = true
@@ -229,26 +204,19 @@ module FPM
229
204
  # Remove all excluded files from the destdir so they do not end up in the
230
205
  # package.
231
206
  def remove_excluded_files(recipe)
232
- Dir.chdir(recipe.destdir.to_s) do
233
- Dir['**/*'].each do |file|
234
- recipe.exclude.each do |ex|
235
- if File.fnmatch(ex, file)
236
- Log.info "Exclude file: #{file}"
237
- FileUtils.rm_f(file)
207
+ if File.directory?(recipe.destdir)
208
+ Dir.chdir(recipe.destdir.to_s) do
209
+ Dir['**/*'].each do |file|
210
+ recipe.exclude.each do |ex|
211
+ if File.fnmatch(ex, file)
212
+ Log.info "Exclude file: #{file}"
213
+ FileUtils.rm_f(file)
214
+ end
238
215
  end
239
216
  end
240
217
  end
241
218
  end
242
219
  end
243
-
244
- private
245
-
246
- def git_config(key)
247
- %x(git config --get #{key}).strip
248
- rescue
249
- Log.warn "Git config command for key '#{key}' failed."
250
- nil
251
- end
252
220
  end
253
221
  end
254
222
  end