fpm 1.12.0 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 28f939bd20768768cb05026a39c8a270596368c654ec5606a43a0e75afa845ad
4
- data.tar.gz: 0d7eea7108832e79994ba3ee9511c3715b384906f7ef3a2ab5e907cfc764609a
3
+ metadata.gz: '079f0bd8cc1fe2a84b6e5dfc38cc0ae2e509d271d9752e0fb739c7cde79c746b'
4
+ data.tar.gz: 28ed14320c22c0dc5767781d3f325cd4e817b16e42999b0a2d1e2713522d0761
5
5
  SHA512:
6
- metadata.gz: 555edd6cd5d4b0098e075011e48db96e52c454b8557735a51202307dcaeb4920a5efe93bb6d99cedf9d3ff95ff445c37059e1fc308e0602482977587d532e4b1
7
- data.tar.gz: 2803ea8cb3af495d5fd20e75bee0eba11dc262ac59b86e63b75ef3cef7417440e88e1fec9172f7a1ea5cf0705e2ce36bc65e7b9c1c5469eb0e78b292ac822716
6
+ metadata.gz: b6287a7079c1f00a327d92a268f46df825cdbcc5008d719a23a4dd8f4fdba574bedf735f559207781794c7c29cf39153092d1f1452d8d3ddd4d23f808a8856ae
7
+ data.tar.gz: 4c90779c8b7990818a76dc4fd60035311fe8ad461e7717271abd11318d1cad10bff03783468ee78fa17bc8455d692deabd69c41bb0ffef8195d6c4be61a56d6e
data/CHANGELOG.rst CHANGED
@@ -1,6 +1,46 @@
1
1
  Release Notes and Change Log
2
2
  ============================
3
3
 
