fpm 0.4.3 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
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