fpm 0.3.11 → 0.4.0pre1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELIST +15 -0
- data/bin/fpm +2 -15
- data/lib/fpm.rb +5 -12
- data/lib/fpm/command.rb +323 -0
- data/lib/fpm/errors.rb +1 -0
- data/lib/fpm/namespace.rb +2 -11
- data/lib/fpm/package.rb +255 -100
- data/lib/fpm/package/deb.rb +367 -0
- data/lib/fpm/package/dir.rb +86 -0
- data/lib/fpm/package/gem.rb +162 -0
- data/lib/fpm/{source → package}/npm.rb +3 -3
- data/lib/fpm/package/pear.rb +41 -0
- data/lib/fpm/{target → package}/puppet.rb +1 -3
- data/lib/fpm/{source → package}/pyfpm/__init__.py +0 -0
- data/lib/fpm/package/pyfpm/__init__.pyc +0 -0
- data/lib/fpm/{source → package}/pyfpm/get_metadata.py +15 -3
- data/lib/fpm/package/pyfpm/get_metadata.pyc +0 -0
- data/lib/fpm/package/python.rb +125 -0
- data/lib/fpm/package/rpm.rb +132 -0
- data/lib/fpm/{target → package}/solaris.rb +3 -2
- data/lib/fpm/package/tar.rb +62 -0
- data/lib/fpm/util.rb +56 -7
- data/templates/deb.erb +12 -12
- data/templates/rpm.erb +32 -38
- data/templates/solaris.erb +1 -1
- metadata +119 -78
- data/lib/fpm/builder.rb +0 -220
- data/lib/fpm/flags.rb +0 -20
- data/lib/fpm/program.rb +0 -273
- data/lib/fpm/rubyfixes.rb +0 -11
- data/lib/fpm/source.rb +0 -155
- data/lib/fpm/source/dir.rb +0 -59
- data/lib/fpm/source/gem.rb +0 -162
- data/lib/fpm/source/python.rb +0 -137
- data/lib/fpm/source/rpm.rb +0 -28
- data/lib/fpm/source/tar.rb +0 -50
- data/lib/fpm/target/deb.rb +0 -184
- data/lib/fpm/target/rpm.rb +0 -68
- data/lib/rpm/header.rb +0 -89
- data/lib/rpm/lead.rb +0 -48
- data/lib/rpm/namespace.rb +0 -1
- data/lib/rpm/rpmfile.rb +0 -81
- data/lib/rpm/tag.rb +0 -304
@@ -0,0 +1,162 @@
|
|
1
|
+
require "fpm/namespace"
|
2
|
+
require "fpm/package"
|
3
|
+
require "rubygems/package"
|
4
|
+
require "rubygems"
|
5
|
+
require "fileutils"
|
6
|
+
require "fpm/util"
|
7
|
+
|
8
|
+
# A rubygems package.
|
9
|
+
#
|
10
|
+
# This does not currently support 'output'
|
11
|
+
#
|
12
|
+
# The following attributes are supported:
|
13
|
+
#
|
14
|
+
# * :gem_bin_path
|
15
|
+
# * :package_name_prefix
|
16
|
+
# * :gem_gem
|
17
|
+
class FPM::Package::Gem < FPM::Package
|
18
|
+
option "--bin-path", "DIRECTORY", "The directory to install gem executables",
|
19
|
+
:default => ::Gem::bindir
|
20
|
+
option "--package-prefix", "NAMEPREFIX",
|
21
|
+
"(DEPRECATED, use --package-name-prefix) Name to prefix the package " \
|
22
|
+
"name with." do |value|
|
23
|
+
@logger.warn("Using deprecated flag: --package-prefix. Please use " \
|
24
|
+
"--package-name-prefix")
|
25
|
+
value
|
26
|
+
end
|
27
|
+
option "--package-name-prefix", "PREFIX", "Name to prefix the package " \
|
28
|
+
"name with.", :default => "rubygem"
|
29
|
+
option "--gem", "PATH_TO_GEM",
|
30
|
+
"The path to the 'gem' tool (defaults to 'gem' and searches " \
|
31
|
+
"your $PATH)", :default => "gem"
|
32
|
+
|
33
|
+
def input(gem)
|
34
|
+
# 'arg' is the name of the rubygem we should unpack.
|
35
|
+
path_to_gem = download_if_necessary(gem, version)
|
36
|
+
|
37
|
+
# Got a good gem now (downloaded or otherwise)
|
38
|
+
#
|
39
|
+
# 1. unpack it into staging_path
|
40
|
+
# 2. take the metadata from it and update our wonderful package with it.
|
41
|
+
load_package_info(path_to_gem)
|
42
|
+
install_to_staging(path_to_gem)
|
43
|
+
end # def input
|
44
|
+
|
45
|
+
def download_if_necessary(gem, gem_version)
|
46
|
+
path = gem
|
47
|
+
if !File.exists?(path)
|
48
|
+
looks_like_name_re = /^[A-Za-z0-9_-]+$/
|
49
|
+
if path =~ looks_like_name_re
|
50
|
+
path = download(gem, gem_version)
|
51
|
+
else
|
52
|
+
raise FPM::Package::InvalidArgument.new("Gem '#{gem}' doesn't appear to be a valid rubygem file or name?")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
@logger.info("Using gem file", :path => path)
|
57
|
+
return path
|
58
|
+
end # def download_if_necessary
|
59
|
+
|
60
|
+
def download(gem_name, gem_version=nil)
|
61
|
+
# This code mostly mutated from rubygem's fetch_command.rb
|
62
|
+
# Code use permissible by rubygems's "GPL or these conditions below"
|
63
|
+
# http://rubygems.rubyforge.org/rubygems-update/LICENSE_txt.html
|
64
|
+
|
65
|
+
@logger.info("Trying to download", :gem => gem_name, :version => gem_version)
|
66
|
+
dep = ::Gem::Dependency.new(gem_name, gem_version)
|
67
|
+
|
68
|
+
# TODO(sissel): Make a flag to allow prerelease gems?
|
69
|
+
#dep.prerelease = options[:prerelease]
|
70
|
+
|
71
|
+
if ::Gem::SpecFetcher.fetcher.respond_to?(:fetch_with_errors)
|
72
|
+
specs_and_sources, errors =
|
73
|
+
::Gem::SpecFetcher.fetcher.fetch_with_errors(dep, true, true, false)
|
74
|
+
else
|
75
|
+
specs_and_sources =
|
76
|
+
::Gem::SpecFetcher.fetcher.fetch(dep, true)
|
77
|
+
errors = "???"
|
78
|
+
end
|
79
|
+
spec, source_uri = specs_and_sources.sort_by { |s,| s.version }.last
|
80
|
+
|
81
|
+
if spec.nil? then
|
82
|
+
@logger.error("Invalid gem?", :name => gem_name, :version => gem_version, :errors => errors)
|
83
|
+
raise InvalidArgument.new("Invalid gem: #{gem_name}")
|
84
|
+
end
|
85
|
+
|
86
|
+
path = ::Gem::RemoteFetcher.fetcher.download(spec, source_uri)
|
87
|
+
return path
|
88
|
+
end # def download
|
89
|
+
|
90
|
+
def load_package_info(gem_path)
|
91
|
+
file = File.new(gem_path, 'r')
|
92
|
+
|
93
|
+
::Gem::Package.open(file, 'r') do |gem|
|
94
|
+
spec = gem.metadata
|
95
|
+
|
96
|
+
if !attributes[:gem_package_prefix].nil?
|
97
|
+
attributes[:gem_package_name_prefix] = attributes[:gem_package_prefix]
|
98
|
+
end
|
99
|
+
|
100
|
+
self.name = [attributes[:gem_package_name_prefix], spec.name].join("-")
|
101
|
+
self.license = (spec.license or "no license listed in #{File.basename(file)}")
|
102
|
+
self.version = spec.version.to_s
|
103
|
+
self.vendor = spec.author
|
104
|
+
self.url = spec.homepage
|
105
|
+
self.category = "Languages/Development/Ruby"
|
106
|
+
|
107
|
+
# if the gemspec has C extensions defined, then this should be a 'native' arch.
|
108
|
+
if !spec.extensions.empty?
|
109
|
+
self.architecture = "native"
|
110
|
+
else
|
111
|
+
self.architecture = "all"
|
112
|
+
end
|
113
|
+
|
114
|
+
# make sure we have a description
|
115
|
+
description_options = [ spec.description, spec.summary, "#{spec.name} - no description given" ]
|
116
|
+
self.description = description_options.find { |d| !(d.nil? or d.strip.empty?) }
|
117
|
+
|
118
|
+
# Upstream rpms seem to do this, might as well share.
|
119
|
+
self.provides << "rubygem(#{self.name})"
|
120
|
+
|
121
|
+
# By default, we'll usually automatically provide this, but in the case that we are
|
122
|
+
# composing multiple packages, it's best to explicitly include it in the provides list.
|
123
|
+
self.provides << "rubygem-#{self.name}"
|
124
|
+
|
125
|
+
spec.runtime_dependencies.map do |dep|
|
126
|
+
# rubygems 1.3.5 doesn't have 'Gem::Dependency#requirement'
|
127
|
+
if dep.respond_to?(:requirement)
|
128
|
+
reqs = dep.requirement.to_s
|
129
|
+
else
|
130
|
+
reqs = dep.version_requirements
|
131
|
+
end
|
132
|
+
|
133
|
+
# Some reqs can be ">= a, < b" versions, let's handle that.
|
134
|
+
reqs.to_s.split(/, */).each do |req|
|
135
|
+
self.dependencies << "#{attributes[:gem_package_name_prefix]}-#{dep.name} #{req}"
|
136
|
+
end
|
137
|
+
end # runtime_dependencies
|
138
|
+
end # ::Gem::Package
|
139
|
+
end # def load_package_info
|
140
|
+
|
141
|
+
def install_to_staging(gem_path)
|
142
|
+
if attributes.include?(:path_prefix)
|
143
|
+
installdir = "#{staging_path}/#{attributes[:path_prefix]}"
|
144
|
+
else
|
145
|
+
installdir = File.join(staging_path, ::Gem::dir)
|
146
|
+
end
|
147
|
+
|
148
|
+
::FileUtils.mkdir_p(installdir)
|
149
|
+
# TODO(sissel): Allow setting gem tool path
|
150
|
+
args = [attributes[:gem_gem], "install", "--quiet", "--no-ri", "--no-rdoc",
|
151
|
+
"--install-dir", installdir, "--ignore-dependencies", "-E"]
|
152
|
+
if attributes[:gem_bin_path]
|
153
|
+
bin_path = File.join(staging_path, attributes[:gem_bin_path])
|
154
|
+
args += ["--bindir", bin_path]
|
155
|
+
end
|
156
|
+
|
157
|
+
args << gem_path
|
158
|
+
safesystem(*args)
|
159
|
+
end # def install_to_staging
|
160
|
+
|
161
|
+
public(:input, :output)
|
162
|
+
end # class FPM::Package::Gem
|
@@ -1,9 +1,9 @@
|
|
1
1
|
require "fpm/namespace"
|
2
|
-
require "fpm/
|
2
|
+
require "fpm/package"
|
3
3
|
require "fpm/util"
|
4
4
|
require "fileutils"
|
5
5
|
|
6
|
-
class FPM::
|
6
|
+
class FPM::Package::NPM < FPM::Package
|
7
7
|
def get_source(params)
|
8
8
|
@npm = @paths.first
|
9
9
|
end # def get_source
|
@@ -33,4 +33,4 @@ class FPM::Source::Npm < FPM::Source
|
|
33
33
|
safesystem(*["gzip", "-f", tar_path])
|
34
34
|
end
|
35
35
|
|
36
|
-
end # class FPM::
|
36
|
+
end # class FPM::Package::NPM
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require "fpm/namespace"
|
2
|
+
require "fpm/package"
|
3
|
+
require "fileutils"
|
4
|
+
require "fpm/util"
|
5
|
+
|
6
|
+
class FPM::Package::PEAR < FPM::Package
|
7
|
+
option "--package-prefix", "PREFIX",
|
8
|
+
"Name prefix for python package", :default => "php-pear"
|
9
|
+
|
10
|
+
def input(input_package)
|
11
|
+
if !program_in_path?("pear")
|
12
|
+
raise ExecutableNotFound.new("pear")
|
13
|
+
end
|
14
|
+
|
15
|
+
# Create a temporary config file
|
16
|
+
@logger.debug("Creating pear config file")
|
17
|
+
config = File.expand_path(build_path("pear.config"))
|
18
|
+
installroot = attributes[:prefix] || "/usr/share"
|
19
|
+
safesystem("pear", "config-create", staging_path(installroot), config)
|
20
|
+
|
21
|
+
@logger.info("Fetching package information", :package => input_package)
|
22
|
+
pear_cmd = "pear -c #{config} remote-info #{input_package}"
|
23
|
+
name = %x{#{pear_cmd} | sed -ne '/^Package\s*/s/^Package\s*//p'}.chomp
|
24
|
+
self.name = "#{attributes[:pear_package_prefix]}-#{name}"
|
25
|
+
self.version = %x{#{pear_cmd} | sed -ne '/^Latest\s*/s/^Latest\s*//p'}.chomp
|
26
|
+
self.description = %x{#{pear_cmd} | sed -ne '/^Summary\s*/s/^Summary\s*//p'}.chomp
|
27
|
+
|
28
|
+
@logger.info("Installing pear package", :package => input_package,
|
29
|
+
:directory => staging_path)
|
30
|
+
::Dir.chdir(staging_path) do
|
31
|
+
safesystem("pear", "-c", config, "install", "-n", "-f", "-P", ".",
|
32
|
+
input_package)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Remove the stuff we don't want
|
36
|
+
delete_these = [".depdb", ".depdblock", ".filemap", ".lock", ".channel"]
|
37
|
+
Find.find(staging_path) do |path|
|
38
|
+
FileUtils.rm_r(path) if delete_these.include?(File.basename(path))
|
39
|
+
end
|
40
|
+
end # def input
|
41
|
+
end # class FPM::Package::PEAR
|
@@ -5,9 +5,7 @@ require "fpm/errors"
|
|
5
5
|
require "etc"
|
6
6
|
require "fileutils"
|
7
7
|
|
8
|
-
|
9
|
-
# IIRC this has to be done as a 'checkinstall' step.
|
10
|
-
class FPM::Target::Puppet < FPM::Package
|
8
|
+
class FPM::Package::Puppet < FPM::Package
|
11
9
|
def architecture
|
12
10
|
case @architecture
|
13
11
|
when nil, "native"
|
File without changes
|
Binary file
|
@@ -61,7 +61,7 @@ class get_metadata(Command):
|
|
61
61
|
dependencies = [dependencies]
|
62
62
|
|
63
63
|
final_deps = []
|
64
|
-
dep_re = re.compile("([^<>= ]+)(?:\s*([<>=]{1,2})\s*(.*))?$")
|
64
|
+
dep_re = re.compile("([^<>= ]+)(?:\s*([<>=]{1,2})\s*([^,]*))?(?:,\s*([<>=]{1,2})\s*(.*))?$")
|
65
65
|
for dep in dependencies:
|
66
66
|
# python deps are strings that look like:
|
67
67
|
# "packagename"
|
@@ -74,10 +74,17 @@ class get_metadata(Command):
|
|
74
74
|
elif m.groups()[1] is None:
|
75
75
|
name, cond, version = m.groups()[0], ">=", 0
|
76
76
|
else:
|
77
|
-
|
77
|
+
groups = m.groups()
|
78
|
+
name, cond, version = groups[0:3]
|
79
|
+
if groups[3] is not None:
|
80
|
+
final_deps.append("%s %s %s" % (groups[0],
|
81
|
+
self._replace_deprecated(groups[3]),
|
82
|
+
groups[4]))
|
78
83
|
# end if
|
79
84
|
|
80
|
-
final_deps.append("%s %s %s" % (name,
|
85
|
+
final_deps.append("%s %s %s" % (name,
|
86
|
+
self._replace_deprecated(cond),
|
87
|
+
version))
|
81
88
|
# end for i in dependencies
|
82
89
|
|
83
90
|
data["dependencies"] = final_deps
|
@@ -90,4 +97,9 @@ class get_metadata(Command):
|
|
90
97
|
print json.write(data)
|
91
98
|
|
92
99
|
# def run
|
100
|
+
|
101
|
+
def _replace_deprecated(self, sign):
|
102
|
+
"""Replace deprecated operators"""
|
103
|
+
return {'<': '<<', '>': '>>'}.get(sign, sign)
|
104
|
+
|
93
105
|
# class list_dependencies
|
Binary file
|
@@ -0,0 +1,125 @@
|
|
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
|
+
class FPM::Package::Python < FPM::Package
|
11
|
+
option "--bin", "PYTHON_EXECUTABLE",
|
12
|
+
"The path to the python executable you wish to run.", :default => "python"
|
13
|
+
option "--easyinstall", "EASYINSTALL_EXECUTABLE",
|
14
|
+
"The path to the easy_install executable tool", :default => "easy_install"
|
15
|
+
option "--pypi", "PYPI_URL",
|
16
|
+
"PyPi Server uri for retrieving packages.",
|
17
|
+
:default => "http://pypi.python.org/simple"
|
18
|
+
option "--package-prefix", "PREFIX",
|
19
|
+
"Name prefix for python package", :default => "python"
|
20
|
+
|
21
|
+
def input(package)
|
22
|
+
path_to_package = download_if_necessary(package, version)
|
23
|
+
|
24
|
+
if File.directory?(path_to_package)
|
25
|
+
setup_py = File.join(path_to_package, "setup.py")
|
26
|
+
else
|
27
|
+
setup_py = path_to_package
|
28
|
+
end
|
29
|
+
|
30
|
+
if !File.exists?(setup_py)
|
31
|
+
@logger.error("Could not find 'setup.py'", :path => setup_py)
|
32
|
+
raise "Unable to find python package; tried #{setup_py}"
|
33
|
+
end
|
34
|
+
|
35
|
+
load_package_info(setup_py)
|
36
|
+
install_to_staging(setup_py)
|
37
|
+
end # def input
|
38
|
+
|
39
|
+
def download_if_necessary(package, version=nil)
|
40
|
+
path = package
|
41
|
+
# If it's a path, assume local build.
|
42
|
+
if File.directory?(path) or (File.exists?(path) and File.basename(path) == "setup.py")
|
43
|
+
return path
|
44
|
+
end
|
45
|
+
|
46
|
+
@logger.info("Trying to download", :package => package)
|
47
|
+
|
48
|
+
if version.nil?
|
49
|
+
want_pkg = "#{package}"
|
50
|
+
else
|
51
|
+
want_pkg = "#{package}==#{version}"
|
52
|
+
end
|
53
|
+
|
54
|
+
# TODO(sissel): support a settable path to 'easy_install'
|
55
|
+
# TODO(sissel): support a tunable for uthe url to pypi
|
56
|
+
safesystem("easy_install", "-i", "http://pypi.python.org/simple",
|
57
|
+
"--editable", "-U", "--build-directory", build_path, want_pkg)
|
58
|
+
|
59
|
+
# easy_install will put stuff in @tmpdir/packagename/, so find that:
|
60
|
+
# @tmpdir/somepackage/setup.py
|
61
|
+
dirs = ::Dir.glob(File.join(build_path, "*"))
|
62
|
+
if dirs.length != 1
|
63
|
+
raise "Unexpected directory layout after easy_install. Maybe file a bug? The directory is #{build_path}"
|
64
|
+
end
|
65
|
+
return dirs.first
|
66
|
+
end # def download
|
67
|
+
|
68
|
+
def load_package_info(setup_py)
|
69
|
+
if !attributes.include?(:package_name_prefix)
|
70
|
+
attributes[:package_name_prefix] = "python"
|
71
|
+
end
|
72
|
+
|
73
|
+
# Add ./pyfpm/ to the python library path
|
74
|
+
pylib = File.expand_path(File.dirname(__FILE__))
|
75
|
+
setup_cmd = "env PYTHONPATH=#{pylib} #{self.attributes[:python_bin]} #{setup_py} --command-packages=pyfpm get_metadata"
|
76
|
+
output = ::Dir.chdir(File.dirname(setup_py)) { `#{setup_cmd}` }
|
77
|
+
puts output
|
78
|
+
metadata = JSON.parse(output[/\{.*\}/msx])
|
79
|
+
|
80
|
+
self.architecture = metadata["architecture"]
|
81
|
+
self.description = metadata["description"]
|
82
|
+
self.license = metadata["license"]
|
83
|
+
self.version = metadata["version"]
|
84
|
+
self.url = metadata["url"]
|
85
|
+
|
86
|
+
self.name = fix_name(metadata["name"])
|
87
|
+
|
88
|
+
self.dependencies += metadata["dependencies"].collect do |dep|
|
89
|
+
name, cmp, version = dep.split
|
90
|
+
name = fix_name(name)
|
91
|
+
"#{name} #{cmp} #{version}"
|
92
|
+
end
|
93
|
+
end # def load_package_info
|
94
|
+
|
95
|
+
# Sanitize package name.
|
96
|
+
# Some PyPI packages can be named 'python-foo', so we don't want to end up
|
97
|
+
# with a package named 'python-python-foo'.
|
98
|
+
# But we want packages named like 'pythonweb' to be suffixed
|
99
|
+
# 'python-pythonweb'.
|
100
|
+
def fix_name(name)
|
101
|
+
if name.start_with?("python")
|
102
|
+
# If the python package is called "python-foo" strip the "python-" part while
|
103
|
+
# prepending the package name prefix.
|
104
|
+
return [attributes[:package_name_prefix], name.gsub(/^python-/, "")].join("-")
|
105
|
+
else
|
106
|
+
return [attributes[:package_name_prefix], name].join("-")
|
107
|
+
end
|
108
|
+
end # def fix_name
|
109
|
+
|
110
|
+
def install_to_staging(setup_py)
|
111
|
+
dir = File.dirname(setup_py)
|
112
|
+
|
113
|
+
# Some setup.py's assume $PWD == current directory of setup.py, so let's
|
114
|
+
# chdir first.
|
115
|
+
::Dir.chdir(dir) do
|
116
|
+
if attributes[:prefix]
|
117
|
+
safesystem(attributes[:python_bin], "setup.py", "install", "--prefix",
|
118
|
+
File.join(staging_path, attributes[:prefix]))
|
119
|
+
else
|
120
|
+
safesystem(attributes[:python_bin], "setup.py", "install", "--root",
|
121
|
+
staging_path)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end # def install_to_staging
|
125
|
+
end # class FPM::Package::Python
|
@@ -0,0 +1,132 @@
|
|
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
|
+
option "--rpmbuild-define", "DEFINITION",
|
18
|
+
"Pass a --define argument to rpmbuild." do |define|
|
19
|
+
attributes[:rpm_rpmbuild_define] ||= []
|
20
|
+
attributes[:rpm_rpmbuild_define] << define
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def architecture
|
26
|
+
case @architecture
|
27
|
+
when nil
|
28
|
+
return %x{uname -m}.chomp # default to current arch
|
29
|
+
when "amd64" # debian and redhat disagree on architecture names
|
30
|
+
return "x86_64"
|
31
|
+
when "native"
|
32
|
+
return %x{uname -m}.chomp # 'native' is current arch
|
33
|
+
when "all"
|
34
|
+
# Translate fpm "all" arch to what it means in RPM.
|
35
|
+
return "noarch"
|
36
|
+
else
|
37
|
+
return @architecture
|
38
|
+
end
|
39
|
+
end # def architecture
|
40
|
+
|
41
|
+
# See FPM::Package#converted_from
|
42
|
+
def converted_from(origin)
|
43
|
+
if origin == FPM::Package::Gem
|
44
|
+
# Gem dependency operator "~>" is not compatible with rpm. Translate any found.
|
45
|
+
fixed_deps = []
|
46
|
+
self.dependencies.collect do |dep|
|
47
|
+
name, op, version = dep.split(/\s+/)
|
48
|
+
if op == "~>"
|
49
|
+
# ~> x.y means: > x.y and < (x+1).0
|
50
|
+
fixed_deps << "#{name} > #{version}"
|
51
|
+
fixed_deps << "#{name} < #{version.to_i + 1}.0.0"
|
52
|
+
else
|
53
|
+
fixed_deps << dep
|
54
|
+
end
|
55
|
+
end
|
56
|
+
self.dependencies = fixed_deps
|
57
|
+
end
|
58
|
+
end # def converted
|
59
|
+
|
60
|
+
def input(path)
|
61
|
+
rpm = ::RPM::File.new(path)
|
62
|
+
|
63
|
+
tags = {}
|
64
|
+
rpm.header.tags.each do |tag|
|
65
|
+
tags[tag.tag] = tag.value
|
66
|
+
end
|
67
|
+
|
68
|
+
self.architecture = tags[:arch]
|
69
|
+
self.category = tags[:group]
|
70
|
+
self.config_files = config_files
|
71
|
+
self.description = tags[:description]
|
72
|
+
self.epoch = (tags[:epoch] || [nil]).first # for some reason epoch is an array
|
73
|
+
self.iteration = tags[:release]
|
74
|
+
self.license = tags[:license]
|
75
|
+
self.maintainer = maintainer
|
76
|
+
self.name = tags[:name]
|
77
|
+
self.url = tags[:url]
|
78
|
+
self.vendor = tags[:vendor]
|
79
|
+
self.version = tags[:version]
|
80
|
+
|
81
|
+
# TODO(sissel): Collect {pre,post}{install,uninstall} scripts
|
82
|
+
# TODO(sissel): put 'trigger scripts' stuff into attributes
|
83
|
+
# TODO(sissel): support provides
|
84
|
+
# TODO(sissel): support conflicts
|
85
|
+
# TODO(sissel): support replaces
|
86
|
+
|
87
|
+
self.dependencies += rpm.requires.collect do |name, operator, version|
|
88
|
+
[name, operator, version].join(" ")
|
89
|
+
end
|
90
|
+
#input.replaces += replaces
|
91
|
+
|
92
|
+
# Extract to the staging directory
|
93
|
+
rpm.extract(staging_path)
|
94
|
+
end # def input
|
95
|
+
|
96
|
+
def output(output_path)
|
97
|
+
%w(BUILD RPMS SRPMS SOURCES SPECS).each { |d| FileUtils.mkdir_p(build_path(d)) }
|
98
|
+
args = ["rpmbuild", "-bb",
|
99
|
+
"--define", "buildroot #{build_path}/BUILD",
|
100
|
+
"--define", "_topdir #{build_path}",
|
101
|
+
"--define", "_sourcedir #{build_path}",
|
102
|
+
"--define", "_rpmdir #{build_path}/RPMS"]
|
103
|
+
|
104
|
+
(attributes[:rpm_rpmbuild_define] or []).each do |define|
|
105
|
+
args += ["--define", define]
|
106
|
+
end
|
107
|
+
|
108
|
+
rpmspec = template("rpm.erb").result(binding)
|
109
|
+
specfile = File.join(build_path("SPECS"), "#{name}.spec")
|
110
|
+
File.write(specfile, rpmspec)
|
111
|
+
File.write("/tmp/rpm.spec", rpmspec)
|
112
|
+
|
113
|
+
args << specfile
|
114
|
+
#if defines.empty?
|
115
|
+
#args = prefixargs + spec
|
116
|
+
#else
|
117
|
+
#args = prefixargs + defines.collect{ |define| ["--define", define] }.flatten + spec
|
118
|
+
#end
|
119
|
+
|
120
|
+
@logger.info("Running rpmbuild", :args => args)
|
121
|
+
safesystem(*args)
|
122
|
+
|
123
|
+
::Dir["#{build_path}/RPMS/**/*.rpm"].each do |rpmpath|
|
124
|
+
# This should only output one rpm, should we verify this?
|
125
|
+
FileUtils.cp(rpmpath, output_path)
|
126
|
+
end
|
127
|
+
|
128
|
+
@logger.log("Created rpm", :path => output_path)
|
129
|
+
end # def output
|
130
|
+
|
131
|
+
public(:input, :output, :converted_from)
|
132
|
+
end # class FPM::Package::RPM
|