4
+ 1.14.1 (November 10, 2021)
5
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^
6
+ * Fix a bug that impacted fpm api usage (from other ruby programs) that caused an error "NameError: uninitialized constant FPM::Package::CPAN" when trying to output a Deb package. (`#1854`_, `#1856`_; Karol Bucek, Jordan Sissel)
7
+
8
+ 1.14.0 (November 9, 2021)
9
+ ^^^^^^^^^^^^^^^^^^^^^^^^^
10
+ * python: Use pip by default for fetching Python packages. This matches the Python 3 "installation" docs which recommend calling pip as ``python -m pip`` where ``python`` depends on ``--python-bin`` (default "python"). Previous default was to use `easy_install` which is no longer available on many newer systems. To use easy_install, you can set ``--no-python-internal-pip`` to revert this pip default. Further, you can specify your own pip path instead of using ``python -m pip`` with the ``--python-pip /path/to/pip`` flag. (`#1820`_, `#1821`_; Jordan Sissel)
11
+ * python: Support extras_require build markers in python packages (`#1307`_, `#1816`_; Joris Vandermeersch)
12
+ * freebsd: Fix bug which caused fpm to generate incorrect FreeBSD packages "missing leading `/`" (`#1811`_, `#1812`_, `#1844`_, `#1832`_, `#1845`_; Vlastimil Holer, Clayton Wong, Markus Ueberall, Jordan Sissel)
13
+ * deb: In order to only allow fpm to create valid packages, fpm now rejects packages with invalid "provides" (``--provides``) values. (`#1829`_, `#1825`_; Jordan Sissel, Peter Teichman)
14
+ * deb: Only show a warning about /etc and config files if there are files in /etc (`#1852`_, `#1851`_; Jordan Sissel)
15
+
16
+ * rpm: replace dash with underscore in rpm's "Release" field aka what fpm calls ``--iteration``. (`#1834`_, `#1833`_; Jordan Sissel)
17
+ * empty: `fpm -s empty ...` now defaults to "all" architecture instead of "native". (`#1850`_, `#1846`_; Jordan Sissel)
18
+ * Significant documentation improvements rewriting most of the documentation. New overview pages, full CLI flag listing, and new sections dedicated package types (rpm, cpan, deb, etc). (`#1815`_, `#1817`_, `#1838`_; Vedant K, Jordan Sissel)
19
+ * Typo fixes in documentation are always appreciated! (`#1842`_; Clayton Wong)
20
+ * fpm can now (we hope!) now be tested more easily from docker (`#1818`_, `#1682`_, `#1453`_; @directionless, Jordan Sissel, Douglas Muth)
21
+
22
+ 1.13.1 (July 6, 2021)
23
+ ^^^^^^^^^^^^^^^^^^^^^
24
+ * deb: The `--provides` flag now allows for versions. Previously, fpm would
25
+ remove the version part of a provides field when generating deb packages.
26
+ (`#1788`_, `#1803`_; Jordan Sissel, Phil Schwartz, tympanix)
27
+ * osxpkg: Update documentation to include installing `rpm` tools on OSX
28
+ (`#1797`_; allen joslin)
29
+
30
+ 1.13.0 (June 19, 2021)
31
+ ^^^^^^^^^^^^^^^^^^^^^^
32
+ * Apple M1 users should now work (`#1772`_, `#1785`_, `#1786`_; Jordan Sissel)
33
+ * Removed `ffi` ruby library as a dependency. This should make it easier to support a wider range of Ruby versions (Ruby 2.2, 3.0, etc) and platforms (like arm64, Apple M1, etc) in the future. (`#1785`_, `#1786`_; Jordan Sissel)
34
+ * Now uses the correct architecture synonym for ARM 64 systems. Debian uses `arm64` as a synonym for what other systems call `aarch64` (linux kernel, RPM, Arch Linux). (`#1775`_; Steve Kamerman)
35
+ * Docs: Fix a typo in an example (`#1785`_; Zoe O'Connell)
36
+ * rpm: File paths can now contain single-quote characters (`#1774`_; Jordan Sissel)
37
+ * rpm: Use correct SPEC syntax when using --after-upgrade or similar features (`#1761`_; Jo Vandeginste. Robert Fielding)
38
+ * Ruby 3.0 support: Added `rexml` as a runtime dependency. In Ruby 2.0, `rexml` came by default, but in Ruby 3.0, `rexml` is now a bundled gem and some distributiosn do not include it by default. (`#1794`_; Jordan Sissel)
39
+ * Fix error "git: not found (Git::GitExecuteError)". Now loads `git` library only when using git features. (`#1753`_, `#1748`_, `#1751`_, `#1766`_; Jordan Sissel, Cameron Nemo, Jason Rogers, Luke Short)
40
+ * deb: Fix syntax error in `postinst` (`--after-install`) script. (`#1752`_, `#1749`_, `#1764`_; rmanus, Adam Mohammed, Elliot Murphy, kimw, Jordan Sissel)
41
+ * deb: --deb-compression now uses the same compression and file suffix on the control.tar file (`#1760`_; Philippe Poilbarbe)
42
+
43
+
4
44
  1.12.0 (January 19, 2021)
5
45
  ^^^^^^^^^^^^^^^^^^^^^^^^^
6
46
 
@@ -36,7 +76,7 @@ Release Notes and Change Log
36
76
  * cpan: Adds `--[no-]cpan-verbose` flag which, when set, runs `cpanm` with the `--verbose` flag (`#1511`_; William N. Braswell, Jr)
37
77
 
38
78
  1.10.0 (May 21, 2018)
39
- ^^^^^^^^^^^^^^^^^^^^
79
+ ^^^^^^^^^^^^^^^^^^^^^
40
80
 
41
81
  * Pin `ruby-xz` dependency to one which allows Ruby versions older than 2.3.0 (`#1494`_; Marat Sharafutdinov)
42
82
  * Documentation improvements: `#1488`_; Arthur Burkart. `#1384`_; Justin Kolberg. `#1452`_; Anatoli Babenia.
@@ -64,7 +104,7 @@ Release Notes and Change Log
64
104
  * rpm: Fix `--config-files` handling (`#1390`_, `#1391`_; Jordan Sissel)
65
105
 
66
106
  1.9.1 (July 28, 2017) happy sysadmin day!
67
- ^^^^^^^^^^^^^^^^^^^^^
107
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
68
108
 
69
109
  * Documentation improvements: `#1291`_; Pablo Castellano. `#1321`_; ge-fa. `#1309`_; jesusbagpuss. `#1349`_; Perry Stole. `#1352`_, Jordan Sissel. `#1384`_; Justin Kolberg.
70
110
  * Testing improvements: `#1320`_; Rob Young. `#1266`_; Ryan Parman. `#1374`_; Thiago Figueiró.
@@ -93,9 +133,9 @@ Release Notes and Change Log
93
133
  * Other: Remove unused archive-tar-minitar as a dependency of fpm (`#1355`_; Diego Martins)
94
134
  * Other: Add stud as a runtime dependency (`#1354`_; Elan Ruusamäe)
95
135
 
96
- .. _reproducible_builds:: https://reproducible-builds.org/
97
- .. _path mapping:: http://fpm.readthedocs.io/en/latest/source/dir.html#path-mapping
98
- .. _Deterministic output:: http://fpm.readthedocs.io/en/latest/source/gem.html
136
+ .. _reproducible_builds: https://reproducible-builds.org/
137
+ .. _path mapping: source/dir.html#path-mapping
138
+ .. _Deterministic output: source/gem.html
99
139
 
100
140
  1.9.0 (July 28, 2017)
101
141
  ^^^^^^^^^^^^^^^^^^^^^
data/CONTRIBUTORS CHANGED
@@ -21,6 +21,7 @@ sbuss
21
21
  Brett Gailey (github: dnbert)
22
22
  Daniel Haskin (github: djhaskin987)
23
23
  Richard Grainger (github: liger1978)
24
+ seph (github: directionless)
24
25
 
25
26
  If you have contributed (bug reports, feature requests, help in IRC, blog
26
27
  posts, code, etc) and aren't listed here, please let me know if you wish to be
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  (This is an MIT-style license)
2
2
 
3
- Copyright (c) 2011-2017 Jordan Sissel and contributors.
3
+ Copyright (c) 2011-2021 Jordan Sissel and contributors.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -8,6 +8,10 @@ require "fileutils"
8
8
  require "digest"
9
9
  require "zlib"
10
10
 
11
+ # For handling conversion
12
+ require "fpm/package/cpan"
13
+ require "fpm/package/gem"
14
+
11
15
  # Support for debian packages (.deb files)
12
16
  #
13
17
  # This class supports both input and output of packages.
@@ -25,6 +29,17 @@ class FPM::Package::Deb < FPM::Package
25
29
  # The list of supported compression types. Default is gz (gzip)
26
30
  COMPRESSION_TYPES = [ "gz", "bzip2", "xz", "none" ]
27
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+~.]+)?)\))?$/
42
+
28
43
  option "--ignore-iteration-in-dependencies", :flag,
