fpm-cookery 0.0.1
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/.gitignore +8 -0
- data/CHANGELOG.md +2 -0
- data/Gemfile +3 -0
- data/README.md +159 -0
- data/Rakefile +10 -0
- data/bin/fpm-cook +7 -0
- data/fpm-cookery.gemspec +24 -0
- data/lib/fpm/cookery/book.rb +16 -0
- data/lib/fpm/cookery/book_hook.rb +17 -0
- data/lib/fpm/cookery/cli.rb +35 -0
- data/lib/fpm/cookery/packager.rb +155 -0
- data/lib/fpm/cookery/path.rb +75 -0
- data/lib/fpm/cookery/path_helper.rb +49 -0
- data/lib/fpm/cookery/recipe.rb +88 -0
- data/lib/fpm/cookery/source_handler.rb +28 -0
- data/lib/fpm/cookery/source_handler/curl.rb +53 -0
- data/lib/fpm/cookery/source_handler/template.rb +32 -0
- data/lib/fpm/cookery/utils.rb +62 -0
- data/lib/fpm/cookery/version.rb +5 -0
- data/recipes/nodejs/recipe.rb +35 -0
- data/recipes/redis/recipe.rb +38 -0
- data/recipes/redis/redis-server.init.d +80 -0
- data/spec/path_spec.rb +123 -0
- data/spec/recipe_spec.rb +248 -0
- data/spec/spec_helper.rb +2 -0
- metadata +104 -0
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module FPM
|
5
|
+
module Cookery
|
6
|
+
class Path < Pathname
|
7
|
+
if '1.9' <= RUBY_VERSION
|
8
|
+
alias_method :to_str, :to_s
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.pwd(path = nil)
|
12
|
+
new(Dir.pwd)/path
|
13
|
+
end
|
14
|
+
|
15
|
+
def +(other)
|
16
|
+
other = Path.new(other) unless Path === other
|
17
|
+
Path.new(plus(@path, other.to_s))
|
18
|
+
end
|
19
|
+
|
20
|
+
def /(path)
|
21
|
+
self + (path || '').gsub(%r{^/}, '')
|
22
|
+
end
|
23
|
+
|
24
|
+
def mkdir
|
25
|
+
FileUtils.mkdir_p(self.to_s)
|
26
|
+
end
|
27
|
+
|
28
|
+
def install(src)
|
29
|
+
case src
|
30
|
+
when Array
|
31
|
+
src.collect {|src| install_p(src) }
|
32
|
+
when Hash
|
33
|
+
src.collect {|src, new_basename| install_p(src, new_basename) }
|
34
|
+
else
|
35
|
+
install_p(src)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def install_p(src, new_basename = nil)
|
40
|
+
if new_basename
|
41
|
+
new_basename = File.basename(new_basename) # rationale: see Pathname.+
|
42
|
+
dst = self/new_basename
|
43
|
+
return_value = Path.new(dst)
|
44
|
+
else
|
45
|
+
dst = self
|
46
|
+
return_value = self/File.basename(src)
|
47
|
+
end
|
48
|
+
|
49
|
+
src = src.to_s
|
50
|
+
dst = dst.to_s
|
51
|
+
|
52
|
+
# if it's a symlink, don't resolve it to a file because if we are moving
|
53
|
+
# files one by one, it's likely we will break the symlink by moving what
|
54
|
+
# it points to before we move it
|
55
|
+
# and also broken symlinks are not the end of the world
|
56
|
+
raise "#{src} does not exist" unless File.symlink? src or File.exist? src
|
57
|
+
|
58
|
+
mkpath
|
59
|
+
FileUtils.cp_r src, dst, :preserve => true
|
60
|
+
|
61
|
+
# if File.symlink? src
|
62
|
+
# # we use the BSD mv command because FileUtils copies the target and
|
63
|
+
# # not the link! I'm beginning to wish I'd used Python quite honestly!
|
64
|
+
# raise unless Kernel.system 'mv', src, dst
|
65
|
+
# else
|
66
|
+
# # we mv when possible as it is faster and you should only be using
|
67
|
+
# # this function when installing from the temporary build directory
|
68
|
+
# FileUtils.mv src, dst
|
69
|
+
# end
|
70
|
+
|
71
|
+
return return_value
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'fpm/cookery/path'
|
2
|
+
|
3
|
+
module FPM
|
4
|
+
module Cookery
|
5
|
+
module PathHelper
|
6
|
+
attr_accessor :installing
|
7
|
+
|
8
|
+
def installing?
|
9
|
+
installing
|
10
|
+
end
|
11
|
+
|
12
|
+
# Most of the path helper stuff comes from brew2deb and homebrew.
|
13
|
+
def prefix(path = nil)
|
14
|
+
current_pathname_for('usr')/path
|
15
|
+
end
|
16
|
+
|
17
|
+
def etc(path = nil)
|
18
|
+
current_pathname_for('etc')/path
|
19
|
+
end
|
20
|
+
|
21
|
+
def var(path = nil)
|
22
|
+
current_pathname_for('var')/path
|
23
|
+
end
|
24
|
+
|
25
|
+
def bin(path = nil) prefix/'bin'/path end
|
26
|
+
def doc(path = nil) prefix/'share/doc'/path/name end
|
27
|
+
def include(path = nil) prefix/'include'/path end
|
28
|
+
def info(path = nil) prefix/'share/info'/path end
|
29
|
+
def lib(path = nil) prefix/'lib'/path end
|
30
|
+
def libexec(path = nil) prefix/'libexec'/path end
|
31
|
+
def man(path = nil) prefix/'share/man'/path end
|
32
|
+
def man1(path = nil) man/'man1'/path end
|
33
|
+
def man2(path = nil) man/'man2'/path end
|
34
|
+
def man3(path = nil) man/'man3'/path end
|
35
|
+
def man4(path = nil) man/'man4'/path end
|
36
|
+
def man5(path = nil) man/'man5'/path end
|
37
|
+
def man6(path = nil) man/'man6'/path end
|
38
|
+
def man7(path = nil) man/'man7'/path end
|
39
|
+
def man8(path = nil) man/'man8'/path end
|
40
|
+
def sbin(path = nil) prefix/'sbin'/path end
|
41
|
+
def share(path = nil) prefix/'share'/path end
|
42
|
+
|
43
|
+
private
|
44
|
+
def current_pathname_for(dir)
|
45
|
+
installing? ? destdir/dir : Path.new("/#{dir}")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'fpm/cookery/source_handler'
|
3
|
+
require 'fpm/cookery/utils'
|
4
|
+
require 'fpm/cookery/path_helper'
|
5
|
+
|
6
|
+
module FPM
|
7
|
+
module Cookery
|
8
|
+
class Recipe
|
9
|
+
include FileUtils
|
10
|
+
include FPM::Cookery::Utils
|
11
|
+
include FPM::Cookery::PathHelper
|
12
|
+
|
13
|
+
def self.attr_rw(*attrs)
|
14
|
+
attrs.each do |attr|
|
15
|
+
class_eval %Q{
|
16
|
+
def self.#{attr}(value = nil)
|
17
|
+
value.nil? ? @#{attr} : @#{attr} = value
|
18
|
+
end
|
19
|
+
|
20
|
+
def #{attr}
|
21
|
+
self.class.#{attr}
|
22
|
+
end
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.attr_rw_list(*attrs)
|
28
|
+
attrs.each do |attr|
|
29
|
+
class_eval %Q{
|
30
|
+
def self.#{attr}(*list)
|
31
|
+
@#{attr} ||= superclass.respond_to?(:#{attr}) ? superclass.#{attr} : []
|
32
|
+
@#{attr} << list
|
33
|
+
@#{attr}.flatten!
|
34
|
+
@#{attr}.uniq!
|
35
|
+
@#{attr}
|
36
|
+
end
|
37
|
+
|
38
|
+
def #{attr}
|
39
|
+
self.class.#{attr}
|
40
|
+
end
|
41
|
+
}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
attr_rw :arch, :description, :homepage, :maintainer, :md5, :name,
|
46
|
+
:revision, :section, :spec, :vendor, :version
|
47
|
+
|
48
|
+
attr_rw_list :build_depends, :config_files, :conflicts, :depends,
|
49
|
+
:exclude, :patches, :provides, :replaces
|
50
|
+
|
51
|
+
class << self
|
52
|
+
def source(source = nil, spec = {})
|
53
|
+
return @source if source.nil?
|
54
|
+
@source = source
|
55
|
+
@spec = spec
|
56
|
+
end
|
57
|
+
alias_method :url, :source
|
58
|
+
end
|
59
|
+
|
60
|
+
def source
|
61
|
+
self.class.source
|
62
|
+
end
|
63
|
+
|
64
|
+
def initialize(filename)
|
65
|
+
@filename = Path.new(filename).expand_path
|
66
|
+
@source_handler = SourceHandler.new(source, spec, cachedir, builddir)
|
67
|
+
|
68
|
+
# Set some defaults.
|
69
|
+
vendor || self.class.vendor('fpm')
|
70
|
+
revision || self.class.revision(0)
|
71
|
+
end
|
72
|
+
|
73
|
+
attr_reader :filename, :source_handler
|
74
|
+
|
75
|
+
def workdir=(value) @workdir = Path.new(value) end
|
76
|
+
def destdir=(value) @destdir = Path.new(value) end
|
77
|
+
def builddir=(value) @builddir = Path.new(value) end
|
78
|
+
def pkgdir=(value) @pkgdir = Path.new(value) end
|
79
|
+
def cachedir=(value) @cachedir = Path.new(value) end
|
80
|
+
|
81
|
+
def workdir(path = nil) (@workdir ||= filename.dirname)/path end
|
82
|
+
def destdir(path = nil) (@destdir ||= workdir('tmp-dest'))/path end
|
83
|
+
def builddir(path = nil) (@builddir ||= workdir('tmp-build'))/path end
|
84
|
+
def pkgdir(path = nil) (@pkgdir ||= workdir('pkg'))/path end
|
85
|
+
def cachedir(path = nil) (@cachedir ||= workdir('cache'))/path end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
require 'fpm/cookery/source_handler/curl'
|
3
|
+
|
4
|
+
module FPM
|
5
|
+
module Cookery
|
6
|
+
class SourceHandler
|
7
|
+
extend Forwardable
|
8
|
+
def_delegators :@handler, :fetch, :extract, :local_path
|
9
|
+
|
10
|
+
def initialize(source_url, options, cachedir, builddir)
|
11
|
+
@source_url = source_url
|
12
|
+
@options = options
|
13
|
+
@cachedir = cachedir
|
14
|
+
@builddir = builddir
|
15
|
+
@handler = get_source_handler
|
16
|
+
end
|
17
|
+
|
18
|
+
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)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'fpm/cookery/source_handler/template'
|
2
|
+
|
3
|
+
module FPM
|
4
|
+
module Cookery
|
5
|
+
class SourceHandler
|
6
|
+
class Curl < FPM::Cookery::SourceHandler::Template
|
7
|
+
def fetch
|
8
|
+
unless local_path.exist?
|
9
|
+
Dir.chdir(cachedir) do
|
10
|
+
curl(url, local_path) unless local_path.exist?
|
11
|
+
end
|
12
|
+
end
|
13
|
+
local_path
|
14
|
+
end
|
15
|
+
|
16
|
+
def extract
|
17
|
+
Dir.chdir(builddir) do
|
18
|
+
case local_path.extname
|
19
|
+
when '.bz2', '.gz', '.tgz'
|
20
|
+
safesystem('tar', 'xf', local_path)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
extracted_source
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
def curl(url, path)
|
28
|
+
safesystem('curl', '-fL', '--progress-bar', '-o', path, url)
|
29
|
+
end
|
30
|
+
|
31
|
+
def extracted_source
|
32
|
+
entries = Dir['*'].select {|dir| File.directory?(dir) }
|
33
|
+
|
34
|
+
case entries.size
|
35
|
+
when 0
|
36
|
+
raise "Empty archive! (#{local_path})"
|
37
|
+
when 1
|
38
|
+
entries.first
|
39
|
+
else
|
40
|
+
ext = Path.new(url).extname
|
41
|
+
dir = local_path.basename(ext)
|
42
|
+
|
43
|
+
if File.exist?(dir)
|
44
|
+
dir
|
45
|
+
else
|
46
|
+
raise "Could not find source directory for #{local_path.basename}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'fpm/cookery/utils'
|
2
|
+
|
3
|
+
module FPM
|
4
|
+
module Cookery
|
5
|
+
class SourceHandler
|
6
|
+
class Template
|
7
|
+
include FPM::Cookery::Utils
|
8
|
+
|
9
|
+
attr_reader :url, :options, :cachedir, :builddir
|
10
|
+
|
11
|
+
def initialize(source_url, options, cachedir, builddir)
|
12
|
+
@url = source_url
|
13
|
+
@options = options
|
14
|
+
@cachedir = cachedir
|
15
|
+
@builddir = builddir
|
16
|
+
end
|
17
|
+
|
18
|
+
def fetch
|
19
|
+
raise "#{self}#fetch not implemented!"
|
20
|
+
end
|
21
|
+
|
22
|
+
def extract
|
23
|
+
raise "#{self}#extract not implemented!"
|
24
|
+
end
|
25
|
+
|
26
|
+
def local_path
|
27
|
+
@local_path ||= cachedir/(options[:as] || File.basename(url))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module FPM
|
2
|
+
module Cookery
|
3
|
+
module Utils
|
4
|
+
protected
|
5
|
+
# From fpm. (lib/fpm/util.rb)
|
6
|
+
def safesystem(*args)
|
7
|
+
success = system(*args)
|
8
|
+
if !success
|
9
|
+
raise "'system(#{args.inspect})' failed with error code: #{$?.exitstatus}"
|
10
|
+
end
|
11
|
+
return success
|
12
|
+
end
|
13
|
+
|
14
|
+
# From brew2deb. (lib/debian_formula.rb)
|
15
|
+
def configure(*args)
|
16
|
+
if args.last.is_a?(Hash)
|
17
|
+
opts = args.pop
|
18
|
+
args += opts.map{ |k,v|
|
19
|
+
option = k.to_s.gsub('_','-')
|
20
|
+
if v == true
|
21
|
+
"--#{option}"
|
22
|
+
else
|
23
|
+
"--#{option}=#{v}"
|
24
|
+
end
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
safesystem './configure', *args
|
29
|
+
end
|
30
|
+
|
31
|
+
# From brew2deb. (lib/debian_formula.rb)
|
32
|
+
def make(*args)
|
33
|
+
env = args.pop if args.last.is_a?(Hash)
|
34
|
+
env ||= {}
|
35
|
+
|
36
|
+
args += env.map{ |k,v| "#{k}=#{v}" }
|
37
|
+
args.map!{ |a| a.to_s }
|
38
|
+
|
39
|
+
safesystem 'make', *args
|
40
|
+
end
|
41
|
+
|
42
|
+
# From homebrew. (Library/Homebrew/utils.rb)
|
43
|
+
def inline_replace(path, before = nil, after = nil)
|
44
|
+
[*path].each do |path|
|
45
|
+
f = File.open(path, 'r')
|
46
|
+
s = f.read
|
47
|
+
|
48
|
+
if before == nil and after == nil
|
49
|
+
# s.extend(StringInreplaceExtension)
|
50
|
+
yield s
|
51
|
+
else
|
52
|
+
s.gsub!(before, after)
|
53
|
+
end
|
54
|
+
|
55
|
+
f.reopen(path, 'w').write(s)
|
56
|
+
f.close
|
57
|
+
end
|
58
|
+
end
|
59
|
+
alias_method :inreplace, :inline_replace # homebrew compat
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
class NodeJS < FPM::Cookery::Recipe
|
2
|
+
source 'http://nodejs.org/dist/node-v0.4.10.tar.gz'
|
3
|
+
# head 'https://github.com/joyent/node.git'
|
4
|
+
homepage 'http://nodejs.org/'
|
5
|
+
md5 '2e8b82a9788308727e285d2d4a129c29'
|
6
|
+
|
7
|
+
section 'interpreters'
|
8
|
+
name 'nodejs'
|
9
|
+
version '0.4.10+github1'
|
10
|
+
description 'Evented I/O for V8 JavaScript'
|
11
|
+
|
12
|
+
build_depends \
|
13
|
+
'libssl-dev',
|
14
|
+
'g++',
|
15
|
+
'python'
|
16
|
+
|
17
|
+
depends \
|
18
|
+
'openssl'
|
19
|
+
|
20
|
+
def build
|
21
|
+
inreplace 'wscript' do |s|
|
22
|
+
s.gsub! '/usr/local', '/usr'
|
23
|
+
s.gsub! '/opt/local/lib', '/usr/lib'
|
24
|
+
end
|
25
|
+
|
26
|
+
configure \
|
27
|
+
:prefix => prefix,
|
28
|
+
:debug => true
|
29
|
+
make
|
30
|
+
end
|
31
|
+
|
32
|
+
def install
|
33
|
+
make :install, 'DESTDIR' => destdir
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class Redis < FPM::Cookery::Recipe
|
2
|
+
homepage 'http://redis.io'
|
3
|
+
source 'http://redis.googlecode.com/files/redis-2.2.5.tar.gz'
|
4
|
+
md5 'fe6395bbd2cadc45f4f20f6bbe05ed09'
|
5
|
+
|
6
|
+
name 'redis-server'
|
7
|
+
version '2.2.5'
|
8
|
+
# revision '0' # => redis-server-2.2.5+fpm1
|
9
|
+
|
10
|
+
description 'An advanced key-value store.'
|
11
|
+
|
12
|
+
conflicts 'redis-server'
|
13
|
+
|
14
|
+
config_files '/etc/redis/redis.conf'
|
15
|
+
|
16
|
+
patches 'patches/test.patch'
|
17
|
+
|
18
|
+
def build
|
19
|
+
make
|
20
|
+
|
21
|
+
inline_replace 'redis.conf' do |s|
|
22
|
+
s.gsub! 'daemonize no', 'daemonize yes # non-default'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def install
|
27
|
+
# make :install, 'DESTDIR' => destdir
|
28
|
+
|
29
|
+
var('lib/redis').mkdir
|
30
|
+
|
31
|
+
%w(run log/redis).each {|p| var(p).mkdir }
|
32
|
+
|
33
|
+
bin.install ['src/redis-server', 'src/redis-cli']
|
34
|
+
|
35
|
+
etc('redis').install 'redis.conf'
|
36
|
+
etc('init.d').install workdir('redis-server.init.d') => 'redis-server'
|
37
|
+
end
|
38
|
+
end
|