fpm 0.4.3 → 0.4.4

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/CHANGELIST CHANGED
@@ -1,3 +1,23 @@
1
+ 0.4.4 (March 30, 2012)
2
+ - Fix a bug in gem bin_dir handling (Calen Pennington)
3
+ - The --config-files flag should work again (Brian Akins)
4
+ - Fix syntax error when using --deb-pre-depends (Andrew Bennett)
5
+ - Make --exclude work again (#185, #186) (Calen Pennington)
6
+ - Fix file listing so that rpm packages don't declare ownership on / and
7
+ /usr, etc.
8
+ - make --deb-custom-control to work again (Tor Arne Vestbø)
9
+ - Add --rpm-digest flag to allow selection of the rpm 'file name' digest
10
+ algorithm. Default is 'md5' since it works on the most rpm systems.
11
+ - Reimplement old behavior assuming "." as the input when using '-s dir' and
12
+ also setting -C (#187)
13
+ - Set BuildRoot on rpm to work around an rpmbuild bug(?) on CentOS 5 (#191)
14
+ - Add --rpm-compression flag to allow selection of the rpm payload
15
+ compression. Default is 'gzip' since it works on the most rpm systems
16
+ - Specs now pass on ubuntu/32bit systems (found by travis-ci.org's test runner)
17
+ - Improve default values of iteration and epoch (#190)
18
+ - Make FPM::Package#files list only 'leaf' nodes (files, empty directories,
19
+ symlinks, etc).
20
+
1
21
  0.4.3 (March 21, 2012)
2
22
  - Fix bug in python packaging when invoked with a relative path to a setup.py
3
23
  (Reported by Thomas Meson, https://github.com/jordansissel/fpm/pull/180)
data/lib/fpm/command.rb CHANGED
@@ -41,11 +41,10 @@ class FPM::Command < Clamp::Command
41
41
  :default => 1.0
42
42
  option "--iteration", "ITERATION",
43
43
  "The iteration to give to the package. RPM calls this the 'release'. " \
44
- "FreeBSD calls it 'PORTREVISION'. Debian calls this 'debian_revision'",
45
- :default => "1"
44
+ "FreeBSD calls it 'PORTREVISION'. Debian calls this 'debian_revision'"
46
45
  option "--epoch", "EPOCH",
47
46
  "The epoch value for this package. RPM and Debian calls this 'epoch'. " \
48
- "FreeBSD calls this 'PORTEPOCH'", :default => "1"
47
+ "FreeBSD calls this 'PORTEPOCH'"
49
48
  option "--license", "LICENSE",
50
49
  "(optional) license name for this package"
51
50
  option "--vendor", "VENDOR",
@@ -95,9 +94,11 @@ class FPM::Command < Clamp::Command
95
94
  option ["-e", "--edit"], :flag,
96
95
  "Edit the package spec before building.", :default => false
97
96
  option ["-x", "--exclude"], "EXCLUDE_PATTERN",
98
- "Exclude paths matching pattern (shell wildcard globs valid here)" do |val|
99
- @exclude_pattern ||= []
100
- @exclude_pattern << val
97
+ "Exclude paths matching pattern (shell wildcard globs valid here). " \
98
+ "If you have multiple file patterns to exclude, specify this flag " \
99
+ "multiple times.", :attribute_name => :excludes do |val|
100
+ @excludes ||= []
101
+ @excludes << val
101
102
  end # -x / --exclude
102
103
  option "--description", "DESCRIPTION", "Add a description for this package.",
103
104
  :default => "no description"
@@ -173,6 +174,7 @@ class FPM::Command < Clamp::Command
173
174
  @provides = []
174
175
  @dependencies = []
175
176
  @config_files = []
177
+ @excludes = []
176
178
  end # def initialize
177
179
 
178
180
  # Execute this command. See Clamp::Command#execute and Clamp's documentation
@@ -181,6 +183,15 @@ class FPM::Command < Clamp::Command
181
183
  @logger.subscribe(STDOUT)
182
184
  @logger.level = :warn
183
185
 
186
+ # Some older behavior, if you specify:
187
+ # 'fpm -s dir -t ... -C somepath'
188
+ # fpm would assume you meant to add '.' to the end of the commandline.
189
+ # Let's hack that. https://github.com/jordansissel/fpm/issues/187
190
+ if input_type == "dir" and args.empty? and !chdir.nil?
191
+ @logger.info("No args, but -s dir and -C are given, assuming '.' as input")
192
+ args << "."
193
+ end
194
+
184
195
  validator = Validator.new(self)
185
196
  if !validator.ok?
186
197
  validator.messages.each do |message|
@@ -277,7 +288,8 @@ class FPM::Command < Clamp::Command
277
288
  input.dependencies += dependencies
278
289
  input.provides += provides
279
290
  input.replaces += replaces
280
-
291
+ input.config_files += config_files
292
+
281
293
  setscript = proc do |scriptname|
282
294
  path = self.send(scriptname)
283
295
  # Skip scripts not set
@@ -285,7 +297,7 @@ class FPM::Command < Clamp::Command
285
297
 
286
298
  # 'self.send(scriptname) == self.before_install == --before-install
287
299
  if !File.exists?(path)
288
- $stderr.puts("No such file (for #{scriptname.to_s}): #{path.inspect}")
300
+ @logger.error("No such file (for #{scriptname.to_s}): #{path.inspect}")
289
301
  return 1
290
302
  end
291
303
  input.scripts[scriptname] = File.read(path)
@@ -295,7 +307,14 @@ class FPM::Command < Clamp::Command
295
307
  setscript.call(:after_install)
296
308
  setscript.call(:before_remove)
297
309
  setscript.call(:after_remove)
298
-
310
+
311
+ # Validate the package
312
+ if input.name.nil? or input.name.empty?
313
+ @logger.fatal("No name given for this package (set name with, " \
314
+ "for example, '-n packagename')")
315
+ return 1
316
+ end
317
+
299
318
  # Convert to the output type
300
319
  output = input.convert(output_class)
301
320
 
data/lib/fpm/package.rb CHANGED
@@ -82,6 +82,9 @@ class FPM::Package
82
82
  # (Not all packages support this)
83
83
  attr_accessor :replaces
84
84
 
85
+ # Array of glob patterns to exclude from this package
86
+ attr_accessor :excludes
87
+
85
88
  # a summary or description of the package
86
89
  attr_accessor :description
87
90
 
@@ -170,6 +173,9 @@ class FPM::Package
170
173
  # Convert this package to a new package type
171
174
  def convert(klass)
172
175
  @logger.info("Converting #{self.type} to #{klass.type}")
176
+
177
+ exclude
178
+
173
179
  pkg = klass.new
174
180
  pkg.cleanup_staging # purge any directories that may have been created by klass.new
175
181
 
@@ -266,15 +272,29 @@ class FPM::Package
266
272
  #
267
273
  # The paths will all be relative to staging_path and will not include that
268
274
  # path.
275
+ #
276
+ # This method will emit 'leaf' paths. Files, symlinks, and other file-like
277
+ # things are emitted. Intermediate directories are ignored, but
278
+ # empty directories are emitted.
269
279
  def files
270
- # Find will print the path you're searching first, so skip it and return
271
- # the rest. Also trim the leading path such that '#{staging_path}/' is removed
272
- # from the path before returning.
280
+ is_leaf = lambda do |path|
281
+ # True if this is a file/symlink/etc, but not a plain directory
282
+ return true if !(File.directory?(path) and !File.symlink?(path))
283
+ # Empty directories are leafs as well.
284
+ return true if ::Dir.entries(path).sort == [".", ".."]
285
+ # False otherwise (non-empty directory, etc)
286
+ return false
287
+ end # is_leaf
288
+
289
+ # Find all leaf-like paths (files, symlink, empty directories, etc)
290
+ # Also trim the leading path such that '#{staging_path}/' is removed from
291
+ # the path before returning.
273
292
  #
274
293
  # Wrapping Find.find in an Enumerator is required for sane operation in ruby 1.8.7,
275
294
  # but requires the 'backports' gem (which is used in other places in fpm)
276
295
  return Enumerator.new { |y| Find.find(staging_path) { |path| y << path } } \
277
296
  .select { |path| path != staging_path } \
297
+ .select { |path| is_leaf.call(path) } \
278
298
  .collect { |path| path[staging_path.length + 1.. -1] }
279
299
  end # def files
280
300
 
@@ -311,6 +331,26 @@ class FPM::Package
311
331
  end
312
332
  end # def edit_file
313
333
 
334
+ # This method removes excluded files from the staging_path. Subclasses can
335
+ # remove the files during the input phase rather than deleting them here
336
+ def exclude
337
+ if @attributes.include?(:prefix)
338
+ installdir = staging_path(@attributes[:prefix])
339
+ else
340
+ installdir = staging_path
341
+ end
342
+
343
+ attributes[:excludes].each do |wildcard|
344
+ @logger.debug("Checking for things to exclude", :wildcard => wildcard)
345
+ files.each do |file|
346
+ if File.fnmatch(wildcard, file)
347
+ @logger.info("Removing excluded file", :path => file, :matches => wildcard)
348
+ FileUtils.remove_entry_secure(staging_path(file))
349
+ end
350
+ end
351
+ end
352
+ end # def exclude
353
+
314
354
 
315
355
  class << self
316
356
  # This method is invoked when subclass occurs.
@@ -25,7 +25,7 @@ class FPM::Package::Deb < FPM::Package
25
25
  "version of a package but any iteration is permitted"
26
26
 
27
27
  option "--pre-depends", "DEPENDENCY",
28
- "Add DEPENDENCY as a Pre-Depends" do |val|
28
+ "Add DEPENDENCY as a Pre-Depends" do |dep|
29
29
  @pre_depends ||= []
30
30
  @pre_depends << dep
31
31
  end
@@ -310,7 +310,7 @@ class FPM::Package::Deb < FPM::Package
310
310
  @logger.info("No deb_installed_size set, calculating now.")
311
311
  total = 0
312
312
  Find.find(staging_path) do |path|
313
- stat = File.stat(path)
313
+ stat = File.lstat(path)
314
314
  next if stat.directory?
315
315
  total += stat.size
316
316
  end
@@ -322,9 +322,9 @@ class FPM::Package::Deb < FPM::Package
322
322
 
323
323
  # Write the control file
324
324
  with(control_path("control")) do |control|
325
- if attributes["deb-custom-control"]
326
- @logger.debug("Using '#{attributes["deb-custom-control"]}' template for the control file")
327
- control_data = File.read(attributes["deb-custom-control"])
325
+ if attributes[:deb_custom_control]
326
+ @logger.debug("Using '#{attributes[:deb_custom_control]}' template for the control file")
327
+ control_data = File.read(attributes[:deb_custom_control])
328
328
  else
329
329
  @logger.debug("Using 'deb.erb' template for the control file")
330
330
  control_data = template("deb.erb").result(binding)
@@ -74,16 +74,16 @@ class FPM::Package::Dir < FPM::Package
74
74
  def clone(source, destination)
75
75
  # Copy all files from 'path' into staging_path
76
76
 
77
- Find.find(source) do |file|
78
- next if source == file && File.directory?(file) # ignore the directory itself
79
- target = File.join(destination, file)
80
- copy(file, target)
77
+ Find.find(source) do |path|
78
+ target = File.join(destination, path)
79
+ copy(path, target)
81
80
  end
82
81
  end # def clone
83
82
 
84
- # Copy, recursively, from source to destination.
83
+ # Copy a path.
85
84
  #
86
85
  # Files will be hardlinked if possible, but copied otherwise.
86
+ # Symlinks should be copied as symlinks.
87
87
  def copy(source, destination)
88
88
  directory = File.dirname(destination)
89
89
  if !File.directory?(directory)
@@ -93,7 +93,9 @@ class FPM::Package::Dir < FPM::Package
93
93
  # Create a directory if this path is a directory
94
94
  if File.directory?(source) and !File.symlink?(source)
95
95
  @logger.debug("Creating", :directory => destination)
96
- FileUtils.mkdir(destination)
96
+ if !File.directory?(destination)
97
+ FileUtils.mkdir(destination)
98
+ end
97
99
  else
98
100
  # Otherwise try copying the file.
99
101
  begin
@@ -102,7 +104,7 @@ class FPM::Package::Dir < FPM::Package
102
104
  rescue Errno::EXDEV
103
105
  # Hardlink attempt failed, copy it instead
104
106
  @logger.debug("Copying", :source => source, :destination => destination)
105
- FileUtils.copy(source, destination)
107
+ FileUtils.copy_entry(source, destination)
106
108
  end
107
109
  end
108
110
  end # def copy
@@ -172,6 +172,7 @@ class FPM::Package::Gem < FPM::Package
172
172
  if attributes[:gem_bin_path]
173
173
  bin_path = File.join(staging_path, attributes[:gem_bin_path])
174
174
  args += ["--bindir", bin_path]
175
+ ::FileUtils.mkdir_p(bin_path)
175
176
  end
176
177
 
177
178
  args << gem_path
@@ -15,14 +15,52 @@ require "arr-pm/file" # gem 'arr-pm'
15
15
  # * :rpm_rpmbuild_define - an array of definitions to give to rpmbuild.
16
16
  # These are used, verbatim, each as: --define ITEM
17
17
  class FPM::Package::RPM < FPM::Package
18
+ DIGEST_ALGORITHM_MAP = {
19
+ "md5" => 1,
20
+ "sha1" => 2,
21
+ "sha256" => 8,
22
+ "sha384" => 9,
23
+ "sha512" => 10
24
+ }
25
+
26
+ COMPRESSION_MAP = {
27
+ "xz" => "w2.xzdio",
28
+ "gzip" => "w9.gzdio",
29
+ "bzip2" => "w9.bzdio"
30
+ }
31
+
32
+
18
33
  option "--rpmbuild-define", "DEFINITION",
19
34
  "Pass a --define argument to rpmbuild." do |define|
20
35
  attributes[:rpm_rpmbuild_define] ||= []
21
36
  attributes[:rpm_rpmbuild_define] << define
22
37
  end
23
38
 
39
+ option "--digest", DIGEST_ALGORITHM_MAP.keys.join("|"),
40
+ "Select a digest algorithm. md5 works on the most platforms.",
41
+ :default => "md5" do |value|
42
+ if !DIGEST_ALGORITHM_MAP.include?(value.downcase)
43
+ raise "Unknown digest algorithm '#{value}'. Valid options " \
44
+ "include: #{DIGEST_ALGORITHM_MAP.keys.join(", ")}"
45
+ end
46
+ value.downcase
47
+ end
48
+
49
+ option "--compression", COMPRESSION_MAP.keys.join("|"),
50
+ "Select a compression method. gzip works on the most platforms.",
51
+ :default => "gzip" do |value|
52
+ if !COMPRESSION_MAP.include?(value.downcase)
53
+ raise "Unknown compression type '#{value}'. Valid options " \
54
+ "include: #{COMPRESSION_MAP.keys.join(", ")}"
55
+ end
56
+ value.downcase
57
+ end
58
+
24
59
  private
25
60
 
61
+ # Handle any architecture naming conversions.
62
+ # For example, debian calls amd64 what redhat calls x86_64, this
63
+ # method fixes those types of things.
26
64
  def architecture
27
65
  case @architecture
28
66
  when nil
@@ -39,6 +77,11 @@ class FPM::Package::RPM < FPM::Package
39
77
  end
40
78
  end # def architecture
41
79
 
80
+ # This method ensures a default value for iteration if none is provided.
81
+ def iteration
82
+ return @iteration ? @iteration : 1
83
+ end # def iteration
84
+
42
85
  # See FPM::Package#converted_from
43
86
  def converted_from(origin)
44
87
  if origin == FPM::Package::Gem
@@ -141,5 +184,14 @@ class FPM::Package::RPM < FPM::Package
141
184
  return super(format)
142
185
  end # def to_s
143
186
 
144
- public(:input, :output, :converted_from, :architecture, :to_s)
187
+ def payload_compression
188
+ return COMPRESSION_MAP[attributes[:rpm_compression]]
189
+ end # def payload_compression
190
+
191
+ def digest_algorithm
192
+ return DIGEST_ALGORITHM_MAP[attributes[:rpm_digest]]
193
+ end # def digest_algorithm
194
+
195
+ public(:input, :output, :converted_from, :architecture, :to_s, :iteration,
196
+ :payload_compression, :digest_algorithm)
145
197
  end # class FPM::Package::RPM
data/templates/rpm.erb CHANGED
@@ -8,6 +8,12 @@
8
8
  # Disable checking for unpackaged files ?
9
9
  #%undefine __check_files
10
10
 
11
+ # Use <%= attributes[:rpm_digest] %> file digest method
12
+ %define _binary_filedigest_algorithm <%= digest_algorithm %>
13
+
14
+ # Use <%= attributes[:rpm_compression] %> payload compression
15
+ %define _binary_payload <%= payload_compression %>
16
+
11
17
  Name: <%= name %>
12
18
  Version: <%= version %>
13
19
  <% if epoch -%>
@@ -18,6 +24,9 @@ Release: <%= iteration or 1 %>
18
24
  Summary: <%= description.split("\n").first.empty? ? "_" : description.split("\n").first %>
19
25
  BuildArch: <%= architecture %>
20
26
  AutoReqProv: no
27
+ # Seems specifying BuildRoot is required on older rpmbuild (like on CentOS 5)
28
+ # fpm passes '--define buildroot ...' on the commandline, so just reuse that.
29
+ BuildRoot: %buildroot
21
30
 
22
31
  Group: <%= category %>
23
32
  License: <%= license %>
@@ -94,10 +103,11 @@ fi
94
103
  <% end -%>
95
104
  <%# list only files, not directories? -%>
96
105
  <%=
97
- # Reject directories or config files already listed, then prefix files with
98
- # "/", then make sure paths with spaces are quoted. I hate rpm so much.
99
- files.reject { |f| x = File.join(staging_path, f); File.directory?(x) && !File.symlink?(x) } \
100
- .collect { |f| "/#{f}" } \
106
+ # Reject config files already listed or parent directories, then prefix files
107
+ # with "/", then make sure paths with spaces are quoted. I hate rpm so much.
108
+
109
+ # 'files' here is the method FPM::Package#files.
110
+ files.collect { |f| "/#{f}" } \
101
111
  .reject { |f| config_files.include?(f) } \
102
112
  .collect { |f| f[/\s/] and "\"#{f}\"" or f } \
103
113
  .join("\n")
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fpm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.3
4
+ version: 0.4.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-21 00:00:00.000000000 Z
12
+ date: 2012-03-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json
@@ -201,7 +201,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
201
201
  version: '0'
202
202
  requirements: []
203
203
  rubyforge_project:
204
- rubygems_version: 1.8.18
204
+ rubygems_version: 1.8.21
205
205
  signing_key:
206
206
  specification_version: 3
207
207
  summary: fpm - package building and mangling