fpm-aeppert 1.6.2 → 1.11.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")
@@ -101,18 +101,7 @@ class FPM::Package::Dir < FPM::Package
101
101
  end
102
102
 
103
103
  # Write the scripts, too.
104
- scripts_path = File.join(output_path, ".scripts")
105
- ::Dir.mkdir(scripts_path)
106
- [:before_install, :after_install, :before_remove, :after_remove].each do |name|
107
- next unless script?(name)
108
- out = File.join(scripts_path, name.to_s)
109
- logger.debug("Writing script", :source => name, :target => out)
110
- File.write(out, script(name))
111
- require "pry"
112
- binding.pry
113
- File.chmod(0755, out)
114
- end
115
-
104
+ write_scripts
116
105
  ensure
117
106
  logger.remove("method")
118
107
  end # def output
@@ -147,14 +136,20 @@ class FPM::Package::Dir < FPM::Package
147
136
 
148
137
  # For single file copies, permit file destinations
149
138
  fileinfo = File.lstat(source)
150
- if fileinfo.file? && !File.directory?(destination)
139
+ destination_is_directory = File.directory?(destination)
140
+ if fileinfo.file? && !destination_is_directory
151
141
  if destination[-1,1] == "/"
152
142
  copy(source, File.join(destination, source))
153
143
  else
154
144
  copy(source, destination)
155
145
  end
156
146
  elsif fileinfo.symlink?
157
- copy(source, File.join(destination, source))
147
+ # Treat them same as files
148
+ if destination[-1,1] == "/"
149
+ copy(source, File.join(destination, source))
150
+ else
151
+ copy(source, destination)
152
+ end
158
153
  else
159
154
  # Copy all files from 'path' into staging_path
160
155
  Find.find(source) do |path|
@@ -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
2
2
  require "fpm/package"
3
3
  require "fpm/util"
4
4
  require "digest"
@@ -12,18 +12,6 @@ class FPM::Package::FreeBSD < FPM::Package
12
12
  :after_remove => "post-deinstall",
13
13
  } unless defined?(SCRIPT_MAP)
14
14
 
15
- def self.default_abi
16
- abi_name = %x{uname -s}.chomp
17
- abi_version = %x{uname -r}.chomp.split(".")[0]
18
- abi_arch = %x{uname -m}.chomp
19
-
20
- [abi_name, abi_version, abi_arch].join(":")
21
- end
22
-
23
- option "--abi", "ABI",
24
- "Sets the FreeBSD abi pkg field to specify binary compatibility.",
25
- :default => default_abi
26
-
27
15
  option "--origin", "ABI",
28
16
  "Sets the FreeBSD 'origin' pkg field",
29
17
  :default => "fpm/<name>"
@@ -58,7 +46,7 @@ class FPM::Package::FreeBSD < FPM::Package
58
46
  pkg_version = (iteration and (iteration.to_i > 0)) ? "#{version}-#{iteration}" : "#{version}"
59
47
 
60
48
  pkgdata = {
61
- "abi" => attributes[:freebsd_abi],
49
+ "arch" => architecture,
62
50
  "name" => name,
63
51
  "version" => pkg_version,
64
52
  "comment" => description,
@@ -110,6 +98,29 @@ class FPM::Package::FreeBSD < FPM::Package
110
98
  end
111
99
  end # def output
112
100
 
101
+ # Handle architecture naming conversion:
102
+ # <osname>:<osversion>:<arch>:<wordsize>[.other]
103
+ def architecture
104
+ osname = %x{uname -s}.chomp
105
+ osversion = %x{uname -r}.chomp.split('.').first
106
+
107
+ # Essentially because no testing on other platforms
108
+ arch = 'x86'
109
+
110
+ wordsize = case @architecture
111
+ when nil, 'native'
112
+ %x{getconf LONG_BIT}.chomp # 'native' is current arch
113
+ when 'amd64'
114
+ '64'
115
+ when 'i386'
116
+ '32'
117
+ else
118
+ %x{getconf LONG_BIT}.chomp # default to native, the current arch
119
+ end
120
+
121
+ return [osname, osversion, arch, wordsize].join(':')
122
+ end
123
+
113
124
  def add_path(tar, tar_path, path)
114
125
  stat = File.lstat(path)
115
126
  if stat.directory?
@@ -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
  #
@@ -44,9 +45,36 @@ class FPM::Package::Gem < FPM::Package
44
45
  option "--disable-dependency", "gem_name",
45
46
  "The gem name to remove from dependency list",
46
47
  :multivalued => true, :attribute_name => :gem_disable_dependencies
48
+ option "--embed-dependencies", :flag, "Should the gem dependencies " \
49
+ "be installed?", :default => false
47
50
 
48
51
  option "--version-bins", :flag, "Append the version to the bins", :default => false
49
52
 
53
+ option "--stagingdir", "STAGINGDIR",
54
+ "The directory where fpm installs the gem temporarily before conversion. " \
55
+ "Normally a random subdirectory of workdir."
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
+
66
+ # Override parent method
67
+ def staging_path(path=nil)
68
+ @gem_staging_path ||= attributes[:gem_stagingdir] || Stud::Temporary.directory("package-#{type}-staging")
69
+ @staging_path = @gem_staging_path
70
+
71
+ if path.nil?
72
+ return @staging_path
73
+ else
74
+ return File.join(@staging_path, path)
75
+ end
76
+ end # def staging_path
77
+
50
78
  def input(gem)
51
79
  # 'arg' is the name of the rubygem we should unpack.
52
80
  path_to_gem = download_if_necessary(gem, version)
@@ -73,21 +101,33 @@ class FPM::Package::Gem < FPM::Package
73
101
 
74
102
  logger.info("Trying to download", :gem => gem_name, :version => gem_version)
75
103
 
76
- gem_fetch = [ "#{attributes[:gem_gem]}", "fetch", gem_name]
77
-
78
- gem_fetch += ["--prerelease"] if attributes[:gem_prerelease?]
79
- gem_fetch += ["--version", gem_version] if gem_version
80
-
81
104
  download_dir = build_path(gem_name)
82
105
  FileUtils.mkdir(download_dir) unless File.directory?(download_dir)
83
106
 
84
- ::Dir.chdir(download_dir) do |dir|
85
- logger.debug("Downloading in directory #{dir}")
86
- 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"))
87
129
  end
88
130
 
89
- gem_files = ::Dir.glob(File.join(download_dir, "*.gem"))
90
-
91
131
  if gem_files.length != 1
92
132
  raise "Unexpected number of gem files in #{download_dir}, #{gem_files.length} should be 1"
93
133
  end
@@ -144,7 +184,7 @@ class FPM::Package::Gem < FPM::Package
144
184
  # composing multiple packages, it's best to explicitly include it in the provides list.
145
185
  self.provides << "#{self.name} = #{self.version}"
146
186
 
147
- if !attributes[:no_auto_depends?]
187
+ if !attributes[:no_auto_depends?] && !attributes[:gem_embed_dependencies?]
148
188
  spec.runtime_dependencies.map do |dep|
149
189
  # rubygems 1.3.5 doesn't have 'Gem::Dependency#requirement'
150
190
  if dep.respond_to?(:requirement)
@@ -180,8 +220,18 @@ class FPM::Package::Gem < FPM::Package
180
220
 
181
221
  ::FileUtils.mkdir_p(installdir)
182
222
  # TODO(sissel): Allow setting gem tool path
183
- args = [attributes[:gem_gem], "install", "--quiet", "--no-ri", "--no-rdoc",
184
- "--no-user-install", "--install-dir", installdir, "--ignore-dependencies"]
223
+ args = [attributes[:gem_gem], "install", "--quiet", "--no-user-install", "--install-dir", installdir]
224
+ if ::Gem::VERSION =~ /^[012]\./
225
+ args += [ "--no-ri", "--no-rdoc" ]
226
+ else
227
+ # Rubygems 3.0.0 changed --no-ri to --no-document
228
+ args += [ "--no-document" ]
229
+ end
230
+
231
+ if !attributes[:gem_embed_dependencies?]
232
+ args += ["--ignore-dependencies"]
233
+ end
234
+
185
235
  if attributes[:gem_env_shebang?]
186
236
  args += ["-E"]
187
237
  end
@@ -231,6 +281,21 @@ class FPM::Package::Gem < FPM::Package
231
281
  FileUtils.mv("#{bin_path}/#{bin}", "#{bin_path}/#{bin}-#{self.version}")
232
282
  end
233
283
  end
284
+
285
+ if attributes[:source_date_epoch_from_changelog?]
286
+ detect_source_date_from_changelog(installdir)
287
+ end
288
+
289
+ # Remove generated Makefile and gem_make.out files, if any; they
290
+ # are not needed, and may contain generated paths that cause
291
+ # different output on successive runs.
292
+ Find.find(installdir) do |path|
293
+ if path =~ /.*(gem_make.out|Makefile|mkmf.log)$/
294
+ logger.info("Removing no longer needed file %s to reduce nondeterminism" % path)
295
+ File.unlink(path)
296
+ end
297
+ end
298
+
234
299
  end # def install_to_staging
235
300
 
236
301
  # Sanitize package name.
@@ -239,5 +304,75 @@ class FPM::Package::Gem < FPM::Package
239
304
  def fix_name(name)
240
305
  return [attributes[:gem_package_name_prefix], name].join("-")
241
306
  end # def fix_name
307
+
308
+ # Regular expression to accept a gem changelog line, and store date & version, if any, in named capture groups.
309
+ # Supports formats suggested by http://keepachangelog.com and https://github.com/tech-angels/vandamme
310
+ # as well as other similar formats that actually occur in the wild.
311
+ # Build it in pieces for readability, and allow version and date in either order.
312
+ # Whenever you change this, add a row to the test case in spec/fpm/package/gem_spec.rb.
313
+ # Don't even try to handle dates that lack four-digit years.
314
+ # Building blocks:
315
+ P_RE_LEADIN = '^[#=]{0,3}\s?'
316
+ P_RE_VERSION_ = '[\w\.-]+\.[\w\.-]+[a-zA-Z0-9]'
317
+ P_RE_SEPARATOR = '\s[-=/(]?\s?'
318
+ P_RE_DATE1 = '\d{4}-\d{2}-\d{2}'
319
+ P_RE_DATE2 = '\w+ \d{1,2}(?:st|nd|rd|th)?,\s\d{4}'
320
+ P_RE_DATE3 = '\w+\s+\w+\s+\d{1,2},\s\d{4}'
321
+ P_RE_DATE = "(?<date>#{P_RE_DATE1}|#{P_RE_DATE2}|#{P_RE_DATE3})"
322
+ P_RE_URL = '\(https?:[-\w/.%]*\)' # In parens, per markdown
323
+ P_RE_GTMAGIC = '\[\]' # github magic version diff, per chandler
324
+ P_RE_VERSION = "\\[?(?:Version |v)?(?<version>#{P_RE_VERSION_})\\]?(?:#{P_RE_URL}|#{P_RE_GTMAGIC})?"
325
+ # The final RE's:
326
+ P_RE_VERSION_DATE = "#{P_RE_LEADIN}#{P_RE_VERSION}#{P_RE_SEPARATOR}#{P_RE_DATE}"
327
+ P_RE_DATE_VERSION = "#{P_RE_LEADIN}#{P_RE_DATE}#{P_RE_SEPARATOR}#{P_RE_VERSION}"
328
+
329
+ # Detect release date, if found, store in attributes[:source_date_epoch]
330
+ def detect_source_date_from_changelog(installdir)
331
+ name = self.name.sub("rubygem-", "") + "-" + self.version
332
+ changelog = nil
333
+ datestr = nil
334
+ r1 = Regexp.new(P_RE_VERSION_DATE)
335
+ r2 = Regexp.new(P_RE_DATE_VERSION)
336
+
337
+ # Changelog doesn't have a standard name, so check all common variations
338
+ # Sort this list using LANG=C, i.e. caps first
339
+ [
340
+ "CHANGELIST",
341
+ "CHANGELOG", "CHANGELOG.asciidoc", "CHANGELOG.md", "CHANGELOG.rdoc", "CHANGELOG.rst", "CHANGELOG.txt",
342
+ "CHANGES", "CHANGES.md", "CHANGES.txt",
343
+ "ChangeLog", "ChangeLog.md", "ChangeLog.txt",
344
+ "Changelog", "Changelog.md", "Changelog.txt",
345
+ "changelog", "changelog.md", "changelog.txt",
346
+ ].each do |changelogname|
347
+ path = File.join(installdir, "gems", name, changelogname)
348
+ if File.exist?(path)
349
+ changelog = path
350
+ File.open path do |file|
351
+ file.each_line do |line|
352
+ if line =~ /#{self.version}/
353
+ [r1, r2].each do |r|
354
+ if r.match(line)
355
+ datestr = $~[:date]
356
+ break
357
+ end
358
+ end
359
+ end
360
+ end
361
+ end
362
+ end
363
+ end
364
+ if datestr
365
+ date = Date.parse(datestr)
366
+ sec = date.strftime("%s")
367
+ attributes[:source_date_epoch] = sec
368
+ logger.debug("Gem %s has changelog date %s, setting source_date_epoch to %s" % [name, datestr, sec])
369
+ elsif changelog
370
+ logger.debug("Gem %s changelog %s did not have recognizable date for release %s" % [name, changelog, self.version])
371
+ else
372
+ logger.debug("Gem %s did not have changelog with recognized name" % [name])
373
+ # FIXME: check rubygems.org?
374
+ end
375
+ end # detect_source_date_from_changelog
376
+
242
377
  public(:input, :output)
243
378
  end # class FPM::Package::Gem
@@ -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
 
@@ -10,13 +10,14 @@ require "pleaserun/cli"
10
10
  # This does not currently support 'output'
11
11
  class FPM::Package::PleaseRun < FPM::Package
12
12
  # TODO(sissel): Implement flags.
13
-
13
+
14
14
  require "pleaserun/platform/systemd"
15
15
  require "pleaserun/platform/upstart"
16
16
  require "pleaserun/platform/launchd"
17
17
  require "pleaserun/platform/sysv"
18
18
 
19
19
  option "--name", "SERVICE_NAME", "The name of the service you are creating"
20
+ option "--chdir", "CHDIR", "The working directory used by the service"
20
21
 
21
22
  private
22
23
  def input(command)
@@ -27,6 +28,10 @@ class FPM::Package::PleaseRun < FPM::Package
27
28
  ::PleaseRun::Platform::Launchd.new("10.9"), # OS X
28
29
  ::PleaseRun::Platform::SYSV.new("lsb-3.1") # Ancient stuff
29
30
  ]
31
+ pleaserun_attributes = [ "chdir", "user", "group", "umask", "chroot", "nice", "limit_coredump",
32
+ "limit_cputime", "limit_data", "limit_file_size", "limit_locked_memory",
33
+ "limit_open_files", "limit_user_processes", "limit_physical_memory", "limit_stack_size",
34
+ "log_directory", "log_file_stderr", "log_file_stdout"]
30
35
 
31
36
  attributes[:pleaserun_name] ||= File.basename(command.first)
32
37
  attributes[:prefix] ||= "/usr/share/pleaserun/#{attributes[:pleaserun_name]}"
@@ -41,6 +46,13 @@ class FPM::Package::PleaseRun < FPM::Package
41
46
  else
42
47
  platform.name
43
48
  end
49
+ pleaserun_attributes.each do |attribute_name|
50
+ attribute = "pleaserun_#{attribute_name}".to_sym
51
+ if attributes.has_key?(attribute) and not attributes[attribute].nil?
52
+ platform.send("#{attribute_name}=", attributes[attribute])
53
+ end
54
+ end
55
+
44
56
  base = staging_path(File.join(attributes[:prefix], "#{platform.platform}/#{platform.target_version || "default"}"))
45
57
  target = File.join(base, "files")
46
58
  actions_script = File.join(base, "install_actions.sh")
