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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9d58721a3f79317f65181422ff3a7e5d28ef823e
4
- data.tar.gz: 85229c608182080d92b67b81c2e6d09f701d19ba
3
+ metadata.gz: 9052cdc66f349423b938cefae76a81ddf5504c65
4
+ data.tar.gz: 6084e244c0f01eb10f0c4ec2dbd6f18f1831ddd4
5
5
  SHA512:
6
- metadata.gz: 5fc67b6dcbe5d6d8944028721665cbee9ae9bdb4f615c68812e012063e66c22ab278b943dc155d1e2ecc58e23021af133e8c0f29185db0ba0b5faa4f2dba5e5e
7
- data.tar.gz: 03c12a7c8743715a8a33fff09c84e423ef67cbcd6a4a3a8659a6f7a1bd0b2e361797932117478950fb6ca6e5ac9af35049a4087c094a521b16a3e16a8d1fe22a
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 that eaching over the
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
- end
30
+ end
24
31
  end
25
32
  end ; end
@@ -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
@@ -90,31 +90,25 @@ module FPM; module Fry
90
90
  df << "FROM #{base}"
91
91
  df << "WORKDIR /tmp/build"
92
92
 
93
- deps = (recipe.build_depends.merge recipe.depends)\
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(deps)}"
100
+ df << "RUN #{update}apt-get install --yes #{Shellwords.join(build_dependencies)}"
111
101
  when 'redhat'
112
- df << "RUN yum -y install #{Shellwords.join(deps)}"
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
@@ -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
- def readpartial( len )
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( len )
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
- Find.find( File.expand_path(key, package.staging_path) ) do | path |
27
- next unless File.file? path
28
- name = path[prefix_length..-1]
29
- candidates << name
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
- def add_file(path, io, options = {})
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
- stop #{Shellwords.shellescape name}
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
- super(variables, recipe.packages[0], options = {})
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
- recipe.steps << Recipe::Step.new(name, code)
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.to_s
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( name, klass )
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 ArgumentError.new("No source provide found for #{url}.\nMaybe try explicitly setting the type using :with parameter. Valid options are: #{source_types.keys.join(', ')}")
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 ArgumentError.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(', ')}")
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
@@ -0,0 +1,15 @@
1
+ require 'fpm/fry/recipe'
2
+ module FPM::Fry
3
+ class Recipe
4
+ class Error < StandardError
5
+
6
+ attr :data
7
+
8
+ def initialize(msg=nil, data={})
9
+ super(msg)
10
+ @data = data
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -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, :steps, :packages, :build_depends, :input_hooks
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 << '**'
@@ -6,6 +6,10 @@ module FPM; module Fry ; module Source
6
6
 
7
7
  REGEX = %r!\A(?:file:|/|\.)!
8
8
 
9
+ def self.name
10
+ :dir
11
+ end
12
+
9
13
  def self.guess( url )
10
14
  Source::guess_regex(REGEX, url)
11
15
  end
@@ -7,6 +7,10 @@ module FPM; module Fry ; module Source
7
7
 
8
8
  REGEX = %r!\A(?:git:|\S+@\S+:\S+\.git\z|https?:.*\.git\z|ssh:.*\.git\z)!
9
9
 
10
+ def self.name
11
+ :git
12
+ end
13
+
10
14
  def self.guess( url )
11
15
  Source::guess_regex(REGEX, url)
12
16
  end
@@ -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
@@ -0,0 +1,8 @@
1
+ module FPM ; module Fry
2
+
3
+ def self.WithData(ex, data)
4
+ ex.define_singleton_method(:data){ data }
5
+ return ex
6
+ end
7
+
8
+ end ; end
@@ -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
- @logger.warn("Found a modified file. You can only create new files in a package",name: ml)
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 != 1
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 != 1
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.0
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: 2015-12-29 00:00:00.000000000 Z
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: packages docker changes with fpm
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.4.8
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: