fpm-aeppert 1.6.2
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 +7 -0
- data/CHANGELIST +661 -0
- data/CONTRIBUTORS +26 -0
- data/LICENSE +21 -0
- data/bin/fpm +8 -0
- data/lib/fpm.rb +20 -0
- data/lib/fpm/command.rb +648 -0
- data/lib/fpm/errors.rb +4 -0
- data/lib/fpm/namespace.rb +4 -0
- data/lib/fpm/package.rb +539 -0
- data/lib/fpm/package/apk.rb +510 -0
- data/lib/fpm/package/cpan.rb +405 -0
- data/lib/fpm/package/deb.rb +935 -0
- data/lib/fpm/package/dir.rb +221 -0
- data/lib/fpm/package/empty.rb +13 -0
- data/lib/fpm/package/freebsd.rb +147 -0
- data/lib/fpm/package/gem.rb +243 -0
- data/lib/fpm/package/npm.rb +120 -0
- data/lib/fpm/package/osxpkg.rb +165 -0
- data/lib/fpm/package/p5p.rb +124 -0
- data/lib/fpm/package/pacman.rb +403 -0
- data/lib/fpm/package/pear.rb +117 -0
- data/lib/fpm/package/pkgin.rb +35 -0
- data/lib/fpm/package/pleaserun.rb +63 -0
- data/lib/fpm/package/puppet.rb +120 -0
- data/lib/fpm/package/pyfpm/__init__.py +1 -0
- data/lib/fpm/package/pyfpm/get_metadata.py +104 -0
- data/lib/fpm/package/python.rb +318 -0
- data/lib/fpm/package/rpm.rb +593 -0
- data/lib/fpm/package/sh.rb +69 -0
- data/lib/fpm/package/solaris.rb +95 -0
- data/lib/fpm/package/tar.rb +86 -0
- data/lib/fpm/package/virtualenv.rb +164 -0
- data/lib/fpm/package/zip.rb +63 -0
- data/lib/fpm/rake_task.rb +60 -0
- data/lib/fpm/util.rb +358 -0
- data/lib/fpm/util/tar_writer.rb +80 -0
- data/lib/fpm/version.rb +3 -0
- data/templates/deb.erb +52 -0
- data/templates/deb/changelog.erb +5 -0
- data/templates/deb/ldconfig.sh.erb +13 -0
- data/templates/deb/postinst_upgrade.sh.erb +62 -0
- data/templates/deb/postrm_upgrade.sh.erb +46 -0
- data/templates/deb/preinst_upgrade.sh.erb +41 -0
- data/templates/deb/prerm_upgrade.sh.erb +39 -0
- data/templates/osxpkg.erb +11 -0
- data/templates/p5p_metadata.erb +12 -0
- data/templates/pacman.erb +47 -0
- data/templates/pacman/INSTALL.erb +41 -0
- data/templates/pleaserun/generate-cleanup.sh +17 -0
- data/templates/pleaserun/install-path.sh +17 -0
- data/templates/pleaserun/install.sh +117 -0
- data/templates/pleaserun/scripts/after-install.sh +4 -0
- data/templates/pleaserun/scripts/before-remove.sh +12 -0
- data/templates/puppet/package.pp.erb +34 -0
- data/templates/puppet/package/remove.pp.erb +13 -0
- data/templates/rpm.erb +260 -0
- data/templates/rpm/filesystem_list +14514 -0
- data/templates/sh.erb +369 -0
- data/templates/solaris.erb +15 -0
- metadata +322 -0
@@ -0,0 +1,318 @@
|
|
1
|
+
require "fpm/namespace"
|
2
|
+
require "fpm/package"
|
3
|
+
require "fpm/util"
|
4
|
+
require "rubygems/package"
|
5
|
+
require "rubygems"
|
6
|
+
require "fileutils"
|
7
|
+
require "tmpdir"
|
8
|
+
require "json"
|
9
|
+
|
10
|
+
# Support for python packages.
|
11
|
+
#
|
12
|
+
# This supports input, but not output.
|
13
|
+
#
|
14
|
+
# Example:
|
15
|
+
#
|
16
|
+
# # Download the django python package:
|
17
|
+
# pkg = FPM::Package::Python.new
|
18
|
+
# pkg.input("Django")
|
19
|
+
#
|
20
|
+
class FPM::Package::Python < FPM::Package
|
21
|
+
# Flags '--foo' will be accessable as attributes[:python_foo]
|
22
|
+
option "--bin", "PYTHON_EXECUTABLE",
|
23
|
+
"The path to the python executable you wish to run.", :default => "python"
|
24
|
+
option "--easyinstall", "EASYINSTALL_EXECUTABLE",
|
25
|
+
"The path to the easy_install executable tool", :default => "easy_install"
|
26
|
+
option "--pip", "PIP_EXECUTABLE",
|
27
|
+
"The path to the pip executable tool. If not specified, easy_install " \
|
28
|
+
"is used instead", :default => nil
|
29
|
+
option "--pypi", "PYPI_URL",
|
30
|
+
"PyPi Server uri for retrieving packages.",
|
31
|
+
:default => "https://pypi.python.org/simple"
|
32
|
+
option "--package-prefix", "NAMEPREFIX",
|
33
|
+
"(DEPRECATED, use --package-name-prefix) Name to prefix the package " \
|
34
|
+
"name with." do |value|
|
35
|
+
logger.warn("Using deprecated flag: --package-prefix. Please use " \
|
36
|
+
"--package-name-prefix")
|
37
|
+
value
|
38
|
+
end
|
39
|
+
option "--package-name-prefix", "PREFIX", "Name to prefix the package " \
|
40
|
+
"name with.", :default => "python"
|
41
|
+
option "--fix-name", :flag, "Should the target package name be prefixed?",
|
42
|
+
:default => true
|
43
|
+
option "--fix-dependencies", :flag, "Should the package dependencies be " \
|
44
|
+
"prefixed?", :default => true
|
45
|
+
|
46
|
+
option "--downcase-name", :flag, "Should the target package name be in " \
|
47
|
+
"lowercase?", :default => true
|
48
|
+
option "--downcase-dependencies", :flag, "Should the package dependencies " \
|
49
|
+
"be in lowercase?", :default => true
|
50
|
+
|
51
|
+
option "--install-bin", "BIN_PATH", "The path to where python scripts " \
|
52
|
+
"should be installed to."
|
53
|
+
option "--install-lib", "LIB_PATH", "The path to where python libs " \
|
54
|
+
"should be installed to (default depends on your python installation). " \
|
55
|
+
"Want to find out what your target platform is using? Run this: " \
|
56
|
+
"python -c 'from distutils.sysconfig import get_python_lib; " \
|
57
|
+
"print get_python_lib()'"
|
58
|
+
option "--install-data", "DATA_PATH", "The path to where data should be " \
|
59
|
+
"installed to. This is equivalent to 'python setup.py --install-data " \
|
60
|
+
"DATA_PATH"
|
61
|
+
option "--dependencies", :flag, "Include requirements defined in setup.py" \
|
62
|
+
" as dependencies.", :default => true
|
63
|
+
option "--obey-requirements-txt", :flag, "Use a requirements.txt file " \
|
64
|
+
"in the top-level directory of the python package for dependency " \
|
65
|
+
"detection.", :default => false
|
66
|
+
option "--scripts-executable", "PYTHON_EXECUTABLE", "Set custom python " \
|
67
|
+
"interpreter in installing scripts. By default distutils will replace " \
|
68
|
+
"python interpreter in installing scripts (specified by shebang) with " \
|
69
|
+
"current python interpreter (sys.executable). This option is equivalent " \
|
70
|
+
"to appending 'build_scripts --executable PYTHON_EXECUTABLE' arguments " \
|
71
|
+
"to 'setup.py install' command."
|
72
|
+
option "--disable-dependency", "python_package_name",
|
73
|
+
"The python package name to remove from dependency list",
|
74
|
+
:multivalued => true, :attribute_name => :python_disable_dependency,
|
75
|
+
:default => []
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
# Input a package.
|
80
|
+
#
|
81
|
+
# The 'package' can be any of:
|
82
|
+
#
|
83
|
+
# * A name of a package on pypi (ie; easy_install some-package)
|
84
|
+
# * The path to a directory containing setup.py
|
85
|
+
# * The path to a setup.py
|
86
|
+
def input(package)
|
87
|
+
path_to_package = download_if_necessary(package, version)
|
88
|
+
|
89
|
+
if File.directory?(path_to_package)
|
90
|
+
setup_py = File.join(path_to_package, "setup.py")
|
91
|
+
else
|
92
|
+
setup_py = path_to_package
|
93
|
+
end
|
94
|
+
|
95
|
+
if !File.exist?(setup_py)
|
96
|
+
logger.error("Could not find 'setup.py'", :path => setup_py)
|
97
|
+
raise "Unable to find python package; tried #{setup_py}"
|
98
|
+
end
|
99
|
+
|
100
|
+
load_package_info(setup_py)
|
101
|
+
install_to_staging(setup_py)
|
102
|
+
end # def input
|
103
|
+
|
104
|
+
# Download the given package if necessary. If version is given, that version
|
105
|
+
# will be downloaded, otherwise the latest is fetched.
|
106
|
+
def download_if_necessary(package, version=nil)
|
107
|
+
# TODO(sissel): this should just be a 'download' method, the 'if_necessary'
|
108
|
+
# part should go elsewhere.
|
109
|
+
path = package
|
110
|
+
# If it's a path, assume local build.
|
111
|
+
if File.directory?(path) or (File.exist?(path) and File.basename(path) == "setup.py")
|
112
|
+
return path
|
113
|
+
end
|
114
|
+
|
115
|
+
logger.info("Trying to download", :package => package)
|
116
|
+
|
117
|
+
if version.nil?
|
118
|
+
want_pkg = "#{package}"
|
119
|
+
else
|
120
|
+
want_pkg = "#{package}==#{version}"
|
121
|
+
end
|
122
|
+
|
123
|
+
target = build_path(package)
|
124
|
+
FileUtils.mkdir(target) unless File.directory?(target)
|
125
|
+
|
126
|
+
if attributes[:python_pip].nil?
|
127
|
+
# no pip, use easy_install
|
128
|
+
logger.debug("no pip, defaulting to easy_install", :easy_install => attributes[:python_easyinstall])
|
129
|
+
safesystem(attributes[:python_easyinstall], "-i",
|
130
|
+
attributes[:python_pypi], "--editable", "-U",
|
131
|
+
"--build-directory", target, want_pkg)
|
132
|
+
else
|
133
|
+
logger.debug("using pip", :pip => attributes[:python_pip])
|
134
|
+
# TODO: Support older versions of pip
|
135
|
+
safesystem(attributes[:python_pip], "download", "--no-clean", "--no-deps", "--no-binary", ":all:", "-i", attributes[:python_pypi], "--build", target, want_pkg)
|
136
|
+
end
|
137
|
+
|
138
|
+
# easy_install will put stuff in @tmpdir/packagename/, so find that:
|
139
|
+
# @tmpdir/somepackage/setup.py
|
140
|
+
dirs = ::Dir.glob(File.join(target, "*"))
|
141
|
+
if dirs.length != 1
|
142
|
+
raise "Unexpected directory layout after easy_install. Maybe file a bug? The directory is #{build_path}"
|
143
|
+
end
|
144
|
+
return dirs.first
|
145
|
+
end # def download
|
146
|
+
|
147
|
+
# Load the package information like name, version, dependencies.
|
148
|
+
def load_package_info(setup_py)
|
149
|
+
if !attributes[:python_package_prefix].nil?
|
150
|
+
attributes[:python_package_name_prefix] = attributes[:python_package_prefix]
|
151
|
+
end
|
152
|
+
|
153
|
+
begin
|
154
|
+
json_test_code = [
|
155
|
+
"try:",
|
156
|
+
" import json",
|
157
|
+
"except ImportError:",
|
158
|
+
" import simplejson as json"
|
159
|
+
].join("\n")
|
160
|
+
safesystem("#{attributes[:python_bin]} -c '#{json_test_code}'")
|
161
|
+
rescue FPM::Util::ProcessFailed => e
|
162
|
+
logger.error("Your python environment is missing json support (either json or simplejson python module). I cannot continue without this.", :python => attributes[:python_bin], :error => e)
|
163
|
+
raise FPM::Util::ProcessFailed, "Python (#{attributes[:python_bin]}) is missing simplejson or json modules."
|
164
|
+
end
|
165
|
+
|
166
|
+
begin
|
167
|
+
safesystem("#{attributes[:python_bin]} -c 'import pkg_resources'")
|
168
|
+
rescue FPM::Util::ProcessFailed => e
|
169
|
+
logger.error("Your python environment is missing a working setuptools module. I tried to find the 'pkg_resources' module but failed.", :python => attributes[:python_bin], :error => e)
|
170
|
+
raise FPM::Util::ProcessFailed, "Python (#{attributes[:python_bin]}) is missing pkg_resources module."
|
171
|
+
end
|
172
|
+
|
173
|
+
# Add ./pyfpm/ to the python library path
|
174
|
+
pylib = File.expand_path(File.dirname(__FILE__))
|
175
|
+
|
176
|
+
# chdir to the directory holding setup.py because some python setup.py's assume that you are
|
177
|
+
# in the same directory.
|
178
|
+
setup_dir = File.dirname(setup_py)
|
179
|
+
|
180
|
+
output = ::Dir.chdir(setup_dir) do
|
181
|
+
tmp = build_path("metadata.json")
|
182
|
+
setup_cmd = "env PYTHONPATH=#{pylib} #{attributes[:python_bin]} " \
|
183
|
+
"setup.py --command-packages=pyfpm get_metadata --output=#{tmp}"
|
184
|
+
|
185
|
+
if attributes[:python_obey_requirements_txt?]
|
186
|
+
setup_cmd += " --load-requirements-txt"
|
187
|
+
end
|
188
|
+
|
189
|
+
# Capture the output, which will be JSON metadata describing this python
|
190
|
+
# package. See fpm/lib/fpm/package/pyfpm/get_metadata.py for more
|
191
|
+
# details.
|
192
|
+
logger.info("fetching package metadata", :setup_cmd => setup_cmd)
|
193
|
+
|
194
|
+
success = safesystem(setup_cmd)
|
195
|
+
#%x{#{setup_cmd}}
|
196
|
+
if !success
|
197
|
+
logger.error("setup.py get_metadata failed", :command => setup_cmd,
|
198
|
+
:exitcode => $?.exitstatus)
|
199
|
+
raise "An unexpected error occurred while processing the setup.py file"
|
200
|
+
end
|
201
|
+
File.read(tmp)
|
202
|
+
end
|
203
|
+
logger.debug("result from `setup.py get_metadata`", :data => output)
|
204
|
+
metadata = JSON.parse(output)
|
205
|
+
logger.info("object output of get_metadata", :json => metadata)
|
206
|
+
|
207
|
+
self.architecture = metadata["architecture"]
|
208
|
+
self.description = metadata["description"]
|
209
|
+
# Sometimes the license field is multiple lines; do best-effort and just
|
210
|
+
# use the first line.
|
211
|
+
self.license = metadata["license"].split(/[\r\n]+/).first
|
212
|
+
self.version = metadata["version"]
|
213
|
+
self.url = metadata["url"]
|
214
|
+
|
215
|
+
# name prefixing is optional, if enabled, a name 'foo' will become
|
216
|
+
# 'python-foo' (depending on what the python_package_name_prefix is)
|
217
|
+
if attributes[:python_fix_name?]
|
218
|
+
self.name = fix_name(metadata["name"])
|
219
|
+
else
|
220
|
+
self.name = metadata["name"]
|
221
|
+
end
|
222
|
+
|
223
|
+
# convert python-Foo to python-foo if flag is set
|
224
|
+
self.name = self.name.downcase if attributes[:python_downcase_name?]
|
225
|
+
|
226
|
+
if !attributes[:no_auto_depends?] and attributes[:python_dependencies?]
|
227
|
+
metadata["dependencies"].each do |dep|
|
228
|
+
dep_re = /^([^<>!= ]+)\s*(?:([<>!=]{1,2})\s*(.*))?$/
|
229
|
+
match = dep_re.match(dep)
|
230
|
+
if match.nil?
|
231
|
+
logger.error("Unable to parse dependency", :dependency => dep)
|
232
|
+
raise FPM::InvalidPackageConfiguration, "Invalid dependency '#{dep}'"
|
233
|
+
end
|
234
|
+
name, cmp, version = match.captures
|
235
|
+
|
236
|
+
next if attributes[:python_disable_dependency].include?(name)
|
237
|
+
|
238
|
+
# convert == to =
|
239
|
+
if cmp == "=="
|
240
|
+
logger.info("Converting == dependency requirement to =", :dependency => dep )
|
241
|
+
cmp = "="
|
242
|
+
end
|
243
|
+
|
244
|
+
# dependency name prefixing is optional, if enabled, a name 'foo' will
|
245
|
+
# become 'python-foo' (depending on what the python_package_name_prefix
|
246
|
+
# is)
|
247
|
+
name = fix_name(name) if attributes[:python_fix_dependencies?]
|
248
|
+
|
249
|
+
# convert dependencies from python-Foo to python-foo
|
250
|
+
name = name.downcase if attributes[:python_downcase_dependencies?]
|
251
|
+
|
252
|
+
self.dependencies << "#{name} #{cmp} #{version}"
|
253
|
+
end
|
254
|
+
end # if attributes[:python_dependencies?]
|
255
|
+
end # def load_package_info
|
256
|
+
|
257
|
+
# Sanitize package name.
|
258
|
+
# Some PyPI packages can be named 'python-foo', so we don't want to end up
|
259
|
+
# with a package named 'python-python-foo'.
|
260
|
+
# But we want packages named like 'pythonweb' to be suffixed
|
261
|
+
# 'python-pythonweb'.
|
262
|
+
def fix_name(name)
|
263
|
+
if name.start_with?("python")
|
264
|
+
# If the python package is called "python-foo" strip the "python-" part while
|
265
|
+
# prepending the package name prefix.
|
266
|
+
return [attributes[:python_package_name_prefix], name.gsub(/^python-/, "")].join("-")
|
267
|
+
else
|
268
|
+
return [attributes[:python_package_name_prefix], name].join("-")
|
269
|
+
end
|
270
|
+
end # def fix_name
|
271
|
+
|
272
|
+
# Install this package to the staging directory
|
273
|
+
def install_to_staging(setup_py)
|
274
|
+
project_dir = File.dirname(setup_py)
|
275
|
+
|
276
|
+
prefix = "/"
|
277
|
+
prefix = attributes[:prefix] unless attributes[:prefix].nil?
|
278
|
+
|
279
|
+
# Some setup.py's assume $PWD == current directory of setup.py, so let's
|
280
|
+
# chdir first.
|
281
|
+
::Dir.chdir(project_dir) do
|
282
|
+
flags = [ "--root", staging_path ]
|
283
|
+
if !attributes[:python_install_lib].nil?
|
284
|
+
flags += [ "--install-lib", File.join(prefix, attributes[:python_install_lib]) ]
|
285
|
+
elsif !attributes[:prefix].nil?
|
286
|
+
# setup.py install --prefix PREFIX still installs libs to
|
287
|
+
# PREFIX/lib64/python2.7/site-packages/
|
288
|
+
# but we really want something saner.
|
289
|
+
#
|
290
|
+
# since prefix is given, but not python_install_lib, assume PREFIX/lib
|
291
|
+
flags += [ "--install-lib", File.join(prefix, "lib") ]
|
292
|
+
end
|
293
|
+
|
294
|
+
if !attributes[:python_install_data].nil?
|
295
|
+
flags += [ "--install-data", File.join(prefix, attributes[:python_install_data]) ]
|
296
|
+
elsif !attributes[:prefix].nil?
|
297
|
+
# prefix given, but not python_install_data, assume PREFIX/data
|
298
|
+
flags += [ "--install-data", File.join(prefix, "data") ]
|
299
|
+
end
|
300
|
+
|
301
|
+
if !attributes[:python_install_bin].nil?
|
302
|
+
flags += [ "--install-scripts", File.join(prefix, attributes[:python_install_bin]) ]
|
303
|
+
elsif !attributes[:prefix].nil?
|
304
|
+
# prefix given, but not python_install_bin, assume PREFIX/bin
|
305
|
+
flags += [ "--install-scripts", File.join(prefix, "bin") ]
|
306
|
+
end
|
307
|
+
|
308
|
+
if !attributes[:python_scripts_executable].nil?
|
309
|
+
# Overwrite installed python scripts shebang binary with provided executable
|
310
|
+
flags += [ "build_scripts", "--executable", attributes[:python_scripts_executable] ]
|
311
|
+
end
|
312
|
+
|
313
|
+
safesystem(attributes[:python_bin], "setup.py", "install", *flags)
|
314
|
+
end
|
315
|
+
end # def install_to_staging
|
316
|
+
|
317
|
+
public(:input)
|
318
|
+
end # class FPM::Package::Python
|
@@ -0,0 +1,593 @@
|
|
1
|
+
require "fpm/package"
|
2
|
+
require "backports"
|
3
|
+
require "fileutils"
|
4
|
+
require "find"
|
5
|
+
require "arr-pm/file" # gem 'arr-pm'
|
6
|
+
|
7
|
+
# RPM Package type.
|
8
|
+
#
|
9
|
+
# Build RPMs without having to waste hours reading Maximum-RPM.
|
10
|
+
# Well, in case you want to read it, here: http://www.rpm.org/max-rpm/
|
11
|
+
#
|
12
|
+
# The following attributes are supported:
|
13
|
+
#
|
14
|
+
# * :rpm_rpmbuild_define - an array of definitions to give to rpmbuild.
|
15
|
+
# These are used, verbatim, each as: --define ITEM
|
16
|
+
class FPM::Package::RPM < FPM::Package
|
17
|
+
DIGEST_ALGORITHM_MAP = {
|
18
|
+
"md5" => 1,
|
19
|
+
"sha1" => 2,
|
20
|
+
"sha256" => 8,
|
21
|
+
"sha384" => 9,
|
22
|
+
"sha512" => 10
|
23
|
+
} unless defined?(DIGEST_ALGORITHM_MAP)
|
24
|
+
|
25
|
+
COMPRESSION_MAP = {
|
26
|
+
"none" => "w0.gzdio",
|
27
|
+
"xz" => "w9.xzdio",
|
28
|
+
"gzip" => "w9.gzdio",
|
29
|
+
"bzip2" => "w9.bzdio"
|
30
|
+
} unless defined?(COMPRESSION_MAP)
|
31
|
+
|
32
|
+
option "--use-file-permissions", :flag,
|
33
|
+
"Use existing file permissions when defining ownership and modes."
|
34
|
+
|
35
|
+
option "--user", "USER", "Set the user to USER in the %files section. Overrides the user when used with use-file-permissions setting."
|
36
|
+
|
37
|
+
option "--group", "GROUP", "Set the group to GROUP in the %files section. Overrides the group when used with use-file-permissions setting."
|
38
|
+
|
39
|
+
option "--defattrfile", "ATTR",
|
40
|
+
"Set the default file mode (%defattr).",
|
41
|
+
:default => '-' do |value|
|
42
|
+
value
|
43
|
+
end
|
44
|
+
|
45
|
+
option "--defattrdir", "ATTR",
|
46
|
+
"Set the default dir mode (%defattr).",
|
47
|
+
:default => '-' do |value|
|
48
|
+
value
|
49
|
+
end
|
50
|
+
|
51
|
+
rpmbuild_define = []
|
52
|
+
option "--rpmbuild-define", "DEFINITION",
|
53
|
+
"Pass a --define argument to rpmbuild." do |define|
|
54
|
+
rpmbuild_define << define
|
55
|
+
next rpmbuild_define
|
56
|
+
end
|
57
|
+
|
58
|
+
option "--dist", "DIST-TAG", "Set the rpm distribution."
|
59
|
+
|
60
|
+
option "--digest", DIGEST_ALGORITHM_MAP.keys.join("|"),
|
61
|
+
"Select a digest algorithm. md5 works on the most platforms.",
|
62
|
+
:default => "md5" do |value|
|
63
|
+
if !DIGEST_ALGORITHM_MAP.include?(value.downcase)
|
64
|
+
raise "Unknown digest algorithm '#{value}'. Valid options " \
|
65
|
+
"include: #{DIGEST_ALGORITHM_MAP.keys.join(", ")}"
|
66
|
+
end
|
67
|
+
value.downcase
|
68
|
+
end
|
69
|
+
|
70
|
+
option "--compression", COMPRESSION_MAP.keys.join("|"),
|
71
|
+
"Select a compression method. gzip works on the most platforms.",
|
72
|
+
:default => "gzip" do |value|
|
73
|
+
if !COMPRESSION_MAP.include?(value.downcase)
|
74
|
+
raise "Unknown compression type '#{value}'. Valid options " \
|
75
|
+
"include: #{COMPRESSION_MAP.keys.join(", ")}"
|
76
|
+
end
|
77
|
+
value.downcase
|
78
|
+
end
|
79
|
+
|
80
|
+
# TODO(sissel): Try to be smart about the default OS.
|
81
|
+
# issue #309
|
82
|
+
option "--os", "OS", "The operating system to target this rpm for. " \
|
83
|
+
"You want to set this to 'linux' if you are using fpm on OS X, for example"
|
84
|
+
|
85
|
+
option "--changelog", "FILEPATH", "Add changelog from FILEPATH contents" do |file|
|
86
|
+
File.read(File.expand_path(file))
|
87
|
+
end
|
88
|
+
|
89
|
+
option "--summary", "SUMMARY",
|
90
|
+
"Set the RPM summary. Overrides the first line on the description if set"
|
91
|
+
|
92
|
+
option "--sign", :flag, "Pass --sign to rpmbuild"
|
93
|
+
|
94
|
+
option "--auto-add-directories", :flag, "Auto add directories not part of filesystem"
|
95
|
+
option "--auto-add-exclude-directories", "DIRECTORIES",
|
96
|
+
"Additional directories ignored by '--rpm-auto-add-directories' flag",
|
97
|
+
:multivalued => true, :attribute_name => :auto_add_exclude_directories
|
98
|
+
|
99
|
+
option "--autoreqprov", :flag, "Enable RPM's AutoReqProv option"
|
100
|
+
option "--autoreq", :flag, "Enable RPM's AutoReq option"
|
101
|
+
option "--autoprov", :flag, "Enable RPM's AutoProv option"
|
102
|
+
|
103
|
+
option "--attr", "ATTRFILE",
|
104
|
+
"Set the attribute for a file (%attr), e.g. --rpm-attr 750,user1,group1:/some/file",
|
105
|
+
:multivalued => true, :attribute_name => :attrs
|
106
|
+
|
107
|
+
option "--init", "FILEPATH", "Add FILEPATH as an init script",
|
108
|
+
:multivalued => true do |file|
|
109
|
+
next File.expand_path(file)
|
110
|
+
end
|
111
|
+
|
112
|
+
rpmbuild_filter_from_provides = []
|
113
|
+
option "--filter-from-provides", "REGEX",
|
114
|
+
"Set %filter_from_provides to the supplied REGEX." do |filter_from_provides|
|
115
|
+
rpmbuild_filter_from_provides << filter_from_provides
|
116
|
+
next rpmbuild_filter_from_provides
|
117
|
+
end
|
118
|
+
rpmbuild_filter_from_requires = []
|
119
|
+
option "--filter-from-requires", "REGEX",
|
120
|
+
"Set %filter_from_requires to the supplied REGEX." do |filter_from_requires|
|
121
|
+
rpmbuild_filter_from_requires << filter_from_requires
|
122
|
+
next rpmbuild_filter_from_requires
|
123
|
+
end
|
124
|
+
|
125
|
+
rpm_tags = []
|
126
|
+
option "--tag", "TAG",
|
127
|
+
"Adds a custom tag in the spec file as is. " \
|
128
|
+
"Example: --rpm-tag 'Requires(post): /usr/sbin/alternatives'" do |add_tag|
|
129
|
+
rpm_tags << add_tag
|
130
|
+
next rpm_tags
|
131
|
+
end
|
132
|
+
|
133
|
+
option "--ignore-iteration-in-dependencies", :flag,
|
134
|
+
"For '=' (equal) dependencies, allow iterations on the specified " \
|
135
|
+
"version. Default is to be specific. This option allows the same " \
|
136
|
+
"version of a package but any iteration is permitted"
|
137
|
+
|
138
|
+
option "--verbatim-gem-dependencies", :flag,
|
139
|
+
"When converting from a gem, leave the old (fpm 0.4.x) style " \
|
140
|
+
"dependency names. This flag will use the old 'rubygem-foo' " \
|
141
|
+
"names in rpm requires instead of the redhat style " \
|
142
|
+
"rubygem(foo).", :default => false
|
143
|
+
|
144
|
+
option "--verifyscript", "FILE",
|
145
|
+
"a script to be run on verification" do |val|
|
146
|
+
File.expand_path(val) # Get the full path to the script
|
147
|
+
end # --verifyscript
|
148
|
+
option "--pretrans", "FILE",
|
149
|
+
"pretrans script" do |val|
|
150
|
+
File.expand_path(val) # Get the full path to the script
|
151
|
+
end # --pretrans
|
152
|
+
option "--posttrans", "FILE",
|
153
|
+
"posttrans script" do |val|
|
154
|
+
File.expand_path(val) # Get the full path to the script
|
155
|
+
end # --posttrans
|
156
|
+
|
157
|
+
["before-install","after-install","before-uninstall","after-target-uninstall"].each do |trigger_type|
|
158
|
+
rpm_trigger = []
|
159
|
+
option "--trigger-#{trigger_type}", "'[OPT]PACKAGE: FILEPATH'", "Adds a rpm trigger script located in FILEPATH, " \
|
160
|
+
"having 'OPT' options and linking to 'PACKAGE'. PACKAGE can be a comma seperated list of packages. " \
|
161
|
+
"See: http://rpm.org/api/4.4.2.2/triggers.html" do |trigger|
|
162
|
+
match = trigger.match(/^(\[.*\]|)(.*): (.*)$/)
|
163
|
+
@logger.fatal("Trigger '#{trigger_type}' definition can't be parsed ('#{trigger}')") unless match
|
164
|
+
opt, pkg, file = match.captures
|
165
|
+
@logger.fatal("File given for --trigger-#{trigger_type} does not exist (#{file})") unless File.exist?(file)
|
166
|
+
rpm_trigger << [pkg, File.read(file), opt.tr('[]','')]
|
167
|
+
next rpm_trigger
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
private
|
172
|
+
|
173
|
+
# Fix path name
|
174
|
+
# Replace [ with [\[] to make rpm not use globs
|
175
|
+
# Replace * with [*] to make rpm not use globs
|
176
|
+
# Replace ? with [?] to make rpm not use globs
|
177
|
+
# Replace % with [%] to make rpm not expand macros
|
178
|
+
def rpm_fix_name(name)
|
179
|
+
name = name.gsub(/(\ |\[|\]|\*|\?|\%|\$)/, {
|
180
|
+
' ' => '?',
|
181
|
+
'%' => '[%]',
|
182
|
+
'$' => '[$]',
|
183
|
+
'?' => '[?]',
|
184
|
+
'*' => '[*]',
|
185
|
+
'[' => '[\[]',
|
186
|
+
']' => '[\]]'
|
187
|
+
})
|
188
|
+
end
|
189
|
+
|
190
|
+
def rpm_file_entry(file)
|
191
|
+
original_file = file
|
192
|
+
file = rpm_fix_name(file)
|
193
|
+
|
194
|
+
if !attributes[:rpm_use_file_permissions?]
|
195
|
+
|
196
|
+
if attrs[file].nil?
|
197
|
+
return file
|
198
|
+
else
|
199
|
+
return sprintf("%%attr(%s) %s\n", attrs[file], file)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
return sprintf("%%attr(%s) %s\n", attrs[file], file) unless attrs[file].nil?
|
204
|
+
|
205
|
+
# Stat the original filename in the relative staging path
|
206
|
+
::Dir.chdir(staging_path) do
|
207
|
+
stat = File.lstat(original_file.gsub(/\"/, '').sub(/^\//,''))
|
208
|
+
|
209
|
+
# rpm_user and rpm_group attribute should override file ownership
|
210
|
+
# otherwise use the current file user/group by name.
|
211
|
+
user = attributes[:rpm_user] || Etc.getpwuid(stat.uid).name
|
212
|
+
group = attributes[:rpm_group] || Etc.getgrgid(stat.gid).name
|
213
|
+
mode = stat.mode
|
214
|
+
return sprintf("%%attr(%o, %s, %s) %s\n", mode & 4095 , user, group, file)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
|
219
|
+
# Handle any architecture naming conversions.
|
220
|
+
# For example, debian calls amd64 what redhat calls x86_64, this
|
221
|
+
# method fixes those types of things.
|
222
|
+
def architecture
|
223
|
+
case @architecture
|
224
|
+
when nil
|
225
|
+
return %x{uname -m}.chomp # default to current arch
|
226
|
+
when "amd64" # debian and redhat disagree on architecture names
|
227
|
+
return "x86_64"
|
228
|
+
when "native"
|
229
|
+
return %x{uname -m}.chomp # 'native' is current arch
|
230
|
+
when "all"
|
231
|
+
# Translate fpm "all" arch to what it means in RPM.
|
232
|
+
return "noarch"
|
233
|
+
else
|
234
|
+
return @architecture
|
235
|
+
end
|
236
|
+
end # def architecture
|
237
|
+
|
238
|
+
# This method ensures a default value for iteration if none is provided.
|
239
|
+
def iteration
|
240
|
+
return @iteration ? @iteration : 1
|
241
|
+
end # def iteration
|
242
|
+
|
243
|
+
# See FPM::Package#converted_from
|
244
|
+
def converted_from(origin)
|
245
|
+
if origin == FPM::Package::Gem
|
246
|
+
fixed_deps = []
|
247
|
+
self.dependencies.collect do |dep|
|
248
|
+
# Gem dependency operator "~>" is not compatible with rpm. Translate any found.
|
249
|
+
fixed_deps = fixed_deps + expand_pessimistic_constraints(dep)
|
250
|
+
end
|
251
|
+
self.dependencies = fixed_deps
|
252
|
+
|
253
|
+
# Convert 'rubygem-foo' provides values to 'rubygem(foo)'
|
254
|
+
# since that's what most rpm packagers seem to do.
|
255
|
+
self.provides = self.provides.collect do |provides|
|
256
|
+
# Tries to match rubygem_prefix [1], gem_name [2] and version [3] if present
|
257
|
+
# and return it in rubygem_prefix(gem_name) form
|
258
|
+
if name=/^(#{attributes[:gem_package_name_prefix]})-([^\s]+)\s*(.*)$/.match(provides)
|
259
|
+
"#{name[1]}(#{name[2]})#{name[3] ? " #{name[3]}" : ""}"
|
260
|
+
else
|
261
|
+
provides
|
262
|
+
end
|
263
|
+
end
|
264
|
+
if !self.attributes[:rpm_verbatim_gem_dependencies?]
|
265
|
+
self.dependencies = self.dependencies.collect do |dependency|
|
266
|
+
# Tries to match rubygem_prefix [1], gem_name [2] and version [3] if present
|
267
|
+
# and return it in rubygem_prefix(gem_name) form
|
268
|
+
if name=/^(#{attributes[:gem_package_name_prefix]})-([^\s]+)\s*(.*)$/.match(dependency)
|
269
|
+
"#{name[1]}(#{name[2]})#{name[3] ? " #{name[3]}" : ""}"
|
270
|
+
else
|
271
|
+
dependency
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
# Convert != dependency as Conflict =, as rpm doesn't understand !=
|
278
|
+
self.dependencies = self.dependencies.select do |dep|
|
279
|
+
name, op, version = dep.split(/\s+/)
|
280
|
+
dep_ok = true
|
281
|
+
if op == '!='
|
282
|
+
self.conflicts << "#{name} = #{version}"
|
283
|
+
dep_ok = false
|
284
|
+
end
|
285
|
+
dep_ok
|
286
|
+
end
|
287
|
+
|
288
|
+
# if --ignore-iteration-in-dependencies is true convert foo = X, to
|
289
|
+
# foo >= X , foo < X+1
|
290
|
+
if self.attributes[:rpm_ignore_iteration_in_dependencies?]
|
291
|
+
self.dependencies = self.dependencies.collect do |dep|
|
292
|
+
name, op, version = dep.split(/\s+/)
|
293
|
+
if op == '='
|
294
|
+
nextversion = version.split('.').collect { |v| v.to_i }
|
295
|
+
nextversion[-1] += 1
|
296
|
+
nextversion = nextversion.join(".")
|
297
|
+
logger.warn("Converting dependency #{dep} to #{name} >= #{version}, #{name} < #{nextversion}")
|
298
|
+
["#{name} >= #{version}", "#{name} < #{nextversion}"]
|
299
|
+
else
|
300
|
+
dep
|
301
|
+
end
|
302
|
+
end.flatten
|
303
|
+
end
|
304
|
+
|
305
|
+
setscript = proc do |scriptname|
|
306
|
+
script_path = self.attributes[scriptname]
|
307
|
+
# Skip scripts not set
|
308
|
+
next if script_path.nil?
|
309
|
+
if !File.exist?(script_path)
|
310
|
+
logger.error("No such file (for #{scriptname.to_s}): #{script_path.inspect}")
|
311
|
+
script_errors << script_path
|
312
|
+
end
|
313
|
+
# Load the script into memory.
|
314
|
+
scripts[scriptname] = File.read(script_path)
|
315
|
+
end
|
316
|
+
|
317
|
+
setscript.call(:rpm_verifyscript)
|
318
|
+
setscript.call(:rpm_posttrans)
|
319
|
+
setscript.call(:rpm_pretrans)
|
320
|
+
end # def converted
|
321
|
+
|
322
|
+
def rpm_get_trigger_type(flag)
|
323
|
+
if (flag & (1 << 25)) == (1 << 25)
|
324
|
+
# RPMSENSE_TRIGGERPREIN = (1 << 25), /*!< %triggerprein dependency. */
|
325
|
+
:rpm_trigger_before_install
|
326
|
+
elsif (flag & (1 << 16)) == (1 << 16)
|
327
|
+
# RPMSENSE_TRIGGERIN = (1 << 16), /*!< %triggerin dependency. */
|
328
|
+
:rpm_trigger_after_install
|
329
|
+
elsif (flag & (1 << 17)) == (1 << 17)
|
330
|
+
# RPMSENSE_TRIGGERUN = (1 << 17), /*!< %triggerun dependency. */
|
331
|
+
:rpm_trigger_before_uninstall
|
332
|
+
elsif (flag & (1 << 18)) == (1 << 18)
|
333
|
+
# RPMSENSE_TRIGGERPOSTUN = (1 << 18), /*!< %triggerpostun dependency. */
|
334
|
+
:rpm_trigger_after_target_uninstall
|
335
|
+
else
|
336
|
+
@logger.fatal("I don't know about this triggerflag ('#{flag}')")
|
337
|
+
end
|
338
|
+
end # def rpm_get_trigger
|
339
|
+
|
340
|
+
def input(path)
|
341
|
+
rpm = ::RPM::File.new(path)
|
342
|
+
|
343
|
+
tags = {}
|
344
|
+
rpm.header.tags.each do |tag|
|
345
|
+
tags[tag.tag] = tag.value
|
346
|
+
end
|
347
|
+
|
348
|
+
self.architecture = tags[:arch]
|
349
|
+
self.category = tags[:group]
|
350
|
+
self.description = tags[:description]
|
351
|
+
self.epoch = (tags[:epoch] || [nil]).first # for some reason epoch is an array
|
352
|
+
self.iteration = tags[:release]
|
353
|
+
self.license = tags[:license]
|
354
|
+
self.maintainer = maintainer
|
355
|
+
self.name = tags[:name]
|
356
|
+
self.url = tags[:url]
|
357
|
+
self.vendor = tags[:vendor]
|
358
|
+
self.version = tags[:version]
|
359
|
+
|
360
|
+
self.scripts[:before_install] = tags[:prein]
|
361
|
+
self.scripts[:after_install] = tags[:postin]
|
362
|
+
self.scripts[:before_remove] = tags[:preun]
|
363
|
+
self.scripts[:after_remove] = tags[:postun]
|
364
|
+
self.scripts[:rpm_verifyscript] = tags[:verifyscript]
|
365
|
+
self.scripts[:rpm_posttrans] = tags[:posttrans]
|
366
|
+
self.scripts[:rpm_pretrans] = tags[:pretrans]
|
367
|
+
# TODO(sissel): prefix these scripts above with a shebang line if there isn't one?
|
368
|
+
# Also taking into account the value of tags[preinprog] etc, something like:
|
369
|
+
# #!#{tags[:preinprog]}
|
370
|
+
# #{tags[prein]}
|
371
|
+
|
372
|
+
if !tags[:triggerindex].nil?
|
373
|
+
val = tags[:triggerindex].zip(tags[:triggername],tags[:triggerflags],tags[:triggerversion]).group_by{ |x| x[0]}
|
374
|
+
val = val.collect do |order,data|
|
375
|
+
new_data = data.collect { |x| [ x[1], rpm.operator(x[2]), x[3]].join(" ").strip}.join(", ")
|
376
|
+
[order, rpm_get_trigger_type(data[0][2]), new_data]
|
377
|
+
end
|
378
|
+
val.each do |order, attr,data|
|
379
|
+
self.attributes[attr] = [] if self.attributes[attr].nil?
|
380
|
+
scriptprog = (tags[:triggerscriptprog][order] == '/bin/sh') ? "" : "-p #{tags[:triggerscriptprog][order]}"
|
381
|
+
self.attributes[attr] << [data,tags[:triggerscripts][order],scriptprog]
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
if !attributes[:no_auto_depends?]
|
386
|
+
self.dependencies += rpm.requires.collect do |name, operator, version|
|
387
|
+
[name, operator, version].join(" ")
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
self.conflicts += rpm.conflicts.collect do |name, operator, version|
|
392
|
+
[name, operator, version].join(" ")
|
393
|
+
end
|
394
|
+
self.provides += rpm.provides.collect do |name, operator, version|
|
395
|
+
[name, operator, version].join(" ")
|
396
|
+
end
|
397
|
+
#input.replaces += replaces
|
398
|
+
|
399
|
+
self.config_files += rpm.config_files
|
400
|
+
|
401
|
+
# rpms support '%dir' things for specifying empty directories to package,
|
402
|
+
# but the rpm header itself doesn't actually record this information.
|
403
|
+
# so there's no 'directories' to copy, so don't try to merge in the
|
404
|
+
# 'directories' feature.
|
405
|
+
# TODO(sissel): If you want this feature, we'll have to find scan
|
406
|
+
# the extracted rpm for empty directories. I'll wait until someone asks for
|
407
|
+
# this feature
|
408
|
+
#self.directories += rpm.directories
|
409
|
+
|
410
|
+
# Extract to the staging directory
|
411
|
+
rpm.extract(staging_path)
|
412
|
+
end # def input
|
413
|
+
|
414
|
+
def prefixed_path(path)
|
415
|
+
Pathname.new(path).absolute?() ? path : File.join(self.prefix, path)
|
416
|
+
end # def prefixed_path
|
417
|
+
|
418
|
+
def output(output_path)
|
419
|
+
output_check(output_path)
|
420
|
+
%w(BUILD RPMS SRPMS SOURCES SPECS).each { |d| FileUtils.mkdir_p(build_path(d)) }
|
421
|
+
args = ["rpmbuild", "-bb"]
|
422
|
+
|
423
|
+
if %x{uname -m}.chomp != self.architecture
|
424
|
+
rpm_target = self.architecture
|
425
|
+
end
|
426
|
+
|
427
|
+
# issue #309
|
428
|
+
if !attributes[:rpm_os].nil?
|
429
|
+
rpm_target = "#{architecture}-unknown-#{attributes[:rpm_os]}"
|
430
|
+
end
|
431
|
+
|
432
|
+
# issue #707
|
433
|
+
if !rpm_target.nil?
|
434
|
+
args += ["--target", rpm_target]
|
435
|
+
end
|
436
|
+
|
437
|
+
# set the rpm dist tag
|
438
|
+
args += ["--define", "dist .#{attributes[:rpm_dist]}"] if attributes[:rpm_dist]
|
439
|
+
|
440
|
+
args += [
|
441
|
+
"--define", "buildroot #{build_path}/BUILD",
|
442
|
+
"--define", "_topdir #{build_path}",
|
443
|
+
"--define", "_sourcedir #{build_path}",
|
444
|
+
"--define", "_rpmdir #{build_path}/RPMS",
|
445
|
+
"--define", "_tmppath #{attributes[:workdir]}"
|
446
|
+
]
|
447
|
+
|
448
|
+
args += ["--sign"] if attributes[:rpm_sign?]
|
449
|
+
|
450
|
+
if attributes[:rpm_auto_add_directories?]
|
451
|
+
fs_dirs_list = File.join(template_dir, "rpm", "filesystem_list")
|
452
|
+
fs_dirs = File.readlines(fs_dirs_list).reject { |x| x =~ /^\s*#/}.map { |x| x.chomp }
|
453
|
+
fs_dirs.concat((attributes[:auto_add_exclude_directories] or []))
|
454
|
+
|
455
|
+
Find.find(staging_path) do |path|
|
456
|
+
next if path == staging_path
|
457
|
+
if File.directory? path and !File.symlink? path
|
458
|
+
add_path = path.gsub(/^#{staging_path}/,'')
|
459
|
+
self.directories << add_path if not fs_dirs.include? add_path
|
460
|
+
end
|
461
|
+
end
|
462
|
+
else
|
463
|
+
self.directories = self.directories.map { |x| self.prefixed_path(x) }
|
464
|
+
alldirs = []
|
465
|
+
self.directories.each do |path|
|
466
|
+
Find.find(File.join(staging_path, path)) do |subpath|
|
467
|
+
if File.directory? subpath and !File.symlink? subpath
|
468
|
+
alldirs << subpath.gsub(/^#{staging_path}/, '')
|
469
|
+
end
|
470
|
+
end
|
471
|
+
end
|
472
|
+
self.directories = alldirs
|
473
|
+
end
|
474
|
+
|
475
|
+
# scan all conf file paths for files and add them
|
476
|
+
allconfigs = []
|
477
|
+
self.config_files.each do |path|
|
478
|
+
cfg_path = File.join(staging_path, path)
|
479
|
+
raise "Config file path #{cfg_path} does not exist" unless File.exist?(cfg_path)
|
480
|
+
Find.find(cfg_path) do |p|
|
481
|
+
allconfigs << p.gsub("#{staging_path}/", '') if File.file? p
|
482
|
+
end
|
483
|
+
end
|
484
|
+
allconfigs.sort!.uniq!
|
485
|
+
|
486
|
+
self.config_files = allconfigs.map { |x| File.join("/", x) }
|
487
|
+
|
488
|
+
# add init script if present
|
489
|
+
(attributes[:rpm_init_list] or []).each do |init|
|
490
|
+
name = File.basename(init, ".init")
|
491
|
+
dest_init = File.join(staging_path, "etc/init.d/#{name}")
|
492
|
+
FileUtils.mkdir_p(File.dirname(dest_init))
|
493
|
+
FileUtils.cp init, dest_init
|
494
|
+
File.chmod(0755, dest_init)
|
495
|
+
end
|
496
|
+
|
497
|
+
(attributes[:rpm_rpmbuild_define] or []).each do |define|
|
498
|
+
args += ["--define", define]
|
499
|
+
end
|
500
|
+
|
501
|
+
# copy all files from staging to BUILD dir
|
502
|
+
Find.find(staging_path) do |path|
|
503
|
+
src = path.gsub(/^#{staging_path}/, '')
|
504
|
+
dst = File.join(build_path, build_sub_dir, src)
|
505
|
+
copy_entry(path, dst)
|
506
|
+
end
|
507
|
+
|
508
|
+
rpmspec = template("rpm.erb").result(binding)
|
509
|
+
specfile = File.join(build_path("SPECS"), "#{name}.spec")
|
510
|
+
File.write(specfile, rpmspec)
|
511
|
+
|
512
|
+
edit_file(specfile) if attributes[:edit?]
|
513
|
+
|
514
|
+
args << specfile
|
515
|
+
|
516
|
+
logger.info("Running rpmbuild", :args => args)
|
517
|
+
safesystem(*args)
|
518
|
+
|
519
|
+
::Dir["#{build_path}/RPMS/**/*.rpm"].each do |rpmpath|
|
520
|
+
# This should only output one rpm, should we verify this?
|
521
|
+
FileUtils.cp(rpmpath, output_path)
|
522
|
+
end
|
523
|
+
end # def output
|
524
|
+
|
525
|
+
def prefix
|
526
|
+
if attributes[:prefix] and attributes[:prefix] != '/'
|
527
|
+
return attributes[:prefix].chomp('/')
|
528
|
+
else
|
529
|
+
return "/"
|
530
|
+
end
|
531
|
+
end # def prefix
|
532
|
+
|
533
|
+
def build_sub_dir
|
534
|
+
return "BUILD"
|
535
|
+
#return File.join("BUILD", prefix)
|
536
|
+
end # def build_sub_dir
|
537
|
+
|
538
|
+
def summary
|
539
|
+
if !attributes[:rpm_summary]
|
540
|
+
return @description.split("\n").first || "_"
|
541
|
+
end
|
542
|
+
|
543
|
+
return attributes[:rpm_summary]
|
544
|
+
end # def summary
|
545
|
+
|
546
|
+
def version
|
547
|
+
if @version.kind_of?(String) and @version.include?("-")
|
548
|
+
logger.warn("Package version '#{@version}' includes dashes, converting" \
|
549
|
+
" to underscores")
|
550
|
+
@version = @version.gsub(/-/, "_")
|
551
|
+
end
|
552
|
+
|
553
|
+
return @version
|
554
|
+
end
|
555
|
+
|
556
|
+
# The default epoch value must be nil, see #381
|
557
|
+
def epoch
|
558
|
+
return @epoch if @epoch.is_a?(Numeric)
|
559
|
+
|
560
|
+
if @epoch.nil? or @epoch.empty?
|
561
|
+
return nil
|
562
|
+
end
|
563
|
+
|
564
|
+
return @epoch
|
565
|
+
end # def epoch
|
566
|
+
|
567
|
+
def to_s_dist;
|
568
|
+
attributes[:rpm_dist] ? "#{attributes[:rpm_dist]}" : "DIST";
|
569
|
+
end
|
570
|
+
|
571
|
+
def to_s(format=nil)
|
572
|
+
if format.nil?
|
573
|
+
format = if attributes[:rpm_dist]
|
574
|
+
"NAME-VERSION-ITERATION.DIST.ARCH.EXTENSION"
|
575
|
+
else
|
576
|
+
"NAME-VERSION-ITERATION.ARCH.EXTENSION"
|
577
|
+
end
|
578
|
+
end
|
579
|
+
return super(format.gsub("DIST", to_s_dist))
|
580
|
+
end # def to_s
|
581
|
+
|
582
|
+
def payload_compression
|
583
|
+
return COMPRESSION_MAP[attributes[:rpm_compression]]
|
584
|
+
end # def payload_compression
|
585
|
+
|
586
|
+
def digest_algorithm
|
587
|
+
return DIGEST_ALGORITHM_MAP[attributes[:rpm_digest]]
|
588
|
+
end # def digest_algorithm
|
589
|
+
|
590
|
+
public(:input, :output, :converted_from, :architecture, :to_s, :iteration,
|
591
|
+
:payload_compression, :digest_algorithm, :prefix, :build_sub_dir,
|
592
|
+
:summary, :epoch, :version, :prefixed_path)
|
593
|
+
end # class FPM::Package::RPM
|