@@ -47,6 +47,11 @@ class get_metadata(Command):
47
47
 
48
48
  def process_dep(self, dep):
49
49
  deps = []
50
+ if hasattr(dep, 'marker') and dep.marker:
51
+ # PEP0508 marker present
52
+ if not dep.marker.evaluate():
53
+ return deps
54
+
50
55
  if dep.specs:
51
56
  for operator, version in dep.specs:
52
57
  deps.append("%s %s %s" % (dep.project_name,
@@ -73,6 +73,10 @@ class FPM::Package::Python < FPM::Package
73
73
  "The python package name to remove from dependency list",
74
74
  :multivalued => true, :attribute_name => :python_disable_dependency,
75
75
  :default => []
76
+ option "--setup-py-arguments", "setup_py_argument",
77
+ "Arbitrary argument(s) to be passed to setup.py",
78
+ :multivalued => true, :attribute_name => :python_setup_py_arguments,
79
+ :default => []
76
80
 
77
81
  private
78
82
 
@@ -225,7 +229,7 @@ class FPM::Package::Python < FPM::Package
225
229
 
226
230
  if !attributes[:no_auto_depends?] and attributes[:python_dependencies?]
227
231
  metadata["dependencies"].each do |dep|
228
- dep_re = /^([^<>!= ]+)\s*(?:([<>!=]{1,2})\s*(.*))?$/
232
+ dep_re = /^([^<>!= ]+)\s*(?:([~<>!=]{1,2})\s*(.*))?$/
229
233
  match = dep_re.match(dep)
230
234
  if match.nil?
231
235
  logger.error("Unable to parse dependency", :dependency => dep)
@@ -236,7 +240,7 @@ class FPM::Package::Python < FPM::Package
236
240
  next if attributes[:python_disable_dependency].include?(name)
237
241
 
238
242
  # convert == to =
239
- if cmp == "=="
243
+ if cmp == "==" or cmp == "~="
240
244
  logger.info("Converting == dependency requirement to =", :dependency => dep )
241
245
  cmp = "="
242
246
  end
@@ -310,6 +314,13 @@ class FPM::Package::Python < FPM::Package
310
314
  flags += [ "build_scripts", "--executable", attributes[:python_scripts_executable] ]
311
315
  end
312
316
 
317
+ if !attributes[:python_setup_py_arguments].nil? and !attributes[:python_setup_py_arguments].empty?
318
+ # Add optional setup.py arguments
319
+ attributes[:python_setup_py_arguments].each do |a|
320
+ flags += [ a ]
321
+ end
322
+ end
323
+
313
324
  safesystem(attributes[:python_bin], "setup.py", "install", *flags)
314
325
  end
315
326
  end # def install_to_staging