fpm 1.6.1 → 1.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/freebsd.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require "backports" # gem backports
|
1
|
+
require "backports/latest" # gem backports/latest
|
2
2
|
require "fpm/package"
|
3
3
|
require "fpm/util"
|
4
4
|
require "digest"
|
@@ -12,27 +12,11 @@ class FPM::Package::FreeBSD < FPM::Package
|
|
12
12
|
:after_remove => "post-deinstall",
|
13
13
|
} unless defined?(SCRIPT_MAP)
|
14
14
|
|
15
|
-
def self.default_abi
|
16
|
-
abi_name = %x{uname -s}.chomp
|
17
|
-
abi_version = %x{uname -r}.chomp.split(".")[0]
|
18
|
-
abi_arch = %x{uname -m}.chomp
|
19
|
-
|
20
|
-
[abi_name, abi_version, abi_arch].join(":")
|
21
|
-
end
|
22
|
-
|
23
|
-
option "--abi", "ABI",
|
24
|
-
"Sets the FreeBSD abi pkg field to specify binary compatibility.",
|
25
|
-
:default => default_abi
|
26
|
-
|
27
15
|
option "--origin", "ABI",
|
28
16
|
"Sets the FreeBSD 'origin' pkg field",
|
29
17
|
:default => "fpm/<name>"
|
30
18
|
|
31
19
|
def output(output_path)
|
32
|
-
# See https://github.com/jordansissel/fpm/issues/1090
|
33
|
-
# require xz later, because this triggers a load of liblzma.so.5 that is
|
34
|
-
# unavailable on older CentOS/RH distros.
|
35
|
-
require "xz"
|
36
20
|
output_check(output_path)
|
37
21
|
|
38
22
|
# Build the packaging metadata files.
|
@@ -58,7 +42,7 @@ class FPM::Package::FreeBSD < FPM::Package
|
|
58
42
|
pkg_version = (iteration and (iteration.to_i > 0)) ? "#{version}-#{iteration}" : "#{version}"
|
59
43
|
|
60
44
|
pkgdata = {
|
61
|
-
"
|
45
|
+
"arch" => architecture,
|
62
46
|
"name" => name,
|
63
47
|
"version" => pkg_version,
|
64
48
|
"comment" => description,
|
@@ -92,24 +76,44 @@ class FPM::Package::FreeBSD < FPM::Package
|
|
92
76
|
file.write(pkgdata.to_json + "\n")
|
93
77
|
end
|
94
78
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
FPM::Util::TarWriter.new(xz) do |tar|
|
99
|
-
# The manifests must come first for pkg.
|
100
|
-
add_path(tar, "+COMPACT_MANIFEST",
|
101
|
-
File.join(staging_path, "+COMPACT_MANIFEST"))
|
102
|
-
add_path(tar, "+MANIFEST",
|
103
|
-
File.join(staging_path, "+MANIFEST"))
|
104
|
-
|
105
|
-
checksums.keys.each do |path|
|
106
|
-
add_path(tar, "/" + path, File.join(staging_path, path))
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
79
|
+
file_list = File.new(build_path("file_list"), "w")
|
80
|
+
files.each do |i|
|
81
|
+
file_list.puts(i)
|
110
82
|
end
|
83
|
+
file_list.close
|
84
|
+
|
85
|
+
# Create the .txz package archive from the files in staging_path.
|
86
|
+
# We use --files-from here to keep the tar entries from having `./` as the prefix.
|
87
|
+
# This is done as a best effor to mimic what FreeBSD packages do, having everything at the top-level as
|
88
|
+
# file names, like "+MANIFEST" instead of "./+MANIFEST"
|
89
|
+
safesystem("tar", "-Jcf", output_path, "-C", staging_path, "--files-from", build_path("file_list"), "--transform", 's|^\([^+]\)|/\1|')
|
111
90
|
end # def output
|
112
91
|
|
92
|
+
# Handle architecture naming conversion:
|
93
|
+
# <osname>:<osversion>:<arch>:<wordsize>[.other]
|
94
|
+
def architecture
|
95
|
+
osname = %x{uname -s}.chomp
|
96
|
+
osversion = %x{uname -r}.chomp.split('.').first
|
97
|
+
|
98
|
+
# Essentially because no testing on other platforms
|
99
|
+
arch = 'x86'
|
100
|
+
|
101
|
+
wordsize = case @architecture
|
102
|
+
when nil, 'native'
|
103
|
+
%x{getconf LONG_BIT}.chomp # 'native' is current arch
|
104
|
+
when 'arm64'
|
105
|
+
'64'
|
106
|
+
when 'amd64'
|
107
|
+
'64'
|
108
|
+
when 'i386'
|
109
|
+
'32'
|
110
|
+
else
|
111
|
+
%x{getconf LONG_BIT}.chomp # default to native, the current arch
|
112
|
+
end
|
113
|
+
|
114
|
+
return [osname, osversion, arch, wordsize].join(':')
|
115
|
+
end
|
116
|
+
|
113
117
|
def add_path(tar, tar_path, path)
|
114
118
|
stat = File.lstat(path)
|
115
119
|
if stat.directory?
|
data/lib/fpm/package/gem.rb
CHANGED
@@ -30,6 +30,9 @@ class FPM::Package::Gem < FPM::Package
|
|
30
30
|
option "--gem", "PATH_TO_GEM",
|
31
31
|
"The path to the 'gem' tool (defaults to 'gem' and searches " \
|
32
32
|
"your $PATH)", :default => "gem"
|
33
|
+
option "--shebang", "SHEBANG",
|
34
|
+
"Replace the shebang in the executables in the bin path with a " \
|
35
|
+
"custom string", :default => nil
|
33
36
|
option "--fix-name", :flag, "Should the target package name be prefixed?",
|
34
37
|
:default => true
|
35
38
|
option "--fix-dependencies", :flag, "Should the package dependencies be " \
|
@@ -41,9 +44,36 @@ class FPM::Package::Gem < FPM::Package
|
|
41
44
|
option "--disable-dependency", "gem_name",
|
42
45
|
"The gem name to remove from dependency list",
|
43
46
|
:multivalued => true, :attribute_name => :gem_disable_dependencies
|
47
|
+
option "--embed-dependencies", :flag, "Should the gem dependencies " \
|
48
|
+
"be installed?", :default => false
|
44
49
|
|
45
50
|
option "--version-bins", :flag, "Append the version to the bins", :default => false
|
46
51
|
|
52
|
+
option "--stagingdir", "STAGINGDIR",
|
53
|
+
"The directory where fpm installs the gem temporarily before conversion. " \
|
54
|
+
"Normally a random subdirectory of workdir."
|
55
|
+
|
56
|
+
option "--git-repo", "GIT_REPO",
|
57
|
+
"Use this git repo address as the source of the gem instead of " \
|
58
|
+
"rubygems.org.", :default => nil
|
59
|
+
|
60
|
+
option "--git-branch", "GIT_BRANCH",
|
61
|
+
"When using a git repo as the source of the gem instead of " \
|
62
|
+
"rubygems.org, use this git branch.",
|
63
|
+
:default => nil
|
64
|
+
|
65
|
+
# Override parent method
|
66
|
+
def staging_path(path=nil)
|
67
|
+
@gem_staging_path ||= attributes[:gem_stagingdir] || Stud::Temporary.directory("package-#{type}-staging")
|
68
|
+
@staging_path = @gem_staging_path
|
69
|
+
|
70
|
+
if path.nil?
|
71
|
+
return @staging_path
|
72
|
+
else
|
73
|
+
return File.join(@staging_path, path)
|
74
|
+
end
|
75
|
+
end # def staging_path
|
76
|
+
|
47
77
|
def input(gem)
|
48
78
|
# 'arg' is the name of the rubygem we should unpack.
|
49
79
|
path_to_gem = download_if_necessary(gem, version)
|
@@ -70,21 +100,34 @@ class FPM::Package::Gem < FPM::Package
|
|
70
100
|
|
71
101
|
logger.info("Trying to download", :gem => gem_name, :version => gem_version)
|
72
102
|
|
73
|
-
gem_fetch = [ "#{attributes[:gem_gem]}", "fetch", gem_name]
|
74
|
-
|
75
|
-
gem_fetch += ["--prerelease"] if attributes[:gem_prerelease?]
|
76
|
-
gem_fetch += ["--version", gem_version] if gem_version
|
77
|
-
|
78
103
|
download_dir = build_path(gem_name)
|
79
104
|
FileUtils.mkdir(download_dir) unless File.directory?(download_dir)
|
80
105
|
|
81
|
-
|
82
|
-
|
83
|
-
|
106
|
+
if attributes[:gem_git_repo]
|
107
|
+
require "git"
|
108
|
+
logger.debug("Git cloning in directory #{download_dir}")
|
109
|
+
g = Git.clone(attributes[:gem_git_repo],gem_name,:path => download_dir)
|
110
|
+
if attributes[:gem_git_branch]
|
111
|
+
g.branch(attributes[:gem_git_branch]).checkout
|
112
|
+
g.pull('origin',attributes[:gem_git_branch])
|
113
|
+
end
|
114
|
+
gem_build = [ "#{attributes[:gem_gem]}", "build", "#{g.dir.to_s}/#{gem_name}.gemspec"]
|
115
|
+
::Dir.chdir(g.dir.to_s) do |dir|
|
116
|
+
logger.debug("Building in directory #{dir}")
|
117
|
+
safesystem(*gem_build)
|
118
|
+
end
|
119
|
+
gem_files = ::Dir.glob(File.join(g.dir.to_s, "*.gem"))
|
120
|
+
else
|
121
|
+
gem_fetch = [ "#{attributes[:gem_gem]}", "fetch", gem_name]
|
122
|
+
gem_fetch += ["--prerelease"] if attributes[:gem_prerelease?]
|
123
|
+
gem_fetch += ["--version", gem_version] if gem_version
|
124
|
+
::Dir.chdir(download_dir) do |dir|
|
125
|
+
logger.debug("Downloading in directory #{dir}")
|
126
|
+
safesystem(*gem_fetch)
|
127
|
+
end
|
128
|
+
gem_files = ::Dir.glob(File.join(download_dir, "*.gem"))
|
84
129
|
end
|
85
130
|
|
86
|
-
gem_files = ::Dir.glob(File.join(download_dir, "*.gem"))
|
87
|
-
|
88
131
|
if gem_files.length != 1
|
89
132
|
raise "Unexpected number of gem files in #{download_dir}, #{gem_files.length} should be 1"
|
90
133
|
end
|
@@ -141,7 +184,7 @@ class FPM::Package::Gem < FPM::Package
|
|
141
184
|
# composing multiple packages, it's best to explicitly include it in the provides list.
|
142
185
|
self.provides << "#{self.name} = #{self.version}"
|
143
186
|
|
144
|
-
if !attributes[:no_auto_depends?]
|
187
|
+
if !attributes[:no_auto_depends?] && !attributes[:gem_embed_dependencies?]
|
145
188
|
spec.runtime_dependencies.map do |dep|
|
146
189
|
# rubygems 1.3.5 doesn't have 'Gem::Dependency#requirement'
|
147
190
|
if dep.respond_to?(:requirement)
|
@@ -177,8 +220,18 @@ class FPM::Package::Gem < FPM::Package
|
|
177
220
|
|
178
221
|
::FileUtils.mkdir_p(installdir)
|
179
222
|
# TODO(sissel): Allow setting gem tool path
|
180
|
-
args = [attributes[:gem_gem], "install", "--quiet", "--no-
|
181
|
-
|
223
|
+
args = [attributes[:gem_gem], "install", "--quiet", "--no-user-install", "--install-dir", installdir]
|
224
|
+
if ::Gem::VERSION =~ /^[012]\./
|
225
|
+
args += [ "--no-ri", "--no-rdoc" ]
|
226
|
+
else
|
227
|
+
# Rubygems 3.0.0 changed --no-ri to --no-document
|
228
|
+
args += [ "--no-document" ]
|
229
|
+
end
|
230
|
+
|
231
|
+
if !attributes[:gem_embed_dependencies?]
|
232
|
+
args += ["--ignore-dependencies"]
|
233
|
+
end
|
234
|
+
|
182
235
|
if attributes[:gem_env_shebang?]
|
183
236
|
args += ["-E"]
|
184
237
|
end
|
@@ -196,6 +249,22 @@ class FPM::Package::Gem < FPM::Package
|
|
196
249
|
args << gem_path
|
197
250
|
safesystem(*args)
|
198
251
|
|
252
|
+
# Replace the shebangs in the executables
|
253
|
+
if attributes[:gem_shebang]
|
254
|
+
::Dir.entries(bin_path).each do |file_name|
|
255
|
+
# exclude . and ..
|
256
|
+
next if ['.', '..'].include?(file_name)
|
257
|
+
# exclude everything which is not a file
|
258
|
+
file_path = File.join(bin_path, file_name)
|
259
|
+
next unless File.ftype(file_path) == 'file'
|
260
|
+
# replace shebang in files if there is one
|
261
|
+
file = File.read(file_path)
|
262
|
+
if file.gsub!(/\A#!.*$/, "#!#{attributes[:gem_shebang]}")
|
263
|
+
File.open(file_path, 'w'){|f| f << file}
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
199
268
|
# Delete bin_path if it's empty, and any empty parents (#612)
|
200
269
|
# Above, we mkdir_p bin_path because rubygems aborts if the parent
|
201
270
|
# directory doesn't exist, for example:
|
@@ -212,6 +281,21 @@ class FPM::Package::Gem < FPM::Package
|
|
212
281
|
FileUtils.mv("#{bin_path}/#{bin}", "#{bin_path}/#{bin}-#{self.version}")
|
213
282
|
end
|
214
283
|
end
|
284
|
+
|
285
|
+
if attributes[:source_date_epoch_from_changelog?]
|
286
|
+
detect_source_date_from_changelog(installdir)
|
287
|
+
end
|
288
|
+
|
289
|
+
# Remove generated Makefile and gem_make.out files, if any; they
|
290
|
+
# are not needed, and may contain generated paths that cause
|
291
|
+
# different output on successive runs.
|
292
|
+
Find.find(installdir) do |path|
|
293
|
+
if path =~ /.*(gem_make.out|Makefile|mkmf.log)$/
|
294
|
+
logger.info("Removing no longer needed file %s to reduce nondeterminism" % path)
|
295
|
+
File.unlink(path)
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
215
299
|
end # def install_to_staging
|
216
300
|
|
217
301
|
# Sanitize package name.
|
@@ -220,5 +304,75 @@ class FPM::Package::Gem < FPM::Package
|
|
220
304
|
def fix_name(name)
|
221
305
|
return [attributes[:gem_package_name_prefix], name].join("-")
|
222
306
|
end # def fix_name
|
307
|
+
|
308
|
+
# Regular expression to accept a gem changelog line, and store date & version, if any, in named capture groups.
|
309
|
+
# Supports formats suggested by http://keepachangelog.com and https://github.com/tech-angels/vandamme
|
310
|
+
# as well as other similar formats that actually occur in the wild.
|
311
|
+
# Build it in pieces for readability, and allow version and date in either order.
|
312
|
+
# Whenever you change this, add a row to the test case in spec/fpm/package/gem_spec.rb.
|
313
|
+
# Don't even try to handle dates that lack four-digit years.
|
314
|
+
# Building blocks:
|
315
|
+
P_RE_LEADIN = '^[#=]{0,3}\s?'
|
316
|
+
P_RE_VERSION_ = '[\w\.-]+\.[\w\.-]+[a-zA-Z0-9]'
|
317
|
+
P_RE_SEPARATOR = '\s[-=/(]?\s?'
|
318
|
+
P_RE_DATE1 = '\d{4}-\d{2}-\d{2}'
|
319
|
+
P_RE_DATE2 = '\w+ \d{1,2}(?:st|nd|rd|th)?,\s\d{4}'
|
320
|
+
P_RE_DATE3 = '\w+\s+\w+\s+\d{1,2},\s\d{4}'
|
321
|
+
P_RE_DATE = "(?<date>#{P_RE_DATE1}|#{P_RE_DATE2}|#{P_RE_DATE3})"
|
322
|
+
P_RE_URL = '\(https?:[-\w/.%]*\)' # In parens, per markdown
|
323
|
+
P_RE_GTMAGIC = '\[\]' # github magic version diff, per chandler
|
324
|
+
P_RE_VERSION = "\\[?(?:Version |v)?(?<version>#{P_RE_VERSION_})\\]?(?:#{P_RE_URL}|#{P_RE_GTMAGIC})?"
|
325
|
+
# The final RE's:
|
326
|
+
P_RE_VERSION_DATE = "#{P_RE_LEADIN}#{P_RE_VERSION}#{P_RE_SEPARATOR}#{P_RE_DATE}"
|
327
|
+
P_RE_DATE_VERSION = "#{P_RE_LEADIN}#{P_RE_DATE}#{P_RE_SEPARATOR}#{P_RE_VERSION}"
|
328
|
+
|
329
|
+
# Detect release date, if found, store in attributes[:source_date_epoch]
|
330
|
+
def detect_source_date_from_changelog(installdir)
|
331
|
+
name = self.name.sub("rubygem-", "") + "-" + self.version
|
332
|
+
changelog = nil
|
333
|
+
datestr = nil
|
334
|
+
r1 = Regexp.new(P_RE_VERSION_DATE)
|
335
|
+
r2 = Regexp.new(P_RE_DATE_VERSION)
|
336
|
+
|
337
|
+
# Changelog doesn't have a standard name, so check all common variations
|
338
|
+
# Sort this list using LANG=C, i.e. caps first
|
339
|
+
[
|
340
|
+
"CHANGELIST",
|
341
|
+
"CHANGELOG", "CHANGELOG.asciidoc", "CHANGELOG.md", "CHANGELOG.rdoc", "CHANGELOG.rst", "CHANGELOG.txt",
|
342
|
+
"CHANGES", "CHANGES.md", "CHANGES.txt",
|
343
|
+
"ChangeLog", "ChangeLog.md", "ChangeLog.txt",
|
344
|
+
"Changelog", "Changelog.md", "Changelog.txt",
|
345
|
+
"changelog", "changelog.md", "changelog.txt",
|
346
|
+
].each do |changelogname|
|
347
|
+
path = File.join(installdir, "gems", name, changelogname)
|
348
|
+
if File.exist?(path)
|
349
|
+
changelog = path
|
350
|
+
File.open path do |file|
|
351
|
+
file.each_line do |line|
|
352
|
+
if line =~ /#{self.version}/
|
353
|
+
[r1, r2].each do |r|
|
354
|
+
if r.match(line)
|
355
|
+
datestr = $~[:date]
|
356
|
+
break
|
357
|
+
end
|
358
|
+
end
|
359
|
+
end
|
360
|
+
end
|
361
|
+
end
|
362
|
+
end
|
363
|
+
end
|
364
|
+
if datestr
|
365
|
+
date = Date.parse(datestr)
|
366
|
+
sec = date.strftime("%s")
|
367
|
+
attributes[:source_date_epoch] = sec
|
368
|
+
logger.debug("Gem %s has changelog date %s, setting source_date_epoch to %s" % [name, datestr, sec])
|
369
|
+
elsif changelog
|
370
|
+
logger.debug("Gem %s changelog %s did not have recognizable date for release %s" % [name, changelog, self.version])
|
371
|
+
else
|
372
|
+
logger.debug("Gem %s did not have changelog with recognized name" % [name])
|
373
|
+
# FIXME: check rubygems.org?
|
374
|
+
end
|
375
|
+
end # detect_source_date_from_changelog
|
376
|
+
|
223
377
|
public(:input, :output)
|
224
378
|
end # class FPM::Package::Gem
|
data/lib/fpm/package/pacman.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
require "fpm/package"
|
3
3
|
require "fpm/util"
|
4
|
-
require "backports"
|
4
|
+
require "backports/latest"
|
5
5
|
require "fileutils"
|
6
6
|
require "find"
|
7
7
|
|
@@ -18,10 +18,10 @@ class FPM::Package::Pacman < FPM::Package
|
|
18
18
|
option "--group", "GROUP", "The group owner of files in this package", :default => 'root'
|
19
19
|
|
20
20
|
# The list of supported compression types. Default is xz (LZMA2)
|
21
|
-
COMPRESSION_TYPES = [ "gz", "bzip2", "xz", "none" ]
|
21
|
+
COMPRESSION_TYPES = [ "gz", "bzip2", "xz", "zstd", "none" ]
|
22
22
|
|
23
23
|
option "--compression", "COMPRESSION", "The compression type to use, must " \
|
24
|
-
"be one of #{COMPRESSION_TYPES.join(", ")}.", :default => "
|
24
|
+
"be one of #{COMPRESSION_TYPES.join(", ")}.", :default => "zstd" do |value|
|
25
25
|
if !COMPRESSION_TYPES.include?(value)
|
26
26
|
raise ArgumentError, "Pacman compression value of '#{value}' is invalid. " \
|
27
27
|
"Must be one of #{COMPRESSION_TYPES.join(", ")}"
|
@@ -58,7 +58,7 @@ class FPM::Package::Pacman < FPM::Package
|
|
58
58
|
end # def config_files
|
59
59
|
|
60
60
|
def dependencies
|
61
|
-
bogus_regex = /[^\sA-Za-z0-9
|
61
|
+
bogus_regex = /[^\sA-Za-z0-9><=+._@-]/
|
62
62
|
# Actually modifies depencies if they are not right
|
63
63
|
bogus_dependencies = @dependencies.grep bogus_regex
|
64
64
|
if bogus_dependencies.any?
|
@@ -137,7 +137,7 @@ class FPM::Package::Pacman < FPM::Package
|
|
137
137
|
# Speaking of just taking the first entry of the field:
|
138
138
|
# A crude thing to do, but I suppose it's better than nothing.
|
139
139
|
# -- Daniel Haskin, 3/24/2015
|
140
|
-
self.category = control["group"][0] || self.category
|
140
|
+
self.category = control["group"] && control["group"][0] || self.category
|
141
141
|
|
142
142
|
# Licenses could include more than one.
|
143
143
|
# Speaking of just taking the first entry of the field:
|
@@ -164,6 +164,10 @@ class FPM::Package::Pacman < FPM::Package
|
|
164
164
|
end
|
165
165
|
|
166
166
|
self.dependencies = control["depend"] || self.dependencies
|
167
|
+
|
168
|
+
if attributes[:no_auto_depends?]
|
169
|
+
self.dependencies = []
|
170
|
+
end
|
167
171
|
|
168
172
|
self.attributes[:pacman_optional_depends] = control["optdepend"] || []
|
169
173
|
# There are other available attributes, but I didn't include them because:
|
@@ -205,31 +209,39 @@ class FPM::Package::Pacman < FPM::Package
|
|
205
209
|
|
206
210
|
def compression_option
|
207
211
|
case self.attributes[:pacman_compression]
|
208
|
-
when nil, "
|
209
|
-
return "--
|
212
|
+
when nil, "zstd"
|
213
|
+
return "--zstd"
|
210
214
|
when "none"
|
211
215
|
return ""
|
212
216
|
when "gz"
|
213
217
|
return "-z"
|
218
|
+
when "xz"
|
219
|
+
return "--xz"
|
214
220
|
when "bzip2"
|
215
221
|
return "-j"
|
222
|
+
when "zstd"
|
223
|
+
return "--zstd"
|
216
224
|
else
|
217
|
-
return "--
|
225
|
+
return "--zstd"
|
218
226
|
end
|
219
227
|
end
|
220
228
|
|
221
229
|
def compression_ending
|
222
230
|
case self.attributes[:pacman_compression]
|
223
|
-
when nil, "
|
224
|
-
return ".
|
231
|
+
when nil, "zstd"
|
232
|
+
return ".zst"
|
225
233
|
when "none"
|
226
234
|
return ""
|
227
235
|
when "gz"
|
228
236
|
return ".gz"
|
237
|
+
when "zx"
|
238
|
+
return ".xz"
|
229
239
|
when "bzip2"
|
230
240
|
return ".bz2"
|
241
|
+
when "zstd"
|
242
|
+
return ".zst"
|
231
243
|
else
|
232
|
-
return ".
|
244
|
+
return ".zst"
|
233
245
|
end
|
234
246
|
end
|
235
247
|
|
@@ -241,7 +253,11 @@ class FPM::Package::Pacman < FPM::Package
|
|
241
253
|
Find.find(staging_path) do |path|
|
242
254
|
src = path.gsub(/^#{staging_path}/, '')
|
243
255
|
dst = build_path(src)
|
244
|
-
|
256
|
+
begin
|
257
|
+
copy_entry(path, dst, preserve=true, remove_destination=true)
|
258
|
+
rescue
|
259
|
+
copy_entry(path, dst, preserve=false, remove_destination=true)
|
260
|
+
end
|
245
261
|
copy_metadata(path, dst)
|
246
262
|
end
|
247
263
|
|
@@ -10,13 +10,14 @@ require "pleaserun/cli"
|
|
10
10
|
# This does not currently support 'output'
|
11
11
|
class FPM::Package::PleaseRun < FPM::Package
|
12
12
|
# TODO(sissel): Implement flags.
|
13
|
-
|
13
|
+
|
14
14
|
require "pleaserun/platform/systemd"
|
15
15
|
require "pleaserun/platform/upstart"
|
16
16
|
require "pleaserun/platform/launchd"
|
17
17
|
require "pleaserun/platform/sysv"
|
18
18
|
|
19
19
|
option "--name", "SERVICE_NAME", "The name of the service you are creating"
|
20
|
+
option "--chdir", "CHDIR", "The working directory used by the service"
|
20
21
|
|
21
22
|
private
|
22
23
|
def input(command)
|
@@ -27,6 +28,10 @@ class FPM::Package::PleaseRun < FPM::Package
|
|
27
28
|
::PleaseRun::Platform::Launchd.new("10.9"), # OS X
|
28
29
|
::PleaseRun::Platform::SYSV.new("lsb-3.1") # Ancient stuff
|
29
30
|
]
|
31
|
+
pleaserun_attributes = [ "chdir", "user", "group", "umask", "chroot", "nice", "limit_coredump",
|
32
|
+
"limit_cputime", "limit_data", "limit_file_size", "limit_locked_memory",
|
33
|
+
"limit_open_files", "limit_user_processes", "limit_physical_memory", "limit_stack_size",
|
34
|
+
"log_directory", "log_file_stderr", "log_file_stdout"]
|
30
35
|
|
31
36
|
attributes[:pleaserun_name] ||= File.basename(command.first)
|
32
37
|
attributes[:prefix] ||= "/usr/share/pleaserun/#{attributes[:pleaserun_name]}"
|
@@ -41,6 +46,13 @@ class FPM::Package::PleaseRun < FPM::Package
|
|
41
46
|
else
|
42
47
|
platform.name
|
43
48
|
end
|
49
|
+
pleaserun_attributes.each do |attribute_name|
|
50
|
+
attribute = "pleaserun_#{attribute_name}".to_sym
|
51
|
+
if attributes.has_key?(attribute) and not attributes[attribute].nil?
|
52
|
+
platform.send("#{attribute_name}=", attributes[attribute])
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
44
56
|
base = staging_path(File.join(attributes[:prefix], "#{platform.platform}/#{platform.target_version || "default"}"))
|
45
57
|
target = File.join(base, "files")
|
46
58
|
actions_script = File.join(base, "install_actions.sh")
|
@@ -47,6 +47,11 @@ class get_metadata(Command):
|
|
47
47
|
|
48
48
|
def process_dep(self, dep):
|
49
49
|
deps = []
|
50
|
+
if hasattr(dep, 'marker') and dep.marker:
|
51
|
+
# PEP0508 marker present
|
52
|
+
if not dep.marker.evaluate():
|
53
|
+
return deps
|
54
|
+
|
50
55
|
if dep.specs:
|
51
56
|
for operator, version in dep.specs:
|
52
57
|
deps.append("%s %s %s" % (dep.project_name,
|
@@ -85,6 +90,11 @@ class get_metadata(Command):
|
|
85
90
|
for dep in pkg_resources.parse_requirements(
|
86
91
|
self.distribution.install_requires):
|
87
92
|
final_deps.extend(self.process_dep(dep))
|
93
|
+
if getattr(self.distribution, 'extras_require', None):
|
94
|
+
for dep in pkg_resources.parse_requirements(
|
95
|
+
v for k, v in self.distribution.extras_require.items()
|
96
|
+
if k.startswith(':') and pkg_resources.evaluate_marker(k[1:])):
|
97
|
+
final_deps.extend(self.process_dep(dep))
|
88
98
|
|
89
99
|
data["dependencies"] = final_deps
|
90
100
|
|
data/lib/fpm/package/python.rb
CHANGED
@@ -29,6 +29,9 @@ class FPM::Package::Python < FPM::Package
|
|
29
29
|
option "--pypi", "PYPI_URL",
|
30
30
|
"PyPi Server uri for retrieving packages.",
|
31
31
|
:default => "https://pypi.python.org/simple"
|
32
|
+
option "--trusted-host", "PYPI_TRUSTED",
|
33
|
+
"Mark this host or host:port pair as trusted for pip",
|
34
|
+
:default => nil
|
32
35
|
option "--package-prefix", "NAMEPREFIX",
|
33
36
|
"(DEPRECATED, use --package-name-prefix) Name to prefix the package " \
|
34
37
|
"name with." do |value|
|
@@ -73,6 +76,14 @@ class FPM::Package::Python < FPM::Package
|
|
73
76
|
"The python package name to remove from dependency list",
|
74
77
|
:multivalued => true, :attribute_name => :python_disable_dependency,
|
75
78
|
:default => []
|
79
|
+
option "--setup-py-arguments", "setup_py_argument",
|
80
|
+
"Arbitrary argument(s) to be passed to setup.py",
|
81
|
+
:multivalued => true, :attribute_name => :python_setup_py_arguments,
|
82
|
+
:default => []
|
83
|
+
option "--internal-pip", :flag,
|
84
|
+
"Use the pip module within python to install modules - aka 'python -m pip'. This is the recommended usage since Python 3.4 (2014) instead of invoking the 'pip' script",
|
85
|
+
:attribute_name => :python_internal_pip,
|
86
|
+
:default => true
|
76
87
|
|
77
88
|
private
|
78
89
|
|
@@ -123,16 +134,47 @@ class FPM::Package::Python < FPM::Package
|
|
123
134
|
target = build_path(package)
|
124
135
|
FileUtils.mkdir(target) unless File.directory?(target)
|
125
136
|
|
126
|
-
if attributes[:
|
137
|
+
if attributes[:python_internal_pip?]
|
138
|
+
# XXX: Should we detect if internal pip is available?
|
139
|
+
attributes[:python_pip] = [ attributes[:python_bin], "-m", "pip"]
|
140
|
+
end
|
141
|
+
|
142
|
+
# attributes[:python_pip] -- expected to be a path
|
143
|
+
if attributes[:python_pip]
|
144
|
+
logger.debug("using pip", :pip => attributes[:python_pip])
|
145
|
+
# TODO: Support older versions of pip
|
146
|
+
|
147
|
+
pip = [attributes[:python_pip]] if pip.is_a?(String)
|
148
|
+
setup_cmd = [
|
149
|
+
*attributes[:python_pip],
|
150
|
+
"download",
|
151
|
+
"--no-clean",
|
152
|
+
"--no-deps",
|
153
|
+
"--no-binary", ":all:",
|
154
|
+
"-d", build_path,
|
155
|
+
"-i", attributes[:python_pypi],
|
156
|
+
]
|
157
|
+
|
158
|
+
if attributes[:python_trusted_host]
|
159
|
+
setup_cmd += [
|
160
|
+
"--trusted-host",
|
161
|
+
attributes[:python_trusted_host],
|
162
|
+
]
|
163
|
+
end
|
164
|
+
|
165
|
+
setup_cmd += [
|
166
|
+
"--build",
|
167
|
+
target,
|
168
|
+
want_pkg,
|
169
|
+
]
|
170
|
+
|
171
|
+
safesystem(*setup_cmd)
|
172
|
+
else
|
127
173
|
# no pip, use easy_install
|
128
174
|
logger.debug("no pip, defaulting to easy_install", :easy_install => attributes[:python_easyinstall])
|
129
175
|
safesystem(attributes[:python_easyinstall], "-i",
|
130
176
|
attributes[:python_pypi], "--editable", "-U",
|
131
177
|
"--build-directory", target, want_pkg)
|
132
|
-
else
|
133
|
-
logger.debug("using pip", :pip => attributes[:python_pip])
|
134
|
-
# TODO: Support older versions of pip
|
135
|
-
safesystem(attributes[:python_pip], "download", "--no-clean", "--no-deps", "--no-binary", ":all:", "-i", attributes[:python_pypi], "--build", target, want_pkg)
|
136
178
|
end
|
137
179
|
|
138
180
|
# easy_install will put stuff in @tmpdir/packagename/, so find that:
|
@@ -179,7 +221,7 @@ class FPM::Package::Python < FPM::Package
|
|
179
221
|
|
180
222
|
output = ::Dir.chdir(setup_dir) do
|
181
223
|
tmp = build_path("metadata.json")
|
182
|
-
setup_cmd = "env PYTHONPATH=#{pylib} #{attributes[:python_bin]} " \
|
224
|
+
setup_cmd = "env PYTHONPATH=#{pylib}:$PYTHONPATH #{attributes[:python_bin]} " \
|
183
225
|
"setup.py --command-packages=pyfpm get_metadata --output=#{tmp}"
|
184
226
|
|
185
227
|
if attributes[:python_obey_requirements_txt?]
|
@@ -225,7 +267,7 @@ class FPM::Package::Python < FPM::Package
|
|
225
267
|
|
226
268
|
if !attributes[:no_auto_depends?] and attributes[:python_dependencies?]
|
227
269
|
metadata["dependencies"].each do |dep|
|
228
|
-
dep_re = /^([^<>!= ]+)\s*(?:([
|
270
|
+
dep_re = /^([^<>!= ]+)\s*(?:([~<>!=]{1,2})\s*(.*))?$/
|
229
271
|
match = dep_re.match(dep)
|
230
272
|
if match.nil?
|
231
273
|
logger.error("Unable to parse dependency", :dependency => dep)
|
@@ -236,7 +278,7 @@ class FPM::Package::Python < FPM::Package
|
|
236
278
|
next if attributes[:python_disable_dependency].include?(name)
|
237
279
|
|
238
280
|
# convert == to =
|
239
|
-
if cmp == "=="
|
281
|
+
if cmp == "==" or cmp == "~="
|
240
282
|
logger.info("Converting == dependency requirement to =", :dependency => dep )
|
241
283
|
cmp = "="
|
242
284
|
end
|
@@ -310,6 +352,13 @@ class FPM::Package::Python < FPM::Package
|
|
310
352
|
flags += [ "build_scripts", "--executable", attributes[:python_scripts_executable] ]
|
311
353
|
end
|
312
354
|
|
355
|
+
if !attributes[:python_setup_py_arguments].nil? and !attributes[:python_setup_py_arguments].empty?
|
356
|
+
# Add optional setup.py arguments
|
357
|
+
attributes[:python_setup_py_arguments].each do |a|
|
358
|
+
flags += [ a ]
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
313
362
|
safesystem(attributes[:python_bin], "setup.py", "install", *flags)
|
314
363
|
end
|
315
364
|
end # def install_to_staging
|