fpm 1.9.3 → 1.12.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.
@@ -1,6 +1,6 @@
1
1
  require "fpm/package"
2
2
  require "fpm/util"
3
- require "backports"
3
+ require "backports/latest"
4
4
  require "fileutils"
5
5
  require "find"
6
6
  require "socket"
@@ -83,8 +83,8 @@ class FPM::Package::Dir < FPM::Package
83
83
  # can include license data from themselves (rpms, gems, etc),
84
84
  # but to make sure a simple dir -> rpm works without having
85
85
  # to specify a license.
86
- self.license = "unknown"
87
- self.vendor = [ENV["USER"], Socket.gethostname].join("@")
86
+ self.license ||= "unknown"
87
+ self.vendor ||= [ENV["USER"], Socket.gethostname].join("@")
88
88
  ensure
89
89
  # Clean up any logger context we added.
90
90
  logger.remove("method")
@@ -1,5 +1,5 @@
1
1
  require "fpm/package"
2
- require "backports"
2
+ require "backports/latest"
3
3
 
4
4
  # Empty Package type. For strict/meta/virtual package creation
5
5
 
@@ -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"
@@ -4,6 +4,7 @@ require "rubygems"
4
4
  require "fileutils"
5
5
  require "fpm/util"
6
6
  require "yaml"
7
+ require "git"
7
8
 
8
9
  # A rubygems package.
9
10
  #
@@ -53,6 +54,15 @@ class FPM::Package::Gem < FPM::Package
53
54
  "The directory where fpm installs the gem temporarily before conversion. " \
54
55
  "Normally a random subdirectory of workdir."
55
56
 
57
+ option "--git-repo", "GIT_REPO",
58
+ "Use this git repo address as the source of the gem instead of " \
59
+ "rubygems.org.", :default => nil
60
+
61
+ option "--git-branch", "GIT_BRANCH",
62
+ "When using a git repo as the source of the gem instead of " \
63
+ "rubygems.org, use this git branch.",
64
+ :default => nil
65
+
56
66
  # Override parent method
57
67
  def staging_path(path=nil)
58
68
  @gem_staging_path ||= attributes[:gem_stagingdir] || Stud::Temporary.directory("package-#{type}-staging")
@@ -91,21 +101,33 @@ class FPM::Package::Gem < FPM::Package
91
101
 
92
102
  logger.info("Trying to download", :gem => gem_name, :version => gem_version)
93
103
 
94
- gem_fetch = [ "#{attributes[:gem_gem]}", "fetch", gem_name]
95
-
96
- gem_fetch += ["--prerelease"] if attributes[:gem_prerelease?]
97
- gem_fetch += ["--version", gem_version] if gem_version
98
-
99
104
  download_dir = build_path(gem_name)
100
105
  FileUtils.mkdir(download_dir) unless File.directory?(download_dir)
101
106
 
102
- ::Dir.chdir(download_dir) do |dir|
103
- logger.debug("Downloading in directory #{dir}")
104
- safesystem(*gem_fetch)
107
+ if attributes[:gem_git_repo]
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"))
105
129
  end
106
130
 
107
- gem_files = ::Dir.glob(File.join(download_dir, "*.gem"))
108
-
109
131
  if gem_files.length != 1
110
132
  raise "Unexpected number of gem files in #{download_dir}, #{gem_files.length} should be 1"
111
133
  end
@@ -198,8 +220,13 @@ class FPM::Package::Gem < FPM::Package
198
220
 
199
221
  ::FileUtils.mkdir_p(installdir)
200
222
  # TODO(sissel): Allow setting gem tool path
201
- args = [attributes[:gem_gem], "install", "--quiet", "--no-ri", "--no-rdoc",
202
- "--no-user-install", "--install-dir", installdir]
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
203
230
 
204
231
  if !attributes[:gem_embed_dependencies?]
205
232
  args += ["--ignore-dependencies"]
@@ -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 => "xz" do |value|
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(", ")}"
@@ -209,31 +209,39 @@ class FPM::Package::Pacman < FPM::Package
209
209
 
210
210
  def compression_option
211
211
  case self.attributes[:pacman_compression]
212
- when nil, "xz"
213
- return "--xz"
212
+ when nil, "zstd"
213
+ return "--zstd"
214
214
  when "none"
215
215
  return ""
216
216
  when "gz"
217
217
  return "-z"
