fpm-fry 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/fpm/fry/block_enumerator.rb +9 -2
- data/lib/fpm/fry/channel.rb +20 -0
- data/lib/fpm/fry/chroot.rb +119 -0
- data/lib/fpm/fry/docker_file.rb +28 -13
- data/lib/fpm/fry/joined_io.rb +17 -2
- data/lib/fpm/fry/plugin/config.rb +27 -4
- data/lib/fpm/fry/plugin/edit_staging.rb +24 -1
- data/lib/fpm/fry/plugin/service.rb +10 -3
- data/lib/fpm/fry/recipe/builder.rb +43 -13
- data/lib/fpm/fry/recipe/error.rb +15 -0
- data/lib/fpm/fry/recipe.rb +10 -1
- data/lib/fpm/fry/source/dir.rb +4 -0
- data/lib/fpm/fry/source/git.rb +4 -0
- data/lib/fpm/fry/source/package.rb +30 -1
- data/lib/fpm/fry/with_data.rb +8 -0
- data/lib/fpm/package/docker.rb +16 -8
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9052cdc66f349423b938cefae76a81ddf5504c65
|
4
|
+
data.tar.gz: 6084e244c0f01eb10f0c4ec2dbd6f18f1831ddd4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3667766c65cb233def8e06ae14029bea06ebae06f03a8f9b5a4c45ae9d851557dcef27a510c8a361d8099b8a50f1ebb632182598192c27ae5355f1c908611ec0
|
7
|
+
data.tar.gz: 81c95585118d529c4438b09aff3c96b3044b60a8b181d65bb6611635dc5fed9d672083796b13afb3fe6b4e38acdf81b1f9b54fbf3ade555b68237b12cc74d132
|
@@ -2,24 +2,31 @@ module FPM; module Fry
|
|
2
2
|
class BlockEnumerator < Struct.new(:io, :blocksize)
|
3
3
|
include Enumerable
|
4
4
|
|
5
|
+
# @param io [IO]
|
6
|
+
# @param blocksize [Numeric]
|
5
7
|
def initialize(_, blocksize = 128)
|
6
8
|
super
|
7
9
|
end
|
8
10
|
|
11
|
+
# @return [Enumerator] unless called with a block
|
12
|
+
# @yield [chunk] One chunk from the io
|
13
|
+
# @yieldparam chunk [String]
|
9
14
|
def each
|
10
15
|
return to_enum unless block_given?
|
11
|
-
# Reading bigger chunks is far more efficient
|
16
|
+
# Reading bigger chunks is far more efficient than invoking #each on an IO.
|
12
17
|
while chunk = io.read(blocksize)
|
13
18
|
yield chunk
|
14
19
|
end
|
20
|
+
return nil
|
15
21
|
end
|
16
22
|
|
23
|
+
# @return [String] chunk or empty string at EOF
|
17
24
|
def call
|
18
25
|
while x = io.read(blocksize)
|
19
26
|
next if x == ""
|
20
27
|
return x
|
21
28
|
end
|
22
29
|
return ""
|
23
|
-
|
30
|
+
end
|
24
31
|
end
|
25
32
|
end ; end
|
data/lib/fpm/fry/channel.rb
CHANGED
@@ -19,5 +19,25 @@ module FPM; module Fry
|
|
19
19
|
|
20
20
|
include Hint
|
21
21
|
|
22
|
+
# @private
|
23
|
+
def _log(message, data={})
|
24
|
+
case message
|
25
|
+
when Hash
|
26
|
+
data.merge!(message)
|
27
|
+
when Exception
|
28
|
+
# message is an exception
|
29
|
+
data[:message] = message.to_s
|
30
|
+
data[:exception] = message
|
31
|
+
data[:backtrace] = message.backtrace
|
32
|
+
if message.respond_to? :data
|
33
|
+
data = message.data.merge(data)
|
34
|
+
end
|
35
|
+
else
|
36
|
+
data = { :message => message }.merge(data)
|
37
|
+
end
|
38
|
+
|
39
|
+
publish(data)
|
40
|
+
end
|
41
|
+
|
22
42
|
end
|
23
43
|
end ; end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'fpm/fry/with_data'
|
2
|
+
module FPM ; module Fry
|
3
|
+
# Helper class for filesystem operations inside staging directory.
|
4
|
+
# Resolves all symlinks relativ to a given base directory.
|
5
|
+
class Chroot
|
6
|
+
|
7
|
+
attr :base
|
8
|
+
|
9
|
+
# @param [String] base filesystem base
|
10
|
+
def initialize(base)
|
11
|
+
raise ArgumentError, "Base #{base.inspect} is not a directory" unless File.directory? base
|
12
|
+
@base = base
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns all directory entries like Dir.entries.
|
16
|
+
# @param [String] path
|
17
|
+
# @result [Array<String>] entries
|
18
|
+
def entries(path)
|
19
|
+
dir = rebase(path)
|
20
|
+
return Dir.entries(dir)
|
21
|
+
rescue => ex
|
22
|
+
raise Fry::WithData(ex, path: path)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Opens a file like File.open.
|
26
|
+
# @param [String] path
|
27
|
+
# @see (File.open)
|
28
|
+
def open(path,*args,&block)
|
29
|
+
file = rebase(path)
|
30
|
+
return File.open(file,*args,&block)
|
31
|
+
rescue => ex
|
32
|
+
raise Fry::WithData(ex, path: path)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Yields all entries recursively like Find.find.
|
36
|
+
# @param [String] path
|
37
|
+
# @yields entry
|
38
|
+
# @yieldparam [String] entry
|
39
|
+
def find(path, &block)
|
40
|
+
if stat(path).directory?
|
41
|
+
catch(:prune) do
|
42
|
+
block.call(path)
|
43
|
+
entries(path).each do | e |
|
44
|
+
next if e == "."
|
45
|
+
next if e == ".."
|
46
|
+
ep = File.join(path,e)
|
47
|
+
find(ep, &block)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
else
|
51
|
+
block.call(path)
|
52
|
+
end
|
53
|
+
return nil
|
54
|
+
end
|
55
|
+
|
56
|
+
# Stats a file without following the last symlink like File.lstat.
|
57
|
+
# @param [String] file
|
58
|
+
# @return [File::Stat] stat
|
59
|
+
# @see (File.lstat)
|
60
|
+
def lstat(file)
|
61
|
+
File.lstat(rebase(file, FOLLOW_ALL_BUT_LAST))
|
62
|
+
end
|
63
|
+
|
64
|
+
# Stats a file like File.stat.
|
65
|
+
# @param [String] file
|
66
|
+
# @return [File::Stat] stat
|
67
|
+
# @see (File.stat)
|
68
|
+
def stat(file)
|
69
|
+
File.stat(rebase(file))
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
FOLLOW = lambda do |base, current, rest|
|
75
|
+
path = [base, *current].join('/')
|
76
|
+
if File.symlink?(path)
|
77
|
+
File.readlink(path)
|
78
|
+
else
|
79
|
+
nil
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
FOLLOW_ALL_BUT_LAST = lambda do |base, current, rest|
|
84
|
+
if rest.any?
|
85
|
+
FOLLOW.call(base, current, rest)
|
86
|
+
else
|
87
|
+
nil
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def rebase(path, symlink_strategy = FOLLOW)
|
92
|
+
segs = path.split('/')
|
93
|
+
current = []
|
94
|
+
while segs.any?
|
95
|
+
seg = segs.shift
|
96
|
+
case seg
|
97
|
+
when '', '.' then next
|
98
|
+
when '..' then
|
99
|
+
# We don't check if anything was actually removed.
|
100
|
+
# This is consistent with File/Dir behavior.
|
101
|
+
current.pop
|
102
|
+
else
|
103
|
+
current << seg
|
104
|
+
rl = symlink_strategy.call(base, current, segs)
|
105
|
+
if rl
|
106
|
+
if rl.start_with? '/'
|
107
|
+
current = []
|
108
|
+
else
|
109
|
+
current.pop
|
110
|
+
end
|
111
|
+
segs.unshift *rl.split('/')
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
return [base,*current].join('/')
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
end ; end
|
data/lib/fpm/fry/docker_file.rb
CHANGED
@@ -90,31 +90,25 @@ module FPM; module Fry
|
|
90
90
|
df << "FROM #{base}"
|
91
91
|
df << "WORKDIR /tmp/build"
|
92
92
|
|
93
|
-
|
94
|
-
.select{|_,v| v.fetch(:install,true) }\
|
95
|
-
.map do |k,v|
|
96
|
-
i = v.fetch(:install,true)
|
97
|
-
if i == true then
|
98
|
-
k
|
99
|
-
else
|
100
|
-
i
|
101
|
-
end
|
102
|
-
end.sort
|
103
|
-
if deps.any?
|
93
|
+
if build_dependencies.any?
|
104
94
|
case(variables[:flavour])
|
105
95
|
when 'debian'
|
106
96
|
update = ''
|
107
97
|
if options[:update]
|
108
98
|
update = 'apt-get update && '
|
109
99
|
end
|
110
|
-
df << "RUN #{update}apt-get install --yes #{Shellwords.join(
|
100
|
+
df << "RUN #{update}apt-get install --yes #{Shellwords.join(build_dependencies)}"
|
111
101
|
when 'redhat'
|
112
|
-
df << "RUN yum -y install #{Shellwords.join(
|
102
|
+
df << "RUN yum -y install #{Shellwords.join(build_dependencies)}"
|
113
103
|
else
|
114
104
|
raise "Unknown flavour: #{variables[:flavour]}"
|
115
105
|
end
|
116
106
|
end
|
117
107
|
|
108
|
+
recipe.before_build_steps.each do |step|
|
109
|
+
df << "RUN #{step.to_s}"
|
110
|
+
end
|
111
|
+
|
118
112
|
df << "ADD .build.sh /tmp/build/"
|
119
113
|
df << "ENTRYPOINT /tmp/build/.build.sh"
|
120
114
|
df << ''
|
@@ -147,6 +141,27 @@ module FPM; module Fry
|
|
147
141
|
sio.rewind
|
148
142
|
return sio
|
149
143
|
end
|
144
|
+
|
145
|
+
private
|
146
|
+
def build_dependencies
|
147
|
+
return @build_dependencies if @build_dependencies
|
148
|
+
deps = []
|
149
|
+
(recipe.build_depends.merge recipe.depends).each do |k,v|
|
150
|
+
install = v.fetch(:install,true)
|
151
|
+
next unless install
|
152
|
+
case( install )
|
153
|
+
when true
|
154
|
+
deps << simplify_build_dependency(k)
|
155
|
+
when String
|
156
|
+
deps << simplify_build_dependency(install)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
@build_dependencies = deps.sort
|
160
|
+
end
|
161
|
+
|
162
|
+
def simplify_build_dependency( dep )
|
163
|
+
dep.split('|').first.strip
|
164
|
+
end
|
150
165
|
end
|
151
166
|
|
152
167
|
end
|
data/lib/fpm/fry/joined_io.rb
CHANGED
@@ -1,13 +1,18 @@
|
|
1
1
|
module FPM; module Fry
|
2
|
+
# Joins together multiple IOs
|
2
3
|
class JoinedIO
|
3
4
|
include Enumerable
|
4
5
|
|
6
|
+
# @param [IO] ios
|
5
7
|
def initialize(*ios)
|
6
8
|
@ios = ios
|
7
9
|
@pos = 0
|
8
10
|
@readbytes = 0
|
9
11
|
end
|
10
12
|
|
13
|
+
# Reads length bytes or all if length is nil.
|
14
|
+
# @param [Numeric, nil] length
|
15
|
+
# @return [String] resulting bytes
|
11
16
|
def read( len = nil )
|
12
17
|
buf = []
|
13
18
|
if len.nil?
|
@@ -35,27 +40,37 @@ module FPM; module Fry
|
|
35
40
|
end
|
36
41
|
end
|
37
42
|
|
38
|
-
|
43
|
+
# Reads up to length bytes.
|
44
|
+
# @param [Numeric] length
|
45
|
+
# @return [String] chunk
|
46
|
+
# @return [nil] at eof
|
47
|
+
def readpartial( length )
|
39
48
|
while (io = @ios[@pos])
|
40
|
-
r = io.read(
|
49
|
+
r = io.read( length )
|
41
50
|
if r.nil?
|
42
51
|
@pos = @pos + 1
|
43
52
|
next
|
44
53
|
else
|
54
|
+
if io.eof?
|
55
|
+
@pos = @pos + 1
|
56
|
+
end
|
45
57
|
return r
|
46
58
|
end
|
47
59
|
end
|
48
60
|
return nil
|
49
61
|
end
|
50
62
|
|
63
|
+
# @return [Numeric] number bytes read
|
51
64
|
def pos
|
52
65
|
@readbytes
|
53
66
|
end
|
54
67
|
|
68
|
+
# @return [true,false]
|
55
69
|
def eof?
|
56
70
|
@pos == @ios.size
|
57
71
|
end
|
58
72
|
|
73
|
+
# Closes all IOs.
|
59
74
|
def close
|
60
75
|
@ios.each(&:close)
|
61
76
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'fpm/fry/plugin'
|
2
|
+
require 'fpm/fry/chroot'
|
2
3
|
module FPM::Fry::Plugin::Config
|
3
4
|
|
4
5
|
# @api private
|
@@ -15,6 +16,7 @@ module FPM::Fry::Plugin::Config
|
|
15
16
|
class Callback < Struct.new(:files)
|
16
17
|
|
17
18
|
def call(_, package)
|
19
|
+
chroot = FPM::Fry::Chroot.new(package.staging_path)
|
18
20
|
prefix_length = package.staging_path.size + 1
|
19
21
|
candidates = []
|
20
22
|
# Sorting is important so that more specific rules override more generic
|
@@ -23,10 +25,31 @@ module FPM::Fry::Plugin::Config
|
|
23
25
|
keys.each do | key |
|
24
26
|
if files[key]
|
25
27
|
# Inclusion rule. Crawl file system for candidates
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
28
|
+
begin
|
29
|
+
lstat = chroot.lstat( key )
|
30
|
+
if lstat.symlink?
|
31
|
+
package.logger.warn("Config file is a symlink",
|
32
|
+
path: key,
|
33
|
+
plugin: 'config',
|
34
|
+
documentation: 'https://github.com/xing/fpm-fry/wiki/Plugin-config#config-path-not-foun://github.com/xing/fpm-fry/wiki/Plugin-config#config-file-is-a-symlink')
|
35
|
+
next
|
36
|
+
end
|
37
|
+
chroot.find( key ) do | path |
|
38
|
+
lstat = chroot.lstat(path)
|
39
|
+
if lstat.symlink?
|
40
|
+
package.logger.debug("Ignoring symlink",
|
41
|
+
path: path,
|
42
|
+
plugin: 'config')
|
43
|
+
throw :prune
|
44
|
+
elsif lstat.file?
|
45
|
+
candidates << path
|
46
|
+
end
|
47
|
+
end
|
48
|
+
rescue Errno::ENOENT
|
49
|
+
package.logger.warn("Config path not found",
|
50
|
+
path: key,
|
51
|
+
plugin: 'config',
|
52
|
+
documentation: 'https://github.com/xing/fpm-fry/wiki/Plugin-config#config-path-not-found')
|
30
53
|
end
|
31
54
|
else
|
32
55
|
# Exclusion rule. Remove matching candidates
|
@@ -1,10 +1,18 @@
|
|
1
|
+
require 'stringio'
|
1
2
|
require 'fpm/fry/plugin'
|
2
3
|
require 'fileutils'
|
4
|
+
# A plugin to edit the final build results.
|
5
|
+
# @example Add a file
|
6
|
+
# plugin 'edit_staging' do
|
7
|
+
# add_file '/a_file'
|
8
|
+
# end
|
3
9
|
module FPM::Fry::Plugin::EditStaging
|
4
10
|
|
11
|
+
# @api private
|
5
12
|
class AddFile < Struct.new(:path, :io, :options)
|
6
13
|
def call(_ , package)
|
7
14
|
file = package.staging_path(path)
|
15
|
+
package.logger.debug("Writing file directly to staging", target: file, content: io.inspect)
|
8
16
|
FileUtils.mkdir_p(File.dirname(file))
|
9
17
|
File.open(file,'w') do | f |
|
10
18
|
IO.copy_stream(io, f)
|
@@ -16,16 +24,28 @@ module FPM::Fry::Plugin::EditStaging
|
|
16
24
|
end
|
17
25
|
end
|
18
26
|
|
27
|
+
# @api private
|
19
28
|
class LnS < Struct.new(:src, :dest)
|
20
29
|
def call(_ , package)
|
21
30
|
file = package.staging_path(dest)
|
31
|
+
package.logger.debug("Linking file directly in staging", target: file, to: src)
|
22
32
|
FileUtils.mkdir_p(File.dirname(file))
|
23
33
|
File.symlink(src, file)
|
24
34
|
end
|
25
35
|
end
|
26
36
|
|
27
37
|
class DSL < Struct.new(:builder)
|
28
|
-
|
38
|
+
|
39
|
+
# @param [String] path
|
40
|
+
# @param [IO, String] content
|
41
|
+
def add_file(path, content, options = {})
|
42
|
+
if content.kind_of?(IO) || content.kind_of?(StringIO)
|
43
|
+
io = content
|
44
|
+
elsif content.kind_of? String
|
45
|
+
io = StringIO.new(content)
|
46
|
+
else
|
47
|
+
raise ArgumentError.new("File content must be a String or IO, got #{content.inspect}")
|
48
|
+
end
|
29
49
|
options = options.dup
|
30
50
|
options[:chmod] = convert_chmod(options[:chmod]) if options[:chmod]
|
31
51
|
options.freeze
|
@@ -51,6 +71,9 @@ module FPM::Fry::Plugin::EditStaging
|
|
51
71
|
|
52
72
|
end
|
53
73
|
|
74
|
+
# @yield [dsl]
|
75
|
+
# @yieldparam [DSL] dsl
|
76
|
+
# @return [DSL]
|
54
77
|
def self.apply(builder, &block)
|
55
78
|
d = DSL.new(builder)
|
56
79
|
if !block
|
@@ -92,9 +92,17 @@ module FPM::Fry::Plugin ; module Service
|
|
92
92
|
sh.after_install_or_upgrade(<<BASH)
|
93
93
|
if status #{Shellwords.shellescape name} 2>/dev/null | grep -q ' start/'; then
|
94
94
|
# It has to be stop+start because upstart doesn't pickup changes with restart.
|
95
|
-
|
95
|
+
if which invoke-rc.d >/dev/null 2>&1; then
|
96
|
+
invoke-rc.d #{Shellwords.shellescape name} stop
|
97
|
+
else
|
98
|
+
stop #{Shellwords.shellescape name}
|
99
|
+
fi
|
100
|
+
fi
|
101
|
+
if which invoke-rc.d >/dev/null 2>&1; then
|
102
|
+
invoke-rc.d #{Shellwords.shellescape name} start
|
103
|
+
else
|
104
|
+
start #{Shellwords.shellescape name}
|
96
105
|
fi
|
97
|
-
start #{Shellwords.shellescape name}
|
98
106
|
BASH
|
99
107
|
sh.before_remove_entirely(<<BASH)
|
100
108
|
if status #{Shellwords.shellescape name} 2>/dev/null | grep -q ' start/'; then
|
@@ -104,7 +112,6 @@ BASH
|
|
104
112
|
end
|
105
113
|
builder.plugin('config', FPM::Fry::Plugin::Config::IMPLICIT => true) do |co|
|
106
114
|
co.include "etc/init/#{name}.conf"
|
107
|
-
co.include "etc/init.d/#{name}"
|
108
115
|
end
|
109
116
|
when 'sysv' then
|
110
117
|
edit.add_file "/etc/init.d/#{name}",StringIO.new( env.render('sysv.erb') ), chmod: '750'
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'fpm/fry/recipe'
|
2
|
+
require 'fpm/fry/recipe/error'
|
2
3
|
require 'forwardable'
|
3
4
|
module FPM::Fry
|
4
5
|
class Recipe
|
@@ -52,11 +53,21 @@ module FPM::Fry
|
|
52
53
|
|
53
54
|
def depends( name , options = {} )
|
54
55
|
name, options = parse_package(name, options)
|
56
|
+
if package_recipe.depends.key? name
|
57
|
+
raise Error.new("duplicate dependency",package: name)
|
58
|
+
elsif package_recipe.conflicts.key? name
|
59
|
+
raise Error.new("depending package is already a conflicting package",package: name)
|
60
|
+
end
|
55
61
|
package_recipe.depends[name] = options
|
56
62
|
end
|
57
63
|
|
58
64
|
def conflicts( name , options = {} )
|
59
65
|
name, options = parse_package(name, options)
|
66
|
+
if package_recipe.conflicts.key? name
|
67
|
+
raise Error.new("duplicate conflict",package: name)
|
68
|
+
elsif package_recipe.depends.key? name
|
69
|
+
raise Error.new("conflicting package is already a dependency",package: name)
|
70
|
+
end
|
60
71
|
package_recipe.conflicts[name] = options
|
61
72
|
end
|
62
73
|
|
@@ -176,7 +187,9 @@ module FPM::Fry
|
|
176
187
|
end
|
177
188
|
variables.freeze
|
178
189
|
@recipe = recipe
|
179
|
-
|
190
|
+
@before_build = false
|
191
|
+
register_default_source_types!
|
192
|
+
super(variables, recipe.packages[0], options)
|
180
193
|
end
|
181
194
|
|
182
195
|
def load_file( file )
|
@@ -213,12 +226,23 @@ module FPM::Fry
|
|
213
226
|
|
214
227
|
def bash( name = nil, code )
|
215
228
|
if name
|
216
|
-
|
229
|
+
code = Recipe::Step.new(name, code)
|
230
|
+
end
|
231
|
+
# Don't do this at home
|
232
|
+
if @before_build
|
233
|
+
recipe.before_build_steps << code
|
217
234
|
else
|
218
|
-
recipe.steps << code
|
235
|
+
recipe.steps << code
|
219
236
|
end
|
220
237
|
end
|
221
238
|
|
239
|
+
def before_build
|
240
|
+
@before_build = true
|
241
|
+
yield
|
242
|
+
ensure
|
243
|
+
@before_build = false
|
244
|
+
end
|
245
|
+
|
222
246
|
def build_depends( name , options = {} )
|
223
247
|
name, options = parse_package(name, options)
|
224
248
|
recipe.build_depends[name] = options
|
@@ -240,19 +264,25 @@ module FPM::Fry
|
|
240
264
|
protected
|
241
265
|
|
242
266
|
def source_types
|
243
|
-
@source_types ||= {
|
244
|
-
git: Source::Git,
|
245
|
-
http: Source::Package,
|
246
|
-
tar: Source::Package,
|
247
|
-
dir: Source::Dir
|
248
|
-
}
|
267
|
+
@source_types ||= {}
|
249
268
|
end
|
250
269
|
|
251
|
-
def register_source_type(
|
270
|
+
def register_source_type( klass )
|
252
271
|
if !klass.respond_to? :new
|
253
272
|
raise ArgumentError.new("Expected something that responds to :new, got #{klass.inspect}")
|
254
273
|
end
|
255
|
-
source_types[name] = klass
|
274
|
+
source_types[klass.name] = klass
|
275
|
+
if klass.respond_to? :aliases
|
276
|
+
klass.aliases.each do |al|
|
277
|
+
source_types[al] = klass
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
def register_default_source_types!
|
283
|
+
register_source_type Source::Git
|
284
|
+
register_source_type Source::Package
|
285
|
+
register_source_type Source::Dir
|
256
286
|
end
|
257
287
|
|
258
288
|
NEG_INF = (-1.0/0.0)
|
@@ -267,10 +297,10 @@ module FPM::Fry
|
|
267
297
|
.sort_by{|score,_| score.nil? ? NEG_INF : score }
|
268
298
|
score, klasses = scores.last
|
269
299
|
if score == nil
|
270
|
-
raise
|
300
|
+
raise Error.new("No source provider found for #{url}.\nMaybe try explicitly setting the type using :with parameter. Valid options are: #{source_types.keys.join(', ')}")
|
271
301
|
end
|
272
302
|
if klasses.size != 1
|
273
|
-
raise
|
303
|
+
raise Error.new("Multiple possible source providers found for #{url}: #{klasses.join(', ')}.\nMaybe try explicitly setting the type using :with parameter. Valid options are: #{source_types.keys.join(', ')}")
|
274
304
|
end
|
275
305
|
return klasses.first
|
276
306
|
end
|
data/lib/fpm/fry/recipe.rb
CHANGED
@@ -18,6 +18,9 @@ module FPM; module Fry
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
+
class DuplicateDependency < ArgumentError
|
22
|
+
end
|
23
|
+
|
21
24
|
class PackageRecipe
|
22
25
|
attr_accessor :name,
|
23
26
|
:iteration,
|
@@ -121,10 +124,16 @@ module FPM; module Fry
|
|
121
124
|
end
|
122
125
|
end
|
123
126
|
|
124
|
-
attr_accessor :source,
|
127
|
+
attr_accessor :source,
|
128
|
+
:before_build_steps,
|
129
|
+
:steps,
|
130
|
+
:packages,
|
131
|
+
:build_depends,
|
132
|
+
:input_hooks
|
125
133
|
|
126
134
|
def initialize
|
127
135
|
@source = Source::Null
|
136
|
+
@before_build_steps = []
|
128
137
|
@steps = []
|
129
138
|
@packages = [PackageRecipe.new]
|
130
139
|
@packages[0].files << '**'
|
data/lib/fpm/fry/source/dir.rb
CHANGED
data/lib/fpm/fry/source/git.rb
CHANGED
@@ -9,6 +9,14 @@ module FPM; module Fry ; module Source
|
|
9
9
|
|
10
10
|
REGEX = %r!\Ahttps?:!
|
11
11
|
|
12
|
+
def self.name
|
13
|
+
:package
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.aliases
|
17
|
+
[:http]
|
18
|
+
end
|
19
|
+
|
12
20
|
def self.guess( url )
|
13
21
|
Source::guess_regex(REGEX, url)
|
14
22
|
end
|
@@ -158,11 +166,32 @@ module FPM; module Fry ; module Source
|
|
158
166
|
end
|
159
167
|
end
|
160
168
|
|
169
|
+
class PlainCache < Cache
|
170
|
+
|
171
|
+
def tar_io
|
172
|
+
update!
|
173
|
+
cmd = ['tar','-c',::File.basename(tempfile)]
|
174
|
+
dir = File.dirname(tempfile)
|
175
|
+
logger.debug("Running tar",cmd: cmd, dir: dir)
|
176
|
+
::Dir.chdir(dir) do
|
177
|
+
return IO.popen(cmd)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def copy_to(dst)
|
182
|
+
update!
|
183
|
+
FileUtils.cp( tempfile, dst )
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
|
161
188
|
CACHE_CLASSES = {
|
162
189
|
'.tar' => TarCache,
|
163
190
|
'.tar.gz' => TarGzCache,
|
164
191
|
'.tgz' => TarGzCache,
|
165
|
-
'.zip' => ZipCache
|
192
|
+
'.zip' => ZipCache,
|
193
|
+
'.bin' => PlainCache,
|
194
|
+
'.bundle' => PlainCache
|
166
195
|
}
|
167
196
|
|
168
197
|
attr :file_map, :data, :url, :extension, :checksum, :checksum_algorithm, :agent, :logger
|
data/lib/fpm/package/docker.rb
CHANGED
@@ -24,8 +24,12 @@ class FPM::Package::Docker < FPM::Package
|
|
24
24
|
|
25
25
|
def split( name, map )
|
26
26
|
changes = changes(name)
|
27
|
-
changes.remove_modified_leaves! do | ml |
|
28
|
-
|
27
|
+
changes.remove_modified_leaves! do | kind, ml |
|
28
|
+
if kind == DELETED
|
29
|
+
@logger.warn("Found a deleted file. You can only create new files in a package",name: ml)
|
30
|
+
else
|
31
|
+
@logger.warn("Found a modified file. You can only create new files in a package",name: ml)
|
32
|
+
end
|
29
33
|
end
|
30
34
|
fmap = {}
|
31
35
|
changes.leaves.each do | change |
|
@@ -72,6 +76,10 @@ private
|
|
72
76
|
return false
|
73
77
|
end
|
74
78
|
|
79
|
+
MODIFIED = 0
|
80
|
+
CREATED = 1
|
81
|
+
DELETED = 2
|
82
|
+
|
75
83
|
class Node < Struct.new(:children, :kind)
|
76
84
|
|
77
85
|
def initialize
|
@@ -105,8 +113,8 @@ private
|
|
105
113
|
def modified_leaves( prefix = '/', &block )
|
106
114
|
return to_enum(:modified_leaves, prefix) unless block
|
107
115
|
if leaf?
|
108
|
-
if kind !=
|
109
|
-
yield prefix
|
116
|
+
if kind != CREATED
|
117
|
+
yield kind, prefix
|
110
118
|
end
|
111
119
|
else
|
112
120
|
children.each do |name, cld|
|
@@ -119,15 +127,15 @@ private
|
|
119
127
|
to_remove = {}
|
120
128
|
children.each do |name, cld|
|
121
129
|
removed_children = cld.remove_modified_leaves!(File.join(prefix,name), &block)
|
122
|
-
if cld.leaf? and cld.kind !=
|
123
|
-
to_remove[name] = removed_children
|
130
|
+
if cld.leaf? and cld.kind != CREATED
|
131
|
+
to_remove[name] = [cld.kind, removed_children]
|
124
132
|
end
|
125
133
|
end
|
126
134
|
if to_remove.any?
|
127
|
-
to_remove.each do |name, removed_children|
|
135
|
+
to_remove.each do |name, (kind, removed_children)|
|
128
136
|
children.delete(name)
|
129
137
|
if !removed_children
|
130
|
-
yield File.join(prefix,name)
|
138
|
+
yield kind, File.join(prefix,name)
|
131
139
|
end
|
132
140
|
end
|
133
141
|
return true
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fpm-fry
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hannes Georg
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-04-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: excon
|
@@ -38,7 +38,7 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '1.0'
|
41
|
-
description:
|
41
|
+
description: deep-fried package builder
|
42
42
|
email: hannes.georg@xing.com
|
43
43
|
executables:
|
44
44
|
- fpm-fry
|
@@ -50,6 +50,7 @@ files:
|
|
50
50
|
- lib/fpm/fry/block_enumerator.rb
|
51
51
|
- lib/fpm/fry/build_output_parser.rb
|
52
52
|
- lib/fpm/fry/channel.rb
|
53
|
+
- lib/fpm/fry/chroot.rb
|
53
54
|
- lib/fpm/fry/client.rb
|
54
55
|
- lib/fpm/fry/command.rb
|
55
56
|
- lib/fpm/fry/command/cook.rb
|
@@ -70,6 +71,7 @@ files:
|
|
70
71
|
- lib/fpm/fry/plugin/user.rb
|
71
72
|
- lib/fpm/fry/recipe.rb
|
72
73
|
- lib/fpm/fry/recipe/builder.rb
|
74
|
+
- lib/fpm/fry/recipe/error.rb
|
73
75
|
- lib/fpm/fry/source.rb
|
74
76
|
- lib/fpm/fry/source/dir.rb
|
75
77
|
- lib/fpm/fry/source/git.rb
|
@@ -86,6 +88,7 @@ files:
|
|
86
88
|
- lib/fpm/fry/templates/sysv.erb
|
87
89
|
- lib/fpm/fry/templates/upstart.erb
|
88
90
|
- lib/fpm/fry/ui.rb
|
91
|
+
- lib/fpm/fry/with_data.rb
|
89
92
|
- lib/fpm/package/docker.rb
|
90
93
|
homepage: https://github.com/xing/fpm-fry
|
91
94
|
licenses:
|
@@ -107,9 +110,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
107
110
|
version: '0'
|
108
111
|
requirements: []
|
109
112
|
rubyforge_project:
|
110
|
-
rubygems_version: 2.
|
113
|
+
rubygems_version: 2.5.1
|
111
114
|
signing_key:
|
112
115
|
specification_version: 4
|
113
116
|
summary: FPM Fry
|
114
117
|
test_files: []
|
115
|
-
has_rdoc:
|