29
44
  "For '=' (equal) dependencies, allow iterations on the specified " \
30
45
  "version. Default is to be specific. This option allows the same " \
@@ -178,7 +193,7 @@ class FPM::Package::Deb < FPM::Package
178
193
  end
179
194
 
180
195
  option "--systemd", "FILEPATH", "Add FILEPATH as a systemd script",
181
- :multivalued => true do |file|
196
+ :multivalued => true do |file|
182
197
  next File.expand_path(file)
183
198
  end
184
199
 
@@ -228,6 +243,9 @@ class FPM::Package::Deb < FPM::Package
228
243
  when "x86_64"
229
244
  # Debian calls x86_64 "amd64"
230
245
  @architecture = "amd64"
246
+ when "aarch64"
247
+ # Debian calls aarch64 "arm64"
248
+ @architecture = "arm64"
231
249
  when "noarch"
232
250
  # Debian calls noarch "all"
233
251
  @architecture = "all"
@@ -424,6 +442,12 @@ class FPM::Package::Deb < FPM::Package
424
442
 
425
443
  def output(output_path)
426
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
427
451
  output_check(output_path)
428
452
  # Abort if the target path already exists.
429
453
 
@@ -588,15 +612,19 @@ class FPM::Package::Deb < FPM::Package
588
612
  case self.attributes[:deb_compression]
589
613
  when "gz", nil
590
614
  datatar = build_path("data.tar.gz")
615
+ controltar = build_path("control.tar.gz")
591
616
  compression = "-z"
592
617
  when "bzip2"
593
618
  datatar = build_path("data.tar.bz2")
619
+ controltar = build_path("control.tar.gz")
594
620
  compression = "-j"
595
621
  when "xz"
596
622
  datatar = build_path("data.tar.xz")
623
+ controltar = build_path("control.tar.xz")
597
624
  compression = "-J"
598
625
  when "none"
599
626
  datatar = build_path("data.tar")
627
+ controltar = build_path("control.tar")
600
628
  compression = ""
601
629
  else
602
630
  raise FPM::InvalidPackageConfiguration,
@@ -616,7 +644,7 @@ class FPM::Package::Deb < FPM::Package
616
644
  # the 'debian-binary' file has to be first
617
645
  File.expand_path(output_path).tap do |output_path|
618
646
  ::Dir.chdir(build_path) do
619
- safesystem(*ar_cmd, output_path, "debian-binary", "control.tar.gz", datatar)
647
+ safesystem(*ar_cmd, output_path, "debian-binary", controltar, datatar)
620
648
  end
621
649
  end
622
650
 
@@ -653,6 +681,43 @@ class FPM::Package::Deb < FPM::Package
653
681
  fix_provides(provides)
654
682
  end.flatten
655
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
+
656
721
  if origin == FPM::Package::Deb
657
722
  changelog_path = staging_path("usr/share/doc/#{name}/changelog.Debian.gz")
658
723
  if File.exists?(changelog_path)
@@ -680,6 +745,19 @@ class FPM::Package::Deb < FPM::Package
680
745
  File.unlink(changelog_path)
681
746
  end
682
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
683
761
  end # def converted_from
684
762
 
685
763
  def debianize_op(op)
@@ -754,6 +832,32 @@ class FPM::Package::Deb < FPM::Package
754
832
  end
