fpm-fry 0.2.2 → 0.4.6
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 +5 -5
- data/lib/cabin/nice_output.rb +16 -1
- data/lib/fpm/fry/block_enumerator.rb +6 -3
- data/lib/fpm/fry/build_output_parser.rb +10 -5
- data/lib/fpm/fry/channel.rb +13 -0
- data/lib/fpm/fry/chroot.rb +2 -2
- data/lib/fpm/fry/client.rb +96 -12
- data/lib/fpm/fry/command.rb +15 -32
- data/lib/fpm/fry/command/cook.rb +38 -56
- data/lib/fpm/fry/detector.rb +43 -98
- data/lib/fpm/fry/docker_file.rb +60 -26
- data/lib/fpm/fry/exec.rb +76 -0
- data/lib/fpm/fry/inspector.rb +70 -0
- data/lib/fpm/fry/joined_io.rb +1 -1
- data/lib/fpm/fry/plugin/apt.rb +52 -0
- data/lib/fpm/fry/plugin/edit_staging.rb +1 -1
- data/lib/fpm/fry/plugin/env.rb +45 -0
- data/lib/fpm/fry/plugin/init.rb +71 -42
- data/lib/fpm/fry/plugin/service.rb +108 -49
- data/lib/fpm/fry/plugin/systemd.rb +75 -0
- data/lib/fpm/fry/recipe.rb +64 -23
- data/lib/fpm/fry/recipe/builder.rb +53 -20
- data/lib/fpm/fry/source.rb +41 -12
- data/lib/fpm/fry/source/{package.rb → archive.rb} +115 -35
- data/lib/fpm/fry/source/dir.rb +13 -8
- data/lib/fpm/fry/source/git.rb +81 -45
- data/lib/fpm/fry/source/patched.rb +61 -32
- data/lib/fpm/fry/tar.rb +63 -0
- data/lib/fpm/fry/templates/debian/after_remove.erb +1 -1
- data/lib/fpm/fry/templates/debian/before_remove.erb +1 -1
- data/lib/fpm/fry/ui.rb +1 -1
- data/lib/fpm/fry/with_data.rb +34 -0
- data/lib/fpm/package/docker.rb +16 -0
- metadata +82 -13
- data/lib/fpm/fry/os_db.rb +0 -36
@@ -4,32 +4,67 @@ require 'net/http'
|
|
4
4
|
require 'forwardable'
|
5
5
|
require 'zlib'
|
6
6
|
require 'fpm/fry/source'
|
7
|
+
require 'fpm/fry/exec'
|
7
8
|
require 'cabin'
|
9
|
+
require 'cabin/channel'
|
10
|
+
|
8
11
|
module FPM; module Fry ; module Source
|
9
|
-
|
12
|
+
# Used to build from an archive.
|
13
|
+
#
|
14
|
+
# @example in a recipe
|
15
|
+
# source 'http://curl.haxx.se/download/curl-7.36.0.tar.gz',
|
16
|
+
# checksum: '33015795d5650a2bfdd9a4a28ce4317cef944722a5cfca0d1563db8479840e90'
|
17
|
+
#
|
18
|
+
# It is highly advised to supply a checksum ( althought it's not mandatory ).
|
19
|
+
# This checksum will be used to test for cache validity and data integrity. The
|
20
|
+
# checksum algorithm is automatically guessed based on the length of the checksum.
|
21
|
+
#
|
22
|
+
# - 40 characters = sha1
|
23
|
+
# - 64 characters = sha256
|
24
|
+
#
|
25
|
+
# Let's be honest: all other checksum algorithms aren't or shouldn't be in use anyway.
|
26
|
+
class Archive
|
10
27
|
|
11
28
|
REGEX = %r!\Ahttps?:!
|
12
29
|
|
30
|
+
# @return [:archive]
|
13
31
|
def self.name
|
14
32
|
:package
|
15
33
|
end
|
16
34
|
|
17
35
|
def self.aliases
|
18
|
-
[:http]
|
36
|
+
[:package,:http]
|
19
37
|
end
|
20
38
|
|
39
|
+
# Guesses if the given url is an archive.
|
40
|
+
#
|
41
|
+
# @example not an archive
|
42
|
+
# FPM::Fry::Source::Archive.guess("bzr://something") # => nil
|
43
|
+
#
|
44
|
+
# @example an archive
|
45
|
+
# FPM::Fry::Source::Archive.guess("https://some/thing.tar.gz") #=> 6
|
46
|
+
#
|
47
|
+
# @return [nil] when it's not an archive
|
48
|
+
# @return [Numeric] number of characters used
|
21
49
|
def self.guess( url )
|
22
50
|
Source::guess_regex(REGEX, url)
|
23
51
|
end
|
24
52
|
|
53
|
+
# Raised when too many redirects happened.
|
25
54
|
class RedirectError < CacheFailed
|
26
55
|
end
|
27
56
|
|
57
|
+
# Raised when the archive type is not known.
|
58
|
+
class UnknownArchiveType < StandardError
|
59
|
+
include WithData
|
60
|
+
end
|
61
|
+
|
28
62
|
class Cache < Struct.new(:package,:tempdir)
|
29
63
|
extend Forwardable
|
30
64
|
|
31
|
-
def_delegators :package, :url, :checksum, :checksum_algorithm, :
|
65
|
+
def_delegators :package, :url, :checksum, :checksum_algorithm, :logger, :file_map, :to
|
32
66
|
|
67
|
+
# @return [String] cachekey which is equal to the checksum
|
33
68
|
def cachekey
|
34
69
|
@observed_checksum || checksum
|
35
70
|
end
|
@@ -92,7 +127,7 @@ module FPM; module Fry ; module Source
|
|
92
127
|
case(resp)
|
93
128
|
when Net::HTTPRedirection
|
94
129
|
if redirs == 0
|
95
|
-
raise RedirectError
|
130
|
+
raise RedirectError.new("Too many redirects", url: url.to_s, location: resp['location'])
|
96
131
|
end
|
97
132
|
logger.debug("Following redirect", url: url.to_s , location: resp['location'])
|
98
133
|
return fetch_url( resp['location'], redirs - 1, &block)
|
@@ -119,9 +154,33 @@ module FPM; module Fry ; module Source
|
|
119
154
|
|
120
155
|
def copy_to(dst)
|
121
156
|
update!
|
122
|
-
|
123
|
-
|
124
|
-
|
157
|
+
Exec['tar','-xf',tempfile,'-C',dst, logger: logger]
|
158
|
+
end
|
159
|
+
|
160
|
+
def prefix
|
161
|
+
update!
|
162
|
+
@prefix ||= prefix!
|
163
|
+
end
|
164
|
+
|
165
|
+
def prefix!
|
166
|
+
longest = nil
|
167
|
+
Exec.popen('tar','-tf',tempfile, logger: logger).each_line.map do |line|
|
168
|
+
line = line.chomp
|
169
|
+
parts = line.split('/')
|
170
|
+
parts.pop unless line[-1] == '/'
|
171
|
+
if longest.nil?
|
172
|
+
longest = parts
|
173
|
+
else
|
174
|
+
longest.each_with_index do | e, i |
|
175
|
+
if parts[i] != e
|
176
|
+
longest = longest[0...i]
|
177
|
+
break
|
178
|
+
end
|
179
|
+
end
|
180
|
+
break if longest.none?
|
181
|
+
end
|
182
|
+
end
|
183
|
+
return Array(longest).join('/')
|
125
184
|
end
|
126
185
|
|
127
186
|
protected
|
@@ -142,9 +201,7 @@ module FPM; module Fry ; module Source
|
|
142
201
|
|
143
202
|
def tar_io
|
144
203
|
update!
|
145
|
-
|
146
|
-
logger.debug("Running bzcat",cmd: cmd)
|
147
|
-
return IO.popen(cmd)
|
204
|
+
return Exec::popen('bzcat', tempfile, logger: logger)
|
148
205
|
end
|
149
206
|
|
150
207
|
end
|
@@ -152,6 +209,22 @@ module FPM; module Fry ; module Source
|
|
152
209
|
class ZipCache < Cache
|
153
210
|
|
154
211
|
def tar_io
|
212
|
+
unpack!
|
213
|
+
return Exec::popen('tar','-c','.', chdir: unpacked_tmpdir)
|
214
|
+
end
|
215
|
+
|
216
|
+
def copy_to(dst)
|
217
|
+
update!
|
218
|
+
Exec['unzip', tempfile, '-d', dst ]
|
219
|
+
end
|
220
|
+
|
221
|
+
def prefix
|
222
|
+
unpack!
|
223
|
+
Source::prefix(unpacked_tmpdir)
|
224
|
+
end
|
225
|
+
private
|
226
|
+
|
227
|
+
def unpack!
|
155
228
|
if !::File.directory?( unpacked_tmpdir )
|
156
229
|
workdir = unpacked_tmpdir + '.tmp'
|
157
230
|
begin
|
@@ -163,18 +236,6 @@ module FPM; module Fry ; module Source
|
|
163
236
|
copy_to( workdir )
|
164
237
|
File.rename(workdir, unpacked_tmpdir)
|
165
238
|
end
|
166
|
-
cmd = ['tar','-c','.']
|
167
|
-
logger.debug("Running tar",cmd: cmd, dir: unpacked_tmpdir)
|
168
|
-
::Dir.chdir(unpacked_tmpdir) do
|
169
|
-
return IO.popen(cmd)
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
def copy_to(dst)
|
174
|
-
update!
|
175
|
-
cmd = ['unzip', tempfile, '-d', dst ]
|
176
|
-
logger.debug("Running unzip",cmd: cmd)
|
177
|
-
system(*cmd, out: '/dev/null')
|
178
239
|
end
|
179
240
|
|
180
241
|
def unpacked_tmpdir
|
@@ -186,12 +247,8 @@ module FPM; module Fry ; module Source
|
|
186
247
|
|
187
248
|
def tar_io
|
188
249
|
update!
|
189
|
-
cmd = ['tar','-c',::File.basename(tempfile)]
|
190
250
|
dir = File.dirname(tempfile)
|
191
|
-
|
192
|
-
::Dir.chdir(dir) do
|
193
|
-
return IO.popen(cmd)
|
194
|
-
end
|
251
|
+
Exec::popen('tar','-c',::File.basename(tempfile), logger: logger, chdir: dir)
|
195
252
|
end
|
196
253
|
|
197
254
|
def copy_to(dst)
|
@@ -199,6 +256,10 @@ module FPM; module Fry ; module Source
|
|
199
256
|
FileUtils.cp( tempfile, dst )
|
200
257
|
end
|
201
258
|
|
259
|
+
def prefix
|
260
|
+
""
|
261
|
+
end
|
262
|
+
|
202
263
|
end
|
203
264
|
|
204
265
|
CACHE_CLASSES = {
|
@@ -211,26 +272,45 @@ module FPM; module Fry ; module Source
|
|
211
272
|
'.bundle' => PlainCache
|
212
273
|
}
|
213
274
|
|
214
|
-
attr :file_map, :data, :url, :
|
275
|
+
attr :file_map, :data, :url, :checksum, :checksum_algorithm, :logger, :to
|
215
276
|
|
277
|
+
# @param [URI] url
|
278
|
+
# @param [Hash] options
|
279
|
+
# @option options [Cabin::Channel] :logger (default cabin channel)
|
280
|
+
# @option options [String] :checksum a checksum of the archive
|
281
|
+
# @raise [UnknownArchiveType] when the archive type is unknown
|
216
282
|
def initialize( url, options = {} )
|
217
283
|
@url = URI(url)
|
218
|
-
@
|
219
|
-
CACHE_CLASSES.keys.find{|ext|
|
220
|
-
@url.path.end_with?(ext)
|
221
|
-
}
|
222
|
-
}
|
284
|
+
@cache_class = guess_cache_class(@url)
|
223
285
|
@logger = options.fetch(:logger){ Cabin::Channel.get }
|
224
286
|
@checksum = options[:checksum]
|
225
287
|
@checksum_algorithm = guess_checksum_algorithm(options[:checksum])
|
226
|
-
@file_map = options
|
288
|
+
@file_map = options[:file_map]
|
289
|
+
@to = options[:to]
|
227
290
|
end
|
228
291
|
|
292
|
+
# Creates a cache.
|
293
|
+
#
|
294
|
+
# @param [String] tempdir
|
295
|
+
# @return [TarCache] for plain .tar files
|
296
|
+
# @return [TarGzCache] for .tar.gz files
|
297
|
+
# @return [TarBz2Cache] for .tar.bz2 files
|
298
|
+
# @return [ZipCache] for .zip files
|
299
|
+
# @return [PlainCache] for .bin files
|
229
300
|
def build_cache(tempdir)
|
230
|
-
|
301
|
+
@cache_class.new(self, tempdir)
|
231
302
|
end
|
232
303
|
private
|
233
304
|
|
305
|
+
def guess_cache_class( url )
|
306
|
+
CACHE_CLASSES.each do |ext,klass|
|
307
|
+
if url.path.end_with?(ext)
|
308
|
+
return klass
|
309
|
+
end
|
310
|
+
end
|
311
|
+
raise UnknownArchiveType.new("Unknown archive type", url: url.to_s, known_extensions: CACHE_CLASSES.keys)
|
312
|
+
end
|
313
|
+
|
234
314
|
def guess_checksum_algorithm( checksum )
|
235
315
|
case(checksum)
|
236
316
|
when nil
|
data/lib/fpm/fry/source/dir.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
require 'fpm/fry/source'
|
2
|
+
require 'fpm/fry/exec'
|
2
3
|
require 'fileutils'
|
3
4
|
require 'digest'
|
5
|
+
require 'cabin/channel'
|
6
|
+
require 'fpm/fry/tar'
|
7
|
+
|
4
8
|
module FPM; module Fry ; module Source
|
5
9
|
class Dir
|
6
10
|
|
@@ -17,14 +21,10 @@ module FPM; module Fry ; module Source
|
|
17
21
|
class Cache < Struct.new(:package, :dir)
|
18
22
|
extend Forwardable
|
19
23
|
|
20
|
-
def_delegators :package, :url, :logger, :file_map
|
24
|
+
def_delegators :package, :url, :logger, :file_map, :to
|
21
25
|
|
22
26
|
def tar_io
|
23
|
-
|
24
|
-
logger.debug("Running tar",cmd: cmd, dir: dir)
|
25
|
-
::Dir.chdir(dir) do
|
26
|
-
return IO.popen(cmd)
|
27
|
-
end
|
27
|
+
Exec::popen('tar','-c','.', chdir: dir, logger: logger)
|
28
28
|
end
|
29
29
|
|
30
30
|
def copy_to(dst)
|
@@ -39,9 +39,13 @@ module FPM; module Fry ; module Source
|
|
39
39
|
end
|
40
40
|
return dig.hexdigest
|
41
41
|
end
|
42
|
+
|
43
|
+
def prefix
|
44
|
+
Source::prefix(dir)
|
45
|
+
end
|
42
46
|
end
|
43
47
|
|
44
|
-
attr :url, :logger, :file_map
|
48
|
+
attr :url, :logger, :file_map, :to
|
45
49
|
|
46
50
|
def initialize( url, options = {} )
|
47
51
|
@url = URI(url)
|
@@ -49,7 +53,8 @@ module FPM; module Fry ; module Source
|
|
49
53
|
@url.path = File.expand_path(@url.path)
|
50
54
|
end
|
51
55
|
@logger = options.fetch(:logger){ Cabin::Channel.get }
|
52
|
-
@file_map = options
|
56
|
+
@file_map = options[:file_map]
|
57
|
+
@to = options[:to]
|
53
58
|
end
|
54
59
|
|
55
60
|
def build_cache(_)
|
data/lib/fpm/fry/source/git.rb
CHANGED
@@ -1,16 +1,41 @@
|
|
1
1
|
require 'fileutils'
|
2
2
|
require 'forwardable'
|
3
|
-
require '
|
3
|
+
require 'fpm/fry/exec'
|
4
4
|
require 'fpm/fry/source'
|
5
5
|
module FPM; module Fry ; module Source
|
6
|
+
# Used to build directly from git.
|
7
|
+
#
|
8
|
+
# @example in a recipe
|
9
|
+
# source 'https://github.com/ggreer/the_silver_searcher.git'
|
10
|
+
#
|
11
|
+
# It automatically recognizes the following url patterns:
|
12
|
+
#
|
13
|
+
# - git://…
|
14
|
+
# - git+…://…
|
15
|
+
# - user@host:….git
|
16
|
+
# - https://….git
|
17
|
+
# - https://git.…
|
18
|
+
#
|
6
19
|
class Git
|
7
20
|
|
8
|
-
REGEX = %r!\A(?:git:|\S+@\S+:\S+\.git\z|https
|
21
|
+
REGEX = %r!\A(?:git:|\S+@\S+:\S+\.git\z|https?:(?://git\.|.*\.git\z)|ssh:.*\.git\z|git\+[a-z0-9]+:)!
|
9
22
|
|
23
|
+
# @return [:git]
|
10
24
|
def self.name
|
11
25
|
:git
|
12
26
|
end
|
13
27
|
|
28
|
+
# Guesses if this url is a git url.
|
29
|
+
#
|
30
|
+
# @example not a git url
|
31
|
+
# FPM::Fry::Source::Git.guess( "bzr://something" ) #=> nil
|
32
|
+
#
|
33
|
+
# @example a git url
|
34
|
+
# FPM::Fry::Source::Git.guess( "git://something" ) #=> 4
|
35
|
+
#
|
36
|
+
# @param [URI,String] url
|
37
|
+
# @return [nil] when this uri doesn't match
|
38
|
+
# @return [Numeric] number of characters that were used
|
14
39
|
def self.guess( url )
|
15
40
|
Source::guess_regex(REGEX, url)
|
16
41
|
end
|
@@ -18,76 +43,87 @@ module FPM; module Fry ; module Source
|
|
18
43
|
class Cache < Struct.new(:package, :tempdir)
|
19
44
|
extend Forwardable
|
20
45
|
|
21
|
-
def_delegators :package, :url, :rev, :logger, :file_map
|
22
|
-
|
23
|
-
def update
|
24
|
-
begin
|
25
|
-
if !File.exists? repodir
|
26
|
-
if (ecode = git('init', '--bare')) != 0
|
27
|
-
raise CacheFailed.new("Initializing git repository failed", exit_code: ecode)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
if (ecode = git('fetch','--depth=1', url.to_s, rev)) != 0
|
31
|
-
raise CacheFailed.new("Failed to fetch from remote", exit_code: ecode, url: url.to_s, rev: rev)
|
32
|
-
end
|
33
|
-
return self
|
34
|
-
rescue Errno::ENOENT
|
35
|
-
raise "Cannot find git binary. Is it installed?"
|
36
|
-
end
|
37
|
-
end
|
46
|
+
def_delegators :package, :url, :rev, :logger, :file_map, :to
|
38
47
|
|
39
48
|
def tar_io
|
40
|
-
|
41
|
-
logger.debug("Running git",cmd: cmd)
|
42
|
-
IO.popen(cmd)
|
49
|
+
Exec::popen(package.git, "--git-dir=#{repodir}",'archive','--format=tar','FETCH_HEAD', logger: logger)
|
43
50
|
end
|
44
51
|
|
45
52
|
def copy_to(dst)
|
46
|
-
|
47
|
-
|
48
|
-
|
53
|
+
Exec[
|
54
|
+
package.git, "--git-dir=#{repodir}", "--work-tree=#{dst}",'checkout','FETCH_HEAD','--','*',
|
55
|
+
chdir: dst, logger: logger
|
56
|
+
]
|
49
57
|
end
|
50
58
|
|
51
59
|
def cachekey
|
52
|
-
|
53
|
-
|
54
|
-
|
60
|
+
Exec::exec(package.git, "--git-dir=#{repodir}",'rev-parse','FETCH_HEAD^{tree}', logger: logger).chomp
|
61
|
+
end
|
62
|
+
|
63
|
+
def prefix
|
64
|
+
""
|
55
65
|
end
|
66
|
+
|
56
67
|
private
|
57
|
-
def
|
58
|
-
|
68
|
+
def initialize(*_)
|
69
|
+
super
|
70
|
+
update
|
59
71
|
end
|
60
72
|
|
61
|
-
def
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
sin.close
|
66
|
-
out.each_line do |line|
|
67
|
-
logger.debug(line.chomp)
|
68
|
-
end
|
69
|
-
err.each_line do |line|
|
70
|
-
logger.debug(line.chomp)
|
73
|
+
def update
|
74
|
+
begin
|
75
|
+
if !File.exists? repodir
|
76
|
+
Exec::exec(package.git, "--git-dir=#{repodir}",'init', '--bare', description: "initializing git repository", logger: logger)
|
71
77
|
end
|
72
|
-
|
78
|
+
Exec::exec(package.git, "--git-dir=#{repodir}",'fetch','--depth=1', url.to_s, rev, description: 'fetching from remote', logger: logger)
|
79
|
+
return self
|
80
|
+
rescue => e
|
81
|
+
raise CacheFailed.new(e, url: url.to_s, rev: rev)
|
73
82
|
end
|
74
83
|
end
|
75
|
-
|
84
|
+
def repodir
|
85
|
+
File.join(tempdir,File.basename(url.path))
|
86
|
+
end
|
76
87
|
end
|
77
88
|
|
78
|
-
|
89
|
+
# @return [Cabin::Channel] logger
|
90
|
+
attr :logger
|
91
|
+
|
92
|
+
# @return [String] the git binary (default: "git")
|
93
|
+
attr :git
|
94
|
+
|
95
|
+
# @return [String] the git rev to pull (default "HEAD")
|
96
|
+
attr :rev
|
97
|
+
|
98
|
+
# @return [Hash<String,String>,nil] the file map for generating a docker file
|
99
|
+
attr :file_map
|
100
|
+
|
101
|
+
# @return [URI] the uri to pull from
|
102
|
+
attr :url
|
103
|
+
|
104
|
+
# @return [String,nil]
|
105
|
+
attr :to
|
79
106
|
|
107
|
+
# @param [URI] url the url to pull from
|
108
|
+
# @param [Hash] options
|
109
|
+
# @option options [Cabin::Channel] :logger (cabin default channel)
|
110
|
+
# @option options [String] :branch git branch to pull
|
111
|
+
# @option options [String] :tag git tag to pull
|
112
|
+
# @option options [Hash<String,String>] :file_map ({""=>""}) the file map to create the docker file from
|
80
113
|
def initialize( url, options = {} )
|
81
114
|
url = url.sub(/\A(\S+@\S+):(\S+\.git)\z/,'ssh://\1/\2')
|
82
115
|
@url = URI(url)
|
83
116
|
@logger = options.fetch(:logger){ Cabin::Channel.get }
|
84
117
|
@rev = options[:branch] || options[:tag] || options[:rev] || 'HEAD'
|
85
|
-
@file_map = options
|
118
|
+
@file_map = options[:file_map]
|
86
119
|
@git = options[:git] || 'git'
|
120
|
+
@to = options[:to]
|
87
121
|
end
|
88
122
|
|
123
|
+
# @param [String] tempdir
|
124
|
+
# @return [Cache]
|
89
125
|
def build_cache(tempdir)
|
90
|
-
Cache.new(self, tempdir)
|
126
|
+
Cache.new(self, tempdir)
|
91
127
|
end
|
92
128
|
|
93
129
|
end
|