fpm-cookery 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ # v0.4.0 (2011-10-28)
2
+ * Add svn source handler. (lusis)
3
+ * Framework for alternate source handlers. (lusis)
4
+ * Add .zip support to the curl source handler.
5
+ * Detect package target based on the platform.
6
+ * Allow platform specific options. (like dependencies) (lusis)
7
+ * Add platform (operating system) detection. (lusis)
8
+
1
9
  # v0.3.0 (2011-10-25)
2
10
  * Select vendor string delimiter based on the package target. (lusis)
3
11
  * Add pre/post install/uninstall script support. (lusis)
data/fpm-cookery.gemspec CHANGED
@@ -22,4 +22,5 @@ Gem::Specification.new do |s|
22
22
  s.add_development_dependency "minitest"
23
23
  s.add_development_dependency "rake"
24
24
  s.add_runtime_dependency "fpm"
25
+ s.add_runtime_dependency "facter"
25
26
  end
@@ -21,6 +21,11 @@ module FPM
21
21
  @target = o
22
22
  end
23
23
 
24
+ options.on("-p PLATFORM", "--platform PLATFORM",
25
+ "Set the target platform. (centos, ubuntu, debian)") do |o|
26
+ @platform = o
27
+ end
28
+
24
29
  # Parse flags and such, remainder is all non-option args.
25
30
  remainder = options.parse(argv)
26
31
 
@@ -55,17 +60,28 @@ module FPM
55
60
  exit 1
56
61
  end
57
62
 
58
- if @target.nil?
59
- # TODO(sissel): Detect platform, try to guess @target?
60
- @target = "deb"
61
- puts "No --target given, assuming #{@target}"
62
- end
63
-
64
63
  # Default action is "package"
65
64
  if @actions.empty?
66
65
  @actions = ["package"]
67
66
  puts "No actions given, assuming 'package'"
68
67
  end
68
+
69
+ # Override the detected platform.
70
+ if @platform
71
+ FPM::Cookery::Facts.platform = @platform
72
+ end
73
+
74
+ if @target
75
+ FPM::Cookery::Facts.target = @target
76
+ end
77
+
78
+ if FPM::Cookery::Facts.target.nil?
79
+ STDERR.puts "No target given and we're unable to detect your platform"
80
+ exit 1
81
+ end
82
+
83
+ puts "Platform: #{FPM::Cookery::Facts.platform}"
84
+ puts "Target: #{FPM::Cookery::Facts.target}"
69
85
  end
70
86
 
71
87
  def run
@@ -75,7 +91,7 @@ module FPM
75
91
 
76
92
  FPM::Cookery::Book.load_recipe(@filename) do |recipe|
77
93
  packager = FPM::Cookery::Packager.new(recipe)
78
- packager.target = @target
94
+ packager.target = FPM::Cookery::Facts.target.to_s
79
95
 
80
96
  @actions.each do |action|
81
97
  case action
@@ -0,0 +1,30 @@
1
+ require 'facter'
2
+
3
+ module FPM
4
+ module Cookery
5
+ class Facts
6
+ def self.platform
7
+ @platform ||= Facter.fact(:operatingsystem).value.downcase.to_sym
8
+ end
9
+
10
+ def self.platform=(value)
11
+ @platform = value.downcase.to_sym
12
+ end
13
+
14
+ def self.target
15
+ @target ||= case platform
16
+ when :centos, :redhat, :fedora then :rpm
17
+ when :debian, :ubuntu then :deb
18
+ end
19
+ end
20
+
21
+ def self.target=(value)
22
+ @target = value.to_sym
23
+ end
24
+
25
+ def self.reset!
26
+ instance_variables.each {|v| instance_variable_set(v, nil) }
27
+ end
28
+ end
29
+ end
30
+ end
@@ -42,25 +42,27 @@ module FPM
42
42
  Dir.chdir(recipe.cachedir) do
43
43
  source.fetch
44
44
 