218
+ when "xz"
219
+ return "--xz"
218
220
  when "bzip2"
219
221
  return "-j"
222
+ when "zstd"
223
+ return "--zstd"
220
224
  else
221
- return "--xz"
225
+ return "--zstd"
222
226
  end
223
227
  end
224
228
 
225
229
  def compression_ending
226
230
  case self.attributes[:pacman_compression]
227
- when nil, "xz"
228
- return ".xz"
231
+ when nil, "zstd"
232
+ return ".zst"
229
233
  when "none"
230
234
  return ""
231
235
  when "gz"
232
236
  return ".gz"
237
+ when "zx"
238
+ return ".xz"
233
239
  when "bzip2"
234
240
  return ".bz2"
241
+ when "zstd"
242
+ return ".zst"
235
243
  else
236
- return ".xz"
244
+ return ".zst"
237
245
  end
238
246
  end
239
247
 
@@ -245,7 +253,11 @@ class FPM::Package::Pacman < FPM::Package
245
253
  Find.find(staging_path) do |path|
246
254
  src = path.gsub(/^#{staging_path}/, '')
247
255
  dst = build_path(src)
248
- copy_entry(path, dst, preserve=true, remove_destination=true)
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
249
261
  copy_metadata(path, dst)
250
262
  end
251
263
 
@@ -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,
@@ -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|
@@ -136,7 +139,31 @@ class FPM::Package::Python < FPM::Package
136
139
  else
137
140
  logger.debug("using pip", :pip => attributes[:python_pip])
138
141
  # TODO: Support older versions of pip
139
- safesystem(attributes[:python_pip], "download", "--no-clean", "--no-deps", "--no-binary", ":all:", "-i", attributes[:python_pypi], "--build", target, want_pkg)
142
+
143
+ setup_cmd = [
144
+ attributes[:python_pip],
145
+ "download",
146
+ "--no-clean",
147
+ "--no-deps",
148
+ "--no-binary",
149
+ ":all:",
150
+ "-i", attributes[:python_pypi],
151
+ ]
152
+
153
+ if attributes[:python_trusted_host]
154
+ setup_cmd += [
155
+ "--trusted-host",
156
+ attributes[:python_trusted_host],
157
+ ]
158
+ end
159
+
160
+ setup_cmd += [
161
+ "--build",
162
+ target,
163
+ want_pkg,
164
+ ]
165
+
166
+ safesystem(*setup_cmd)
140
167
  end
141
168
 
142
169
  # easy_install will put stuff in @tmpdir/packagename/, so find that:
@@ -183,7 +210,7 @@ class FPM::Package::Python < FPM::Package
183
210
 
184
211
  output = ::Dir.chdir(setup_dir) do
185
212
  tmp = build_path("metadata.json")
186
- setup_cmd = "env PYTHONPATH=#{pylib} #{attributes[:python_bin]} " \
213
+ setup_cmd = "env PYTHONPATH=#{pylib}:$PYTHONPATH #{attributes[:python_bin]} " \
187
214
  "setup.py --command-packages=pyfpm get_metadata --output=#{tmp}"
188
215
 
189
216
  if attributes[:python_obey_requirements_txt?]
@@ -229,7 +256,7 @@ class FPM::Package::Python < FPM::Package
229
256
 
230
257
  if !attributes[:no_auto_depends?] and attributes[:python_dependencies?]
231
258
  metadata["dependencies"].each do |dep|
232
- dep_re = /^([^<>!= ]+)\s*(?:([<>!=]{1,2})\s*(.*))?$/
259
+ dep_re = /^([^<>!= ]+)\s*(?:([~<>!=]{1,2})\s*(.*))?$/
233
260
  match = dep_re.match(dep)
234
261
  if match.nil?
235
262
  logger.error("Unable to parse dependency", :dependency => dep)
@@ -240,7 +267,7 @@ class FPM::Package::Python < FPM::Package
240
267
  next if attributes[:python_disable_dependency].include?(name)
241
268
 
242
269
  # convert == to =
243
- if cmp == "=="
270
+ if cmp == "==" or cmp == "~="
244
271
  logger.info("Converting == dependency requirement to =", :dependency => dep )
245
272
  cmp = "="
246
273
  end
@@ -1,5 +1,5 @@
1
1
  require "fpm/package"
2
- require "backports"
2
+ require "backports/latest"
3
3
  require "fileutils"
4
4
  require "find"
5
5
  require "arr-pm/file" # gem 'arr-pm'
@@ -24,9 +24,10 @@ class FPM::Package::RPM < FPM::Package
24
24
 
25
25
  COMPRESSION_MAP = {
26
26
  "none" => "w0.gzdio",
27
- "xz" => "w9.xzdio",
28
- "gzip" => "w9.gzdio",
29
- "bzip2" => "w9.bzdio"
27
+ "xz" => ".xzdio",
28
+ "xzmt" => "T.xzdio",
29
+ "gzip" => ".gzdio",
30
+ "bzip2" => ".bzdio"
30
31
  } unless defined?(COMPRESSION_MAP)
31
32
 
32
33
  option "--use-file-permissions", :flag,
@@ -67,6 +68,15 @@ class FPM::Package::RPM < FPM::Package
67
68
  value.downcase
68
69
  end
69
70
 
71
+ option "--compression-level", "[0-9]", "Select a compression level. 0 is store-only. 9 is max compression.",
72
+ :default => "9" do |value|
73
+ valint = value.to_i
74
+ unless value =~ /^\d$/ && valint >= 0 && valint <= 9
75
+ raise "Invalid compression level '#{value}'. Valid values are integers between 0 and 9 inclusive."
76
+ end
77
+ valint
78
+ end
79
+
70
80
  option "--compression", COMPRESSION_MAP.keys.join("|"),
71
81
  "Select a compression method. gzip works on the most platforms.",
72
82
  :default => "gzip" do |value|
@@ -141,6 +151,10 @@ class FPM::Package::RPM < FPM::Package
141
151
  "names in rpm requires instead of the redhat style " \
142
152
  "rubygem(foo).", :default => false
143
153
 
154
+ option "--macro-expansion", :flag,
155
+ "install-time macro expansion in %pre %post %preun %postun scripts " \
156
+ "(see: https://rpm.org/user_doc/scriptlet_expansion.html)", :default => false
157
+
144
158
  option "--verifyscript", "FILE",
145
159
  "a script to be run on verification" do |val|
146
160
  File.expand_path(val) # Get the full path to the script
@@ -515,10 +529,11 @@ class FPM::Package::RPM < FPM::Package
515
529
  end
516
530
 
517
531
  # copy all files from staging to BUILD dir
532
+ # [#1538] Be sure to preserve the original timestamps.
518
533
  Find.find(staging_path) do |path|
519
534
  src = path.gsub(/^#{staging_path}/, '')
520
535
  dst = File.join(build_path, build_sub_dir, src)
521
- copy_entry(path, dst)
536
+ copy_entry(path, dst, preserve=true)
522
537
  end
523
538
 
524
539
  rpmspec = template("rpm.erb").result(binding)
@@ -596,7 +611,12 @@ class FPM::Package::RPM < FPM::Package
596
611
  end # def to_s
597
612
 
598
613
  def payload_compression
599
- return COMPRESSION_MAP[attributes[:rpm_compression]]
614
+ if attributes[:rpm_compression] == 'none'
615
+ # when 'none' ignore any compression level and return w0.gzdio
616
+ return COMPRESSION_MAP[attributes[:rpm_compression]]
617
+ else
618
+ return "w#{attributes[:rpm_compression_level]}" + COMPRESSION_MAP[attributes[:rpm_compression]]
619
+ end
600
620
  end # def payload_compression
601
621
 
602
622
  def digest_algorithm
@@ -3,7 +3,7 @@ require "fpm/namespace"
3
3
  require "fpm/package"
4
4
  require "fpm/errors"
5
5
  require "fpm/util"
6
- require "backports"
6
+ require "backports/latest"
7
7
  require "fileutils"
8
8
  require "digest"
9
9
 
@@ -0,0 +1,130 @@
1
+ require "yaml"
2
+
3
+ require "fpm/package"
4
+ require "fpm/util"
5
+ require "fileutils"
6
+ require "fpm/package/dir"
7
+
8
+ # Support for snaps (.snap files).
9
+ #
10
+ # This supports the input and output of snaps.
11
+ class FPM::Package::Snap < FPM::Package
12
+
13
+ option "--yaml", "FILEPATH",
14
+ "Custom version of the snap.yaml file." do | snap_yaml |
15
+ File.expand_path(snap_yaml)
16
+ end
17
+
18
+ option "--confinement", "CONFINEMENT",
19
+ "Type of confinement to use for this snap.",
20
+ default: "devmode" do | confinement |
21
+ if ['strict', 'devmode', 'classic'].include? confinement
22
+ confinement
23
+ else
24
+ raise "Unsupported confinement type '#{confinement}'"
25
+ end
26
+ end
27
+
28
+ option "--grade", "GRADE", "Grade of this snap.",
29
+ default: "devel" do | grade |
30
+ if ['stable', 'devel'].include? grade
31
+ grade
32
+ else
33
+ raise "Unsupported grade type '#{grade}'"
34
+ end
35
+ end
36
+
37
+ # Input a snap
38
+ def input(input_snap)
39
+ extract_snap_to_staging input_snap
40
+ extract_snap_metadata_from_staging
41
+ end # def input
42
+
43
+ # Output a snap.
44
+ def output(output_snap)
45
+ output_check(output_snap)
46
+
47
+ write_snap_yaml
48
+
49
+ # Create the snap from the staging path
50
+ safesystem("mksquashfs", staging_path, output_snap, "-noappend", "-comp",
51
+ "xz", "-no-xattrs", "-no-fragments", "-all-root")
52
+ end # def output
53
+
54
+ def to_s(format=nil)
55
+ # Default format if nil
56
+ # name_version_arch.snap
57
+ return super(format.nil? ? "NAME_FULLVERSION_ARCH.EXTENSION" : format)
58
+ end # def to_s
59
+
60
+ private
61
+
62
+ def extract_snap_to_staging(snap_path)
63
+ safesystem("unsquashfs", "-f", "-d", staging_path, snap_path)
64
+ end
65
+
66
+ def extract_snap_metadata_from_staging
67
+ metadata = YAML.safe_load(File.read(
68
+ staging_path(File.join("meta", "snap.yaml"))))
69
+
70
+ self.name = metadata["name"]
71
+ self.version = metadata["version"]
72
+ self.description = metadata["summary"] + "\n" + metadata["description"]
73
+ self.architecture = metadata["architectures"][0]
74
+ self.attributes[:snap_confinement] = metadata["confinement"]
75
+ self.attributes[:snap_grade] = metadata["grade"]
76
+
77
+ if metadata["apps"].nil?
78
+ attributes[:snap_apps] = []
79
+ else
80
+ attributes[:snap_apps] = metadata["apps"]
81
+ end
82
+
83
+ if metadata["hooks"].nil?
84
+ attributes[:snap_hooks] = []
85
+ else
86
+ attributes[:snap_hooks] = metadata["hooks"]
87
+ end
88
+ end
89
+
90
+ def write_snap_yaml
91
+ # Write the snap.yaml
92
+ if attributes[:snap_yaml]
93
+ logger.debug("Using '#{attributes[:snap_yaml]}' as the snap.yaml")
94
+ yaml_data = File.read(attributes[:snap_yaml])
95
+ else
96
+ summary, *remainder = (self.description or "no summary given").split("\n")
97
+ description = "no description given"
98
+ if remainder.any?
99
+ description = remainder.join("\n")
100
+ end
101
+
102
+ yaml_data = {
103
+ "name" => self.name,
104
+ "version" => self.version,
105
+ "summary" => summary,
106
+ "description" => description,
107
+ "architectures" => [self.architecture],
108
+ "confinement" => self.attributes[:snap_confinement],
109
+ "grade" => self.attributes[:snap_grade],
110
+ }
111
+
112
+ unless attributes[:snap_apps].nil? or attributes[:snap_apps].empty?
113
+ yaml_data["apps"] = attributes[:snap_apps]
114
+ end
115
+
116
+ unless attributes[:snap_hooks].nil? or attributes[:snap_hooks].empty?
117
+ yaml_data["hooks"] = attributes[:snap_hooks]
118
+ end
119
+
120
+ yaml_data = yaml_data.to_yaml
121
+ end
122
+
123
+ FileUtils.mkdir_p(staging_path("meta"))
124
+ snap_yaml_path = staging_path(File.join("meta", "snap.yaml"))
125
+ logger.debug("Writing snap.yaml", :path => snap_yaml_path)
126
+ File.write(snap_yaml_path, yaml_data)
127
+ File.chmod(0644, snap_yaml_path)
128
+ edit_file(snap_yaml_path) if attributes[:edit?]
129
+ end # def write_snap_yaml
130
+ end # class FPM::Package::Snap