fpm-aeppert 1.6.2 → 1.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.rst +617 -0
- data/CONTRIBUTORS +1 -0
- data/LICENSE +1 -1
- data/bin/fpm +0 -1
- data/lib/fpm.rb +1 -0
- data/lib/fpm/command.rb +26 -12
- data/lib/fpm/package.rb +24 -4
- data/lib/fpm/package/apk.rb +6 -6
- data/lib/fpm/package/cpan.rb +57 -29
- data/lib/fpm/package/deb.rb +177 -40
- data/lib/fpm/package/dir.rb +12 -17
- data/lib/fpm/package/empty.rb +1 -1
- data/lib/fpm/package/freebsd.rb +25 -14
- data/lib/fpm/package/gem.rb +148 -13
- data/lib/fpm/package/pacman.rb +1 -1
- data/lib/fpm/package/pleaserun.rb +13 -1
- data/lib/fpm/package/pyfpm/get_metadata.py +5 -0
- data/lib/fpm/package/python.rb +13 -2
- data/lib/fpm/package/rpm.rb +43 -7
- 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 +53 -12
- data/lib/fpm/package/zip.rb +6 -22
- data/lib/fpm/util.rb +88 -18
- data/lib/fpm/util/tar_writer.rb +2 -0
- data/lib/fpm/version.rb +1 -1
- data/templates/deb.erb +1 -1
- data/templates/deb/changelog.erb +1 -1
- data/templates/deb/deb.changes.erb +30 -0
- data/templates/deb/postinst_upgrade.sh.erb +24 -8
- data/templates/deb/postrm_upgrade.sh.erb +12 -5
- data/templates/deb/prerm_upgrade.sh.erb +7 -4
- data/templates/rpm.erb +12 -9
- metadata +84 -76
- data/CHANGELIST +0 -661
data/lib/fpm/package/rpm.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require "fpm/package"
|
2
|
-
require "backports"
|
2
|
+
require "backports/latest"
|
3
3
|
require "fileutils"
|
4
4
|
require "find"
|
5
5
|
require "arr-pm/file" # gem 'arr-pm'
|
@@ -24,9 +24,10 @@ class FPM::Package::RPM < FPM::Package
|
|
24
24
|
|
25
25
|
COMPRESSION_MAP = {
|
26
26
|
"none" => "w0.gzdio",
|
27
|
-
"xz" => "
|
28
|
-
"
|
29
|
-
"
|
27
|
+
"xz" => ".xzdio",
|
28
|
+
"xzmt" => "T.xzdio",
|
29
|
+
"gzip" => ".gzdio",
|
30
|
+
"bzip2" => ".bzdio"
|
30
31
|
} unless defined?(COMPRESSION_MAP)
|
31
32
|
|
32
33
|
option "--use-file-permissions", :flag,
|
@@ -67,6 +68,15 @@ class FPM::Package::RPM < FPM::Package
|
|
67
68
|
value.downcase
|
68
69
|
end
|
69
70
|
|
71
|
+
option "--compression-level", "[0-9]", "Select a compression level. 0 is store-only. 9 is max compression.",
|
72
|
+
:default => "9" do |value|
|
73
|
+
valint = value.to_i
|
74
|
+
unless value =~ /^\d$/ && valint >= 0 && valint <= 9
|
75
|
+
raise "Invalid compression level '#{value}'. Valid values are integers between 0 and 9 inclusive."
|
76
|
+
end
|
77
|
+
valint
|
78
|
+
end
|
79
|
+
|
70
80
|
option "--compression", COMPRESSION_MAP.keys.join("|"),
|
71
81
|
"Select a compression method. gzip works on the most platforms.",
|
72
82
|
:default => "gzip" do |value|
|
@@ -141,6 +151,10 @@ class FPM::Package::RPM < FPM::Package
|
|
141
151
|
"names in rpm requires instead of the redhat style " \
|
142
152
|
"rubygem(foo).", :default => false
|
143
153
|
|
154
|
+
option "--macro-expansion", :flag,
|
155
|
+
"install-time macro expansion in %pre %post %preun %postun scripts " \
|
156
|
+
"(see: https://rpm.org/user_doc/scriptlet_expansion.html)", :default => false
|
157
|
+
|
144
158
|
option "--verifyscript", "FILE",
|
145
159
|
"a script to be run on verification" do |val|
|
146
160
|
File.expand_path(val) # Get the full path to the script
|
@@ -472,6 +486,22 @@ class FPM::Package::RPM < FPM::Package
|
|
472
486
|
self.directories = alldirs
|
473
487
|
end
|
474
488
|
|
489
|
+
# include external config files
|
490
|
+
(attributes[:config_files] or []).each do |conf|
|
491
|
+
dest_conf = File.join(staging_path, conf)
|
492
|
+
|
493
|
+
if File.exist?(dest_conf)
|
494
|
+
logger.debug("Using --config-file from staging area", :path => conf)
|
495
|
+
elsif File.exist?(conf)
|
496
|
+
logger.info("Copying --config-file from local path", :path => conf)
|
497
|
+
FileUtils.mkdir_p(File.dirname(dest_conf))
|
498
|
+
FileUtils.cp_r conf, dest_conf
|
499
|
+
else
|
500
|
+
logger.error("Failed to find given --config-file", :path => conf)
|
501
|
+
raise "Could not find config file '#{conf}' in staging area or on host. This can happen if you specify `--config-file '#{conf}'` but this file does not exist in the source package and also does not exist in filesystem."
|
502
|
+
end
|
503
|
+
end
|
504
|
+
|
475
505
|
# scan all conf file paths for files and add them
|
476
506
|
allconfigs = []
|
477
507
|
self.config_files.each do |path|
|
@@ -499,10 +529,11 @@ class FPM::Package::RPM < FPM::Package
|
|
499
529
|
end
|
500
530
|
|
501
531
|
# copy all files from staging to BUILD dir
|
532
|
+
# [#1538] Be sure to preserve the original timestamps.
|
502
533
|
Find.find(staging_path) do |path|
|
503
534
|
src = path.gsub(/^#{staging_path}/, '')
|
504
535
|
dst = File.join(build_path, build_sub_dir, src)
|
505
|
-
copy_entry(path, dst)
|
536
|
+
copy_entry(path, dst, preserve=true)
|
506
537
|
end
|
507
538
|
|
508
539
|
rpmspec = template("rpm.erb").result(binding)
|
@@ -537,7 +568,7 @@ class FPM::Package::RPM < FPM::Package
|
|
537
568
|
|
538
569
|
def summary
|
539
570
|
if !attributes[:rpm_summary]
|
540
|
-
return @description.split("\n").
|
571
|
+
return @description.split("\n").find { |line| !line.strip.empty? } || "_"
|
541
572
|
end
|
542
573
|
|
543
574
|
return attributes[:rpm_summary]
|
@@ -580,7 +611,12 @@ class FPM::Package::RPM < FPM::Package
|
|
580
611
|
end # def to_s
|
581
612
|
|
582
613
|
def payload_compression
|
583
|
-
|
614
|
+
if attributes[:rpm_compression] == 'none'
|
615
|
+
# when 'none' ignore any compression level and return w0.gzdio
|
616
|
+
return COMPRESSION_MAP[attributes[:rpm_compression]]
|
617
|
+
else
|
618
|
+
return "w#{attributes[:rpm_compression_level]}" + COMPRESSION_MAP[attributes[:rpm_compression]]
|
619
|
+
end
|
584
620
|
end # def payload_compression
|
585
621
|
|
586
622
|
def digest_algorithm
|
data/lib/fpm/package/sh.rb
CHANGED
@@ -0,0 +1,130 @@
|
|
1
|
+
require "yaml"
|
2
|
+
|
3
|
+
require "fpm/package"
|
4
|
+
require "fpm/util"
|
5
|
+
require "fileutils"
|
6
|
+
require "fpm/package/dir"
|
7
|
+
|
8
|
+
# Support for snaps (.snap files).
|
9
|
+
#
|
10
|
+
# This supports the input and output of snaps.
|
11
|
+
class FPM::Package::Snap < FPM::Package
|
12
|
+
|
13
|
+
option "--yaml", "FILEPATH",
|
14
|
+
"Custom version of the snap.yaml file." do | snap_yaml |
|
15
|
+
File.expand_path(snap_yaml)
|
16
|
+
end
|
17
|
+
|
18
|
+
option "--confinement", "CONFINEMENT",
|
19
|
+
"Type of confinement to use for this snap.",
|
20
|
+
default: "devmode" do | confinement |
|
21
|
+
if ['strict', 'devmode', 'classic'].include? confinement
|
22
|
+
confinement
|
23
|
+
else
|
24
|
+
raise "Unsupported confinement type '#{confinement}'"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
option "--grade", "GRADE", "Grade of this snap.",
|
29
|
+
default: "devel" do | grade |
|
30
|
+
if ['stable', 'devel'].include? grade
|
31
|
+
grade
|
32
|
+
else
|
33
|
+
raise "Unsupported grade type '#{grade}'"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Input a snap
|
38
|
+
def input(input_snap)
|
39
|
+
extract_snap_to_staging input_snap
|
40
|
+
extract_snap_metadata_from_staging
|
41
|
+
end # def input
|
42
|
+
|
43
|
+
# Output a snap.
|
44
|
+
def output(output_snap)
|
45
|
+
output_check(output_snap)
|
46
|
+
|
47
|
+
write_snap_yaml
|
48
|
+
|
49
|
+
# Create the snap from the staging path
|
50
|
+
safesystem("mksquashfs", staging_path, output_snap, "-noappend", "-comp",
|
51
|
+
"xz", "-no-xattrs", "-no-fragments", "-all-root")
|
52
|
+
end # def output
|
53
|
+
|
54
|
+
def to_s(format=nil)
|
55
|
+
# Default format if nil
|
56
|
+
# name_version_arch.snap
|
57
|
+
return super(format.nil? ? "NAME_FULLVERSION_ARCH.EXTENSION" : format)
|
58
|
+
end # def to_s
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def extract_snap_to_staging(snap_path)
|
63
|
+
safesystem("unsquashfs", "-f", "-d", staging_path, snap_path)
|
64
|
+
end
|
65
|
+
|
66
|
+
def extract_snap_metadata_from_staging
|
67
|
+
metadata = YAML.safe_load(File.read(
|
68
|
+
staging_path(File.join("meta", "snap.yaml"))))
|
69
|
+
|
70
|
+
self.name = metadata["name"]
|
71
|
+
self.version = metadata["version"]
|
72
|
+
self.description = metadata["summary"] + "\n" + metadata["description"]
|
73
|
+
self.architecture = metadata["architectures"][0]
|
74
|
+
self.attributes[:snap_confinement] = metadata["confinement"]
|
75
|
+
self.attributes[:snap_grade] = metadata["grade"]
|
76
|
+
|
77
|
+
if metadata["apps"].nil?
|
78
|
+
attributes[:snap_apps] = []
|
79
|
+
else
|
80
|
+
attributes[:snap_apps] = metadata["apps"]
|
81
|
+
end
|
82
|
+
|
83
|
+
if metadata["hooks"].nil?
|
84
|
+
attributes[:snap_hooks] = []
|
85
|
+
else
|
86
|
+
attributes[:snap_hooks] = metadata["hooks"]
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def write_snap_yaml
|
91
|
+
# Write the snap.yaml
|
92
|
+
if attributes[:snap_yaml]
|
93
|
+
logger.debug("Using '#{attributes[:snap_yaml]}' as the snap.yaml")
|
94
|
+
yaml_data = File.read(attributes[:snap_yaml])
|
95
|
+
else
|
96
|
+
summary, *remainder = (self.description or "no summary given").split("\n")
|
97
|
+
description = "no description given"
|
98
|
+
if remainder.any?
|
99
|
+
description = remainder.join("\n")
|
100
|
+
end
|
101
|
+
|
102
|
+
yaml_data = {
|
103
|
+
"name" => self.name,
|
104
|
+
"version" => self.version,
|
105
|
+
"summary" => summary,
|
106
|
+
"description" => description,
|
107
|
+
"architectures" => [self.architecture],
|
108
|
+
"confinement" => self.attributes[:snap_confinement],
|
109
|
+
"grade" => self.attributes[:snap_grade],
|
110
|
+
}
|
111
|
+
|
112
|
+
unless attributes[:snap_apps].nil? or attributes[:snap_apps].empty?
|
113
|
+
yaml_data["apps"] = attributes[:snap_apps]
|
114
|
+
end
|
115
|
+
|
116
|
+
unless attributes[:snap_hooks].nil? or attributes[:snap_hooks].empty?
|
117
|
+
yaml_data["hooks"] = attributes[:snap_hooks]
|
118
|
+
end
|
119
|
+
|
120
|
+
yaml_data = yaml_data.to_yaml
|
121
|
+
end
|
122
|
+
|
123
|
+
FileUtils.mkdir_p(staging_path("meta"))
|
124
|
+
snap_yaml_path = staging_path(File.join("meta", "snap.yaml"))
|
125
|
+
logger.debug("Writing snap.yaml", :path => snap_yaml_path)
|
126
|
+
File.write(snap_yaml_path, yaml_data)
|
127
|
+
File.chmod(0644, snap_yaml_path)
|
128
|
+
edit_file(snap_yaml_path) if attributes[:edit?]
|
129
|
+
end # def write_snap_yaml
|
130
|
+
end # class FPM::Package::Snap
|
data/lib/fpm/package/tar.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require "backports" # gem backports
|
1
|
+
require "backports/latest" # gem backports
|
2
2
|
require "fpm/package"
|
3
3
|
require "fpm/util"
|
4
4
|
require "fileutils"
|
@@ -50,15 +50,7 @@ class FPM::Package::Tar < FPM::Package
|
|
50
50
|
output_check(output_path)
|
51
51
|
|
52
52
|
# Write the scripts, too.
|
53
|
-
|
54
|
-
::Dir.mkdir(scripts_path)
|
55
|
-
[:before_install, :after_install, :before_remove, :after_remove].each do |name|
|
56
|
-
next unless script?(name)
|
57
|
-
out = File.join(scripts_path, name.to_s)
|
58
|
-
logger.debug("Writing script", :source => name, :target => out)
|
59
|
-
File.write(out, script(name))
|
60
|
-
File.chmod(0755, out)
|
61
|
-
end
|
53
|
+
write_scripts
|
62
54
|
|
63
55
|
# Unpack the tarball to the staging path
|
64
56
|
args = ["-cf", output_path, "-C", staging_path]
|
@@ -15,8 +15,11 @@ class FPM::Package::Virtualenv < FPM::Package
|
|
15
15
|
option "--package-name-prefix", "PREFIX", "Name to prefix the package " \
|
16
16
|
"name with.", :default => "virtualenv"
|
17
17
|
|
18
|
-
option "--install-location", "DIRECTORY", "
|
19
|
-
|
18
|
+
option "--install-location", "DIRECTORY", "DEPRECATED: Use --prefix instead." \
|
19
|
+
" Location to which to install the virtualenv by default.",
|
20
|
+
:default => "/usr/share/python" do |path|
|
21
|
+
logger.warn("Using deprecated flag: --install-location. Please use " \
|
22
|
+
"--prefix instead.")
|
20
23
|
File.expand_path(path)
|
21
24
|
end
|
22
25
|
|
@@ -30,6 +33,19 @@ class FPM::Package::Virtualenv < FPM::Package
|
|
30
33
|
:multivalued => true, :attribute_name => :virtualenv_pypi_extra_index_urls,
|
31
34
|
:default => nil
|
32
35
|
|
36
|
+
option "--setup-install", :flag, "After building virtualenv run setup.py install "\
|
37
|
+
"useful when building a virtualenv for packages and including their requirements from "
|
38
|
+
"requirements.txt"
|
39
|
+
|
40
|
+
option "--system-site-packages", :flag, "Give the virtual environment access to the "\
|
41
|
+
"global site-packages"
|
42
|
+
|
43
|
+
option "--find-links", "PIP_FIND_LINKS", "If a url or path to an html file, then parse for "\
|
44
|
+
"links to archives. If a local path or file:// url that's a directory, then look "\
|
45
|
+
"for archives in the directory listing.",
|
46
|
+
:multivalued => true, :attribute_name => :virtualenv_find_links_urls,
|
47
|
+
:default => nil
|
48
|
+
|
33
49
|
private
|
34
50
|
|
35
51
|
# Input a package.
|
@@ -69,23 +85,33 @@ class FPM::Package::Virtualenv < FPM::Package
|
|
69
85
|
self.name].join("-")
|
70
86
|
end
|
71
87
|
|
88
|
+
# prefix wins over previous virtual_install_location behaviour
|
72
89
|
virtualenv_folder =
|
73
|
-
|
74
|
-
|
90
|
+
if self.attributes[:prefix]
|
91
|
+
self.attributes[:prefix]
|
92
|
+
else
|
93
|
+
File.join(installdir,
|
94
|
+
virtualenv_name)
|
95
|
+
end
|
75
96
|
|
76
97
|
virtualenv_build_folder = build_path(virtualenv_folder)
|
77
98
|
|
78
99
|
::FileUtils.mkdir_p(virtualenv_build_folder)
|
79
100
|
|
80
|
-
|
101
|
+
if self.attributes[:virtualenv_system_site_packages?]
|
102
|
+
logger.info("Creating virtualenv with --system-site-packages")
|
103
|
+
safesystem("virtualenv", "--system-site-packages", virtualenv_build_folder)
|
104
|
+
else
|
105
|
+
safesystem("virtualenv", virtualenv_build_folder)
|
106
|
+
end
|
107
|
+
|
81
108
|
pip_exe = File.join(virtualenv_build_folder, "bin", "pip")
|
82
109
|
python_exe = File.join(virtualenv_build_folder, "bin", "python")
|
83
110
|
|
84
111
|
# Why is this hack here? It looks important, so I'll keep it in.
|
85
|
-
safesystem(pip_exe, "install", "-U", "-i",
|
112
|
+
safesystem(python_exe, pip_exe, "install", "-U", "-i",
|
86
113
|
attributes[:virtualenv_pypi],
|
87
|
-
"pip"
|
88
|
-
safesystem(pip_exe, "uninstall", "-y", "distribute")
|
114
|
+
"pip")
|
89
115
|
|
90
116
|
extra_index_url_args = []
|
91
117
|
if attributes[:virtualenv_pypi_extra_index_urls]
|
@@ -94,6 +120,13 @@ class FPM::Package::Virtualenv < FPM::Package
|
|
94
120
|
end
|
95
121
|
end
|
96
122
|
|
123
|
+
find_links_url_args = []
|
124
|
+
if attributes[:virtualenv_find_links_urls]
|
125
|
+
attributes[:virtualenv_find_links_urls].each do |links_url|
|
126
|
+
find_links_url_args << "--find-links" << links_url
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
97
130
|
target_args = []
|
98
131
|
if is_requirements_file
|
99
132
|
target_args << "-r" << package
|
@@ -101,12 +134,19 @@ class FPM::Package::Virtualenv < FPM::Package
|
|
101
134
|
target_args << package
|
102
135
|
end
|
103
136
|
|
104
|
-
pip_args = [pip_exe, "install", "-i", attributes[:virtualenv_pypi]] << extra_index_url_args << target_args
|
137
|
+
pip_args = [python_exe, pip_exe, "install", "-i", attributes[:virtualenv_pypi]] << extra_index_url_args << find_links_url_args << target_args
|
105
138
|
safesystem(*pip_args.flatten)
|
106
139
|
|
140
|
+
if attributes[:virtualenv_setup_install?]
|
141
|
+
logger.info("Running PACKAGE setup.py")
|
142
|
+
setup_args = [python_exe, "setup.py", "install"]
|
143
|
+
safesystem(*setup_args.flatten)
|
144
|
+
end
|
145
|
+
|
107
146
|
if ! is_requirements_file && package_version.nil?
|
108
|
-
frozen = safesystemout(pip_exe, "freeze")
|
109
|
-
|
147
|
+
frozen = safesystemout(python_exe, pip_exe, "freeze")
|
148
|
+
frozen_version = frozen[/#{package}==[^=]+$/]
|
149
|
+
package_version = frozen_version && frozen_version.split("==")[1].chomp!
|
110
150
|
self.version ||= package_version
|
111
151
|
end
|
112
152
|
|
@@ -135,7 +175,8 @@ class FPM::Package::Virtualenv < FPM::Package
|
|
135
175
|
# use dir to set stuff up properly, mainly so I don't have to reimplement
|
136
176
|
# the chdir/prefix stuff special for tar.
|
137
177
|
dir = convert(FPM::Package::Dir)
|
138
|
-
|
178
|
+
# don't double prefix the files
|
179
|
+
dir.attributes[:prefix] = nil
|
139
180
|
if attributes[:chdir]
|
140
181
|
dir.attributes[:chdir] = File.join(build_path, attributes[:chdir])
|
141
182
|
else
|
data/lib/fpm/package/zip.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require "backports" # gem backports
|
1
|
+
require "backports/latest" # gem backports
|
2
2
|
require "fpm/package"
|
3
3
|
require "fpm/util"
|
4
4
|
require "fileutils"
|
@@ -36,28 +36,12 @@ class FPM::Package::Zip < FPM::Package
|
|
36
36
|
dir.cleanup_build
|
37
37
|
end # def input
|
38
38
|
|
39
|
-
# Output a
|
40
|
-
#
|
41
|
-
# If the output path ends predictably (like in .tar.gz) it will try to obey
|
42
|
-
# the compression type.
|
39
|
+
# Output a zipfile.
|
43
40
|
def output(output_path)
|
44
41
|
output_check(output_path)
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
end # def output
|
49
|
-
|
50
|
-
# Generate the proper tar flags based on the path name.
|
51
|
-
def tar_compression_flag(path)
|
52
|
-
case path
|
53
|
-
when /\.tar\.bz2$/
|
54
|
-
return "-j"
|
55
|
-
when /\.tar\.gz$|\.tgz$/
|
56
|
-
return "-z"
|
57
|
-
when /\.tar\.xz$/
|
58
|
-
return "-J"
|
59
|
-
else
|
60
|
-
return nil
|
42
|
+
realpath = Pathname.new(output_path).realdirpath.to_s
|
43
|
+
::Dir.chdir(staging_path) do
|
44
|
+
safesystem("zip", "-9r", realpath, ".")
|
61
45
|
end
|
62
|
-
end # def
|
46
|
+
end # def output
|
63
47
|
end # class FPM::Package::Tar
|
data/lib/fpm/util.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require "fpm/namespace"
|
2
2
|
require "childprocess"
|
3
3
|
require "ffi"
|
4
|
+
require "fileutils"
|
4
5
|
|
5
6
|
# Some utility functions
|
6
7
|
module FPM::Util
|
@@ -190,9 +191,14 @@ module FPM::Util
|
|
190
191
|
if args.size == 1
|
191
192
|
args = [ default_shell, "-c", args[0] ]
|
192
193
|
end
|
193
|
-
program = args[0]
|
194
194
|
|
195
|
-
|
195
|
+
if args[0].kind_of?(Hash)
|
196
|
+
env = args.shift()
|
197
|
+
exit_code = execmd(env, args)
|
198
|
+
else
|
199
|
+
exit_code = execmd(args)
|
200
|
+
end
|
201
|
+
program = args[0]
|
196
202
|
success = (exit_code == 0)
|
197
203
|
|
198
204
|
if !success
|
@@ -226,26 +232,90 @@ module FPM::Util
|
|
226
232
|
return stdout_r_str
|
227
233
|
end # def safesystemout
|
228
234
|
|
235
|
+
# Get an array containing the recommended 'ar' command for this platform
|
236
|
+
# and the recommended options to quickly create/append to an archive
|
237
|
+
# without timestamps or uids (if possible).
|
238
|
+
def ar_cmd
|
239
|
+
return @@ar_cmd if defined? @@ar_cmd
|
240
|
+
|
241
|
+
@@ar_cmd_deterministic = false
|
242
|
+
|
243
|
+
# FIXME: don't assume current directory writeable
|
244
|
+
FileUtils.touch(["fpm-dummy.tmp"])
|
245
|
+
["ar", "gar"].each do |ar|
|
246
|
+
["-qc", "-qcD"].each do |ar_create_opts|
|
247
|
+
FileUtils.rm_f(["fpm-dummy.ar.tmp"])
|
248
|
+
# Return this combination if it creates archives without uids or timestamps.
|
249
|
+
# Exitstatus will be nonzero if the archive can't be created,
|
250
|
+
# or its table of contents doesn't match the regular expression.
|
251
|
+
# Be extra-careful about locale and timezone when matching output.
|
252
|
+
system("#{ar} #{ar_create_opts} fpm-dummy.ar.tmp fpm-dummy.tmp 2>/dev/null && env TZ=UTC LANG=C LC_TIME=C #{ar} -tv fpm-dummy.ar.tmp | grep '0/0.*1970' > /dev/null 2>&1")
|
253
|
+
if $?.exitstatus == 0
|
254
|
+
@@ar_cmd = [ar, ar_create_opts]
|
255
|
+
@@ar_cmd_deterministic = true
|
256
|
+
return @@ar_cmd
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
# If no combination of ar and options omits timestamps, fall back to default.
|
261
|
+
@@ar_cmd = ["ar", "-qc"]
|
262
|
+
return @@ar_cmd
|
263
|
+
ensure
|
264
|
+
# Clean up
|
265
|
+
FileUtils.rm_f(["fpm-dummy.ar.tmp", "fpm-dummy.tmp"])
|
266
|
+
end # def ar_cmd
|
267
|
+
|
268
|
+
# Return whether the command returned by ar_cmd can create deterministic archives
|
269
|
+
def ar_cmd_deterministic?
|
270
|
+
ar_cmd if not defined? @@ar_cmd_deterministic
|
271
|
+
return @@ar_cmd_deterministic
|
272
|
+
end
|
273
|
+
|
229
274
|
# Get the recommended 'tar' command for this platform.
|
230
275
|
def tar_cmd
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
276
|
+
return @@tar_cmd if defined? @@tar_cmd
|
277
|
+
|
278
|
+
# FIXME: don't assume current directory writeable
|
279
|
+
FileUtils.touch(["fpm-dummy.tmp"])
|
280
|
+
|
281
|
+
# Prefer tar that supports more of the features we want, stop if we find tar of our dreams
|
282
|
+
best="tar"
|
283
|
+
bestscore=0
|
284
|
+
@@tar_cmd_deterministic = false
|
285
|
+
# GNU Tar, if not the default, is usually on the path as gtar, but
|
286
|
+
# Mac OS X 10.8 and earlier shipped it as /usr/bin/gnutar
|
287
|
+
["tar", "gtar", "gnutar"].each do |tar|
|
288
|
+
opts=[]
|
289
|
+
score=0
|
290
|
+
["--sort=name", "--mtime=@0"].each do |opt|
|
291
|
+
system("#{tar} #{opt} -cf fpm-dummy.tar.tmp fpm-dummy.tmp > /dev/null 2>&1")
|
292
|
+
if $?.exitstatus == 0
|
293
|
+
opts << opt
|
294
|
+
score += 1
|
295
|
+
end
|
296
|
+
end
|
297
|
+
if score > bestscore
|
298
|
+
best=tar
|
299
|
+
bestscore=score
|
300
|
+
if score == 2
|
301
|
+
@@tar_cmd_deterministic = true
|
302
|
+
break
|
303
|
+
end
|
240
304
|
end
|
241
|
-
when "FreeBSD"
|
242
|
-
# use gnutar instead
|
243
|
-
return "gtar"
|
244
|
-
else
|
245
|
-
return "tar"
|
246
305
|
end
|
306
|
+
@@tar_cmd = best
|
307
|
+
return @@tar_cmd
|
308
|
+
ensure
|
309
|
+
# Clean up
|
310
|
+
FileUtils.rm_f(["fpm-dummy.tar.tmp", "fpm-dummy.tmp"])
|
247
311
|
end # def tar_cmd
|
248
312
|
|
313
|
+
# Return whether the command returned by tar_cmd can create deterministic archives
|
314
|
+
def tar_cmd_supports_sort_names_and_set_mtime?
|
315
|
+
tar_cmd if not defined? @@tar_cmd_deterministic
|
316
|
+
return @@tar_cmd_deterministic
|
317
|
+
end
|
318
|
+
|
249
319
|
# wrapper around mknod ffi calls
|
250
320
|
def mknod_w(path, mode, dev)
|
251
321
|
rc = -1
|
@@ -298,8 +368,8 @@ module FPM::Util
|
|
298
368
|
if known_entry
|
299
369
|
FileUtils.ln(known_entry, dst)
|
300
370
|
else
|
301
|
-
FileUtils.copy_entry(src, dst, preserve
|
302
|
-
remove_destination
|
371
|
+
FileUtils.copy_entry(src, dst, preserve, false,
|
372
|
+
remove_destination)
|
303
373
|
copied_entries[[st.dev, st.ino]] = dst
|
304
374
|
end
|
305
375
|
end # else...
|