45
- SourceIntegrityCheck.new(recipe).tap do |check|
46
- if check.checksum_missing?
47
- STDERR.puts <<-__WARN
48
- WARNING: Recipe does not provide a checksum. (sha256, sha1 or md5)
49
- ------------------------------------------------------------------
50
- Digest: #{check.digest}
51
- Checksum: #{check.checksum_actual}
52
- Filename: #{check.filename}
53
- __WARN
54
- elsif check.error?
55
- STDERR.puts <<-__ERROR
56
- ERROR: Integrity check failed!
57
- ------------------------------
58
- Digest: #{check.digest}
59
- Checksum expected: #{check.checksum_expected}
60
- Checksum actual: #{check.checksum_actual}
61
- Filename: #{check.filename}
62
- __ERROR
63
- exit 1
45
+ if source.checksum?
46
+ SourceIntegrityCheck.new(recipe).tap do |check|
47
+ if check.checksum_missing?
48
+ STDERR.puts <<-__WARN
49
+ WARNING: Recipe does not provide a checksum. (sha256, sha1 or md5)
50
+ ------------------------------------------------------------------
51
+ Digest: #{check.digest}
52
+ Checksum: #{check.checksum_actual}
53
+ Filename: #{check.filename}
54
+ __WARN
55
+ elsif check.error?
56
+ STDERR.puts <<-__ERROR
57
+ ERROR: Integrity check failed!
58
+ ------------------------------
59
+ Digest: #{check.digest}
60
+ Checksum expected: #{check.checksum_expected}
61
+ Checksum actual: #{check.checksum_actual}
62
+ Filename: #{check.filename}
63
+ __ERROR
64
+ exit 1
65
+ end
64
66
  end
65
67
  end
66
68
  end
@@ -1,5 +1,6 @@
1
1
  require 'forwardable'
2
2
  require 'fileutils'
3
+ require 'fpm/cookery/facts'
3
4
  require 'fpm/cookery/source_handler'
4
5
  require 'fpm/cookery/utils'
5
6
  require 'fpm/cookery/path_helper'
@@ -25,6 +26,10 @@ module FPM
25
26
  end
26
27
  end
27
28
 
29
+ def self.platforms(valid_platforms)
30
+ Array(valid_platforms).member?(self.platform) and block_given? ? yield : false
31
+ end
32
+
28
33
  def self.attr_rw_list(*attrs)
29
34
  attrs.each do |attr|