755
833
  end # def fix_dependency
756
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
+
757
861
  def fix_provides(provides)
758
862
  name_re = /^[^ \(]+/
759
863
  name = provides[name_re]
@@ -768,6 +872,11 @@ class FPM::Package::Deb < FPM::Package
768
872
  "debs don't like underscores")
769
873
  provides = provides.gsub("_", "-")
770
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
771
880
  return provides.rstrip
772
881
  end
773
882
 
@@ -795,12 +904,9 @@ class FPM::Package::Deb < FPM::Package
795
904
 
796
905
  # Tar up the staging_path into control.tar.{compression type}
797
906
  case self.attributes[:deb_compression]
798
- when "gz", nil
907
+ when "gz", "bzip2", nil
799
908
  controltar = "control.tar.gz"
800
909
  compression = "-z"
801
- when "bzip2"
802
- controltar = "control.tar.bz2"
803
- compression = "-j"
804
910
  when "xz"
805
911
  controltar = "control.tar.xz"
806
912
  compression = "-J"
@@ -905,7 +1011,7 @@ class FPM::Package::Deb < FPM::Package
905
1011
  etcfiles = []
906
1012
  # Add everything in /etc
907
1013
  begin
908
- if !attributes[:deb_no_default_config_files?]
1014
+ if !attributes[:deb_no_default_config_files?] && File.exists?(staging_path("/etc"))
909
1015
  logger.warn("Debian packaging tools generally labels all files in /etc as config files, " \
910
1016
  "as mandated by policy, so fpm defaults to this behavior for deb packages. " \
911
1017
  "You can disable this default behavior with --deb-no-default-config-files flag")
@@ -4,6 +4,18 @@ require "backports/latest"
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
@@ -17,10 +17,6 @@ class FPM::Package::FreeBSD < FPM::Package
17
17
  :default => "fpm/<name>"
18
18
 
19
19
  def output(output_path)
20
- # See https://github.com/jordansissel/fpm/issues/1090
21
- # require xz later, because this triggers a load of liblzma.so.5 that is
22
- # unavailable on older CentOS/RH distros.
23
- require "xz"
24
20
  output_check(output_path)
25
21
 
26
22
  # Build the packaging metadata files.
@@ -80,22 +76,17 @@ class FPM::Package::FreeBSD < FPM::Package
80
76
  file.write(pkgdata.to_json + "\n")
81
77
  end
82
78
 
83
- # Create the .txz package archive from the files in staging_path.
84
- File.open(output_path, "wb") do |file|
85
- XZ::StreamWriter.new(file) do |xz|
86
- FPM::Util::TarWriter.new(xz) do |tar|
87
- # The manifests must come first for pkg.
88
- add_path(tar, "+COMPACT_MANIFEST",
89
- File.join(staging_path, "+COMPACT_MANIFEST"))
90
- add_path(tar, "+MANIFEST",
91
- File.join(staging_path, "+MANIFEST"))
92
-
93
- checksums.keys.each do |path|
94
- add_path(tar, "/" + path, File.join(staging_path, path))
95
- end
96
- end
97
- end
79
+ file_list = File.new(build_path("file_list"), "w")
80
+ files.each do |i|
81
+ file_list.puts(i)
98
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|')
99
90
  end # def output
100
91
 
101
92
  # Handle architecture naming conversion:
@@ -110,6 +101,8 @@ class FPM::Package::FreeBSD < FPM::Package
110
101
  wordsize = case @architecture
111
102
  when nil, 'native'
112
103
  %x{getconf LONG_BIT}.chomp # 'native' is current arch
104
+ when 'arm64'
105
+ '64'
113
106
  when 'amd64'
114
107
  '64'
115
108
  when 'i386'
@@ -4,7 +4,6 @@ require "rubygems"
4
4
  require "fileutils"
5
5
  require "fpm/util"
6
6
  require "yaml"
7
- require "git"
8
7
 
9
8
  # A rubygems package.
10
9
  #
@@ -105,6 +104,7 @@ class FPM::Package::Gem < FPM::Package
105
104
  FileUtils.mkdir(download_dir) unless File.directory?(download_dir)
106
105
 
107
106
  if attributes[:gem_git_repo]
107
+ require "git"
108
108
  logger.debug("Git cloning in directory #{download_dir}")
109
109
  g = Git.clone(attributes[:gem_git_repo],gem_name,:path => download_dir)
110
110
  if attributes[:gem_git_branch]
@@ -90,6 +90,11 @@ class get_metadata(Command):
90
90
  for dep in pkg_resources.parse_requirements(
91
91
  self.distribution.install_requires):
92
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))
93
98
 
94
99
  data["dependencies"] = final_deps
95
100
 
