fpm 1.6.1 → 1.14.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.rst +674 -0
- data/CONTRIBUTORS +2 -0
- data/LICENSE +1 -1
- data/bin/fpm +0 -1
- data/lib/fpm/command.rb +26 -12
- data/lib/fpm/package/apk.rb +6 -6
- data/lib/fpm/package/cpan.rb +85 -30
- data/lib/fpm/package/deb.rb +298 -44
- data/lib/fpm/package/dir.rb +12 -17
- data/lib/fpm/package/empty.rb +13 -1
- data/lib/fpm/package/freebsd.rb +37 -33
- data/lib/fpm/package/gem.rb +167 -13
- data/lib/fpm/package/pacman.rb +28 -12
- data/lib/fpm/package/pleaserun.rb +13 -1
- data/lib/fpm/package/pyfpm/get_metadata.py +10 -0
- data/lib/fpm/package/python.rb +57 -8
- data/lib/fpm/package/rpm.rb +62 -10
- data/lib/fpm/package/sh.rb +1 -1
- data/lib/fpm/package/snap.rb +130 -0
- data/lib/fpm/package/tar.rb +2 -10
- data/lib/fpm/package/virtualenv.rb +76 -14
- data/lib/fpm/package/zip.rb +6 -22
- data/lib/fpm/package.rb +27 -6
- data/lib/fpm/util/tar_writer.rb +3 -1
- data/lib/fpm/util.rb +115 -62
- data/lib/fpm/version.rb +1 -1
- data/lib/fpm.rb +2 -0
- data/templates/deb/changelog.erb +1 -1
- data/templates/deb/deb.changes.erb +30 -0
- data/templates/deb/postinst_upgrade.sh.erb +30 -8
- data/templates/deb/postrm_upgrade.sh.erb +17 -5
- data/templates/deb/preinst_upgrade.sh.erb +5 -0
- data/templates/deb/prerm_upgrade.sh.erb +12 -4
- data/templates/deb.erb +7 -7
- data/templates/rpm.erb +14 -12
- data/templates/sh.erb +6 -1
- metadata +33 -64
- data/CHANGELIST +0 -650
- data/lib/fpm/package/pyfpm/__init__.pyc +0 -0
- data/lib/fpm/package/pyfpm/get_metadata.pyc +0 -0
data/lib/fpm/package/deb.rb
CHANGED
@@ -3,9 +3,14 @@ require "fpm/namespace"
|
|
3
3
|
require "fpm/package"
|
4
4
|
require "fpm/errors"
|
5
5
|
require "fpm/util"
|
6
|
-
require "backports"
|
6
|
+
require "backports/latest"
|
7
7
|
require "fileutils"
|
8
8
|
require "digest"
|
9
|
+
require "zlib"
|
10
|
+
|
11
|
+
# For handling conversion
|
12
|
+
require "fpm/package/cpan"
|
13
|
+
require "fpm/package/gem"
|
9
14
|
|
10
15
|
# Support for debian packages (.deb files)
|
11
16
|
#
|
@@ -18,10 +23,22 @@ class FPM::Package::Deb < FPM::Package
|
|
18
23
|
:after_install => "postinst",
|
19
24
|
:before_remove => "prerm",
|
20
25
|
:after_remove => "postrm",
|
26
|
+
:after_purge => "postrm",
|
21
27
|
} unless defined?(SCRIPT_MAP)
|
22
28
|
|
23
29
|
# The list of supported compression types. Default is gz (gzip)
|
24
|
-
COMPRESSION_TYPES = [ "gz", "bzip2", "xz" ]
|
30
|
+
COMPRESSION_TYPES = [ "gz", "bzip2", "xz", "none" ]
|
31
|
+
|
32
|
+
# https://www.debian.org/doc/debian-policy/ch-relationships.html#syntax-of-relationship-fields
|
33
|
+
# Example value with version relationship: libc6 (>= 2.2.1)
|
34
|
+
# Example value: libc6
|
35
|
+
|
36
|
+
# Version string docs here: https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-version
|
37
|
+
# The format is: [epoch:]upstream_version[-debian_revision].
|
38
|
+
# epoch - This is a single (generally small) unsigned integer
|
39
|
+
# upstream_version - must contain only alphanumerics 6 and the characters . + - ~
|
40
|
+
# debian_revision - only alphanumerics and the characters + . ~
|
41
|
+
RELATIONSHIP_FIELD_PATTERN = /^(?<name>[A-z0-9_-]+)(?: *\((?<relation>[<>=]+) *(?<version>(?:[0-9]+:)?[0-9A-Za-z+~.-]+(?:-[0-9A-Za-z+~.]+)?)\))?$/
|
25
42
|
|
26
43
|
option "--ignore-iteration-in-dependencies", :flag,
|
27
44
|
"For '=' (equal) dependencies, allow iterations on the specified " \
|
@@ -49,6 +66,8 @@ class FPM::Package::Deb < FPM::Package
|
|
49
66
|
value
|
50
67
|
end
|
51
68
|
|
69
|
+
option "--dist", "DIST-TAG", "Set the deb distribution.", :default => "unstable"
|
70
|
+
|
52
71
|
# Take care about the case when we want custom control file but still use fpm ...
|
53
72
|
option "--custom-control", "FILEPATH",
|
54
73
|
"Custom version of the Debian control file." do |control|
|
@@ -87,6 +106,10 @@ class FPM::Package::Deb < FPM::Package
|
|
87
106
|
File.expand_path(file)
|
88
107
|
end
|
89
108
|
|
109
|
+
option "--generate-changes", :flag,
|
110
|
+
"Generate PACKAGENAME.changes file.",
|
111
|
+
:default => false
|
112
|
+
|
90
113
|
option "--upstream-changelog", "FILEPATH", "Add FILEPATH as upstream changelog" do |file|
|
91
114
|
File.expand_path(file)
|
92
115
|
end
|
@@ -121,6 +144,18 @@ class FPM::Package::Deb < FPM::Package
|
|
121
144
|
next @activated_triggers
|
122
145
|
end
|
123
146
|
|
147
|
+
option "--interest-noawait", "EVENT", "Package is interested in EVENT trigger without awaiting" do |event|
|
148
|
+
@interested_noawait_triggers ||= []
|
149
|
+
@interested_noawait_triggers << event
|
150
|
+
next @interested_noawait_triggers
|
151
|
+
end
|
152
|
+
|
153
|
+
option "--activate-noawait", "EVENT", "Package activates EVENT trigger" do |event|
|
154
|
+
@activated_noawait_triggers ||= []
|
155
|
+
@activated_noawait_triggers << event
|
156
|
+
next @activated_noawait_triggers
|
157
|
+
end
|
158
|
+
|
124
159
|
option "--field", "'FIELD: VALUE'", "Add custom field to the control file" do |fv|
|
125
160
|
@custom_fields ||= {}
|
126
161
|
field, value = fv.split(/: */, 2)
|
@@ -158,12 +193,27 @@ class FPM::Package::Deb < FPM::Package
|
|
158
193
|
end
|
159
194
|
|
160
195
|
option "--systemd", "FILEPATH", "Add FILEPATH as a systemd script",
|
161
|
-
|
196
|
+
:multivalued => true do |file|
|
162
197
|
next File.expand_path(file)
|
163
198
|
end
|
164
199
|
|
200
|
+
option "--systemd-enable", :flag , "Enable service on install or upgrade", :default => false
|
201
|
+
|
202
|
+
option "--systemd-auto-start", :flag , "Start service after install or upgrade", :default => false
|
203
|
+
|
165
204
|
option "--systemd-restart-after-upgrade", :flag , "Restart service after upgrade", :default => true
|
166
205
|
|
206
|
+
option "--after-purge", "FILE",
|
207
|
+
"A script to be run after package removal to purge remaining (config) files " \
|
208
|
+
"(a.k.a. postrm purge within apt-get purge)" do |val|
|
209
|
+
File.expand_path(val) # Get the full path to the script
|
210
|
+
end # --after-purge
|
211
|
+
|
212
|
+
option "--maintainerscripts-force-errorchecks", :flag ,
|
213
|
+
"Activate errexit shell option according to lintian. " \
|
214
|
+
"https://lintian.debian.org/tags/maintainer-script-ignores-errors.html",
|
215
|
+
:default => false
|
216
|
+
|
167
217
|
def initialize(*args)
|
168
218
|
super(*args)
|
169
219
|
attributes[:deb_priority] = "extra"
|
@@ -193,6 +243,9 @@ class FPM::Package::Deb < FPM::Package
|
|
193
243
|
when "x86_64"
|
194
244
|
# Debian calls x86_64 "amd64"
|
195
245
|
@architecture = "amd64"
|
246
|
+
when "aarch64"
|
247
|
+
# Debian calls aarch64 "arm64"
|
248
|
+
@architecture = "arm64"
|
196
249
|
when "noarch"
|
197
250
|
# Debian calls noarch "all"
|
198
251
|
@architecture = "all"
|
@@ -240,10 +293,32 @@ class FPM::Package::Deb < FPM::Package
|
|
240
293
|
end # def input
|
241
294
|
|
242
295
|
def extract_info(package)
|
296
|
+
compression = `#{ar_cmd[0]} t #{package}`.split("\n").grep(/control.tar/).first.split(".").last
|
297
|
+
case compression
|
298
|
+
when "gz"
|
299
|
+
controltar = "control.tar.gz"
|
300
|
+
compression = "-z"
|
301
|
+
when "bzip2","bz2"
|
302
|
+
controltar = "control.tar.bz2"
|
303
|
+
compression = "-j"
|
304
|
+
when "xz"
|
305
|
+
controltar = "control.tar.xz"
|
306
|
+
compression = "-J"
|
307
|
+
when 'tar'
|
308
|
+
controltar = "control.tar"
|
309
|
+
compression = ""
|
310
|
+
when nil
|
311
|
+
raise FPM::InvalidPackageConfiguration, "Missing control.tar in deb source package #{package}"
|
312
|
+
else
|
313
|
+
raise FPM::InvalidPackageConfiguration,
|
314
|
+
"Unknown compression type '#{compression}' for control.tar in deb source package #{package}"
|
315
|
+
end
|
316
|
+
|
243
317
|
build_path("control").tap do |path|
|
244
318
|
FileUtils.mkdir(path) if !File.directory?(path)
|
319
|
+
# unpack the control.tar.{,gz,bz2,xz} from the deb package into staging_path
|
245
320
|
# Unpack the control tarball
|
246
|
-
safesystem("
|
321
|
+
safesystem(ar_cmd[0] + " p #{package} #{controltar} | tar #{compression} -xf - -C #{path}")
|
247
322
|
|
248
323
|
control = File.read(File.join(path, "control"))
|
249
324
|
|
@@ -340,30 +415,39 @@ class FPM::Package::Deb < FPM::Package
|
|
340
415
|
|
341
416
|
def extract_files(package)
|
342
417
|
# Find out the compression type
|
343
|
-
compression =
|
418
|
+
compression = `#{ar_cmd[0]} t #{package}`.split("\n").grep(/data.tar/).first.split(".").last
|
344
419
|
case compression
|
345
420
|
when "gz"
|
346
421
|
datatar = "data.tar.gz"
|
347
422
|
compression = "-z"
|
348
|
-
when "bzip2"
|
423
|
+
when "bzip2","bz2"
|
349
424
|
datatar = "data.tar.bz2"
|
350
425
|
compression = "-j"
|
351
426
|
when "xz"
|
352
427
|
datatar = "data.tar.xz"
|
353
428
|
compression = "-J"
|
429
|
+
when 'tar'
|
430
|
+
datatar = "data.tar"
|
431
|
+
compression = ""
|
432
|
+
when nil
|
433
|
+
raise FPM::InvalidPackageConfiguration, "Missing data.tar in deb source package #{package}"
|
354
434
|
else
|
355
435
|
raise FPM::InvalidPackageConfiguration,
|
356
|
-
"Unknown compression type '#{
|
357
|
-
"in deb source package #{package}"
|
436
|
+
"Unknown compression type '#{compression}' for data.tar in deb source package #{package}"
|
358
437
|
end
|
359
438
|
|
360
439
|
# unpack the data.tar.{gz,bz2,xz} from the deb package into staging_path
|
361
|
-
safesystem("
|
362
|
-
"| tar #{compression} -xf - -C #{staging_path}")
|
440
|
+
safesystem(ar_cmd[0] + " p #{package} #{datatar} | tar #{compression} -xf - -C #{staging_path}")
|
363
441
|
end # def extract_files
|
364
442
|
|
365
443
|
def output(output_path)
|
366
444
|
self.provides = self.provides.collect { |p| fix_provides(p) }
|
445
|
+
|
446
|
+
self.provides.each do |provide|
|
447
|
+
if !valid_provides_field?(provide)
|
448
|
+
raise FPM::InvalidPackageConfiguration, "Found invalid Provides field values (#{provide.inspect}). This is not valid in a Debian package."
|
449
|
+
end
|
450
|
+
end
|
367
451
|
output_check(output_path)
|
368
452
|
# Abort if the target path already exists.
|
369
453
|
|
@@ -387,6 +471,23 @@ class FPM::Package::Deb < FPM::Package
|
|
387
471
|
end
|
388
472
|
end
|
389
473
|
|
474
|
+
if attributes[:source_date_epoch].nil? and not attributes[:source_date_epoch_default].nil?
|
475
|
+
attributes[:source_date_epoch] = attributes[:source_date_epoch_default]
|
476
|
+
end
|
477
|
+
if attributes[:source_date_epoch] == "0"
|
478
|
+
logger.error("Alas, ruby's Zlib::GzipWriter does not support setting an mtime of zero. Aborting.")
|
479
|
+
raise "#{name}: source_date_epoch of 0 not supported."
|
480
|
+
end
|
481
|
+
if not attributes[:source_date_epoch].nil? and not ar_cmd_deterministic?
|
482
|
+
logger.error("Alas, could not find an ar that can handle -D option. Try installing recent gnu binutils. Aborting.")
|
483
|
+
raise "#{name}: ar is insufficient to support source_date_epoch."
|
484
|
+
end
|
485
|
+
if not attributes[:source_date_epoch].nil? and not tar_cmd_supports_sort_names_and_set_mtime?
|
486
|
+
logger.error("Alas, could not find a tar that can set mtime and sort. Try installing recent gnu tar. Aborting.")
|
487
|
+
raise "#{name}: tar is insufficient to support source_date_epoch."
|
488
|
+
end
|
489
|
+
|
490
|
+
attributes[:deb_systemd] = []
|
390
491
|
attributes.fetch(:deb_systemd_list, []).each do |systemd|
|
391
492
|
name = File.basename(systemd, ".service")
|
392
493
|
dest_systemd = staging_path("lib/systemd/system/#{name}.service")
|
@@ -394,42 +495,27 @@ class FPM::Package::Deb < FPM::Package
|
|
394
495
|
FileUtils.cp(systemd, dest_systemd)
|
395
496
|
File.chmod(0644, dest_systemd)
|
396
497
|
|
397
|
-
#
|
398
|
-
attributes[:deb_systemd]
|
498
|
+
# add systemd service name to attribute
|
499
|
+
attributes[:deb_systemd] << name
|
399
500
|
end
|
400
501
|
|
401
|
-
if script?(:before_upgrade) or script?(:after_upgrade) or attributes[:deb_systemd]
|
502
|
+
if script?(:before_upgrade) or script?(:after_upgrade) or attributes[:deb_systemd].any?
|
402
503
|
puts "Adding action files"
|
403
504
|
if script?(:before_install) or script?(:before_upgrade)
|
404
505
|
scripts[:before_install] = template("deb/preinst_upgrade.sh.erb").result(binding)
|
405
506
|
end
|
406
|
-
if script?(:before_remove) or attributes[:deb_systemd]
|
507
|
+
if script?(:before_remove) or not attributes[:deb_systemd].empty?
|
407
508
|
scripts[:before_remove] = template("deb/prerm_upgrade.sh.erb").result(binding)
|
408
509
|
end
|
409
|
-
if script?(:after_install) or script?(:after_upgrade) or attributes[:deb_systemd]
|
510
|
+
if script?(:after_install) or script?(:after_upgrade) or attributes[:deb_systemd].any?
|
410
511
|
scripts[:after_install] = template("deb/postinst_upgrade.sh.erb").result(binding)
|
411
512
|
end
|
412
513
|
if script?(:after_remove)
|
413
514
|
scripts[:after_remove] = template("deb/postrm_upgrade.sh.erb").result(binding)
|
414
515
|
end
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
# Tar up the staging_path into data.tar.{compression type}
|
420
|
-
case self.attributes[:deb_compression]
|
421
|
-
when "gz", nil
|
422
|
-
datatar = build_path("data.tar.gz")
|
423
|
-
compression = "-z"
|
424
|
-
when "bzip2"
|
425
|
-
datatar = build_path("data.tar.bz2")
|
426
|
-
compression = "-j"
|
427
|
-
when "xz"
|
428
|
-
datatar = build_path("data.tar.xz")
|
429
|
-
compression = "-J"
|
430
|
-
else
|
431
|
-
raise FPM::InvalidPackageConfiguration,
|
432
|
-
"Unknown compression type '#{self.attributes[:deb_compression]}'"
|
516
|
+
if script?(:after_purge)
|
517
|
+
scripts[:after_purge] = template("deb/postrm_upgrade.sh.erb").result(binding)
|
518
|
+
end
|
433
519
|
end
|
434
520
|
|
435
521
|
# There are two changelogs that may appear:
|
@@ -442,6 +528,9 @@ class FPM::Package::Deb < FPM::Package
|
|
442
528
|
mkdir_p(File.dirname(dest_changelog))
|
443
529
|
File.new(dest_changelog, "wb", 0644).tap do |changelog|
|
444
530
|
Zlib::GzipWriter.new(changelog, Zlib::BEST_COMPRESSION).tap do |changelog_gz|
|
531
|
+
if not attributes[:source_date_epoch].nil?
|
532
|
+
changelog_gz.mtime = attributes[:source_date_epoch].to_i
|
533
|
+
end
|
445
534
|
if attributes[:deb_changelog]
|
446
535
|
logger.info("Writing user-specified changelog", :source => attributes[:deb_changelog])
|
447
536
|
File.new(attributes[:deb_changelog]).tap do |fd|
|
@@ -461,6 +550,9 @@ class FPM::Package::Deb < FPM::Package
|
|
461
550
|
if attributes[:deb_upstream_changelog]
|
462
551
|
File.new(dest_upstream_changelog, "wb", 0644).tap do |changelog|
|
463
552
|
Zlib::GzipWriter.new(changelog, Zlib::BEST_COMPRESSION).tap do |changelog_gz|
|
553
|
+
if not attributes[:source_date_epoch].nil?
|
554
|
+
changelog_gz.mtime = attributes[:source_date_epoch].to_i
|
555
|
+
end
|
464
556
|
logger.info("Writing user-specified upstream changelog", :source => attributes[:deb_upstream_changelog])
|
465
557
|
File.new(attributes[:deb_upstream_changelog]).tap do |fd|
|
466
558
|
chunk = nil
|
@@ -494,6 +586,7 @@ class FPM::Package::Deb < FPM::Package
|
|
494
586
|
|
495
587
|
attributes.fetch(:deb_upstart_list, []).each do |upstart|
|
496
588
|
name = File.basename(upstart, ".upstart")
|
589
|
+
dest_init = staging_path("etc/init.d/#{name}")
|
497
590
|
name = "#{name}.conf" if !(name =~ /\.conf$/)
|
498
591
|
dest_upstart = staging_path("etc/init/#{name}")
|
499
592
|
mkdir_p(File.dirname(dest_upstart))
|
@@ -501,7 +594,6 @@ class FPM::Package::Deb < FPM::Package
|
|
501
594
|
File.chmod(0644, dest_upstart)
|
502
595
|
|
503
596
|
# Install an init.d shim that calls upstart
|
504
|
-
dest_init = staging_path("etc/init.d/#{name}")
|
505
597
|
mkdir_p(File.dirname(dest_init))
|
506
598
|
FileUtils.ln_s("/lib/init/upstart-job", dest_init)
|
507
599
|
end
|
@@ -520,28 +612,65 @@ class FPM::Package::Deb < FPM::Package
|
|
520
612
|
case self.attributes[:deb_compression]
|
521
613
|
when "gz", nil
|
522
614
|
datatar = build_path("data.tar.gz")
|
615
|
+
controltar = build_path("control.tar.gz")
|
523
616
|
compression = "-z"
|
524
617
|
when "bzip2"
|
525
618
|
datatar = build_path("data.tar.bz2")
|
619
|
+
controltar = build_path("control.tar.gz")
|
526
620
|
compression = "-j"
|
527
621
|
when "xz"
|
528
622
|
datatar = build_path("data.tar.xz")
|
623
|
+
controltar = build_path("control.tar.xz")
|
529
624
|
compression = "-J"
|
625
|
+
when "none"
|
626
|
+
datatar = build_path("data.tar")
|
627
|
+
controltar = build_path("control.tar")
|
628
|
+
compression = ""
|
530
629
|
else
|
531
630
|
raise FPM::InvalidPackageConfiguration,
|
532
631
|
"Unknown compression type '#{self.attributes[:deb_compression]}'"
|
533
632
|
end
|
534
633
|
|
535
634
|
args = [ tar_cmd, "-C", staging_path, compression ] + data_tar_flags + [ "-cf", datatar, "." ]
|
635
|
+
if tar_cmd_supports_sort_names_and_set_mtime? and not attributes[:source_date_epoch].nil?
|
636
|
+
# Use gnu tar options to force deterministic file order and timestamp
|
637
|
+
args += ["--sort=name", ("--mtime=@%s" % attributes[:source_date_epoch])]
|
638
|
+
# gnu tar obeys GZIP environment variable with options for gzip; -n = forget original filename and date
|
639
|
+
args.unshift({"GZIP" => "-9n"})
|
640
|
+
end
|
536
641
|
safesystem(*args)
|
537
642
|
|
538
643
|
# pack up the .deb, which is just an 'ar' archive with 3 files
|
539
644
|
# the 'debian-binary' file has to be first
|
540
645
|
File.expand_path(output_path).tap do |output_path|
|
541
646
|
::Dir.chdir(build_path) do
|
542
|
-
safesystem(
|
647
|
+
safesystem(*ar_cmd, output_path, "debian-binary", controltar, datatar)
|
543
648
|
end
|
544
649
|
end
|
650
|
+
|
651
|
+
# if a PACKAGENAME.changes file is to be created
|
652
|
+
if self.attributes[:deb_generate_changes?]
|
653
|
+
distribution = self.attributes[:deb_dist]
|
654
|
+
|
655
|
+
# gather information about the files to distribute
|
656
|
+
files = [ output_path ]
|
657
|
+
changes_files = []
|
658
|
+
files.each do |path|
|
659
|
+
changes_files.push({
|
660
|
+
:name => path,
|
661
|
+
:size => File.size?(path),
|
662
|
+
:md5sum => Digest::MD5.file(path).hexdigest,
|
663
|
+
:sha1sum => Digest::SHA1.file(path).hexdigest,
|
664
|
+
:sha256sum => Digest::SHA2.file(path).hexdigest,
|
665
|
+
})
|
666
|
+
end
|
667
|
+
|
668
|
+
# write change infos to .changes file
|
669
|
+
changes_path = File.basename(output_path, '.deb') + '.changes'
|
670
|
+
changes_data = template("deb/deb.changes.erb").result(binding)
|
671
|
+
File.write(changes_path, changes_data)
|
672
|
+
logger.log("Created changes", :path => changes_path)
|
673
|
+
end # if deb_generate_changes
|
545
674
|
end # def output
|
546
675
|
|
547
676
|
def converted_from(origin)
|
@@ -552,6 +681,43 @@ class FPM::Package::Deb < FPM::Package
|
|
552
681
|
fix_provides(provides)
|
553
682
|
end.flatten
|
554
683
|
|
684
|
+
if origin == FPM::Package::CPAN
|
685
|
+
# The fpm cpan code presents dependencies and provides fields as perl(ModuleName)
|
686
|
+
# so we'll need to convert them to something debian supports.
|
687
|
+
|
688
|
+
# Replace perl(ModuleName) > 1.0 with Debian-style perl-ModuleName (> 1.0)
|
689
|
+
perldepfix = lambda do |dep|
|
690
|
+
m = dep.match(/perl\((?<name>[A-Za-z0-9_:]+)\)\s*(?<op>.*$)/)
|
691
|
+
if m.nil?
|
692
|
+
# 'dep' syntax didn't look like 'perl(Name) > 1.0'
|
693
|
+
dep
|
694
|
+
else
|
695
|
+
# Also replace '::' in the perl module name with '-'
|
696
|
+
modulename = m["name"].gsub("::", "-")
|
697
|
+
|
698
|
+
# Fix any upper-casing or other naming concerns Debian has about packages
|
699
|
+
name = "#{attributes[:cpan_package_name_prefix]}-#{modulename}"
|
700
|
+
|
701
|
+
if m["op"].empty?
|
702
|
+
name
|
703
|
+
else
|
704
|
+
# 'dep' syntax was like this (version constraint): perl(Module) > 1.0
|
705
|
+
"#{name} (#{m["op"]})"
|
706
|
+
end
|
707
|
+
end
|
708
|
+
end
|
709
|
+
|
710
|
+
rejects = [ "perl(vars)", "perl(warnings)", "perl(strict)", "perl(Config)" ]
|
711
|
+
self.dependencies = self.dependencies.reject do |dep|
|
712
|
+
# Reject non-module Perl dependencies like 'vars' and 'warnings'
|
713
|
+
rejects.include?(dep)
|
714
|
+
end.collect(&perldepfix).collect(&method(:fix_dependency))
|
715
|
+
|
716
|
+
# Also fix the Provides field 'perl(ModuleName) = version' to be 'perl-modulename (= version)'
|
717
|
+
self.provides = self.provides.collect(&perldepfix).collect(&method(:fix_provides))
|
718
|
+
|
719
|
+
end # if origin == FPM::Packagin::CPAN
|
720
|
+
|
555
721
|
if origin == FPM::Package::Deb
|
556
722
|
changelog_path = staging_path("usr/share/doc/#{name}/changelog.Debian.gz")
|
557
723
|
if File.exists?(changelog_path)
|
@@ -579,6 +745,19 @@ class FPM::Package::Deb < FPM::Package
|
|
579
745
|
File.unlink(changelog_path)
|
580
746
|
end
|
581
747
|
end
|
748
|
+
|
749
|
+
if origin == FPM::Package::Gem
|
750
|
+
# fpm's gem input will have provides as "rubygem-name = version"
|
751
|
+
# and we need to convert this to Debian-style "rubygem-name (= version)"
|
752
|
+
self.provides = self.provides.collect do |provides|
|
753
|
+
m = /^(#{attributes[:gem_package_name_prefix]})-([^\s]+)\s*=\s*(.*)$/.match(provides)
|
754
|
+
if m
|
755
|
+
"#{m[1]}-#{m[2]} (= #{m[3]})"
|
756
|
+
else
|
757
|
+
provides
|
758
|
+
end
|
759
|
+
end
|
760
|
+
end
|
582
761
|
end # def converted_from
|
583
762
|
|
584
763
|
def debianize_op(op)
|
@@ -620,8 +799,13 @@ class FPM::Package::Deb < FPM::Package
|
|
620
799
|
name, version = dep.gsub(/[()~>]/, "").split(/ +/)[0..1]
|
621
800
|
nextversion = version.split(".").collect { |v| v.to_i }
|
622
801
|
l = nextversion.length
|
623
|
-
|
624
|
-
|
802
|
+
if l > 1
|
803
|
+
nextversion[l-2] += 1
|
804
|
+
nextversion[l-1] = 0
|
805
|
+
else
|
806
|
+
# Single component versions ~> 1
|
807
|
+
nextversion[l-1] += 1
|
808
|
+
end
|
625
809
|
nextversion = nextversion.join(".")
|
626
810
|
return ["#{name} (>= #{version})", "#{name} (<< #{nextversion})"]
|
627
811
|
elsif (m = dep.match(/(\S+)\s+\(!= (.+)\)/))
|
@@ -648,6 +832,32 @@ class FPM::Package::Deb < FPM::Package
|
|
648
832
|
end
|
649
833
|
end # def fix_dependency
|
650
834
|
|
835
|
+
def valid_provides_field?(text)
|
836
|
+
m = RELATIONSHIP_FIELD_PATTERN.match(text)
|
837
|
+
if m.nil?
|
838
|
+
logger.error("Invalid relationship field for debian package: #{text}")
|
839
|
+
return false
|
840
|
+
end
|
841
|
+
|
842
|
+
# Per Debian Policy manual, https://www.debian.org/doc/debian-policy/ch-relationships.html#syntax-of-relationship-fields
|
843
|
+
# >> The relations allowed are <<, <=, =, >= and >> for strictly earlier, earlier or equal,
|
844
|
+
# >> exactly equal, later or equal and strictly later, respectively. The exception is the
|
845
|
+
# >> Provides field, for which only = is allowed
|
846
|
+
if m["relation"] == "=" || m["relation"] == nil
|
847
|
+
return true
|
848
|
+
end
|
849
|
+
return false
|
850
|
+
end
|
851
|
+
|
852
|
+
def valid_relationship_field?(text)
|
853
|
+
m = RELATIONSHIP_FIELD_PATTERN.match(text)
|
854
|
+
if m.nil?
|
855
|
+
logger.error("Invalid relationship field for debian package: #{text}")
|
856
|
+
return false
|
857
|
+
end
|
858
|
+
return true
|
859
|
+
end
|
860
|
+
|
651
861
|
def fix_provides(provides)
|
652
862
|
name_re = /^[^ \(]+/
|
653
863
|
name = provides[name_re]
|
@@ -662,6 +872,11 @@ class FPM::Package::Deb < FPM::Package
|
|
662
872
|
"debs don't like underscores")
|
663
873
|
provides = provides.gsub("_", "-")
|
664
874
|
end
|
875
|
+
|
876
|
+
if m = provides.match(/^([A-Za-z0-9_-]+)\s*=\s*(\d+.*$)/)
|
877
|
+
logger.warn("Replacing 'provides' entry #{provides} with syntax 'name (= version)'")
|
878
|
+
provides = "#{m[1]} (= #{m[2]})"
|
879
|
+
end
|
665
880
|
return provides.rstrip
|
666
881
|
end
|
667
882
|
|
@@ -687,12 +902,34 @@ class FPM::Package::Deb < FPM::Package
|
|
687
902
|
write_triggers # write trigger config to 'triggers' file
|
688
903
|
write_md5sums # write the md5sums file
|
689
904
|
|
905
|
+
# Tar up the staging_path into control.tar.{compression type}
|
906
|
+
case self.attributes[:deb_compression]
|
907
|
+
when "gz", "bzip2", nil
|
908
|
+
controltar = "control.tar.gz"
|
909
|
+
compression = "-z"
|
910
|
+
when "xz"
|
911
|
+
controltar = "control.tar.xz"
|
912
|
+
compression = "-J"
|
913
|
+
when "none"
|
914
|
+
controltar = "control.tar"
|
915
|
+
compression = ""
|
916
|
+
else
|
917
|
+
raise FPM::InvalidPackageConfiguration,
|
918
|
+
"Unknown compression type '#{self.attributes[:deb_compression]}'"
|
919
|
+
end
|
920
|
+
|
690
921
|
# Make the control.tar.gz
|
691
|
-
build_path(
|
922
|
+
build_path(controltar).tap do |controltar|
|
692
923
|
logger.info("Creating", :path => controltar, :from => control_path)
|
693
924
|
|
694
|
-
args = [ tar_cmd, "-C", control_path, "-
|
925
|
+
args = [ tar_cmd, "-C", control_path, compression, "-cf", controltar,
|
695
926
|
"--owner=0", "--group=0", "--numeric-owner", "." ]
|
927
|
+
if tar_cmd_supports_sort_names_and_set_mtime? and not attributes[:source_date_epoch].nil?
|
928
|
+
# Force deterministic file order and timestamp
|
929
|
+
args += ["--sort=name", ("--mtime=@%s" % attributes[:source_date_epoch])]
|
930
|
+
# gnu tar obeys GZIP environment variable with options for gzip; -n = forget original filename and date
|
931
|
+
args.unshift({"GZIP" => "-9n"})
|
932
|
+
end
|
696
933
|
safesystem(*args)
|
697
934
|
end
|
698
935
|
|
@@ -774,7 +1011,7 @@ class FPM::Package::Deb < FPM::Package
|
|
774
1011
|
etcfiles = []
|
775
1012
|
# Add everything in /etc
|
776
1013
|
begin
|
777
|
-
if !attributes[:deb_no_default_config_files?]
|
1014
|
+
if !attributes[:deb_no_default_config_files?] && File.exists?(staging_path("/etc"))
|
778
1015
|
logger.warn("Debian packaging tools generally labels all files in /etc as config files, " \
|
779
1016
|
"as mandated by policy, so fpm defaults to this behavior for deb packages. " \
|
780
1017
|
"You can disable this default behavior with --deb-no-default-config-files flag")
|
@@ -789,11 +1026,25 @@ class FPM::Package::Deb < FPM::Package
|
|
789
1026
|
|
790
1027
|
# scan all conf file paths for files and add them
|
791
1028
|
config_files.each do |path|
|
1029
|
+
logger.debug("Checking if #{path} exists")
|
1030
|
+
cfe = File.exist?("#{path}")
|
1031
|
+
logger.debug("Check result #{cfe}")
|
792
1032
|
begin
|
793
1033
|
add_path(path, allconfigs)
|
794
1034
|
rescue Errno::ENOENT
|
795
|
-
|
796
|
-
|
1035
|
+
if !cfe
|
1036
|
+
raise FPM::InvalidPackageConfiguration,
|
1037
|
+
"Error trying to use '#{path}' as a config file in the package. Does it exist?"
|
1038
|
+
else
|
1039
|
+
dcl = File.join(staging_path, path)
|
1040
|
+
if !File.exist?("#{dcl}")
|
1041
|
+
logger.debug("Adding config file #{path} to Staging area #{staging_path}")
|
1042
|
+
FileUtils.mkdir_p(File.dirname(dcl))
|
1043
|
+
FileUtils.cp_r path, dcl
|
1044
|
+
else
|
1045
|
+
logger.debug("Config file aready exists in staging area.")
|
1046
|
+
end
|
1047
|
+
end
|
797
1048
|
end
|
798
1049
|
end
|
799
1050
|
|
@@ -849,7 +1100,7 @@ class FPM::Package::Deb < FPM::Package
|
|
849
1100
|
|
850
1101
|
if attributes[:deb_templates]
|
851
1102
|
FileUtils.cp(attributes[:deb_templates], control_path("templates"))
|
852
|
-
File.chmod(
|
1103
|
+
File.chmod(0644, control_path("templates"))
|
853
1104
|
end
|
854
1105
|
end # def write_debconf
|
855
1106
|
|
@@ -865,7 +1116,10 @@ class FPM::Package::Deb < FPM::Package
|
|
865
1116
|
|
866
1117
|
def write_triggers
|
867
1118
|
lines = [['interest', :deb_interest],
|
868
|
-
['activate', :deb_activate]
|
1119
|
+
['activate', :deb_activate],
|
1120
|
+
['interest-noawait', :deb_interest_noawait],
|
1121
|
+
['activate-noawait', :deb_activate_noawait],
|
1122
|
+
].map { |label, attr|
|
869
1123
|
(attributes[attr] || []).map { |e| "#{label} #{e}\n" }
|
870
1124
|
}.flatten.join('')
|
871
1125
|
|
data/lib/fpm/package/dir.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require "fpm/package"
|
2
2
|
require "fpm/util"
|
3
|
-
require "backports"
|
3
|
+
require "backports/latest"
|
4
4
|
require "fileutils"
|
5
5
|
require "find"
|
6
6
|
require "socket"
|
@@ -83,8 +83,8 @@ class FPM::Package::Dir < FPM::Package
|
|
83
83
|
# can include license data from themselves (rpms, gems, etc),
|
84
84
|
# but to make sure a simple dir -> rpm works without having
|
85
85
|
# to specify a license.
|
86
|
-
self.license
|
87
|
-
self.vendor
|
86
|
+
self.license ||= "unknown"
|
87
|
+
self.vendor ||= [ENV["USER"], Socket.gethostname].join("@")
|
88
88
|
ensure
|
89
89
|
# Clean up any logger context we added.
|
90
90
|
logger.remove("method")
|
@@ -101,18 +101,7 @@ class FPM::Package::Dir < FPM::Package
|
|
101
101
|
end
|
102
102
|
|
103
103
|
# Write the scripts, too.
|
104
|
-
|
105
|
-
::Dir.mkdir(scripts_path)
|
106
|
-
[:before_install, :after_install, :before_remove, :after_remove].each do |name|
|
107
|
-
next unless script?(name)
|
108
|
-
out = File.join(scripts_path, name.to_s)
|
109
|
-
logger.debug("Writing script", :source => name, :target => out)
|
110
|
-
File.write(out, script(name))
|
111
|
-
require "pry"
|
112
|
-
binding.pry
|
113
|
-
File.chmod(0755, out)
|
114
|
-
end
|
115
|
-
|
104
|
+
write_scripts
|
116
105
|
ensure
|
117
106
|
logger.remove("method")
|
118
107
|
end # def output
|
@@ -147,14 +136,20 @@ class FPM::Package::Dir < FPM::Package
|
|
147
136
|
|
148
137
|
# For single file copies, permit file destinations
|
149
138
|
fileinfo = File.lstat(source)
|
150
|
-
|
139
|
+
destination_is_directory = File.directory?(destination)
|
140
|
+
if fileinfo.file? && !destination_is_directory
|
151
141
|
if destination[-1,1] == "/"
|
152
142
|
copy(source, File.join(destination, source))
|
153
143
|
else
|
154
144
|
copy(source, destination)
|
155
145
|
end
|
156
146
|
elsif fileinfo.symlink?
|
157
|
-
|
147
|
+
# Treat them same as files
|
148
|
+
if destination[-1,1] == "/"
|
149
|
+
copy(source, File.join(destination, source))
|
150
|
+
else
|
151
|
+
copy(source, destination)
|
152
|
+
end
|
158
153
|
else
|
159
154
|
# Copy all files from 'path' into staging_path
|
160
155
|
Find.find(source) do |path|
|
data/lib/fpm/package/empty.rb
CHANGED
@@ -1,9 +1,21 @@
|
|
1
1
|
require "fpm/package"
|
2
|
-
require "backports"
|
2
|
+
require "backports/latest"
|
3
3
|
|
4
4
|
# Empty Package type. For strict/meta/virtual package creation
|
5
5
|
|
6
6
|
class FPM::Package::Empty < FPM::Package
|
7
|
+
def initialize(*args)
|
8
|
+
super(*args)
|
9
|
+
|
10
|
+
# Override FPM::Package's default "native" architecture value
|
11
|
+
# This feels like the right default because an empty package has no
|
12
|
+
# architecture-specific files, and in most cases an empty package should be
|
13
|
+
# installable anywhere.
|
14
|
+
#
|
15
|
+
# https://github.com/jordansissel/fpm/issues/1846
|
16
|
+
@architecture = "all"
|
17
|
+
end
|
18
|
+
|
7
19
|
def output(output_path)
|
8
20
|
logger.warn("Your package has gone into the void.")
|
9
21
|
end
|