30
35
  class_eval %Q{
@@ -57,6 +62,10 @@ module FPM
57
62
  @spec = spec
58
63
  end
59
64
  alias_method :url, :source
65
+
66
+ def platform
67
+ FPM::Cookery::Facts.platform
68
+ end
60
69
  end
61
70
 
62
71
  def source
@@ -4,6 +4,10 @@ module FPM
4
4
  module Cookery
5
5
  class SourceHandler
6
6
  class Curl < FPM::Cookery::SourceHandler::Template
7
+
8
+ NAME = :curl
9
+ CHECKSUM = true
10
+
7
11
  def fetch
8
12
  unless local_path.exist?
9
13
  Dir.chdir(cachedir) do
@@ -18,6 +22,8 @@ module FPM
18
22
  case local_path.extname
19
23
  when '.bz2', '.gz', '.tgz'
20
24
  safesystem('tar', 'xf', local_path)
25
+ when '.zip'
26
+ safesystem('unzip', '-d', local_path.basename('.zip'), local_path)
21
27
  end
22
28
  end
23
29
  extracted_source
@@ -0,0 +1,54 @@
1
+ require 'fpm/cookery/source_handler/template'
2
+
3
+ module FPM
4
+ module Cookery
5
+ class SourceHandler
6
+ class Svn < FPM::Cookery::SourceHandler::Template
7
+
8
+ CHECKSUM = false
9
+ NAME = :svn
10
+
11
+ def fetch
12
+ # TODO(lusis) - implement some caching using 'svn info'?
13
+ Dir.chdir(cachedir) do
14
+ svn(url, local_path)
15
+ end
16
+ local_path
17
+ end
18
+
19
+ def extract
20
+ Dir.chdir(builddir) do
21
+ safesystem('cp', '-Rp', local_path, '.')
22
+ end
23
+ extracted_source
24
+ end
25
+
26
+ private
27
+ def svn(url, path)
28
+ @options.has_key?(:revision) ? revision=@options[:revision] : revision='HEAD'
29
+ safesystem('svn', 'export', '--force', '-q', '-r', revision, url, path)
30
+ end
31
+
32
+ def extracted_source
33
+ entries = Dir['*'].select {|dir| File.directory?(dir) }
34
+
35
+ case entries.size
36
+ when 0
37
+ raise "Empty checkout! (#{local_path})"
38
+ when 1
39
+ entries.first
40
+ else
41
+ ext = Path.new(url).extname
42
+ dir = local_path.basename(ext)
43
+
44
+ if File.exist?(dir)
45
+ dir
46
+ else
47
+ raise "Could not find source directory for #{local_path.basename}"
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -6,13 +6,18 @@ module FPM
6
6
  class Template
7
7
  include FPM::Cookery::Utils
8
8
 
9
- attr_reader :url, :options, :cachedir, :builddir
9
+ NAME = :template
10
+ CHECKSUM = true
11
+
12
+ attr_reader :url, :options, :cachedir, :builddir, :has_checksum, :name
10
13
 
11
14
  def initialize(source_url, options, cachedir, builddir)
12
15
  @url = source_url
13
16
  @options = options
14
17
  @cachedir = cachedir
15
18
  @builddir = builddir
19
+ @has_checksum = self.class::CHECKSUM
20
+ @name = self.class::NAME
16
21
  end
17
22
 
18
23
  def fetch
@@ -23,6 +28,10 @@ module FPM
23
28
  raise "#{self}#extract not implemented!"
24
29
  end
25
30
 
31
+ def checksum?
32
+ @has_checksum
33
+ end
34
+
26
35
  def local_path
27
36
  @local_path ||= cachedir/(options[:as] || File.basename(url))
28
37
  end
@@ -1,26 +1,44 @@
1
1
  require 'forwardable'
2
2
  require 'fpm/cookery/source_handler/curl'
3
+ require 'fpm/cookery/source_handler/svn'
3
4
 
4
5
  module FPM
5
6
  module Cookery
6
7
  class SourceHandler
8
+ DEFAULT_HANDLER = :curl
9
+
7
10
  extend Forwardable
8
- def_delegators :@handler, :fetch, :extract, :local_path
11
+ def_delegators :@handler, :fetch, :extract, :local_path, :checksum?
9
12
 
10
13
  def initialize(source_url, options, cachedir, builddir)
14
+ # The reason for these checks is related to the test cases
15
+ # Test cases for individual recipe attributes
16
+ # are not setting spec before hand (due to delegation chain?)
17
+ # Additionally, one test actually has options being sent as a String
18
+ if ( options.nil? || options.class == String || options.has_key?(:with) == false)
19
+ @source_provider = DEFAULT_HANDLER
20
+ else
21
+ @source_provider = options[:with]
22
+ end
11
23
  @source_url = source_url
12
24
  @options = options
13
25
  @cachedir = cachedir
14
26
  @builddir = builddir
15
- @handler = get_source_handler
27
+ @handler = get_source_handler(@source_provider)
16
28
  end
17
29
 
18
30
  private
19
- def get_source_handler
20
- case @source_url.to_s
21
- when 'NONE YET'
22
- else
23
- SourceHandler::Curl.new(@source_url, @options, @cachedir, @builddir)
31
+ def get_source_handler(provider)
32
+ klass = handler_to_class(provider)
33
+ klass.new(@source_url, @options, @cachedir, @builddir)
34
+ end
35
+
36
+ def handler_to_class(provider)
37
+ begin
38
+ self.class.const_get(provider.to_s.capitalize)
39
+ rescue NameError
40
+ STDERR.puts "Specified provider #{provider} does not exist."
41
+ exit(1)
24
42
  end
25
43
  end
26
44
  end
@@ -1,5 +1,5 @@
1
1
  module FPM
2
2
  module Cookery
3
- VERSION = '0.3.0'
3
+ VERSION = '0.4.0'
4
4
  end
5
5
  end
@@ -1,10 +1,13 @@
1
1
  class Redis < FPM::Cookery::Recipe
2
2
  homepage 'http://redis.io'
3
- source 'http://redis.googlecode.com/files/redis-2.2.5.tar.gz'
4
- md5 'fe6395bbd2cadc45f4f20f6bbe05ed09'
3
+ # different source methods
4
+ #source 'https://github.com/antirez/redis/trunk', :with => :svn
5
+ #source 'https://github.com/antirez/redis/trunk', :with => :svn, :revision => '2400'
6
+ source 'http://redis.googlecode.com/files/redis-2.4.2.tar.gz'
7
+ md5 'c4b0b5e4953a11a503cb54cf6b09670e'
5
8
 
6
9
  name 'redis-server'
7
- version '2.2.5'
10
+ version '2.4.2'
8
11
  # revision '0' # => redis-server-2.2.5+fpm1
9
12
 
10
13
  description 'An advanced key-value store.'
@@ -0,0 +1,77 @@
1
+ require 'spec_helper'
2
+ require 'ostruct'
3
+ require 'fpm/cookery/facts'
4
+
5
+ describe "Facts" do
6
+ before do
7
+ FPM::Cookery::Facts.reset!
8
+ end
9
+
10
+ describe "platform" do
11
+ before do
12
+ Facter.class_eval do
13
+ def self.fact(v)
14
+ v == :operatingsystem ? OpenStruct.new(:value => 'CentOS') : nil
15
+ end
16
+ end
17
+ end
18
+
19
+ it "is using Facter to autodetect the platform" do
20
+ FPM::Cookery::Facts.platform.must_equal :centos
21
+ end
22
+
23
+ it "can be set" do
24
+ FPM::Cookery::Facts.platform = 'CentOS'
25
+ FPM::Cookery::Facts.platform.must_equal :centos
26
+ end
27
+ end
28
+
29
+ describe "target" do
30
+ describe "with platform CentOS" do
31
+ it "returns rpm" do
32
+ FPM::Cookery::Facts.platform = 'CentOS'
33
+ FPM::Cookery::Facts.target.must_equal :rpm
34
+ end
35
+ end
36
+
37
+ describe "with platform RedHat" do
38
+ it "returns rpm" do
39
+ FPM::Cookery::Facts.platform = 'RedHat'
40
+ FPM::Cookery::Facts.target.must_equal :rpm
41
+ end
42
+ end
43
+
44
+ describe "with platform Fedora" do
45
+ it "returns rpm" do
46
+ FPM::Cookery::Facts.platform = 'Fedora'
47
+ FPM::Cookery::Facts.target.must_equal :rpm
48
+ end
49
+ end
50
+
51
+ describe "with platform Debian" do
52
+ it "returns rpm" do
53
+ FPM::Cookery::Facts.platform = 'Debian'
54
+ FPM::Cookery::Facts.target.must_equal :deb
55
+ end
56
+ end
57
+
58
+ describe "with platform Ubuntu" do
59
+ it "returns rpm" do
60
+ FPM::Cookery::Facts.platform = 'Ubuntu'
61
+ FPM::Cookery::Facts.target.must_equal :deb
62
+ end
63
+ end
64
+
65
+ describe "with an unknown platform" do
66
+ it "returns nil" do
67
+ FPM::Cookery::Facts.platform = '___X___'
68
+ FPM::Cookery::Facts.target.must_equal nil
69
+ end
70
+ end
71
+
72
+ it "can be set" do
73
+ FPM::Cookery::Facts.target = 'rpm'
74
+ FPM::Cookery::Facts.target.must_equal :rpm
75
+ end
76
+ end
77
+ end
data/spec/recipe_spec.rb CHANGED
@@ -2,6 +2,8 @@ require 'spec_helper'
2
2
  require 'fpm/cookery/recipe'
3
3
 
4
4
  class TestRecipe < FPM::Cookery::Recipe
5
+ NAME = :test_recipe
6
+ CHECKSUM = true
5
7
  end
6
8
 
7
9
  describe "Recipe" do
@@ -72,6 +74,8 @@ describe "Recipe" do
72
74
  spec_recipe_attribute(:name, 'redis')
73
75
  spec_recipe_attribute(:revision, 12)
74
76
  spec_recipe_attribute(:section, 'lang')
77
+ # NOTE(lusis)
78
+ # see comment in `SourceHandler#initialize` r.e. options as `String`
75
79
  spec_recipe_attribute(:spec, {:foo => true})
76
80
  spec_recipe_attribute(:vendor, 'myvendor')
77
81
  spec_recipe_attribute(:version, '1.2')
@@ -174,6 +178,56 @@ describe "Recipe" do
174
178
  end
175
179
  end
176
180
 
181
+ describe ".platforms" do
182
+ describe "with a list of platforms" do
183
+ it "allows platform specific settings" do
184
+ klass.class_eval do
185
+ def self.platform; :ubuntu; end
186
+
187
+ vendor 'a'
188
+
189
+ platforms [:centos, :ubuntu] do
190
+ vendor 'b'
191
+ end
192
+ end
193
+
194
+ klass.new(__FILE__).vendor.must_equal 'b'
195
+ end
196
+ end
197
+
198
+ describe "with a single platform" do
199
+ it "allows platform specific settings" do
200
+ klass.class_eval do
201
+ def self.platform; :ubuntu; end
202
+
203
+ vendor 'a'
204
+
205
+ platforms :ubuntu do
206
+ vendor 'b'
207
+ end
208
+ end
209
+
210
+ klass.new(__FILE__).vendor.must_equal 'b'
211
+ end
212
+ end
213
+
214
+ describe "without a matching platform" do
215
+ it "does not set platform specific stuff" do
216
+ klass.class_eval do
217
+ def self.platform; :centos; end
218
+
219
+ vendor 'a'
220
+
221
+ platforms :ubuntu do
222
+ vendor 'b'
223
+ end
224
+ end
225
+
226
+ klass.new(__FILE__).vendor.must_equal 'a'
227
+ end
228
+ end
229
+ end
230
+
177
231
 
178
232
  #############################################################################
179
233
  # Directories
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fpm-cookery
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-10-25 00:00:00.000000000 Z
12
+ date: 2011-10-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: fpm
16
- requirement: &71291120 !ruby/object:Gem::Requirement
16
+ requirement: &84112030 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *71291120
24
+ version_requirements: *84112030
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: minitest
27
- requirement: &71290880 !ruby/object:Gem::Requirement
27
+ requirement: &84111800 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *71290880
35
+ version_requirements: *84111800
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rake
38
- requirement: &71290650 !ruby/object:Gem::Requirement
38
+ requirement: &84127950 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *71290650
46
+ version_requirements: *84127950
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: fpm
49
- requirement: &71290430 !ruby/object:Gem::Requirement
49
+ requirement: &84127720 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,7 +54,18 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *71290430
57
+ version_requirements: *84127720
58
+ - !ruby/object:Gem::Dependency
59
+ name: facter
60
+ requirement: &84127470 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :runtime
67
+ prerelease: false
68
+ version_requirements: *84127470
58
69
  description: A tool for building software packages with fpm.
59
70
  email:
60
71
  - bernd@tuneafish.de
@@ -74,12 +85,14 @@ files:
74
85
  - lib/fpm/cookery/book.rb
75
86
  - lib/fpm/cookery/book_hook.rb
76
87
  - lib/fpm/cookery/cli.rb
88
+ - lib/fpm/cookery/facts.rb
77
89
  - lib/fpm/cookery/packager.rb
78
90
  - lib/fpm/cookery/path.rb
79
91
  - lib/fpm/cookery/path_helper.rb
80
92
  - lib/fpm/cookery/recipe.rb
81
93
  - lib/fpm/cookery/source_handler.rb
82
94
  - lib/fpm/cookery/source_handler/curl.rb
95
+ - lib/fpm/cookery/source_handler/svn.rb
83
96
  - lib/fpm/cookery/source_handler/template.rb
84
97
  - lib/fpm/cookery/source_integrity_check.rb
85
98
  - lib/fpm/cookery/utils.rb
@@ -87,6 +100,7 @@ files:
87
100
  - recipes/nodejs/recipe.rb
88
101
  - recipes/redis/recipe.rb
89
102
  - recipes/redis/redis-server.init.d
103
+ - spec/facts_spec.rb
90
104
  - spec/fixtures/test-source-1.0.tar.gz
91
105
  - spec/path_helper_spec.rb
92
106
  - spec/path_spec.rb