@@ -79,7 +79,11 @@ class FPM::Package::Python < FPM::Package
79
79
  option "--setup-py-arguments", "setup_py_argument",
80
80
  "Arbitrary argument(s) to be passed to setup.py",
81
81
  :multivalued => true, :attribute_name => :python_setup_py_arguments,
82
- :default => []
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
83
87
 
84
88
  private
85
89
 
@@ -130,23 +134,24 @@ class FPM::Package::Python < FPM::Package
130
134
  target = build_path(package)
131
135
  FileUtils.mkdir(target) unless File.directory?(target)
132
136
 
133
- if attributes[:python_pip].nil?
134
- # no pip, use easy_install
135
- logger.debug("no pip, defaulting to easy_install", :easy_install => attributes[:python_easyinstall])
136
- safesystem(attributes[:python_easyinstall], "-i",
137
- attributes[:python_pypi], "--editable", "-U",
138
- "--build-directory", target, want_pkg)
139
- else
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]
140
144
  logger.debug("using pip", :pip => attributes[:python_pip])
141
145
  # TODO: Support older versions of pip
142
146
 
147
+ pip = [attributes[:python_pip]] if pip.is_a?(String)
143
148
  setup_cmd = [
144
- attributes[:python_pip],
149
+ *attributes[:python_pip],
145
150
  "download",
146
151
  "--no-clean",
147
152
  "--no-deps",
148
- "--no-binary",
149
- ":all:",
153
+ "--no-binary", ":all:",
154
+ "-d", build_path,
150
155
  "-i", attributes[:python_pypi],
151
156
  ]
152
157
 
@@ -164,6 +169,12 @@ class FPM::Package::Python < FPM::Package
164
169
  ]
165
170
 
166
171
  safesystem(*setup_cmd)
172
+ else
173
+ # no pip, use easy_install
174
+ logger.debug("no pip, defaulting to easy_install", :easy_install => attributes[:python_easyinstall])
175
+ safesystem(attributes[:python_easyinstall], "-i",
176
+ attributes[:python_pypi], "--editable", "-U",
177
+ "--build-directory", target, want_pkg)
167
178
  end
168
179
 
169
180
  # easy_install will put stuff in @tmpdir/packagename/, so find that:
@@ -4,6 +4,9 @@ require "fileutils"
4
4
  require "find"
5
5
  require "arr-pm/file" # gem 'arr-pm'
6
6
 
7
+ # For conversion handling
8
+ require "fpm/package/gem"
9
+
7
10
  # RPM Package type.
8
11
  #
9
12
  # Build RPMs without having to waste hours reading Maximum-RPM.
@@ -190,14 +193,15 @@ class FPM::Package::RPM < FPM::Package
190
193
  # Replace ? with [?] to make rpm not use globs
191
194
  # Replace % with [%] to make rpm not expand macros
192
195
  def rpm_fix_name(name)
