fpm 0.4.31 → 0.4.32

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELIST CHANGED
@@ -1,3 +1,38 @@
1
+ 0.4.32 (April 9, 2013)
2
+ - COMPATIBILITY WARNING: rpm: The default epoch is now nothing because this
3
+ aligns more closely with typical rpm packages in the real world. This
4
+ decision was reached in #381. If you need the previous behavior, you
5
+ must now specify '--epoch 1' (#388, patch by Pranay Kanwar)
6
+ - python: new flag --python-obey-requirements-txt which makes a
7
+ requirements.txt file from the python package used for the package
8
+ dependencies instead of the usual setup.py dependencies. The default
9
+ behavior without this flag is to respect setup.py. (#384)
10
+ - deb: new flag --deb-shlibs to specify the content of the 'shlibs' file
11
+ in the debian package (#405, patch by Aman Gupta)
12
+ - deb: fixed a few lintian errors (empty conffiles, md5sums on symlinks, etc)
13
+ - Add '-f' / '--force' flag to force overwriting an existing package output
14
+ path (#385, Timothy Sutton)
15
+ - New flag: --no-auto-depends flag to skip any automatic dependencies
16
+ that would normally be added by gem, python, deb, and rpms input packages.
17
+ (#386, #374; patch by Pranay Kanwar)
18
+ - gem: Use 'gem' command to download gems and read gem package information.
19
+ (#389, #394, #378, #233; patches by Pranay Kanwar and Chris Roberts)
20
+ - rpm: dashes are now replaced with underscores in rpm version strings
21
+ (#395, #393, #399; patches by Jeff Terrace and Richard Guest)
22
+ - python: Only use the first line of a license; some python packages (like
23
+ 'requests') embed their full license copy into the license field. For
24
+ the sake of sanity and function with most packaging systems, fpm only
25
+ uses the first line of that license.
26
+ - rpm: Add new 'none' option to --rpm-compression to disable compression
27
+ entirely. (#398, patch by Richard Guest)
28
+ - deb: Make dependencies using the '!=' operator represented as "Breaks"
29
+ in the deb package (previously used "Conflicts"). (#400)
30
+ - deb: Add md5sums to the debian packages which improves correctness
31
+ of the package. (#403, #401; patch by Pranay Kanwar)
32
+ - rpm: Convert all '!=' dependency operators to 'Conflicts'. Previously,
33
+ this only applied to packages converting from python to rpm.
34
+ (#404, #396; patch by Pranay Kanwar)
35
+
1
36
  0.4.31 (March 21, 2013)
2
37
  - rpm: new flag --rpm-use-file-permissions which try to create an rpm
3
38
  that has file ownership/modes that exactly mirror how they are on
data/lib/fpm.rb CHANGED
@@ -5,5 +5,6 @@ require "fpm/package/dir"
5
5
  require "fpm/package/gem"
6
6
  require "fpm/package/deb"
7
7
  require "fpm/package/rpm"
8
+ require "fpm/package/tar"
8
9
  require "fpm/package/python"
9
- require "fpm/package/osxpkg"
10
+ require "fpm/package/osxpkg"
@@ -55,6 +55,8 @@ class FPM::Command < Clamp::Command
55
55
  "be necessary for all input packages. For example, the 'gem' type will" \
56
56
  "prefix with your gem directory automatically."
57
57
  option ["-p", "--package"], "OUTPUT", "The package file path to output."
58
+ option ["-f", "--force"], :flag, "Force output even if it will overwrite an " \
59
+ "existing file", :default => false
58
60
  option ["-n", "--name"], "NAME", "The name to give to the package"
59
61
  option "--verbose", :flag, "Enable verbose output"
60
62
  option "--debug", :flag, "Enable debug output"
@@ -85,6 +87,9 @@ class FPM::Command < Clamp::Command
85
87
  option "--no-depends", :flag, "Do not list any dependencies in this package",
86
88
  :default => false
87
89
 
90
+ option "--no-auto-depends", :flag, "Do not list any dependencies in this package automatically",
91
+ :default => false
92
+
88
93
  option "--provides", "PROVIDES",
89
94
  "What this package provides (usually a name). This flag can be "\
90
95
  "specified multiple times." do |val|
@@ -99,7 +99,10 @@ class FPM::Package
99
99
  # a summary or description of the package
100
100
  attr_accessor :description
101
101
 
102
- # hash of paths for maintainer/package scripts (postinstall, etc)
102
+ # hash of scripts for maintainer/package scripts (postinstall, etc)
103
+ #
104
+ # The keys are :before_install, etc
105
+ # The values are the text to use in the script.
103
106
  attr_accessor :scripts
104
107
 
105
108
  # Array of configuration files
@@ -313,7 +316,7 @@ class FPM::Package
313
316
  end # def files
314
317
 
315
318
  def template(path)
316
- template_dir = File.join(File.dirname(__FILE__), "..", "..", "templates")
319
+ template_dir = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "templates"))
317
320
  template_path = File.join(template_dir, path)
318
321
  template_code = File.read(template_path)
319
322
  @logger.info("Reading template", :path => template_path)
@@ -487,6 +490,14 @@ class FPM::Package
487
490
  if !File.directory?(File.dirname(output_path))
488
491
  raise ParentDirectoryMissing.new(output_path)
489
492
  end
493
+ if File.file?(output_path)
494
+ if attributes[:force?]
495
+ @logger.warn("Force flag given. Overwriting package at #{output_path}")
496
+ File.delete(output_path)
497
+ else
498
+ raise FileAlreadyExists.new(output_path)
499
+ end
500
+ end
490
501
  end # def output_path
491
502
 
492
503
  def provides=(value)
@@ -5,6 +5,7 @@ require "fpm/errors"
5
5
  require "fpm/util"
6
6
  require "backports"
7
7
  require "fileutils"
8
+ require "digest"
8
9
 
9
10
  # Support for debian packages (.deb files)
10
11
  #
@@ -47,13 +48,13 @@ class FPM::Package::Deb < FPM::Package
47
48
  "Custom version of the Debian control file." do |control|
48
49
  File.expand_path(control)
49
50
  end
50
-
51
+
51
52
  # Add custom debconf config file
52
53
  option "--config", "SCRIPTPATH",
53
54
  "Add SCRIPTPATH as debconf config file." do |config|
54
55
  File.expand_path(config)
55
56
  end
56
-
57
+
57
58
  # Add custom debconf templates file
58
59
  option "--templates", "FILEPATH",
59
60
  "Add FILEPATH as debconf templates file." do |templates|
@@ -96,6 +97,11 @@ class FPM::Package::Deb < FPM::Package
96
97
  next @custom_fields
97
98
  end
98
99
 
100
+ option "--shlibs", "SHLIBS", "Include control/shlibs content. This flag " \
101
+ "expects a string that is used as the contents of the shlibs file. " \
102
+ "See the following url for a description of this file and its format: " \
103
+ "http://www.debian.org/doc/debian-policy/ch-sharedlibs.html#s-shlibs"
104
+
99
105
  def initialize(*args)
100
106
  super(*args)
101
107
  attributes[:deb_priority] = "extra"
@@ -177,7 +183,7 @@ class FPM::Package::Deb < FPM::Package
177
183
  return value.split(": ",2).last
178
184
  end
179
185
  end
180
-
186
+
181
187
  # Parse 'epoch:version-iteration' in the version string
182
188
  version_re = /^(?:([0-9]+):)?(.+?)(?:-(.*))?$/
183
189
  m = version_re.match(parse.call("Version"))
@@ -204,7 +210,7 @@ class FPM::Package::Deb < FPM::Package
204
210
 
205
211
  #self.config_files = config_files
206
212
 
207
- self.dependencies += parse_depends(parse.call("Depends"))
213
+ self.dependencies += parse_depends(parse.call("Depends")) if !attributes[:no_auto_depends?]
208
214
  end
209
215
  end # def extract_info
210
216
 
@@ -267,11 +273,27 @@ class FPM::Package::Deb < FPM::Package
267
273
  def output(output_path)
268
274
  output_check(output_path)
269
275
  # Abort if the target path already exists.
270
- raise FileAlreadyExists.new(output_path) if File.exists?(output_path)
271
276
 
272
277
  # create 'debian-binary' file, required to make a valid debian package
273
278
  File.write(build_path("debian-binary"), "2.0\n")
274
279
 
280
+ # If we are given --deb-shlibs but no --after-install script, we
281
+ # should implicitly create a before/after scripts that run ldconfig
282
+ if attributes[:deb_shlibs]
283
+ if !script?(:after_install)
284
+ @logger.info("You gave --deb-shlibs but no --after-install, so " \
285
+ "I am adding an after-install script that runs " \
286
+ "ldconfig to update the system library cache")
287
+ scripts[:after_install] = template("deb/ldconfig.sh.erb").result(binding)
288
+ end
289
+ if !script?(:after_remove)
290
+ @logger.info("You gave --deb-shlibs but no --after-remove, so " \
291
+ "I am adding an after-remove script that runs " \
292
+ "ldconfig to update the system library cache")
293
+ scripts[:after_remove] = template("deb/ldconfig.sh.erb").result(binding)
294
+ end
295
+ end
296
+
275
297
  write_control_tarball
276
298
 
277
299
  # Tar up the staging_path into data.tar.{compression type}
@@ -368,8 +390,9 @@ class FPM::Package::Deb < FPM::Package
368
390
  nextversion = nextversion.join(".")
369
391
  return ["#{name} (>= #{version})", "#{name} (<< #{nextversion})"]
370
392
  elsif (m = dep.match(/(\S+)\s+\(!= (.+)\)/))
371
- # Append this to conflicts
372
- self.conflicts += [dep.gsub(/!=/,"=")]
393
+ # Move '!=' dependency specifications into 'Breaks'
394
+ self.attributes[:deb_breaks] ||= []
395
+ self.attributes[:deb_breaks] << dep.gsub(/!=/,"=")
373
396
  return []
374
397
  elsif (m = dep.match(/(\S+)\s+\(= (.+)\)/)) and
375
398
  self.attributes[:deb_ignore_iteration_in_dependencies?]
@@ -400,9 +423,11 @@ class FPM::Package::Deb < FPM::Package
400
423
  def write_control_tarball
401
424
  # Use custom Debian control file when given ...
402
425
  write_control # write the control file
426
+ write_shlibs # write optional shlibs file
403
427
  write_scripts # write the maintainer scripts
404
428
  write_conffiles # write the conffiles
405
429
  write_debconf # write the debconf files
430
+ write_md5sums # write the md5sums file
406
431
 
407
432
  # Make the control.tar.gz
408
433
  with(build_path("control.tar.gz")) do |controltar|
@@ -466,6 +491,7 @@ class FPM::Package::Deb < FPM::Package
466
491
  end # def write_scripts
467
492
 
468
493
  def write_conffiles
494
+ return unless config_files.any?
469
495
  File.open(control_path("conffiles"), "w") do |out|
470
496
  # 'config_files' comes from FPM::Package and is usually set with
471
497
  # FPM::Command's --config-files flag
@@ -473,6 +499,14 @@ class FPM::Package::Deb < FPM::Package
473
499
  end
474
500
  end # def write_conffiles
475
501
 
502
+ def write_shlibs
503
+ return unless attributes[:deb_shlibs]
504
+ @logger.info("Adding shlibs", :content => attributes[:deb_shlibs])
505
+ File.open(control_path("shlibs"), "w") do |out|
506
+ out.write(attributes[:deb_shlibs])
507
+ end
508
+ end # def write_shlibs
509
+
476
510
  def write_debconf
477
511
  if attributes[:deb_config]
478
512
  FileUtils.cp(attributes[:deb_config], control_path("config"))
@@ -485,6 +519,26 @@ class FPM::Package::Deb < FPM::Package
485
519
  end
486
520
  end # def write_debconf
487
521
 
522
+ def write_md5sums
523
+ md5_sums = {}
524
+
525
+ Find.find(staging_path) do |path|
526
+ if File.file?(path) && !File.symlink?(path)
527
+ md5 = Digest::MD5.file(path).hexdigest
528
+ md5_path = path.gsub("#{staging_path}/", "")
529
+ md5_sums[md5_path] = md5
530
+ end
531
+ end
532
+
533
+ if not md5_sums.empty?
534
+ File.open(control_path("md5sums"), "w") do |out|
535
+ md5_sums.each do |path, md5|
536
+ out.puts "#{md5} #{path}"
537
+ end
538
+ end
539
+ end
540
+ end # def write_md5sums
541
+
488
542
  def to_s(format=nil)
489
543
  # Default format if nil
490
544
  # git_1.7.9.3-1_amd64.deb
@@ -1,9 +1,9 @@
1
1
  require "fpm/namespace"
2
2
  require "fpm/package"
3
- require "rubygems/package"
4
3
  require "rubygems"
5
4
  require "fileutils"
6
5
  require "fpm/util"
6
+ require "yaml"
7
7
 
8
8
  # A rubygems package.
9
9
  #
@@ -38,6 +38,8 @@ class FPM::Package::Gem < FPM::Package
38
38
  option "--env-shebang", :flag, "Should the target package have the " \
39
39
  "shebang rewritten to use env?", :default => true
40
40
 
41
+ option "--prerelease", :flag, "Allow prerelease versions of a gem", :default => false
42
+
41
43
  def input(gem)
42
44
  # 'arg' is the name of the rubygem we should unpack.
43
45
  path_to_gem = download_if_necessary(gem, version)
@@ -61,86 +63,81 @@ class FPM::Package::Gem < FPM::Package
61
63
  end # def download_if_necessary
62
64
 
63
65
  def download(gem_name, gem_version=nil)
64
- # This code mostly mutated from rubygem's fetch_command.rb
65
- # Code use permissible by rubygems's "GPL or these conditions below"
66
- # http://rubygems.rubyforge.org/rubygems-update/LICENSE_txt.html
67
66
 
68
67
  @logger.info("Trying to download", :gem => gem_name, :version => gem_version)
69
- dep = ::Gem::Dependency.new(gem_name, gem_version)
70
68
 
71
- # TODO(sissel): Make a flag to allow prerelease gems?
72
- #dep.prerelease = options[:prerelease]
69
+ gem_fetch = [ "#{attributes[:gem_gem]}", "fetch", gem_name]
73
70
 
74
- if ::Gem::SpecFetcher.fetcher.respond_to?(:fetch_with_errors)
75
- specs_and_sources, errors =
76
- ::Gem::SpecFetcher.fetcher.fetch_with_errors(dep, true, true, false)
77
- else
78
- specs_and_sources =
79
- ::Gem::SpecFetcher.fetcher.fetch(dep, true)
80
- errors = "???"
71
+ gem_fetch += ["--prerelease"] if attributes[:gem_prerelease?]
72
+ gem_fetch += ["--version", gem_version] if gem_version
73
+
74
+ download_dir = build_path(gem_name)
75
+ FileUtils.mkdir(download_dir) unless File.directory?(download_dir)
76
+
77
+ ::Dir.chdir(download_dir) do |dir|
78
+ @logger.debug("Downloading in directory #{dir}")
79
+ safesystem(*gem_fetch)
81
80
  end
82
- spec, source_uri = specs_and_sources.sort_by { |s,| s.version }.last
83
81
 
84
- if spec.nil? then
85
- @logger.error("Invalid gem?", :name => gem_name, :version => gem_version, :errors => errors)
86
- raise InvalidArgument.new("Invalid gem: #{gem_name}")
82
+ gem_files = ::Dir.glob(File.join(download_dir, "*.gem"))
83
+
84
+ if gem_files.length != 1
85
+ raise "Unexpected number of gem files in #{download_dir}, #{gem_files.length} should be 1"
87
86
  end
88
87
 
89
- path = ::Gem::RemoteFetcher.fetcher.download(spec, source_uri)
90
- return path
88
+ return gem_files.first
91
89
  end # def download
92
90
 
93
91
  def load_package_info(gem_path)
94
- file = File.new(gem_path, 'r')
95
-
96
- ::Gem::Package.open(file, 'r') do |gem|
97
- spec = gem.metadata
98
-
99
- if !attributes[:gem_package_prefix].nil?
100
- attributes[:gem_package_name_prefix] = attributes[:gem_package_prefix]
101
- end
102
-
103
- # name prefixing is optional, if enabled, a name 'foo' will become
104
- # 'rubygem-foo' (depending on what the gem_package_name_prefix is)
105
- self.name = spec.name
106
- if attributes[:gem_fix_name?]
107
- self.name = fix_name(spec.name)
108
- end
109
-
110
- #self.name = [attributes[:gem_package_name_prefix], spec.name].join("-")
111
- self.license = (spec.license or "no license listed in #{File.basename(file)}")
112
-
113
- # expand spec's version to match RationalVersioningPolicy to prevent cases
114
- # where missing 'build' number prevents correct dependency resolution by target
115
- # package manager. Ie. for dpkg 1.1 != 1.1.0
116
- m = spec.version.to_s.scan(/(\d+)\.?/)
117
- self.version = m.flatten.fill('0', m.length..2).join('.')
118
-
119
- self.vendor = spec.author
120
- self.url = spec.homepage
121
- self.category = "Languages/Development/Ruby"
122
-
123
- # if the gemspec has C extensions defined, then this should be a 'native' arch.
124
- if !spec.extensions.empty?
125
- self.architecture = "native"
126
- else
127
- self.architecture = "all"
128
- end
129
-
130
- # make sure we have a description
131
- description_options = [ spec.description, spec.summary, "#{spec.name} - no description given" ]
132
- self.description = description_options.find { |d| !(d.nil? or d.strip.empty?) }
133
-
134
- # Upstream rpms seem to do this, might as well share.
135
- # TODO(sissel): Figure out how to hint this only to rpm?
136
- # maybe something like attributes[:rpm_provides] for rpm specific stuff?
137
- # Or just ignore it all together.
138
- #self.provides << "rubygem(#{self.name})"
139
-
140
- # By default, we'll usually automatically provide this, but in the case that we are
141
- # composing multiple packages, it's best to explicitly include it in the provides list.
142
- self.provides << "#{self.name} = #{self.version}"
143
92
 
93
+ spec = YAML.load(%x{#{attributes[:gem_gem]} spec #{gem_path} --yaml})
94
+
95
+ if !attributes[:gem_package_prefix].nil?
96
+ attributes[:gem_package_name_prefix] = attributes[:gem_package_prefix]
97
+ end
98
+
99
+ # name prefixing is optional, if enabled, a name 'foo' will become
100
+ # 'rubygem-foo' (depending on what the gem_package_name_prefix is)
101
+ self.name = spec.name
102
+ if attributes[:gem_fix_name?]
103
+ self.name = fix_name(spec.name)
104
+ end
105
+
106
+ #self.name = [attributes[:gem_package_name_prefix], spec.name].join("-")
107
+ self.license = (spec.license or "no license listed in #{File.basename(gem_path)}")
108
+
109
+ # expand spec's version to match RationalVersioningPolicy to prevent cases
110
+ # where missing 'build' number prevents correct dependency resolution by target
111
+ # package manager. Ie. for dpkg 1.1 != 1.1.0
112
+ m = spec.version.to_s.scan(/(\d+)\.?/)
113
+ self.version = m.flatten.fill('0', m.length..2).join('.')
114
+
115
+ self.vendor = spec.author
116
+ self.url = spec.homepage
117
+ self.category = "Languages/Development/Ruby"
118
+
119
+ # if the gemspec has C extensions defined, then this should be a 'native' arch.
120
+ if !spec.extensions.empty?
121
+ self.architecture = "native"
122
+ else
123
+ self.architecture = "all"
124
+ end
125
+
126
+ # make sure we have a description
127
+ description_options = [ spec.description, spec.summary, "#{spec.name} - no description given" ]
128
+ self.description = description_options.find { |d| !(d.nil? or d.strip.empty?) }
129
+
130
+ # Upstream rpms seem to do this, might as well share.
131
+ # TODO(sissel): Figure out how to hint this only to rpm?
132
+ # maybe something like attributes[:rpm_provides] for rpm specific stuff?
133
+ # Or just ignore it all together.
134
+ #self.provides << "rubygem(#{self.name})"
135
+
136
+ # By default, we'll usually automatically provide this, but in the case that we are
137
+ # composing multiple packages, it's best to explicitly include it in the provides list.
138
+ self.provides << "#{self.name} = #{self.version}"
139
+
140
+ if !attributes[:no_auto_depends?]
144
141
  spec.runtime_dependencies.map do |dep|
145
142
  # rubygems 1.3.5 doesn't have 'Gem::Dependency#requirement'
146
143
  if dep.respond_to?(:requirement)
@@ -151,15 +148,15 @@ class FPM::Package::Gem < FPM::Package
151
148
 
152
149
  # Some reqs can be ">= a, < b" versions, let's handle that.
153
150
  reqs.to_s.split(/, */).each do |req|
154
- if attributes[:gem_fix_dependencies?]
155
- name = fix_name(dep.name)
156
- else
151
+ if attributes[:gem_fix_dependencies?]
152
+ name = fix_name(dep.name)
153
+ else
157
154
  name = dep.name
158
155
  end
159
156
  self.dependencies << "#{name} #{req}"
160
157
  end
161
158
  end # runtime_dependencies
162
- end # ::Gem::Package
159
+ end #no_auto_depends
163
160
  end # def load_package_info
164
161
 
165
162
  def install_to_staging(gem_path)
@@ -130,7 +130,6 @@ class FPM::Package::OSXpkg < FPM::Package
130
130
  # Output a pkgbuild pkg.
131
131
  def output(output_path)
132
132
  output_check(output_path)
133
- raise FileAlreadyExists.new(output_path) if File.exists?(output_path)
134
133
 
135
134
  temp_info = pkginfo_template_path
136
135
 
@@ -1 +1 @@
1
- __all__ = [ "list_dependencies" ]
1
+ __all__ = [ "get_metadata" ]
@@ -1,4 +1,5 @@
1
1
  from distutils.core import Command
2
+ import os
2
3
  import pkg_resources
3
4
  try:
4
5
  import json
@@ -10,15 +11,41 @@ except ImportError:
10
11
  # possible some of my techniques below are outdated or bad.
11
12
  # If you have fixes, let me know.
12
13
 
14
+
13
15
  class get_metadata(Command):
14
16
  description = "get package metadata"
15
- user_options = []
17
+ user_options = [
18
+ ('load-requirements-txt', 'l',
19
+ "load dependencies from requirements.txt"),
20
+ ]
21
+ boolean_options = ['load-requirements-txt']
16
22
 
17
23
  def initialize_options(self):
18
- pass
24
+ self.load_requirements_txt = False
25
+ self.cwd = None
19
26
 
20
27
  def finalize_options(self):
21
- pass
28
+ self.cwd = os.getcwd()
29
+ self.requirements_txt = os.path.join(self.cwd, "requirements.txt")
30
+ # make sure we have a requirements.txt
31
+ if self.load_requirements_txt:
32
+ self.load_requirements_txt = os.path.exists(self.requirements_txt)
33
+
34
+ def process_dep(self, dep):
35
+ deps = []
36
+ if dep.specs:
37
+ for operator, version in dep.specs:
38
+ final_operator = operator
39
+
40
+ if operator == "==":
41
+ final_operator = "="
42
+
43
+ deps.append("%s %s %s" % (dep.project_name,
44
+ final_operator, version))
45
+ else:
46
+ deps.append(dep.project_name)
47
+
48
+ return deps
22
49
 
23
50
  def run(self):
24
51
  data = {
@@ -26,7 +53,7 @@ class get_metadata(Command):
26
53
  "version": self.distribution.get_version(),
27
54
  "author": "%s <%s>" % (
28
55
  self.distribution.get_author(),
29
- self.distribution.get_author_email()
56
+ self.distribution.get_author_email(),
30
57
  ),
31
58
  "description": self.distribution.get_description(),
32
59
  "license": self.distribution.get_license(),
@@ -39,19 +66,16 @@ class get_metadata(Command):
39
66
  data["architecture"] = "all"
40
67
 
41
68
  final_deps = []
42
- if getattr(self.distribution, 'install_requires', None):
43
- for dep in pkg_resources.parse_requirements(
44
- self.distribution.install_requires):
45
- # add all defined specs to the dependecy list separately.
46
- if dep.specs:
47
- for operator, version in dep.specs:
48
- final_deps.append("%s %s %s" % (
49
- dep.project_name,
50
- (lambda x: "=" if x == "==" else x)(operator),
51
- version
52
- ))
53
- else:
54
- final_deps.append(dep.project_name)
69
+
70
+ if self.load_requirements_txt:
71
+ requirement = open(self.requirements_txt).readlines()
72
+ for dep in pkg_resources.parse_requirements(requirement):
73
+ final_deps.extend(self.process_dep(dep))
74
+ else:
75
+ if getattr(self.distribution, 'install_requires', None):
76
+ for dep in pkg_resources.parse_requirements(
77
+ self.distribution.install_requires):
78
+ final_deps.extend(self.process_dep(dep))
55
79
 
56
80
  data["dependencies"] = final_deps
57
81
 
@@ -60,6 +60,9 @@ class FPM::Package::Python < FPM::Package
60
60
  "DATA_PATH"
61
61
  option "--dependencies", :flag, "Include requirements defined in setup.py" \
62
62
  " as dependencies.", :default => true
63
+ option "--obey-requirements-txt", :flag, "Use a requirements.txt file" \
64
+ "in the top-level directory of the python package for dependency " \
65
+ "detection.", :default => false
63
66
 
64
67
  private
65
68
 
@@ -147,10 +150,17 @@ class FPM::Package::Python < FPM::Package
147
150
  output = ::Dir.chdir(setup_dir) do
148
151
  setup_cmd = "env PYTHONPATH=#{pylib} #{attributes[:python_bin]} " \
149
152
  "setup.py --command-packages=pyfpm get_metadata"
153
+
154
+ if attributes[:python_obey_requirements_txt?]
155
+ setup_cmd += " --load-requirements-txt"
156
+ end
157
+
150
158
  # Capture the output, which will be JSON metadata describing this python
151
159
  # package. See fpm/lib/fpm/package/pyfpm/get_metadata.py for more
152
160
  # details.
153
- output = `#{setup_cmd}`
161
+ @logger.info("fetching package metadata", :setup_cmd => setup_cmd)
162
+
163
+ output = %x{#{setup_cmd}}
154
164
  if !$?.success?
155
165
  @logger.error("setup.py get_metadata failed", :command => setup_cmd,
156
166
  :exitcode => $?.exitcode)
@@ -164,7 +174,9 @@ class FPM::Package::Python < FPM::Package
164
174
 
165
175
  self.architecture = metadata["architecture"]
166
176
  self.description = metadata["description"]
167
- self.license = metadata["license"]
177
+ # Sometimes the license field is multiple lines; do best-effort and just
178
+ # use the first line.
179
+ self.license = metadata["license"].split(/[\r\n]+/).first
168
180
  self.version = metadata["version"]
169
181
  self.url = metadata["url"]
170
182
 
@@ -179,27 +191,8 @@ class FPM::Package::Python < FPM::Package
179
191
  # convert python-Foo to python-foo if flag is set
180
192
  self.name = self.name.downcase if attributes[:python_downcase_name?]
181
193
 
182
- requirements_txt = File.join(setup_dir, "requirements.txt")
183
- if File.exists?(requirements_txt)
184
- @logger.info("Found requirements.txt, using it instead of setup.py " \
185
- "for dependency information", :path => requirements_txt)
186
- @logger.debug("Clearing dependency list (from setup.py) in prep for " \
187
- "reading requirements.txt")
188
- # Best I can tell, requirements.txt are a superset of what
189
- # is already supported as 'dependencies' in setup.py
190
- # So we'll parse them the same way below.
191
-
192
- # requirements.txt can have dependencies, flags, and comments.
193
- # We only want the comments, so remove comment and flag lines.
194
- metadata["dependencies"] = File.read(requirements_txt).split("\n") \
195
- .reject { |l| l =~ /^\s*$/ } \
196
- .reject { |l| l =~ /^\s*#/ } \
197
- .reject { |l| l =~ /^-/ } \
198
- .map(&:strip)
199
- end
200
-
201
- if attributes[:python_dependencies?]
202
- self.dependencies += metadata["dependencies"].collect do |dep|
194
+ if !attributes[:no_auto_depends?] and attributes[:python_dependencies?]
195
+ self.dependencies = metadata["dependencies"].collect do |dep|
203
196
  dep_re = /^([^<>!= ]+)\s*(?:([<>!=]{1,2})\s*(.*))?$/
204
197
  match = dep_re.match(dep)
205
198
  if match.nil?
@@ -23,6 +23,7 @@ class FPM::Package::RPM < FPM::Package
23
23
  } unless defined?(DIGEST_ALGORITHM_MAP)
24
24
 
25
25
  COMPRESSION_MAP = {
26
+ "none" => "w0.gzdio",
26
27
  "xz" => "w2.xzdio",
27
28
  "gzip" => "w9.gzdio",
28
29
  "bzip2" => "w9.bzdio"
@@ -160,17 +161,29 @@ class FPM::Package::RPM < FPM::Package
160
161
  end
161
162
 
162
163
  # Convert != dependency as Conflict =, as rpm doesn't understand !=
163
- if origin == FPM::Package::Python
164
- self.dependencies = self.dependencies.select do |dep|
165
- name, op, version = dep.split(/\s+/)
166
- dep_ok = true
167
- if op == '!='
168
- self.conflicts << "#{name} = #{version}"
169
- dep_ok = false
170
- end
171
- dep_ok
164
+ self.dependencies = self.dependencies.select do |dep|
165
+ name, op, version = dep.split(/\s+/)
166
+ dep_ok = true
167
+ if op == '!='
168
+ self.conflicts << "#{name} = #{version}"
169
+ dep_ok = false
172
170
  end
171
+ dep_ok
173
172
  end
173
+
174
+ # Convert any dashes in version strings to underscores.
175
+ self.dependencies = self.dependencies.collect do |dep|
176
+ name, op, version = dep.split(/\s+/)
177
+ if !version.nil? and version.include?("-")
178
+ @logger.warn("Dependency package '#{name}' version '#{version}' " \
179
+ "includes dashes, converting to underscores")
180
+ version = version.gsub(/-/, "_")
181
+ "#{name} #{op} #{version}"
182
+ else
183
+ dep
184
+ end
185
+ end
186
+
174
187
  end # def converted
175
188
 
176
189
  def input(path)
@@ -203,9 +216,12 @@ class FPM::Package::RPM < FPM::Package
203
216
  # #{tags[prein]}
204
217
  # TODO(sissel): put 'trigger scripts' stuff into attributes
205
218
 
206
- self.dependencies += rpm.requires.collect do |name, operator, version|
207
- [name, operator, version].join(" ")
219
+ if !attributes[:no_auto_depends?]
220
+ self.dependencies += rpm.requires.collect do |name, operator, version|
221
+ [name, operator, version].join(" ")
222
+ end
208
223
  end
224
+
209
225
  self.conflicts += rpm.conflicts.collect do |name, operator, version|
210
226
  [name, operator, version].join(" ")
211
227
  end
@@ -231,7 +247,6 @@ class FPM::Package::RPM < FPM::Package
231
247
 
232
248
  def output(output_path)
233
249
  output_check(output_path)
234
- raise FileAlreadyExists.new(output_path) if File.exists?(output_path)
235
250
  %w(BUILD RPMS SRPMS SOURCES SPECS).each { |d| FileUtils.mkdir_p(build_path(d)) }
236
251
  args = ["rpmbuild", "-bb"]
237
252
 
@@ -282,12 +297,25 @@ class FPM::Package::RPM < FPM::Package
282
297
  #return File.join("BUILD", prefix)
283
298
  end # def prefix
284
299
 
285
- # The default epoch value must be 1 (backward compatibility for rpms built
286
- # with fpm 0.4.3 and older)
300
+ def version
301
+ if @version.kind_of?(String) and @version.include?("-")
302
+ @logger.warn("Package version '#{@version}' includes dashes, converting" \
303
+ " to underscores")
304
+ @version = @version.gsub(/-/, "_")
305
+ end
306
+
307
+ return @version
308
+ end
309
+
310
+ # The default epoch value must be nil, see #381
287
311
  def epoch
288
- return 1 if @epoch.nil?
289
312
  return @epoch if @epoch.is_a?(Numeric)
290
- return nil if @epoch.empty?
313
+
314
+ if @epoch.nil? or @epoch.empty?
315
+ @logger.warn("no value for epoch is set, defaulting to nil")
316
+ return nil
317
+ end
318
+
291
319
  return @epoch
292
320
  end # def epoch
293
321
 
@@ -48,7 +48,6 @@ class FPM::Package::Tar < FPM::Package
48
48
  # the compression type.
49
49
  def output(output_path)
50
50
  output_check(output_path)
51
- raise FileAlreadyExists.new(output_path) if File.exists?(output_path)
52
51
  # Unpack the tarball to the staging path
53
52
  args = ["-cf", output_path, "-C", staging_path, "."]
54
53
  with(tar_compression_flag(output_path)) do |flag|
@@ -1,3 +1,3 @@
1
1
  module FPM
2
- VERSION = "0.4.31"
2
+ VERSION = "0.4.32"
3
3
  end
@@ -11,6 +11,9 @@ Depends: <%= dependencies.collect { |d| fix_dependency(d) }.flatten.join(", ") %
11
11
  <% if !conflicts.empty? -%>
12
12
  Conflicts: <%= conflicts.join(", ") %>
13
13
  <% end -%>
14
+ <% if attributes[:deb_breaks] -%>
15
+ Breaks: <%= attributes[:deb_breaks].join(", ") %>
16
+ <% end -%>
14
17
  <% if attributes[:deb_pre_depends_given?] -%>
15
18
  Pre-Depends: <%= attributes[:deb_pre_depends].collect { |d| fix_dependency(d) }.flatten.join(", ") %>
16
19
  <% end -%>
@@ -0,0 +1,13 @@
1
+ #!/bin/sh
2
+ # This script is automatically added by fpm when you specify
3
+ # conditions that usually require running ldconfig upon
4
+ # package installation and removal.
5
+ #
6
+ # For example, if you set '--deb-shlibs' in creating your package,
7
+ # fpm will use this script if you don't provide your own --after-install or
8
+ # --after-remove
9
+ set -e
10
+
11
+ case $1 in
12
+ configure|remove) ldconfig ;;
13
+ esac
metadata CHANGED
@@ -1,235 +1,240 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: fpm
3
- version: !ruby/object:Gem::Version
4
- hash: 49
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.32
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 4
9
- - 31
10
- version: 0.4.31
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Jordan Sissel
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2013-03-21 00:00:00 Z
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
12
+ date: 2013-04-09 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
21
15
  name: json
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
24
17
  none: false
25
- requirements:
18
+ requirements:
26
19
  - - ~>
27
- - !ruby/object:Gem::Version
28
- hash: 5
29
- segments:
30
- - 1
31
- - 7
32
- - 7
20
+ - !ruby/object:Gem::Version
33
21
  version: 1.7.7
34
22
  type: :runtime
35
- version_requirements: *id001
36
- - !ruby/object:Gem::Dependency
37
- name: cabin
38
23
  prerelease: false
39
- requirement: &id002 !ruby/object:Gem::Requirement
40
- none: false
41
- requirements:
42
- - - ">="
43
- - !ruby/object:Gem::Version
44
- hash: 7
45
- segments:
46
- - 0
47
- - 6
48
- - 0
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 1.7.7
30
+ - !ruby/object:Gem::Dependency
31
+ name: cabin
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
49
37
  version: 0.6.0
50
38
  type: :runtime
51
- version_requirements: *id002
52
- - !ruby/object:Gem::Dependency
53
- name: backports
54
39
  prerelease: false
55
- requirement: &id003 !ruby/object:Gem::Requirement
56
- none: false
57
- requirements:
58
- - - "="
59
- - !ruby/object:Gem::Version
60
- hash: 19
61
- segments:
62
- - 2
63
- - 6
64
- - 2
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 0.6.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: backports
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - '='
52
+ - !ruby/object:Gem::Version
65
53
  version: 2.6.2
66
54
  type: :runtime
67
- version_requirements: *id003
68
- - !ruby/object:Gem::Dependency
69
- name: arr-pm
70
55
  prerelease: false
71
- requirement: &id004 !ruby/object:Gem::Requirement
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 2.6.2
62
+ - !ruby/object:Gem::Dependency
63
+ name: arr-pm
64
+ requirement: !ruby/object:Gem::Requirement
72
65
  none: false
73
- requirements:
66
+ requirements:
74
67
  - - ~>
75
- - !ruby/object:Gem::Version
76
- hash: 15
77
- segments:
78
- - 0
79
- - 0
80
- - 8
68
+ - !ruby/object:Gem::Version
81
69
  version: 0.0.8
82
70
  type: :runtime
83
- version_requirements: *id004
84
- - !ruby/object:Gem::Dependency
85
- name: clamp
86
71
  prerelease: false
87
- requirement: &id005 !ruby/object:Gem::Requirement
88
- none: false
89
- requirements:
90
- - - "="
91
- - !ruby/object:Gem::Version
92
- hash: 17
93
- segments:
94
- - 0
95
- - 3
96
- - 1
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 0.0.8
78
+ - !ruby/object:Gem::Dependency
79
+ name: clamp
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - '='
84
+ - !ruby/object:Gem::Version
97
85
  version: 0.3.1
98
86
  type: :runtime
99
- version_requirements: *id005
100
- - !ruby/object:Gem::Dependency
101
- name: open4
102
87
  prerelease: false
103
- requirement: &id006 !ruby/object:Gem::Requirement
104
- none: false
105
- requirements:
106
- - - ">="
107
- - !ruby/object:Gem::Version
108
- hash: 3
109
- segments:
110
- - 0
111
- version: "0"
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - '='
92
+ - !ruby/object:Gem::Version
93
+ version: 0.3.1
94
+ - !ruby/object:Gem::Dependency
95
+ name: open4
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
112
102
  type: :runtime
113
- version_requirements: *id006
114
- - !ruby/object:Gem::Dependency
115
- name: rush
116
103
  prerelease: false
117
- requirement: &id007 !ruby/object:Gem::Requirement
118
- none: false
119
- requirements:
120
- - - ">="
121
- - !ruby/object:Gem::Version
122
- hash: 3
123
- segments:
124
- - 0
125
- version: "0"
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: rush
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
126
118
  type: :development
127
- version_requirements: *id007
128
- - !ruby/object:Gem::Dependency
129
- name: rspec
130
119
  prerelease: false
131
- requirement: &id008 !ruby/object:Gem::Requirement
132
- none: false
133
- requirements:
134
- - - ">="
135
- - !ruby/object:Gem::Version
136
- hash: 3
137
- segments:
138
- - 0
139
- version: "0"
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: rspec
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
140
134
  type: :development
141
- version_requirements: *id008
142
- - !ruby/object:Gem::Dependency
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ - !ruby/object:Gem::Dependency
143
143
  name: insist
144
+ requirement: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ~>
148
+ - !ruby/object:Gem::Version
149
+ version: 0.0.5
150
+ type: :development
144
151
  prerelease: false
145
- requirement: &id009 !ruby/object:Gem::Requirement
152
+ version_requirements: !ruby/object:Gem::Requirement
146
153
  none: false
147
- requirements:
154
+ requirements:
148
155
  - - ~>
149
- - !ruby/object:Gem::Version
150
- hash: 21
151
- segments:
152
- - 0
153
- - 0
154
- - 5
156
+ - !ruby/object:Gem::Version
155
157
  version: 0.0.5
158
+ - !ruby/object:Gem::Dependency
159
+ name: minitest
160
+ requirement: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
156
166
  type: :development
157
- version_requirements: *id009
158
- description: Convert directories, rpms, python eggs, rubygems, and more to rpms, debs, solaris packages and more. Win at package management without wasting pointless hours debugging bad rpm specs!
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ description: Convert directories, rpms, python eggs, rubygems, and more to rpms, debs,
175
+ solaris packages and more. Win at package management without wasting pointless hours
176
+ debugging bad rpm specs!
159
177
  email: jls@semicomplete.com
160
- executables:
178
+ executables:
161
179
  - fpm
162
180
  extensions: []
163
-
164
181
  extra_rdoc_files: []
165
-
166
- files:
167
- - lib/fpm.rb
182
+ files:
168
183
  - lib/fpm/errors.rb
169
184
  - lib/fpm/namespace.rb
170
185
  - lib/fpm/package/npm.rb
171
- - lib/fpm/package/osxpkg.rb
172
186
  - lib/fpm/package/puppet.rb
173
187
  - lib/fpm/package/pyfpm/__init__.py
174
- - lib/fpm/package/pyfpm/__init__.pyc
175
188
  - lib/fpm/package/pyfpm/get_metadata.py
176
- - lib/fpm/package/pyfpm/get_metadata.pyc
177
- - lib/fpm/package/tar.rb
178
189
  - lib/fpm/package/dir.rb
179
- - lib/fpm/package/pear.rb
180
190
  - lib/fpm/package/empty.rb
191
+ - lib/fpm/package/pear.rb
181
192
  - lib/fpm/package/solaris.rb
182
- - lib/fpm/package/python.rb
183
- - lib/fpm/package/deb.rb
184
193
  - lib/fpm/package/gem.rb
194
+ - lib/fpm/package/osxpkg.rb
195
+ - lib/fpm/package/python.rb
185
196
  - lib/fpm/package/rpm.rb
197
+ - lib/fpm/package/tar.rb
198
+ - lib/fpm/package/deb.rb
186
199
  - lib/fpm/util.rb
187
200
  - lib/fpm/command.rb
188
201
  - lib/fpm/package.rb
189
202
  - lib/fpm/version.rb
203
+ - lib/fpm.rb
190
204
  - bin/fpm
191
- - templates/deb.erb
192
- - templates/osxpkg.erb
193
205
  - templates/puppet/package.pp.erb
194
206
  - templates/puppet/package/remove.pp.erb
195
207
  - templates/solaris.erb
208
+ - templates/osxpkg.erb
209
+ - templates/deb.erb
196
210
  - templates/rpm.erb
211
+ - templates/deb/ldconfig.sh.erb
197
212
  - LICENSE
198
213
  - CONTRIBUTORS
199
214
  - CHANGELIST
200
215
  homepage: https://github.com/jordansissel/fpm
201
216
  licenses: []
202
-
203
217
  post_install_message:
204
218
  rdoc_options: []
205
-
206
- require_paths:
219
+ require_paths:
207
220
  - lib
208
221
  - lib
209
- required_ruby_version: !ruby/object:Gem::Requirement
222
+ required_ruby_version: !ruby/object:Gem::Requirement
210
223
  none: false
211
- requirements:
212
- - - ">="
213
- - !ruby/object:Gem::Version
214
- hash: 3
215
- segments:
216
- - 0
217
- version: "0"
218
- required_rubygems_version: !ruby/object:Gem::Requirement
224
+ requirements:
225
+ - - ! '>='
226
+ - !ruby/object:Gem::Version
227
+ version: '0'
228
+ required_rubygems_version: !ruby/object:Gem::Requirement
219
229
  none: false
220
- requirements:
221
- - - ">="
222
- - !ruby/object:Gem::Version
223
- hash: 3
224
- segments:
225
- - 0
226
- version: "0"
230
+ requirements:
231
+ - - ! '>='
232
+ - !ruby/object:Gem::Version
233
+ version: '0'
227
234
  requirements: []
228
-
229
235
  rubyforge_project:
230
- rubygems_version: 1.8.25
236
+ rubygems_version: 1.8.24
231
237
  signing_key:
232
238
  specification_version: 3
233
239
  summary: fpm - package building and mangling
234
240
  test_files: []
235
-