fpm 1.17.0 → 1.18.0
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 +4 -4
- data/CHANGELOG.rst +11 -0
- data/lib/fpm/command.rb +2 -2
- data/lib/fpm/package/cpan.rb +89 -27
- data/lib/fpm/package/deb.rb +38 -6
- data/lib/fpm/package/gem.rb +1 -1
- data/lib/fpm/package/pyfpm/parse_requires.py +3 -3
- data/lib/fpm/package/python.rb +6 -6
- data/lib/fpm/package.rb +5 -5
- data/lib/fpm/util.rb +5 -5
- data/lib/fpm/version.rb +1 -1
- data/templates/sh.erb +1 -1
- metadata +6 -4
- data/lib/fpm/package/pyfpm/get_metadata.py +0 -115
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0a0ebf62e58835b9331f5f56ec9689e95e725666d7fc2563afd617f2fc882bb4
|
|
4
|
+
data.tar.gz: 7d0043765bdef7b5db3f493978cc94951fbb6cb5ad15bc823a9875e67ad2afd5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e887592f69377440a23e193c3a2ce049c0fdc286b6699931bed7c4589785da9532998ef3ccd09946e61974a3f441719d28d9b19332d4a5aa3ccf3c63bfb5c210
|
|
7
|
+
data.tar.gz: 1d21ed70407432b95a8c7095e226073e357bbf7754579df271e216ffc28f4121df949ecb01b4a8718d47033ebd6687175fb133edcca4793269f8bc3f9ffb31db
|
data/CHANGELOG.rst
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
Release Notes and Change Log
|
|
2
2
|
============================
|
|
3
3
|
|
|
4
|
+
1.18.0 (August 26, 2026)
|
|
5
|
+
^^^^^^^^^^^^^^^^^^^^^^^^
|
|
6
|
+
|
|
7
|
+
* deb/macOS: Fix a bug on macOS caused by a behavior change to the ``ar`` utility provided by Xcode (`#2149`_, `#2148`_; Dan Pashin)
|
|
8
|
+
* Ruby 2.x support: Restored compatibility with older versions of Ruby such as Ruby 2.5.0. (`#2123`_; Jordan Sissel)
|
|
9
|
+
* cpan: Add flag --cpan-metacpan-api-url for custom MetaCPAN urls (`#2146`_; Nicholas B. Hubbard)
|
|
10
|
+
* cpan: Add flag ``--cpan-disable-dependency <name>`` to remove a dependency from the package (`#2128`_, `#2125`_; Nicholas B. Hubbard)
|
|
11
|
+
* cpan: MetaCPAN upgraded their Elasticsearch version which means fpm also needs to use the newer query syntax. (`#2144`_, `#2143`_; Jordan Sissel)
|
|
12
|
+
* cpan: Improvements to cpan search to better support cpan distributions (`#2125`_; Nicholas B. Hubbard)
|
|
13
|
+
* tests: Fixed a bunch of tests that were failing under Github Actions (`#2122`_; Nicholas B. Hubbard)
|
|
14
|
+
|
|
4
15
|
1.17.0 (October 2, 2025)
|
|
5
16
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
|
6
17
|
|
data/lib/fpm/command.rb
CHANGED
|
@@ -673,7 +673,7 @@ class FPM::Command < Clamp::Command
|
|
|
673
673
|
option.of(self).take(value)
|
|
674
674
|
end
|
|
675
675
|
end
|
|
676
|
-
end
|
|
676
|
+
end # def load_options
|
|
677
677
|
|
|
678
678
|
# A simple flag validator
|
|
679
679
|
#
|
|
@@ -757,4 +757,4 @@ class FPM::Command < Clamp::Command
|
|
|
757
757
|
|
|
758
758
|
public(:initialize, :ok?, :messages)
|
|
759
759
|
end # class Validator
|
|
760
|
-
end # class FPM::
|
|
760
|
+
end # class FPM::Command
|
data/lib/fpm/package/cpan.rb
CHANGED
|
@@ -22,6 +22,13 @@ class FPM::Package::CPAN < FPM::Package
|
|
|
22
22
|
option "--package-name-prefix", "NAME_PREFIX",
|
|
23
23
|
"Name to prefix the package name with.", :default => "perl"
|
|
24
24
|
|
|
25
|
+
option "--disable-dependency", "MODULE",
|
|
26
|
+
"Filter modules matching MODULE from those generated by " \
|
|
27
|
+
"the auto-depends for CPAN modules. This flag can be specified " \
|
|
28
|
+
"multiple times. Use the perl module name, IE: URI::Escape.",
|
|
29
|
+
:multivalued => true, :attribute_name => :rejects,
|
|
30
|
+
:default => ['vars','warnings','strict','Config']
|
|
31
|
+
|
|
25
32
|
option "--test", :flag,
|
|
26
33
|
"Run the tests before packaging?", :default => true
|
|
27
34
|
|
|
@@ -37,6 +44,10 @@ class FPM::Package::CPAN < FPM::Package
|
|
|
37
44
|
option "--cpanm-force", :flag,
|
|
38
45
|
"Pass the --force parameter to cpanm", :default => false
|
|
39
46
|
|
|
47
|
+
option "--metacpan-api-url", "URL",
|
|
48
|
+
"URL for the MetaCPAN api",
|
|
49
|
+
:default => "https://fastapi.metacpan.org"
|
|
50
|
+
|
|
40
51
|
private
|
|
41
52
|
def input(package)
|
|
42
53
|
#if RUBY_VERSION =~ /^1\.8/
|
|
@@ -46,7 +57,6 @@ class FPM::Package::CPAN < FPM::Package
|
|
|
46
57
|
#"me know by filing an issue: " \
|
|
47
58
|
#"https://github.com/jordansissel/fpm/issues"
|
|
48
59
|
#end
|
|
49
|
-
#require "ftw" # for http access
|
|
50
60
|
require "net/http"
|
|
51
61
|
require "json"
|
|
52
62
|
|
|
@@ -54,7 +64,7 @@ class FPM::Package::CPAN < FPM::Package
|
|
|
54
64
|
moduledir = package
|
|
55
65
|
result = {}
|
|
56
66
|
else
|
|
57
|
-
result =
|
|
67
|
+
result = search_module(package, version)
|
|
58
68
|
tarball = download(result, version)
|
|
59
69
|
moduledir = unpack(tarball)
|
|
60
70
|
end
|
|
@@ -92,20 +102,17 @@ class FPM::Package::CPAN < FPM::Package
|
|
|
92
102
|
else; metadata["license"]
|
|
93
103
|
end
|
|
94
104
|
|
|
95
|
-
unless metadata["
|
|
105
|
+
unless metadata["release"].nil?
|
|
106
|
+
dist_name, _, dist_version = metadata["release"].rpartition('-')
|
|
96
107
|
logger.info("Setting package name from 'distribution'",
|
|
97
|
-
|
|
98
|
-
self.name = fix_name(
|
|
108
|
+
:distribution => dist_name)
|
|
109
|
+
self.name = fix_name(dist_name)
|
|
110
|
+
self.provides = search_provided_modules(dist_name, dist_version)
|
|
99
111
|
else
|
|
100
112
|
logger.info("Setting package name from 'name'",
|
|
101
113
|
:name => metadata["name"])
|
|
102
114
|
self.name = fix_name(metadata["name"])
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
unless metadata["module"].nil?
|
|
106
|
-
metadata["module"].each do |m|
|
|
107
|
-
self.provides << cap_name(m["name"]) + " = #{self.version}"
|
|
108
|
-
end
|
|
115
|
+
self.provides << cap_name(metadata["name"]) + " = #{self.version}"
|
|
109
116
|
end
|
|
110
117
|
|
|
111
118
|
# author is not always set or it may be a string instead of an array
|
|
@@ -168,7 +175,6 @@ class FPM::Package::CPAN < FPM::Package
|
|
|
168
175
|
self.dependencies << "#{dep_name} >= #{version}"
|
|
169
176
|
next
|
|
170
177
|
end
|
|
171
|
-
dep = search(dep_name)
|
|
172
178
|
|
|
173
179
|
name = cap_name(dep_name)
|
|
174
180
|
|
|
@@ -299,7 +305,7 @@ class FPM::Package::CPAN < FPM::Package
|
|
|
299
305
|
self.architecture = "native"
|
|
300
306
|
end
|
|
301
307
|
end
|
|
302
|
-
end
|
|
308
|
+
end # def input
|
|
303
309
|
|
|
304
310
|
def unpack(tarball)
|
|
305
311
|
directory = build_path("module")
|
|
@@ -308,7 +314,7 @@ class FPM::Package::CPAN < FPM::Package
|
|
|
308
314
|
%q{--transform=s,[./]*[^/]*/,,} ]
|
|
309
315
|
safesystem("tar", *args)
|
|
310
316
|
return directory
|
|
311
|
-
end
|
|
317
|
+
end # def unpack
|
|
312
318
|
|
|
313
319
|
def download(metadata, cpan_version=nil)
|
|
314
320
|
distribution = metadata["distribution"]
|
|
@@ -326,8 +332,8 @@ class FPM::Package::CPAN < FPM::Package
|
|
|
326
332
|
end
|
|
327
333
|
|
|
328
334
|
# Search metacpan to get download URL for this version of the module
|
|
329
|
-
metacpan_search_url = "
|
|
330
|
-
metacpan_search_query =
|
|
335
|
+
metacpan_search_url = "#{attributes[:cpan_metacpan_api_url]}/v1/release/_search?_source=download_url"
|
|
336
|
+
metacpan_search_query = {"query":{"term":{"name": "#{distribution}-#{self.version}" } } }.to_json
|
|
331
337
|
begin
|
|
332
338
|
search_response = httppost(metacpan_search_url,metacpan_search_query)
|
|
333
339
|
rescue Net::HTTPServerException => e
|
|
@@ -339,7 +345,7 @@ class FPM::Package::CPAN < FPM::Package
|
|
|
339
345
|
data = search_response.body
|
|
340
346
|
release_metadata = JSON.parse(data)
|
|
341
347
|
|
|
342
|
-
download_url = release_metadata['hits']['hits'][0]['
|
|
348
|
+
download_url = release_metadata['hits']['hits'][0]['_source']['download_url']
|
|
343
349
|
download_path = URI.parse(download_url).path
|
|
344
350
|
tarball = File.basename(download_path)
|
|
345
351
|
|
|
@@ -365,25 +371,81 @@ class FPM::Package::CPAN < FPM::Package
|
|
|
365
371
|
return build_path(tarball)
|
|
366
372
|
end # def download
|
|
367
373
|
|
|
368
|
-
def
|
|
369
|
-
logger.info("Asking metacpan about a module", :module =>
|
|
370
|
-
|
|
374
|
+
def search_module(module_name, version=nil)
|
|
375
|
+
logger.info("Asking metacpan about a module", :module => module_name, :version => version)
|
|
376
|
+
metacpan_api_url = "#{attributes[:cpan_metacpan_api_url]}/v1/module/_search"
|
|
377
|
+
metacpan_api_query = <<-EOS
|
|
378
|
+
{
|
|
379
|
+
"query": {
|
|
380
|
+
"bool": {
|
|
381
|
+
"must": [
|
|
382
|
+
{ "term": { "module.name": "#{module_name}" } },
|
|
383
|
+
{ "term": { "maturity": "released" } },
|
|
384
|
+
{ "term": { #{version.nil? ? '"status": "latest"' : '"module.version": "' + version + '"'} } }
|
|
385
|
+
]
|
|
386
|
+
}
|
|
387
|
+
},
|
|
388
|
+
"size": 1
|
|
389
|
+
}
|
|
390
|
+
EOS
|
|
371
391
|
begin
|
|
372
|
-
response =
|
|
392
|
+
response = httppost(metacpan_api_url, metacpan_api_query)
|
|
373
393
|
rescue Net::HTTPServerException => e
|
|
374
394
|
#logger.error("metacpan query failed.", :error => response.status_line,
|
|
375
395
|
#:module => package, :url => metacpan_url)
|
|
376
396
|
logger.error("metacpan query failed.", :error => e.message,
|
|
377
|
-
:module =>
|
|
397
|
+
:module => module_name, :version => version, :url => metacpan_api_url)
|
|
378
398
|
raise FPM::InvalidPackageConfiguration, "metacpan query failed"
|
|
379
399
|
end
|
|
380
400
|
|
|
381
401
|
#data = ""
|
|
382
402
|
#response.read_body { |c| p c; data << c }
|
|
383
403
|
data = response.body
|
|
384
|
-
metadata = JSON.parse(data)
|
|
404
|
+
metadata = JSON.parse(data)['hits']['hits'][0]['_source']
|
|
385
405
|
return metadata
|
|
386
|
-
end # def
|
|
406
|
+
end # def search
|
|
407
|
+
|
|
408
|
+
def search_provided_modules(distribution, version)
|
|
409
|
+
logger.info("Asking metacpan about a releases provided modules",
|
|
410
|
+
:distribution => distribution,
|
|
411
|
+
:version => version)
|
|
412
|
+
metacpan_api_url = "#{attributes[:cpan_metacpan_api_url]}/v1/module/_search?_source=module.name,module.version"
|
|
413
|
+
metacpan_api_query = <<-EOS
|
|
414
|
+
{
|
|
415
|
+
"query": {
|
|
416
|
+
"bool": {
|
|
417
|
+
"filter": [
|
|
418
|
+
{ "exists": { "field": "module" } },
|
|
419
|
+
{ "term": { "release": "#{distribution}-#{version}" } }
|
|
420
|
+
]
|
|
421
|
+
}
|
|
422
|
+
},
|
|
423
|
+
"sort": [ { "module.name": { "order": "asc" } } ],
|
|
424
|
+
"size": 5000
|
|
425
|
+
}
|
|
426
|
+
EOS
|
|
427
|
+
|
|
428
|
+
begin
|
|
429
|
+
response = httppost(metacpan_api_url, metacpan_api_query)
|
|
430
|
+
rescue Net::HTTPServerException => e
|
|
431
|
+
logger.error("metacpan release query failed.", :error => e.message,
|
|
432
|
+
:url => metacpan_api_url)
|
|
433
|
+
raise FPM::InvalidPackageConfiguration, "metacpan release query failed"
|
|
434
|
+
end
|
|
435
|
+
query_hits = JSON.parse(response.body)['hits']['hits']
|
|
436
|
+
|
|
437
|
+
provided_modules = []
|
|
438
|
+
query_hits.each do |h|
|
|
439
|
+
h["_source"]["module"].each do |m|
|
|
440
|
+
module_name = m["name"]
|
|
441
|
+
module_version = m["version"]
|
|
442
|
+
Array(module_name).zip(Array(module_version)).each do |name, version|
|
|
443
|
+
provided_modules << cap_name(name) + (version ? " = #{version}" : "")
|
|
444
|
+
end
|
|
445
|
+
end
|
|
446
|
+
end
|
|
447
|
+
return provided_modules
|
|
448
|
+
end # def search_provided_modules
|
|
387
449
|
|
|
388
450
|
def cap_name(name)
|
|
389
451
|
return "perl(" + name.gsub("-", "::") + ")"
|
|
@@ -411,7 +473,7 @@ class FPM::Package::CPAN < FPM::Package
|
|
|
411
473
|
when Net::HTTPRedirection; return httpfetch(response["location"])
|
|
412
474
|
else; response.error!
|
|
413
475
|
end
|
|
414
|
-
end
|
|
476
|
+
end # def httpfetch
|
|
415
477
|
|
|
416
478
|
def httppost(url, body)
|
|
417
479
|
uri = URI.parse(url)
|
|
@@ -428,7 +490,7 @@ class FPM::Package::CPAN < FPM::Package
|
|
|
428
490
|
when Net::HTTPRedirection; return httppost(response["location"])
|
|
429
491
|
else; response.error!
|
|
430
492
|
end
|
|
431
|
-
end
|
|
493
|
+
end # def httppost
|
|
432
494
|
|
|
433
495
|
public(:input)
|
|
434
|
-
end # class FPM::Package::
|
|
496
|
+
end # class FPM::Package::CPAN
|
data/lib/fpm/package/deb.rb
CHANGED
|
@@ -542,6 +542,20 @@ class FPM::Package::Deb < FPM::Package
|
|
|
542
542
|
raise FPM::InvalidPackageConfiguration, "#{name}: tar is insufficient to support source_date_epoch."
|
|
543
543
|
end
|
|
544
544
|
|
|
545
|
+
systemd_file_extensions = [
|
|
546
|
+
".service",
|
|
547
|
+
".socket",
|
|
548
|
+
".device",
|
|
549
|
+
".mount",
|
|
550
|
+
".automount",
|
|
551
|
+
".swap",
|
|
552
|
+
".target",
|
|
553
|
+
".path",
|
|
554
|
+
".timer",
|
|
555
|
+
".slice",
|
|
556
|
+
".scope",
|
|
557
|
+
]
|
|
558
|
+
|
|
545
559
|
attributes[:deb_systemd] = []
|
|
546
560
|
attributes.fetch(:deb_systemd_list, []).each do |systemd|
|
|
547
561
|
name = File.basename(systemd)
|
|
@@ -549,10 +563,16 @@ class FPM::Package::Deb < FPM::Package
|
|
|
549
563
|
|
|
550
564
|
name_with_extension = if extname.empty?
|
|
551
565
|
"#{name}.service"
|
|
552
|
-
elsif
|
|
566
|
+
elsif systemd_file_extensions.include?(extname)
|
|
553
567
|
name
|
|
554
568
|
else
|
|
555
|
-
|
|
569
|
+
# Mutating the array is fine as we raise directly after, and the array will be re-initialised next time
|
|
570
|
+
# this method is called. If this branch is changed in the future so as not to diverge, care should be
|
|
571
|
+
# taken to ensure that this mutated version of the array is only used for generating the error message.
|
|
572
|
+
systemd_file_extensions[-1] = systemd_file_extensions[-1].prepend("or ")
|
|
573
|
+
possible_extensions_str = systemd_file_extensions.join(", ")
|
|
574
|
+
raise FPM::InvalidPackageConfiguration,
|
|
575
|
+
"Invalid systemd unit file extension: #{extname}. Expected one of: #{possible_extensions_str}"
|
|
556
576
|
end
|
|
557
577
|
|
|
558
578
|
dest_systemd = staging_path(File.join(attributes[:deb_systemd_path], "#{name_with_extension}"))
|
|
@@ -767,10 +787,19 @@ class FPM::Package::Deb < FPM::Package
|
|
|
767
787
|
self.provides = self.provides.reject { |p| p.empty? }
|
|
768
788
|
|
|
769
789
|
if origin == FPM::Package::CPAN
|
|
790
|
+
|
|
791
|
+
# By default, we'd prefer to name Debian-targeted Perl packages using the
|
|
792
|
+
# same naming scheme that Debian itself uses, which is usually something
|
|
793
|
+
# like "lib<module-name-hyphenated>-perl", such as libregexp-common-perl
|
|
794
|
+
#
|
|
795
|
+
logger.info("Changing package name to match Debian's typical libmodule-name-perl style")
|
|
796
|
+
self.name = "lib#{self.name.sub(/^perl-/, "")}-perl"
|
|
797
|
+
|
|
770
798
|
# The fpm cpan code presents dependencies and provides fields as perl(ModuleName)
|
|
771
799
|
# so we'll need to convert them to something debian supports.
|
|
772
800
|
|
|
773
|
-
# Replace perl(
|
|
801
|
+
# Replace perl(Module::Name) > 1.0 with Debian-style libmodule-name-perl (> 1.0)
|
|
802
|
+
# per: https://www.debian.org/doc/packaging-manuals/perl-policy/ch-module_packages.html
|
|
774
803
|
perldepfix = lambda do |dep|
|
|
775
804
|
m = dep.match(/perl\((?<name>[A-Za-z0-9_:]+)\)\s*(?<op>.*$)/)
|
|
776
805
|
if m.nil?
|
|
@@ -781,7 +810,7 @@ class FPM::Package::Deb < FPM::Package
|
|
|
781
810
|
modulename = m["name"].gsub("::", "-")
|
|
782
811
|
|
|
783
812
|
# Fix any upper-casing or other naming concerns Debian has about packages
|
|
784
|
-
name = "#{
|
|
813
|
+
name = "lib#{modulename}-perl"
|
|
785
814
|
|
|
786
815
|
if m["op"].empty?
|
|
787
816
|
name
|
|
@@ -792,9 +821,12 @@ class FPM::Package::Deb < FPM::Package
|
|
|
792
821
|
end
|
|
793
822
|
end
|
|
794
823
|
|
|
795
|
-
rejects = [
|
|
824
|
+
rejects = attributes[:rejects].map do |skip|
|
|
825
|
+
"perl(#{skip})"
|
|
826
|
+
end
|
|
796
827
|
self.dependencies = self.dependencies.reject do |dep|
|
|
797
828
|
# Reject non-module Perl dependencies like 'vars' and 'warnings'
|
|
829
|
+
dep, _ = dep.split(' ') # strip potential version component
|
|
798
830
|
rejects.include?(dep)
|
|
799
831
|
end.collect(&perldepfix).collect(&method(:fix_dependency))
|
|
800
832
|
|
|
@@ -1174,7 +1206,7 @@ class FPM::Package::Deb < FPM::Package
|
|
|
1174
1206
|
end
|
|
1175
1207
|
upstarts.each do |upstart|
|
|
1176
1208
|
name = File.basename(upstart, ".upstart")
|
|
1177
|
-
upstartscript = "etc/init/#{name}.conf"
|
|
1209
|
+
upstartscript = "/etc/init/#{name}.conf"
|
|
1178
1210
|
logger.debug("Add conf file declaration for upstart script", :script => upstartscript)
|
|
1179
1211
|
allconfigs << upstartscript[1..-1]
|
|
1180
1212
|
end
|
data/lib/fpm/package/gem.rb
CHANGED
|
@@ -381,7 +381,7 @@ class FPM::Package::Gem < FPM::Package
|
|
|
381
381
|
logger.debug("Gem %s did not have changelog with recognized name" % [name])
|
|
382
382
|
# FIXME: check rubygems.org?
|
|
383
383
|
end
|
|
384
|
-
end # detect_source_date_from_changelog
|
|
384
|
+
end # def detect_source_date_from_changelog
|
|
385
385
|
|
|
386
386
|
public(:input, :output)
|
|
387
387
|
end # class FPM::Package::Gem
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
#import pkg_resources
|
|
4
4
|
import packaging.requirements
|
|
5
|
+
import packaging.markers
|
|
5
6
|
import json
|
|
6
7
|
import sys
|
|
7
8
|
|
|
@@ -11,10 +12,9 @@ import sys
|
|
|
11
12
|
# Process environment markers, if any, and produce a list of requirements for the current environment.
|
|
12
13
|
def evaluate_requirements(fd):
|
|
13
14
|
all_requirements = [packaging.requirements.Requirement(line) for line in sys.stdin]
|
|
14
|
-
|
|
15
|
+
default_env = packaging.markers.default_environment()
|
|
15
16
|
for req in all_requirements:
|
|
16
|
-
|
|
17
|
-
if req.marker is None or req.marker.evaluate():
|
|
17
|
+
if req.marker is None or req.marker.evaluate(environment=default_env):
|
|
18
18
|
if len(req.specifier) > 0:
|
|
19
19
|
for spec in req.specifier:
|
|
20
20
|
yield "%s%s" % (req.name, spec)
|
data/lib/fpm/package/python.rb
CHANGED
|
@@ -119,7 +119,7 @@ class FPM::Package::Python < FPM::Package
|
|
|
119
119
|
headers[field] = []
|
|
120
120
|
end
|
|
121
121
|
|
|
122
|
-
while !s.eos? and !s.scan(
|
|
122
|
+
while !s.eos? and !s.scan(/\n/) do
|
|
123
123
|
# Field is non-space up, but excluding the colon
|
|
124
124
|
field = s.scan(/[^\s:]+/)
|
|
125
125
|
|
|
@@ -148,11 +148,11 @@ class FPM::Package::Python < FPM::Package
|
|
|
148
148
|
# Per Python core-metadata spec:
|
|
149
149
|
# > Changed in version 2.1: This field may be specified in the message body instead.
|
|
150
150
|
#return PythonMetadata.new(headers, s.string[s.pos ...])
|
|
151
|
-
return headers, s.string[s.pos
|
|
151
|
+
return headers, s.string[s.pos .. -1]
|
|
152
152
|
elsif headers["Metadata-Version"].to_f >= 2.0
|
|
153
153
|
# dnspython v1.15.0 has a description body and Metadata-Version 2.0
|
|
154
154
|
# this seems out of spec, but let's accept it anyway.
|
|
155
|
-
return headers, s.string[s.pos
|
|
155
|
+
return headers, s.string[s.pos .. -1]
|
|
156
156
|
else
|
|
157
157
|
raise "After reading METADATA headers, extra data is in the file but was not expected. This may be a bug in fpm."
|
|
158
158
|
end
|
|
@@ -166,7 +166,7 @@ class FPM::Package::Python < FPM::Package
|
|
|
166
166
|
puts "---"
|
|
167
167
|
puts input
|
|
168
168
|
puts "==="
|
|
169
|
-
puts input[s.pointer
|
|
169
|
+
puts input[s.pointer..-1]
|
|
170
170
|
puts "---"
|
|
171
171
|
raise e
|
|
172
172
|
end # self.parse
|
|
@@ -453,7 +453,7 @@ class FPM::Package::Python < FPM::Package
|
|
|
453
453
|
|
|
454
454
|
safesystem(*setup_cmd)
|
|
455
455
|
|
|
456
|
-
files = ::Dir.entries(target).
|
|
456
|
+
files = ::Dir.entries(target).select { |entry| entry =~ /\.(whl|tgz|tar\.gz|zip)$/ }
|
|
457
457
|
if files.length != 1
|
|
458
458
|
raise "Unexpected directory layout after `pip download ...`. This might be an fpm bug? The directory contains these files: #{files.inspect}"
|
|
459
459
|
end
|
|
@@ -605,7 +605,7 @@ class FPM::Package::Python < FPM::Package
|
|
|
605
605
|
flags = [ "--root", staging_path ]
|
|
606
606
|
flags += [ "--prefix", prefix ] if !attributes[:prefix].nil?
|
|
607
607
|
|
|
608
|
-
safesystem(*attributes[:python_pip], "install", "--no-deps", *flags, path)
|
|
608
|
+
safesystem(*attributes[:python_pip], "install", "--no-deps", "--ignore-installed", *flags, path)
|
|
609
609
|
end # def install_to_staging
|
|
610
610
|
|
|
611
611
|
public(:input)
|
data/lib/fpm/package.rb
CHANGED
|
@@ -226,7 +226,7 @@ class FPM::Package
|
|
|
226
226
|
def converted_from(origin)
|
|
227
227
|
# nothing to do by default. Subclasses may implement this.
|
|
228
228
|
# See the RPM package class for an example.
|
|
229
|
-
end # def
|
|
229
|
+
end # def converted_from
|
|
230
230
|
|
|
231
231
|
# Add a new source to this package.
|
|
232
232
|
# The exact behavior depends on the kind of package being managed.
|
|
@@ -324,7 +324,7 @@ class FPM::Package
|
|
|
324
324
|
|
|
325
325
|
def template_dir
|
|
326
326
|
File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "templates"))
|
|
327
|
-
end
|
|
327
|
+
end # def template_dir
|
|
328
328
|
|
|
329
329
|
def template(path)
|
|
330
330
|
template_path = File.join(template_dir, path)
|
|
@@ -437,7 +437,7 @@ class FPM::Package
|
|
|
437
437
|
|
|
438
438
|
help = "(#{type} only) #{help}"
|
|
439
439
|
@options << [flag, param, help, options, block]
|
|
440
|
-
end # def
|
|
440
|
+
end # def option
|
|
441
441
|
|
|
442
442
|
# Apply the options for this package on the clamp command
|
|
443
443
|
#
|
|
@@ -510,7 +510,7 @@ class FPM::Package
|
|
|
510
510
|
File.chmod(0755, out)
|
|
511
511
|
end
|
|
512
512
|
end
|
|
513
|
-
end
|
|
513
|
+
end # def write_scripts
|
|
514
514
|
|
|
515
515
|
# Get the contents of the script by a given name.
|
|
516
516
|
#
|
|
@@ -547,7 +547,7 @@ class FPM::Package
|
|
|
547
547
|
else
|
|
548
548
|
@provides = value
|
|
549
549
|
end
|
|
550
|
-
end
|
|
550
|
+
end # def provides=
|
|
551
551
|
|
|
552
552
|
# General public API
|
|
553
553
|
public(:type, :initialize, :convert, :input, :output, :to_s, :cleanup, :files,
|
data/lib/fpm/util.rb
CHANGED
|
@@ -38,7 +38,7 @@ module FPM::Util
|
|
|
38
38
|
shell = ENV["SHELL"]
|
|
39
39
|
return "/bin/sh" if shell.nil? || shell.empty?
|
|
40
40
|
return shell
|
|
41
|
-
end
|
|
41
|
+
end # def default_shell
|
|
42
42
|
|
|
43
43
|
############################################################################
|
|
44
44
|
# execmd([env,] cmd [,opts])
|
|
@@ -250,7 +250,7 @@ module FPM::Util
|
|
|
250
250
|
end
|
|
251
251
|
end
|
|
252
252
|
# If no combination of ar and options omits timestamps, fall back to default.
|
|
253
|
-
@@ar_cmd = ["ar", "-
|
|
253
|
+
@@ar_cmd = ["ar", "-qcS"]
|
|
254
254
|
FileUtils.rm_f([testarchive, emptyfile])
|
|
255
255
|
return @@ar_cmd
|
|
256
256
|
end # def ar_cmd
|
|
@@ -259,7 +259,7 @@ module FPM::Util
|
|
|
259
259
|
def ar_cmd_deterministic?
|
|
260
260
|
ar_cmd if not defined? @@ar_cmd_deterministic
|
|
261
261
|
return @@ar_cmd_deterministic
|
|
262
|
-
end
|
|
262
|
+
end # def ar_cmd_deterministic?
|
|
263
263
|
|
|
264
264
|
# Get the recommended 'tar' command for this platform.
|
|
265
265
|
def tar_cmd
|
|
@@ -306,7 +306,7 @@ module FPM::Util
|
|
|
306
306
|
def tar_cmd_supports_sort_names_and_set_mtime?
|
|
307
307
|
tar_cmd if not defined? @@tar_cmd_deterministic
|
|
308
308
|
return @@tar_cmd_deterministic
|
|
309
|
-
end
|
|
309
|
+
end # def tar_cmd_supports_sort_names_and_set_mtime?
|
|
310
310
|
|
|
311
311
|
def copy_metadata(source, destination)
|
|
312
312
|
source_stat = File::lstat(source)
|
|
@@ -452,7 +452,7 @@ module FPM::Util
|
|
|
452
452
|
# Ruby 3.1.0 and newer
|
|
453
453
|
return ERB.new(template_code, trim_mode: "-")
|
|
454
454
|
end
|
|
455
|
-
end
|
|
455
|
+
end # def erbnew
|
|
456
456
|
end # module FPM::Util
|
|
457
457
|
|
|
458
458
|
require 'fpm/util/tar_writer'
|
data/lib/fpm/version.rb
CHANGED
data/templates/sh.erb
CHANGED
|
@@ -137,7 +137,7 @@ function save_environment(){
|
|
|
137
137
|
|
|
138
138
|
# just piping env to a file doesn't quote the variables. This does
|
|
139
139
|
# filter out multiline junk, _, and functions. _ is a readonly variable.
|
|
140
|
-
env | grep -v "^_=" | grep -v "^[^=(]*()=" | egrep "^[^ ]+=" | while read ENVVAR ; do
|
|
140
|
+
env | grep -v "^_=" | grep -v "^[^=(]*()=" | grep -v "^BASH_FUNC_.*%%=" |egrep "^[^ ]+=" | while read ENVVAR ; do
|
|
141
141
|
local NAME=${ENVVAR%%=*}
|
|
142
142
|
# sed is to preserve variable values with dollars (for escaped variables or $() style command replacement),
|
|
143
143
|
# and command replacement backticks
|
metadata
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fpm
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.18.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jordan Sissel
|
|
8
|
+
autorequire:
|
|
8
9
|
bindir: bin
|
|
9
10
|
cert_chain: []
|
|
10
|
-
date:
|
|
11
|
+
date: 2026-08-26 00:00:00.000000000 Z
|
|
11
12
|
dependencies:
|
|
12
13
|
- !ruby/object:Gem::Dependency
|
|
13
14
|
name: cabin
|
|
@@ -197,7 +198,6 @@ files:
|
|
|
197
198
|
- lib/fpm/package/pleaserun.rb
|
|
198
199
|
- lib/fpm/package/puppet.rb
|
|
199
200
|
- lib/fpm/package/pyfpm/__init__.py
|
|
200
|
-
- lib/fpm/package/pyfpm/get_metadata.py
|
|
201
201
|
- lib/fpm/package/pyfpm/parse_requires.py
|
|
202
202
|
- lib/fpm/package/python.rb
|
|
203
203
|
- lib/fpm/package/rpm.rb
|
|
@@ -238,6 +238,7 @@ homepage: https://github.com/jordansissel/fpm
|
|
|
238
238
|
licenses:
|
|
239
239
|
- MIT-like
|
|
240
240
|
metadata: {}
|
|
241
|
+
post_install_message:
|
|
241
242
|
rdoc_options: []
|
|
242
243
|
require_paths:
|
|
243
244
|
- lib
|
|
@@ -253,7 +254,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
253
254
|
- !ruby/object:Gem::Version
|
|
254
255
|
version: '0'
|
|
255
256
|
requirements: []
|
|
256
|
-
rubygems_version: 3.
|
|
257
|
+
rubygems_version: 3.0.3.1
|
|
258
|
+
signing_key:
|
|
257
259
|
specification_version: 4
|
|
258
260
|
summary: fpm - package building and mangling
|
|
259
261
|
test_files: []
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
from distutils.core import Command
|
|
2
|
-
import os
|
|
3
|
-
import sys
|
|
4
|
-
import pkg_resources
|
|
5
|
-
try:
|
|
6
|
-
import json
|
|
7
|
-
except ImportError:
|
|
8
|
-
import simplejson as json
|
|
9
|
-
|
|
10
|
-
PY3 = sys.version_info[0] == 3
|
|
11
|
-
|
|
12
|
-
if PY3:
|
|
13
|
-
def u(s):
|
|
14
|
-
return s
|
|
15
|
-
else:
|
|
16
|
-
def u(s):
|
|
17
|
-
if isinstance(u, unicode):
|
|
18
|
-
return u
|
|
19
|
-
return s.decode('utf-8')
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
# Note, the last time I coded python daily was at Google, so it's entirely
|
|
23
|
-
# possible some of my techniques below are outdated or bad.
|
|
24
|
-
# If you have fixes, let me know.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
class get_metadata(Command):
|
|
28
|
-
description = "get package metadata"
|
|
29
|
-
user_options = [
|
|
30
|
-
('load-requirements-txt', 'l',
|
|
31
|
-
"load dependencies from requirements.txt"),
|
|
32
|
-
("output=", "o", "output destination for metadata json")
|
|
33
|
-
]
|
|
34
|
-
boolean_options = ['load-requirements-txt']
|
|
35
|
-
|
|
36
|
-
def initialize_options(self):
|
|
37
|
-
self.load_requirements_txt = False
|
|
38
|
-
self.cwd = None
|
|
39
|
-
self.output = None
|
|
40
|
-
|
|
41
|
-
def finalize_options(self):
|
|
42
|
-
self.cwd = os.getcwd()
|
|
43
|
-
self.requirements_txt = os.path.join(self.cwd, "requirements.txt")
|
|
44
|
-
# make sure we have a requirements.txt
|
|
45
|
-
if self.load_requirements_txt:
|
|
46
|
-
self.load_requirements_txt = os.path.exists(self.requirements_txt)
|
|
47
|
-
|
|
48
|
-
def process_dep(self, dep):
|
|
49
|
-
deps = []
|
|
50
|
-
if hasattr(dep, 'marker') and dep.marker:
|
|
51
|
-
# PEP0508 marker present
|
|
52
|
-
if not dep.marker.evaluate():
|
|
53
|
-
return deps
|
|
54
|
-
|
|
55
|
-
if dep.specs:
|
|
56
|
-
for operator, version in dep.specs:
|
|
57
|
-
deps.append("%s %s %s" % (dep.project_name,
|
|
58
|
-
operator, version))
|
|
59
|
-
else:
|
|
60
|
-
deps.append(dep.project_name)
|
|
61
|
-
|
|
62
|
-
return deps
|
|
63
|
-
|
|
64
|
-
def run(self):
|
|
65
|
-
data = {
|
|
66
|
-
"name": self.distribution.get_name(),
|
|
67
|
-
"version": self.distribution.get_version(),
|
|
68
|
-
"author": u("%s <%s>") % (
|
|
69
|
-
u(self.distribution.get_author()),
|
|
70
|
-
u(self.distribution.get_author_email()),
|
|
71
|
-
),
|
|
72
|
-
"description": self.distribution.get_description(),
|
|
73
|
-
"license": self.distribution.get_license(),
|
|
74
|
-
"url": self.distribution.get_url(),
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
if self.distribution.has_ext_modules():
|
|
78
|
-
data["architecture"] = "native"
|
|
79
|
-
else:
|
|
80
|
-
data["architecture"] = "all"
|
|
81
|
-
|
|
82
|
-
final_deps = []
|
|
83
|
-
|
|
84
|
-
if self.load_requirements_txt:
|
|
85
|
-
requirement = open(self.requirements_txt).readlines()
|
|
86
|
-
for dep in pkg_resources.parse_requirements(requirement):
|
|
87
|
-
final_deps.extend(self.process_dep(dep))
|
|
88
|
-
else:
|
|
89
|
-
if getattr(self.distribution, 'install_requires', None):
|
|
90
|
-
for dep in pkg_resources.parse_requirements(
|
|
91
|
-
self.distribution.install_requires):
|
|
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))
|
|
98
|
-
|
|
99
|
-
data["dependencies"] = final_deps
|
|
100
|
-
|
|
101
|
-
output = open(self.output, "w")
|
|
102
|
-
if hasattr(json, 'dumps'):
|
|
103
|
-
def default_to_str(obj):
|
|
104
|
-
""" Fall back to using __str__ if possible """
|
|
105
|
-
# This checks if the class of obj defines __str__ itself,
|
|
106
|
-
# so we don't fall back to an inherited __str__ method.
|
|
107
|
-
if "__str__" in type(obj).__dict__:
|
|
108
|
-
return str(obj)
|
|
109
|
-
return json.JSONEncoder.default(self, obj)
|
|
110
|
-
|
|
111
|
-
output.write(json.dumps(data, indent=2, default=default_to_str))
|
|
112
|
-
else:
|
|
113
|
-
# For Python 2.5 and Debian's python-json
|
|
114
|
-
output.write(json.write(data))
|
|
115
|
-
output.close()
|