fpm-fry 0.2.0 → 0.2.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.
- 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:
|