193
- name = name.gsub(/(\ |\[|\]|\*|\?|\%|\$)/, {
196
+ name = name.gsub(/(\ |\[|\]|\*|\?|\%|\$|')/, {
194
197
  ' ' => '?',
195
198
  '%' => '[%]',
196
199
  '$' => '[$]',
197
200
  '?' => '[?]',
198
201
  '*' => '[*]',
199
202
  '[' => '[\[]',
200
- ']' => '[\]]'
203
+ ']' => '[\]]',
204
+ "'" => "\\'",
201
205
  })
202
206
  end
203
207
 
@@ -239,6 +243,8 @@ class FPM::Package::RPM < FPM::Package
239
243
  return %x{uname -m}.chomp # default to current arch
240
244
  when "amd64" # debian and redhat disagree on architecture names
241
245
  return "x86_64"
246
+ when "arm64" # debian and redhat disagree on architecture names
247
+ return "aarch64"
242
248
  when "native"
243
249
  return %x{uname -m}.chomp # 'native' is current arch
244
250
  when "all"
@@ -251,6 +257,12 @@ class FPM::Package::RPM < FPM::Package
251
257
 
252
258
  # This method ensures a default value for iteration if none is provided.
253
259
  def iteration
260
+ if @iteration.kind_of?(String) and @iteration.include?("-")
261
+ logger.warn("Package iteration '#{@iteration}' includes dashes, converting" \
262
+ " to underscores. rpmbuild does not allow the dashes in the package iteration (called 'Release' in rpm)")
263
+ @iteration = @iteration.gsub(/-/, "_")
264
+ end
265
+
254
266
  return @iteration ? @iteration : 1
255
267
  end # def iteration
256
268
 
@@ -2,6 +2,8 @@ require "fpm/namespace"
2
2
  require "fpm/package"
3
3
  require "fpm/util"
4
4
 
5
+ require "fpm/package/dir"
6
+
5
7
  # Support for python virtualenv packages.
6
8
  #
7
9
  # This supports input, but not output.
data/lib/fpm/util.rb CHANGED
@@ -1,21 +1,8 @@
1
1
  require "fpm/namespace"
2
- require "childprocess"
3
- require "ffi"
4
2
  require "fileutils"
5
3
 
6
4
  # Some utility functions
7
5
  module FPM::Util
8
- extend FFI::Library
9
- ffi_lib FFI::Library::LIBC
10
-
11
- # mknod is __xmknod in glibc a wrapper around mknod to handle
12
- # various stat struct formats. See bits/stat.h in glibc source
13
- begin
14
- attach_function :mknod, :mknod, [:string, :uint, :ulong], :int
15
- rescue FFI::NotFoundError
16
- # glibc/io/xmknod.c int __xmknod (int vers, const char *path, mode_t mode, dev_t *dev)
17
- attach_function :xmknod, :__xmknod, [:int, :string, :uint, :pointer], :int
18
- end
19
6
 
20
7
  # Raised if safesystem cannot find the program to run.
21
8
  class ExecutableNotFound < StandardError; end
@@ -23,6 +10,12 @@ module FPM::Util
23
10
  # Raised if a safesystem program exits nonzero
24
11
  class ProcessFailed < StandardError; end
25
12
 
13
+ # Raised when a named pipe cannot be copied due to missing functions in fpm and ruby.
14
+ class NamedPipeCannotBeCopied < StandardError; end
15
+
16
+ # Raised when an attempting to copy a special file such as a block device.
17
+ class UnsupportedSpecialFile < StandardError; end
18
+
26
19
  # Is the given program in the system's PATH?
27
20
  def program_in_path?(program)
28
21
  # return false if path is not set
@@ -146,31 +139,22 @@ module FPM::Util
146
139
 
147
140
  stdout_r, stdout_w = IO.pipe
148
141
  stderr_r, stderr_w = IO.pipe
142
+ stdin_r, stdin_w = IO.pipe
149
143
 
150
- process = ChildProcess.build(*args2)
151
- process.environment.merge!(env)
152
-
153
- process.io.stdout = stdout_w
154
- process.io.stderr = stderr_w
155
-
156
- if block_given? and opts[:stdin]
157
- process.duplex = true
158
- end
159
-
160
- process.start
144
+ pid = Process.spawn(env, *args2, :out => stdout_w, :err => stderr_w, :in => stdin_r)
161
145
 
162
146
  stdout_w.close; stderr_w.close
163
- logger.debug("Process is running", :pid => process.pid)
147
+ logger.debug("Process is running", :pid => pid)
164
148
  if block_given?
165
149
  args3 = []
166
150
  args3.push(process) if opts[:process]
167
- args3.push(process.io.stdin) if opts[:stdin]
151
+ args3.push(stdin_w) if opts[:stdin]
168
152
  args3.push(stdout_r) if opts[:stdout]
169
153
  args3.push(stderr_r) if opts[:stderr]
170
154
 
171
155
  yield(*args3)
172
156
 
173
- process.io.stdin.close if opts[:stdin] and not process.io.stdin.closed?
157
+ stdin_w_close if opts[:stdin] and not stdin_w.closed?
174
158
  stdout_r.close unless stdout_r.closed?
175
159
  stderr_r.close unless stderr_r.closed?
176
160
  else
@@ -179,9 +163,10 @@ module FPM::Util
179
163
  logger.pipe(stdout_r => :info, stderr_r => :info)
180
164
  end
181
165
 
182
- process.wait if process.alive?
166
+ Process.waitpid(pid)
167
+ status = $?
183
168
 
184
- return process.exit_code
169
+ return status.exitstatus
185
170
  end # def execmd
186
171
 
187
172
  # Run a command safely in a way that gets reports useful errors.
@@ -316,19 +301,6 @@ module FPM::Util
316
301
  return @@tar_cmd_deterministic
317
302
  end
318
303
 
319
- # wrapper around mknod ffi calls
320
- def mknod_w(path, mode, dev)
321
- rc = -1
322
- case %x{uname -s}.chomp
323
- when 'Linux'
324
- # bits/stat.h #define _MKNOD_VER_LINUX 0
325
- rc = xmknod(0, path, mode, FFI::MemoryPointer.new(dev))
326
- else
327
- rc = mknod(path, mode, dev)
328
- end
329
- rc
330
- end
331
-
332
304
  def copy_metadata(source, destination)
333
305
  source_stat = File::lstat(source)
334
306
  dest_stat = File::lstat(destination)
@@ -354,10 +326,21 @@ module FPM::Util
354
326
 
355
327
  def copy_entry(src, dst, preserve=false, remove_destination=false)
356
328
  case File.ftype(src)
357
- when 'fifo', 'characterSpecial', 'blockSpecial', 'socket'
358
- st = File.stat(src)
359
- rc = mknod_w(dst, st.mode, st.dev)
360
- raise SystemCallError.new("mknod error", FFI.errno) if rc == -1
329
+ when 'fifo'
330
+ if File.respond_to?(:mkfifo)
331
+ File.mkfifo(dst)
332
+ elsif program_exists?("mkfifo")
333
+ safesystem("mkfifo", dst)
334
+ else
335
+ raise NamedPipeCannotBeCopied("Unable to copy. Cannot find program 'mkfifo' and Ruby is missing the 'File.mkfifo' method: #{src}")
336
+ end
337
+ when 'socket'
338
+ require "socket"
339
+ # In 2019, Ruby's FileUtils added this as a way to "copy" a unix socket.
340
+ # Reference: https://github.com/ruby/fileutils/pull/36/files
341
+ UNIXServer.new(dst).close()
342
+ when 'characterSpecial', 'blockSpecial'
343
+ raise UnsupportedSpecialFile.new("File is device which fpm doesn't know how to copy (#{File.ftype(src)}): #{src}")
361
344
  when 'directory'
362
345
  FileUtils.mkdir(dst) unless File.exists? dst
363
346
  else
data/lib/fpm/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module FPM
2
- VERSION = "1.12.0"
2
+ VERSION = "1.14.1"
3
3
  end
@@ -20,6 +20,7 @@ debsystemctl=$(command -v deb-systemd-invoke || echo systemctl)
20
20
  <% attributes[:deb_systemd].each do |service| -%>
21
21
  if ! systemctl is-enabled <%= service %> >/dev/null
22
22
  then
23
+ : # Ensure this if-clause is not empty. If it were empty, and we had an 'else', then it is an error in shell syntax
23
24
  <% if attributes[:deb_systemd_enable?]-%>
24
25
  systemctl enable <%= service %> >/dev/null || true
25
26
  <% end -%>
data/templates/deb.erb CHANGED
@@ -25,7 +25,7 @@ Build-Depends: <%= attributes[:deb_build_depends].collect { |d| fix_dependency(d
25
25
  <% if !provides.empty? -%>
26
26
  <%# Turn each provides from 'foo = 123' to simply 'foo' because Debian :\ -%>
27
27
  <%# http://www.debian.org/doc/debian-policy/ch-relationships.html -%>
28
- Provides: <%= provides.map {|p| p.split(" ").first}.join ", " %>
28
+ Provides: <%= provides.join ", " %>
29
29
  <% end -%>
30
30
  <% if !replaces.empty? -%>
31
31
  Replaces: <%= replaces.collect { |d| fix_dependency(d) }.flatten.join(", ") %>
data/templates/rpm.erb CHANGED
@@ -126,7 +126,7 @@ Obsoletes: <%= repl %>
126
126
  -%>
127
127
  <% if script?(:before_upgrade) or script?(:after_upgrade) -%>
128
128
  <% if script?(:before_upgrade) or script?(:before_install) -%>
129
- %pre <% if attributes[:rpm_macro_expansion?] -%><%= " -e " %> <% end -%>
129
+ %pre <% if attributes[:rpm_macro_expansion?] -%><%= " -e " %> <% end %>
130
130
  upgrade() {
131
131
  <%# Making sure that at least one command is in the function -%>
132
132
  <%# avoids a lot of potential errors, including the case that -%>
@@ -156,7 +156,7 @@ then
156
156
  fi
157
157
  <% end -%>
158
158
  <% if script?(:after_upgrade) or script?(:after_install) -%>
159
- %post <% if attributes[:rpm_macro_expansion?] -%><%= " -e " %> <% end -%>
159
+ %post <% if attributes[:rpm_macro_expansion?] -%><%= " -e " %> <% end %>
160
160
  upgrade() {
161
161
  <%# Making sure that at least one command is in the function -%>
162
162
  <%# avoids a lot of potential errors, including the case that -%>
@@ -186,7 +186,7 @@ then
186
186
  fi
187
187
  <% end -%>
188
188
  <% if script?(:before_remove) -%>
189
- %preun <% if attributes[:rpm_macro_expansion?] -%><%= " -e " %> <% end -%>
189
+ %preun <% if attributes[:rpm_macro_expansion?] -%><%= " -e " %> <% end %>
190
190
  if [ "${1}" -eq 0 ]
191
191
  then
192
192
  <%# Making sure that at least one command is in the function -%>
@@ -197,7 +197,7 @@ then
197
197
  fi
198
198
  <% end -%>
199
199
  <% if script?(:after_remove) -%>
200
- %postun <% if attributes[:rpm_macro_expansion?] -%><%= " -e " %> <% end -%>
200
+ %postun <% if attributes[:rpm_macro_expansion?] -%><%= " -e " %> <% end %>
201
201
  if [ "${1}" -eq 0 ]
202
202
  then
203
203
  <%# Making sure that at least one command is in the function -%>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fpm
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.12.0
4
+ version: 1.14.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jordan Sissel
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-19 00:00:00.000000000 Z
11
+ date: 2021-11-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -64,14 +64,14 @@ dependencies:
64
64
  requirements:
65
65
  - - "~>"
66
66
  - !ruby/object:Gem::Version
67
- version: 0.0.10
67
+ version: 0.0.11
68
68
  type: :runtime
69
69
  prerelease: false
70
70
  version_requirements: !ruby/object:Gem::Requirement
71
71
  requirements:
72
72
  - - "~>"
73
73
  - !ruby/object:Gem::Version
74
- version: 0.0.10
74
+ version: 0.0.11
75
75
  - !ruby/object:Gem::Dependency
76
76
  name: clamp
77
77
  requirement: !ruby/object:Gem::Requirement
@@ -86,62 +86,6 @@ dependencies:
86
86
  - - "~>"
87
87
  - !ruby/object:Gem::Version
88
88
  version: 1.0.0
89
- - !ruby/object:Gem::Dependency
90
- name: childprocess
91
- requirement: !ruby/object:Gem::Requirement
92
- requirements:
93
- - - "<"
94
- - !ruby/object:Gem::Version
95
- version: 1.0.0
96
- type: :runtime
97
- prerelease: false
98
- version_requirements: !ruby/object:Gem::Requirement
99
- requirements:
100
- - - "<"
101
- - !ruby/object:Gem::Version
102
- version: 1.0.0
103
- - !ruby/object:Gem::Dependency
104
- name: ffi
105
- requirement: !ruby/object:Gem::Requirement
106
- requirements:
107
- - - "~>"
108
- - !ruby/object:Gem::Version
109
- version: 1.12.0
110
- type: :runtime
111
- prerelease: false
112
- version_requirements: !ruby/object:Gem::Requirement
113
- requirements:
114
- - - "~>"
115
- - !ruby/object:Gem::Version
116
- version: 1.12.0
117
- - !ruby/object:Gem::Dependency
118
- name: rake
119
- requirement: !ruby/object:Gem::Requirement
120
- requirements:
121
- - - "~>"
122
- - !ruby/object:Gem::Version
123
- version: '10'
124
- type: :development
125
- prerelease: false
126
- version_requirements: !ruby/object:Gem::Requirement
127
- requirements:
128
- - - "~>"
129
- - !ruby/object:Gem::Version
130
- version: '10'
131
- - !ruby/object:Gem::Dependency
132
- name: ruby-xz
133
- requirement: !ruby/object:Gem::Requirement
134
- requirements:
135
- - - "~>"
136
- - !ruby/object:Gem::Version
137
- version: 0.2.3
138
- type: :runtime
139
- prerelease: false
140
- version_requirements: !ruby/object:Gem::Requirement
141
- requirements:
142
- - - "~>"
143
- - !ruby/object:Gem::Version
144
- version: 0.2.3
145
89
  - !ruby/object:Gem::Dependency
146
90
  name: pleaserun
147
91
  requirement: !ruby/object:Gem::Requirement
@@ -190,6 +134,20 @@ dependencies:
190
134
  - - ">="
191
135
  - !ruby/object:Gem::Version
192
136
  version: '0'
137
+ - !ruby/object:Gem::Dependency
138
+ name: rexml
139
+ requirement: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ type: :runtime
145
+ prerelease: false
146
+ version_requirements: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - ">="
149
+ - !ruby/object:Gem::Version
150
+ version: '0'
193
151
  - !ruby/object:Gem::Dependency
194
152
  name: rspec
195
153
  requirement: !ruby/object:Gem::Requirement
@@ -306,7 +264,7 @@ homepage: https://github.com/jordansissel/fpm
306
264
  licenses:
307
265
  - MIT-like
308
266
  metadata: {}
309
- post_install_message:
267
+ post_install_message:
310
268
  rdoc_options: []
311
269
  require_paths:
312
270
  - lib
@@ -322,9 +280,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
322
280
  - !ruby/object:Gem::Version
323
281
  version: '0'
324
282
  requirements: []
325
- rubyforge_project:
326
- rubygems_version: 2.7.6
327
- signing_key:
283
+ rubygems_version: 3.2.31
284
+ signing_key:
328
285
  specification_version: 4
329
286
  summary: fpm - package building and mangling
330
287
  test_files: []