fpm 1.9.3 → 1.12.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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