fpm 0.4.0pre3 → 0.4.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.
- data/CHANGELIST +0 -1
- data/lib/fpm/command.rb +81 -34
- data/lib/fpm/package.rb +39 -2
- data/lib/fpm/package/deb.rb +26 -11
- data/lib/fpm/package/dir.rb +24 -0
- data/lib/fpm/package/gem.rb +27 -4
- data/lib/fpm/package/pear.rb +13 -3
- data/lib/fpm/package/python.rb +70 -16
- data/lib/fpm/package/rpm.rb +22 -11
- data/templates/rpm.erb +18 -12
- metadata +69 -29
data/CHANGELIST
CHANGED
@@ -11,7 +11,6 @@
|
|
11
11
|
- rpm support: Add --rpm-rpmbuild-define for passing a --define flag to rpmbuild
|
12
12
|
(via Naresh V)
|
13
13
|
- PHP pear source support (fpm -s pear ...) (via Andrew Gaffney)
|
14
|
-
TODO(sissel): pull/163, make sure --post-process is supported
|
15
14
|
|
16
15
|
0.3.10 (Oct 10, 2011)
|
17
16
|
- Allow taking a list of files/inputs on stdin with '-' or with the --inputs
|
data/lib/fpm/command.rb
CHANGED
@@ -33,12 +33,12 @@ class FPM::Command < Clamp::Command
|
|
33
33
|
"A path to prefix files with when building the target package. This may " \
|
34
34
|
"be necessary for all input packages. For example, the 'gem' type will" \
|
35
35
|
"prefix with your gem directory automatically."
|
36
|
-
option ["-p", "--package"], "OUTPUT",
|
37
|
-
"The package file path to output.", :default => "NAME-FULLVERSION.ARCH.TYPE"
|
36
|
+
option ["-p", "--package"], "OUTPUT", "The package file path to output."
|
38
37
|
option ["-n", "--name"], "NAME", "The name to give to the package"
|
39
38
|
option "--verbose", :flag, "Enable verbose output"
|
40
39
|
option "--debug", :flag, "Enable debug output"
|
41
|
-
option ["-v", "--version"], "VERSION", "The version to give to the package"
|
40
|
+
option ["-v", "--version"], "VERSION", "The version to give to the package",
|
41
|
+
:default => 1.0
|
42
42
|
option "--iteration", "ITERATION",
|
43
43
|
"The iteration to give to the package. RPM calls this the 'release'. " \
|
44
44
|
"FreeBSD calls it 'PORTREVISION'. Debian calls this 'debian_revision'",
|
@@ -78,7 +78,8 @@ class FPM::Command < Clamp::Command
|
|
78
78
|
end # --replaces
|
79
79
|
option "--config-files", "CONFIG_FILES",
|
80
80
|
"Mark a file in the package as being a config file. This uses 'conffiles'" \
|
81
|
-
" in debs and %config in rpm."
|
81
|
+
" in debs and %config in rpm. You can specify a directory to have it " \
|
82
|
+
"scanned marking all files found as config files" do |val|
|
82
83
|
@config_files ||= []
|
83
84
|
@config_files << val
|
84
85
|
end # --config-files
|
@@ -98,28 +99,6 @@ class FPM::Command < Clamp::Command
|
|
98
99
|
@exclude_pattern ||= []
|
99
100
|
@exclude_pattern << val
|
100
101
|
end # -x / --exclude
|
101
|
-
option "--post-install", "FILE",
|
102
|
-
"a script to be run after package installation",
|
103
|
-
:attribute_name => :after_install do |val|
|
104
|
-
File.expand_path(val) # Get the full path to the script
|
105
|
-
end # --post-install
|
106
|
-
option "--pre-install", "FILE",
|
107
|
-
"a script to be run before package installation",
|
108
|
-
:attribute_name => :before_install do |val|
|
109
|
-
File.expand_path(val) # Get the full path to the script
|
110
|
-
end # --pre-install
|
111
|
-
# TODO(sissel): Name the flag --post-remove for clarity
|
112
|
-
option "--post-uninstall", "FILE",
|
113
|
-
"a script to be run after package removal",
|
114
|
-
:attribute_name => :after_remove do |val|
|
115
|
-
File.expand_path(val) # Get the full path to the script
|
116
|
-
end # --post-uninstall
|
117
|
-
# TODO(sissel): Name the flag --pre-remove for clarity
|
118
|
-
option "--pre-uninstall", "FILE",
|
119
|
-
"a script to be run before package removal",
|
120
|
-
:attribute_name => :before_remove do |val|
|
121
|
-
File.expand_path(val) # Get the full path to the script
|
122
|
-
end # --pre-uninstall
|
123
102
|
option "--description", "DESCRIPTION", "Add a description for this package.",
|
124
103
|
:default => "no description"
|
125
104
|
option "--url", "URI", "Add a url for this package.",
|
@@ -127,13 +106,50 @@ class FPM::Command < Clamp::Command
|
|
127
106
|
option "--inputs", "INPUTS_PATH",
|
128
107
|
"The path to a file containing a newline-separated list of " \
|
129
108
|
"files and dirs to use as input."
|
109
|
+
|
110
|
+
option "--post-install", "FILE",
|
111
|
+
"(DEPRECATED, use --after-install) a script to be run after " \
|
112
|
+
"package installation" do |val|
|
113
|
+
@after_install = File.expand_path(val) # Get the full path to the script
|
114
|
+
end # --post-install (DEPRECATED)
|
115
|
+
option "--pre-install", "FILE",
|
116
|
+
"(DEPRECATED, use --before-install) a script to be run before " \
|
117
|
+
"package installation" do |val|
|
118
|
+
@before_install = File.expand_path(val) # Get the full path to the script
|
119
|
+
end # --pre-install (DEPRECATED)
|
120
|
+
option "--post-uninstall", "FILE",
|
121
|
+
"(DEPRECATED, use --after-remove) a script to be run after " \
|
122
|
+
"package removal" do |val|
|
123
|
+
@after_remove = File.expand_path(val) # Get the full path to the script
|
124
|
+
end # --post-uninstall (DEPRECATED)
|
125
|
+
option "--pre-uninstall", "FILE",
|
126
|
+
"(DEPRECATED, use --before-remove) a script to be run before " \
|
127
|
+
"package removal" do |val|
|
128
|
+
@before_remove = File.expand_path(val) # Get the full path to the script
|
129
|
+
end # --pre-uninstall (DEPRECATED)
|
130
|
+
|
131
|
+
option "--after-install", "FILE",
|
132
|
+
"a script to be run after package installation" do |val|
|
133
|
+
File.expand_path(val) # Get the full path to the script
|
134
|
+
end # --after-install
|
135
|
+
option "--before-install", "FILE",
|
136
|
+
"a script to be run before package installation" do |val|
|
137
|
+
File.expand_path(val) # Get the full path to the script
|
138
|
+
end # --pre-install
|
139
|
+
option "--after-remove", "FILE",
|
140
|
+
"a script to be run after package removal" do |val|
|
141
|
+
File.expand_path(val) # Get the full path to the script
|
142
|
+
end # --after-remove
|
143
|
+
option "--before-remove", "FILE",
|
144
|
+
"a script to be run before package removal" do |val|
|
145
|
+
File.expand_path(val) # Get the full path to the script
|
146
|
+
end # --before-remove
|
147
|
+
|
130
148
|
parameter "[ARGS] ...",
|
131
149
|
"Inputs to the source package type. For the 'dir' type, this is the files" \
|
132
150
|
" and directories you want to include in the package. For others, like " \
|
133
151
|
"'gem', it specifies the packages to download and use as the gem input",
|
134
152
|
:attribute_name => :args
|
135
|
-
|
136
|
-
# package-level settings
|
137
153
|
def settings
|
138
154
|
@settings ||= {}
|
139
155
|
end
|
@@ -207,6 +223,17 @@ class FPM::Command < Clamp::Command
|
|
207
223
|
input.input(arg)
|
208
224
|
end
|
209
225
|
|
226
|
+
# If --inputs was specified, read it as a file.
|
227
|
+
if !inputs.nil?
|
228
|
+
if !File.exists?(inputs)
|
229
|
+
@logger.fatal("File given for --inputs does not exist (#{inputs})")
|
230
|
+
return 1
|
231
|
+
end
|
232
|
+
|
233
|
+
# Read each line as a path
|
234
|
+
File.new(inputs, "r").each_line { |path| input.input(path) }
|
235
|
+
end
|
236
|
+
|
210
237
|
# Override package settings if they are not the default flag values
|
211
238
|
# the below proc essentially does:
|
212
239
|
#
|
@@ -239,16 +266,36 @@ class FPM::Command < Clamp::Command
|
|
239
266
|
input.provides += provides
|
240
267
|
input.replaces += replaces
|
241
268
|
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
269
|
+
setscript = proc do |scriptname|
|
270
|
+
path = self.send(scriptname)
|
271
|
+
# Skip scripts not set
|
272
|
+
next if path.nil?
|
273
|
+
|
274
|
+
# 'self.send(scriptname) == self.before_install == --before-install
|
275
|
+
if !File.exists?(path)
|
276
|
+
$stderr.puts("No such file (for #{scriptname.to_s}): #{path.inspect}")
|
277
|
+
return 1
|
278
|
+
end
|
279
|
+
input.scripts[scriptname] = File.read(path)
|
280
|
+
end
|
281
|
+
|
282
|
+
setscript.call(:before_install)
|
283
|
+
setscript.call(:after_install)
|
284
|
+
setscript.call(:before_remove)
|
285
|
+
setscript.call(:after_remove)
|
246
286
|
|
247
287
|
# Convert to the output type
|
248
288
|
output = input.convert(output_class)
|
249
289
|
|
250
|
-
# Write the output somewhere
|
251
|
-
|
290
|
+
# Write the output somewhere, package can be nil if no --package is specified,
|
291
|
+
# and that's OK.
|
292
|
+
begin
|
293
|
+
output.output(output.to_s(package))
|
294
|
+
rescue FPM::Package::FileAlreadyExists => e
|
295
|
+
@logger.fatal(e.message)
|
296
|
+
return 1
|
297
|
+
end
|
298
|
+
|
252
299
|
return 0
|
253
300
|
ensure
|
254
301
|
input.cleanup unless input.nil?
|
data/lib/fpm/package.rb
CHANGED
@@ -13,6 +13,13 @@ class FPM::Package
|
|
13
13
|
|
14
14
|
# This class is raised if there's something wrong with a setting in the package.
|
15
15
|
class InvalidArgument < StandardError; end
|
16
|
+
|
17
|
+
# This class is raised when a file already exists when trying to write.
|
18
|
+
class FileAlreadyExists < StandardError
|
19
|
+
def to_s
|
20
|
+
return "File already exists, refusing to continue: #{super}"
|
21
|
+
end # def to_s
|
22
|
+
end # class FileAlreadyExists
|
16
23
|
|
17
24
|
# The name of this package
|
18
25
|
attr_accessor :name
|
@@ -109,8 +116,15 @@ class FPM::Package
|
|
109
116
|
@maintainer = "<#{ENV["USER"]}@#{Socket.gethostname}>"
|
110
117
|
end
|
111
118
|
|
119
|
+
# Set attribute defaults based on flags
|
120
|
+
# This allows you to define command line options with default values
|
121
|
+
# that also are obeyed if fpm is used programmatically.
|
122
|
+
self.class.default_attributes do |attribute, value|
|
123
|
+
attributes[attribute] = value
|
124
|
+
end
|
125
|
+
|
112
126
|
@name = nil
|
113
|
-
@architecture = "
|
127
|
+
@architecture = "native"
|
114
128
|
@description = "no description given"
|
115
129
|
@version = nil
|
116
130
|
@epoch = nil
|
@@ -119,6 +133,19 @@ class FPM::Package
|
|
119
133
|
@category = "default"
|
120
134
|
@license = "unknown"
|
121
135
|
@vendor = "none"
|
136
|
+
|
137
|
+
# Iterate over all the options and set defaults
|
138
|
+
if self.class.respond_to?(:declared_options)
|
139
|
+
self.class.declared_options.each do |option|
|
140
|
+
with(option.attribute_name) do |attr|
|
141
|
+
# clamp makes option attributes available as accessor methods
|
142
|
+
# do --foo-bar is available as 'foo_bar'
|
143
|
+
# make these available as package attributes.
|
144
|
+
attr = "#{attr}?" if !respond_to?(attr)
|
145
|
+
input.attributes[attr.to_sym] = send(attr) if respond_to?(attr)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
122
149
|
|
123
150
|
@provides = []
|
124
151
|
@conflicts = []
|
@@ -264,7 +291,8 @@ class FPM::Package
|
|
264
291
|
.gsub("NAME", name.to_s) \
|
265
292
|
.gsub("FULLVERSION", fullversion) \
|
266
293
|
.gsub("VERSION", version.to_s) \
|
267
|
-
.gsub("
|
294
|
+
.gsub("ITERATION", iteration.to_s) \
|
295
|
+
.gsub("EPOCH", epoch.to_s) \
|
268
296
|
.gsub("TYPE", type.to_s)
|
269
297
|
end # def to_s
|
270
298
|
|
@@ -330,6 +358,15 @@ class FPM::Package
|
|
330
358
|
end
|
331
359
|
end # def apply_options
|
332
360
|
|
361
|
+
def default_attributes(&block)
|
362
|
+
return if @options.nil?
|
363
|
+
@options.each do |flag, param, help, options, block|
|
364
|
+
attr = flag.first.gsub(/^-+/, "").gsub(/-/, "_")
|
365
|
+
attr += "?" if param == :flag
|
366
|
+
yield attr.to_sym, options[:default]
|
367
|
+
end
|
368
|
+
end # def default_attributes
|
369
|
+
|
333
370
|
# Get the type of this package class.
|
334
371
|
#
|
335
372
|
# For "Foo::Bar::BAZ" this will return "baz"
|
data/lib/fpm/package/deb.rb
CHANGED
@@ -4,8 +4,10 @@ require "fpm/package"
|
|
4
4
|
require "fpm/errors"
|
5
5
|
require "fpm/util"
|
6
6
|
require "fileutils"
|
7
|
-
require "insist"
|
8
7
|
|
8
|
+
# Support for debian packages (.deb files)
|
9
|
+
#
|
10
|
+
# This class supports both input and output of packages.
|
9
11
|
class FPM::Package::Deb < FPM::Package
|
10
12
|
# Map of what scripts are named.
|
11
13
|
SCRIPT_MAP = {
|
@@ -50,6 +52,8 @@ class FPM::Package::Deb < FPM::Package
|
|
50
52
|
value.to_i
|
51
53
|
end
|
52
54
|
|
55
|
+
private
|
56
|
+
|
53
57
|
# Return the architecture. This will default to native if not yet set.
|
54
58
|
# It will also try to use dpkg and 'uname -m' to figure out what the
|
55
59
|
# native 'architecture' value should be.
|
@@ -63,11 +67,11 @@ class FPM::Package::Deb < FPM::Package
|
|
63
67
|
else
|
64
68
|
@architecture = %x{uname -m}.chomp
|
65
69
|
end
|
66
|
-
|
70
|
+
end
|
71
|
+
if @architecture == "x86_64"
|
67
72
|
# Debian calls x86_64 "amd64"
|
68
73
|
@architecture = "amd64"
|
69
74
|
end
|
70
|
-
|
71
75
|
return @architecture
|
72
76
|
end # def architecture
|
73
77
|
|
@@ -182,10 +186,11 @@ class FPM::Package::Deb < FPM::Package
|
|
182
186
|
end # def extract_files
|
183
187
|
|
184
188
|
def output(output_path)
|
185
|
-
|
189
|
+
# Abort if the target path already exists.
|
190
|
+
raise FileAlreadyExists.new(output_path) if File.exists?(output_path)
|
186
191
|
|
187
192
|
# create 'debian-binary' file, required to make a valid debian package
|
188
|
-
File.write(build_path("debian-binary"), "2.0")
|
193
|
+
File.write(build_path("debian-binary"), "2.0\n")
|
189
194
|
|
190
195
|
write_control_tarball
|
191
196
|
|
@@ -325,6 +330,7 @@ class FPM::Package::Deb < FPM::Package
|
|
325
330
|
|
326
331
|
@logger.debug("Writing control file", :path => control)
|
327
332
|
File.write(control, control_data)
|
333
|
+
edit_file(control) if attributes[:edit?]
|
328
334
|
end
|
329
335
|
end # def write_control
|
330
336
|
|
@@ -333,13 +339,14 @@ class FPM::Package::Deb < FPM::Package
|
|
333
339
|
# SCRIPT_MAP is a map from the package ':after_install' to debian
|
334
340
|
# 'post_install' names
|
335
341
|
def write_scripts
|
336
|
-
SCRIPT_MAP.each do |
|
337
|
-
next if scripts[
|
342
|
+
SCRIPT_MAP.each do |scriptname, filename|
|
343
|
+
next if scripts[scriptname].nil?
|
338
344
|
|
339
|
-
with(control_path(filename)) do |
|
340
|
-
|
345
|
+
with(control_path(filename)) do |controlscript|
|
346
|
+
@logger.debug("Writing control script", :source => filename, :target => controlscript)
|
347
|
+
File.write(controlscript, scripts[scriptname])
|
341
348
|
# deb maintainer scripts are required to be executable
|
342
|
-
File.chmod(0755,
|
349
|
+
File.chmod(0755, controlscript)
|
343
350
|
end
|
344
351
|
end
|
345
352
|
end # def write_scripts
|
@@ -363,5 +370,13 @@ class FPM::Package::Deb < FPM::Package
|
|
363
370
|
File.chmod(0755, control_path("templates"))
|
364
371
|
end
|
365
372
|
end # def write_debconf
|
366
|
-
|
373
|
+
|
374
|
+
def to_s(format=nil)
|
375
|
+
# Default format if nil
|
376
|
+
# git_1.7.9.3-1_amd64.deb
|
377
|
+
return super("NAME_FULLVERSION_ARCH.TYPE") if format.nil?
|
378
|
+
return super(format)
|
379
|
+
end # def to_s
|
380
|
+
|
381
|
+
public(:input, :output, :architecture, :name, :converted_from, :to_s)
|
367
382
|
end # class FPM::Target::Deb
|
data/lib/fpm/package/dir.rb
CHANGED
@@ -4,9 +4,28 @@ require "fileutils"
|
|
4
4
|
require "find"
|
5
5
|
require "socket"
|
6
6
|
|
7
|
+
# A directory package.
|
8
|
+
#
|
9
|
+
# This class supports both input and output. As a note, 'output' will
|
10
|
+
# only emit the files, not any metadata. This is an effective way
|
11
|
+
# to extract another package type.
|
7
12
|
class FPM::Package::Dir < FPM::Package
|
8
13
|
private
|
9
14
|
|
15
|
+
# Add a new path to this package.
|
16
|
+
#
|
17
|
+
# If the path is a directory, it is copied recursively. The behavior
|
18
|
+
# of the copying is modified by the :chdir and :prefix attributes.
|
19
|
+
#
|
20
|
+
# If :prefix is set, the destination path is prefixed with that value.
|
21
|
+
# If :chdir is set, the current directory is changed to that value
|
22
|
+
# during the copy.
|
23
|
+
#
|
24
|
+
# Example: Copy /etc/X11 into this package as /opt/xorg/X11:
|
25
|
+
#
|
26
|
+
# package.attributes[:prefix] = "/opt/xorg"
|
27
|
+
# package.attributes[:chdir] = "/etc"
|
28
|
+
# package.input("X11")
|
10
29
|
def input(path)
|
11
30
|
@logger.debug("Copying", :input => path)
|
12
31
|
@logger["method"] = "input"
|
@@ -25,9 +44,11 @@ class FPM::Package::Dir < FPM::Package
|
|
25
44
|
self.license = "unknown"
|
26
45
|
self.vendor = [ENV["USER"], Socket.gethostname].join("@")
|
27
46
|
ensure
|
47
|
+
# Clean up any logger context we added.
|
28
48
|
@logger.remove("method")
|
29
49
|
end # def input
|
30
50
|
|
51
|
+
# Output this package to the given directory.
|
31
52
|
def output(dir)
|
32
53
|
dir = File.expand_path(dir)
|
33
54
|
::Dir.chdir(staging_path) do
|
@@ -60,6 +81,9 @@ class FPM::Package::Dir < FPM::Package
|
|
60
81
|
end
|
61
82
|
end # def clone
|
62
83
|
|
84
|
+
# Copy, recursively, from source to destination.
|
85
|
+
#
|
86
|
+
# Files will be hardlinked if possible, but copied otherwise.
|
63
87
|
def copy(source, destination)
|
64
88
|
directory = File.dirname(destination)
|
65
89
|
if !File.directory?(directory)
|
data/lib/fpm/package/gem.rb
CHANGED
@@ -12,9 +12,10 @@ require "fpm/util"
|
|
12
12
|
# The following attributes are supported:
|
13
13
|
#
|
14
14
|
# * :gem_bin_path
|
15
|
-
# * :
|
15
|
+
# * :gem_package_name_prefix
|
16
16
|
# * :gem_gem
|
17
17
|
class FPM::Package::Gem < FPM::Package
|
18
|
+
# Flags '--foo' will be accessable as attributes[:gem_foo]
|
18
19
|
option "--bin-path", "DIRECTORY", "The directory to install gem executables",
|
19
20
|
:default => ::Gem::bindir
|
20
21
|
option "--package-prefix", "NAMEPREFIX",
|
@@ -29,6 +30,10 @@ class FPM::Package::Gem < FPM::Package
|
|
29
30
|
option "--gem", "PATH_TO_GEM",
|
30
31
|
"The path to the 'gem' tool (defaults to 'gem' and searches " \
|
31
32
|
"your $PATH)", :default => "gem"
|
33
|
+
option "--fix-name", :flag, "Should the target package name be prefixed?",
|
34
|
+
:default => true
|
35
|
+
option "--fix-dependencies", :flag, "Should the package dependencies be " \
|
36
|
+
"prefixed?", :default => true
|
32
37
|
|
33
38
|
def input(gem)
|
34
39
|
# 'arg' is the name of the rubygem we should unpack.
|
@@ -97,7 +102,14 @@ class FPM::Package::Gem < FPM::Package
|
|
97
102
|
attributes[:gem_package_name_prefix] = attributes[:gem_package_prefix]
|
98
103
|
end
|
99
104
|
|
100
|
-
|
105
|
+
# name prefixing is optional, if enabled, a name 'foo' will become
|
106
|
+
# 'rubygem-foo' (depending on what the gem_package_name_prefix is)
|
107
|
+
self.name = spec.name
|
108
|
+
if attributes[:gem_fix_name?]
|
109
|
+
self.name = fix_name(spec.name)
|
110
|
+
end
|
111
|
+
|
112
|
+
#self.name = [attributes[:gem_package_name_prefix], spec.name].join("-")
|
101
113
|
self.license = (spec.license or "no license listed in #{File.basename(file)}")
|
102
114
|
self.version = spec.version.to_s
|
103
115
|
self.vendor = spec.author
|
@@ -132,7 +144,12 @@ class FPM::Package::Gem < FPM::Package
|
|
132
144
|
|
133
145
|
# Some reqs can be ">= a, < b" versions, let's handle that.
|
134
146
|
reqs.to_s.split(/, */).each do |req|
|
135
|
-
|
147
|
+
if attributes[:gem_fix_dependencies?]
|
148
|
+
name = fix_name(dep.name)
|
149
|
+
else
|
150
|
+
name = dep.name
|
151
|
+
end
|
152
|
+
self.dependencies << "#{name} #{req}"
|
136
153
|
end
|
137
154
|
end # runtime_dependencies
|
138
155
|
end # ::Gem::Package
|
@@ -157,6 +174,12 @@ class FPM::Package::Gem < FPM::Package
|
|
157
174
|
args << gem_path
|
158
175
|
safesystem(*args)
|
159
176
|
end # def install_to_staging
|
160
|
-
|
177
|
+
|
178
|
+
# Sanitize package name.
|
179
|
+
# This prefixes the package name with 'rubygem' (but depends on the attribute
|
180
|
+
# :gem_package_name_prefix
|
181
|
+
def fix_name(name)
|
182
|
+
return [attributes[:gem_package_name_prefix], name].join("-")
|
183
|
+
end # def fix_name
|
161
184
|
public(:input, :output)
|
162
185
|
end # class FPM::Package::Gem
|
data/lib/fpm/package/pear.rb
CHANGED
@@ -3,10 +3,20 @@ require "fpm/package"
|
|
3
3
|
require "fileutils"
|
4
4
|
require "fpm/util"
|
5
5
|
|
6
|
+
# This provides PHP PEAR package support.
|
7
|
+
#
|
8
|
+
# This provides input support, but not output support.
|
6
9
|
class FPM::Package::PEAR < FPM::Package
|
7
|
-
option "--package-prefix", "PREFIX",
|
8
|
-
"Name prefix for
|
10
|
+
option "--package-name-prefix", "PREFIX",
|
11
|
+
"Name prefix for pear package", :default => "php-pear"
|
9
12
|
|
13
|
+
# Input a PEAR package.
|
14
|
+
#
|
15
|
+
# The parameter is a PHP PEAR package name.
|
16
|
+
#
|
17
|
+
# Attributes that affect behavior here:
|
18
|
+
# * :prefix - changes the install root, default is /usr/share
|
19
|
+
# * :pear_package_name_prefix - changes the
|
10
20
|
def input(input_package)
|
11
21
|
if !program_in_path?("pear")
|
12
22
|
raise ExecutableNotFound.new("pear")
|
@@ -21,7 +31,7 @@ class FPM::Package::PEAR < FPM::Package
|
|
21
31
|
@logger.info("Fetching package information", :package => input_package)
|
22
32
|
pear_cmd = "pear -c #{config} remote-info #{input_package}"
|
23
33
|
name = %x{#{pear_cmd} | sed -ne '/^Package\s*/s/^Package\s*//p'}.chomp
|
24
|
-
self.name = "#{attributes[:
|
34
|
+
self.name = "#{attributes[:pear_package_name_prefix]}-#{name}"
|
25
35
|
self.version = %x{#{pear_cmd} | sed -ne '/^Latest\s*/s/^Latest\s*//p'}.chomp
|
26
36
|
self.description = %x{#{pear_cmd} | sed -ne '/^Summary\s*/s/^Summary\s*//p'}.chomp
|
27
37
|
|
data/lib/fpm/package/python.rb
CHANGED
@@ -7,7 +7,18 @@ require "fileutils"
|
|
7
7
|
require "tmpdir"
|
8
8
|
require "json"
|
9
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
|
+
#
|
10
20
|
class FPM::Package::Python < FPM::Package
|
21
|
+
# Flags '--foo' will be accessable as attributes[:python_foo]
|
11
22
|
option "--bin", "PYTHON_EXECUTABLE",
|
12
23
|
"The path to the python executable you wish to run.", :default => "python"
|
13
24
|
option "--easyinstall", "EASYINSTALL_EXECUTABLE",
|
@@ -15,9 +26,30 @@ class FPM::Package::Python < FPM::Package
|
|
15
26
|
option "--pypi", "PYPI_URL",
|
16
27
|
"PyPi Server uri for retrieving packages.",
|
17
28
|
:default => "http://pypi.python.org/simple"
|
18
|
-
option "--package-prefix", "
|
19
|
-
"
|
20
|
-
|
29
|
+
option "--package-prefix", "NAMEPREFIX",
|
30
|
+
"(DEPRECATED, use --package-name-prefix) Name to prefix the package " \
|
31
|
+
"name with." do |value|
|
32
|
+
@logger.warn("Using deprecated flag: --package-prefix. Please use " \
|
33
|
+
"--package-name-prefix")
|
34
|
+
value
|
35
|
+
end
|
36
|
+
option "--package-name-prefix", "PREFIX", "Name to prefix the package " \
|
37
|
+
"name with.", :default => "python"
|
38
|
+
option "--fix-name", :flag, "Should the target package name be prefixed?",
|
39
|
+
:default => true
|
40
|
+
option "--fix-dependencies", :flag, "Should the package dependencies be " \
|
41
|
+
"prefixed?", :default => true
|
42
|
+
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
# Input a package.
|
47
|
+
#
|
48
|
+
# The 'package' can be any of:
|
49
|
+
#
|
50
|
+
# * A name of a package on pypi (ie; easy_install some-package)
|
51
|
+
# * The path to a directory containing setup.py
|
52
|
+
# * The path to a setup.py
|
21
53
|
def input(package)
|
22
54
|
path_to_package = download_if_necessary(package, version)
|
23
55
|
|
@@ -36,7 +68,11 @@ class FPM::Package::Python < FPM::Package
|
|
36
68
|
install_to_staging(setup_py)
|
37
69
|
end # def input
|
38
70
|
|
71
|
+
# Download the given package if necessary. If version is given, that version
|
72
|
+
# will be downloaded, otherwise the latest is fetched.
|
39
73
|
def download_if_necessary(package, version=nil)
|
74
|
+
# TODO(sissel): this should just be a 'download' method, the 'if_necessary'
|
75
|
+
# part should go elsewhere.
|
40
76
|
path = package
|
41
77
|
# If it's a path, assume local build.
|
42
78
|
if File.directory?(path) or (File.exists?(path) and File.basename(path) == "setup.py")
|
@@ -51,30 +87,32 @@ class FPM::Package::Python < FPM::Package
|
|
51
87
|
want_pkg = "#{package}==#{version}"
|
52
88
|
end
|
53
89
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
90
|
+
target = build_path(package)
|
91
|
+
FileUtils.mkdir(target) unless File.directory?(target)
|
92
|
+
|
93
|
+
safesystem(attributes[:python_easyinstall], "-i", attributes[:python_pypi],
|
94
|
+
"--editable", "-U", "--build-directory", target, want_pkg)
|
58
95
|
|
59
96
|
# easy_install will put stuff in @tmpdir/packagename/, so find that:
|
60
97
|
# @tmpdir/somepackage/setup.py
|
61
|
-
dirs = ::Dir.glob(File.join(
|
98
|
+
dirs = ::Dir.glob(File.join(target, "*"))
|
62
99
|
if dirs.length != 1
|
63
100
|
raise "Unexpected directory layout after easy_install. Maybe file a bug? The directory is #{build_path}"
|
64
101
|
end
|
65
102
|
return dirs.first
|
66
103
|
end # def download
|
67
104
|
|
105
|
+
# Load the package information like name, version, dependencies.
|
68
106
|
def load_package_info(setup_py)
|
69
|
-
if !attributes.
|
70
|
-
attributes[:
|
107
|
+
if !attributes[:python_package_prefix].nil?
|
108
|
+
attributes[:python_package_name_prefix] = attributes[:python_package_prefix]
|
71
109
|
end
|
72
110
|
|
73
111
|
# Add ./pyfpm/ to the python library path
|
74
112
|
pylib = File.expand_path(File.dirname(__FILE__))
|
75
|
-
setup_cmd = "env PYTHONPATH=#{pylib} #{
|
113
|
+
setup_cmd = "env PYTHONPATH=#{pylib} #{attributes[:python_bin]} #{setup_py} --command-packages=pyfpm get_metadata"
|
76
114
|
output = ::Dir.chdir(File.dirname(setup_py)) { `#{setup_cmd}` }
|
77
|
-
|
115
|
+
@logger.warn("json output from setup.py", :data => output)
|
78
116
|
metadata = JSON.parse(output[/\{.*\}/msx])
|
79
117
|
|
80
118
|
self.architecture = metadata["architecture"]
|
@@ -83,11 +121,20 @@ class FPM::Package::Python < FPM::Package
|
|
83
121
|
self.version = metadata["version"]
|
84
122
|
self.url = metadata["url"]
|
85
123
|
|
86
|
-
|
124
|
+
# name prefixing is optional, if enabled, a name 'foo' will become
|
125
|
+
# 'python-foo' (depending on what the python_package_name_prefix is)
|
126
|
+
if attributes[:python_fix_name?]
|
127
|
+
self.name = fix_name(metadata["name"])
|
128
|
+
else
|
129
|
+
self.name = metadata["name"]
|
130
|
+
end
|
87
131
|
|
88
132
|
self.dependencies += metadata["dependencies"].collect do |dep|
|
89
133
|
name, cmp, version = dep.split
|
90
|
-
name
|
134
|
+
# dependency name prefixing is optional, if enabled, a name 'foo' will
|
135
|
+
# become 'python-foo' (depending on what the python_package_name_prefix
|
136
|
+
# is)
|
137
|
+
name = fix_name(name) if attributes[:python_fix_dependencies?]
|
91
138
|
"#{name} #{cmp} #{version}"
|
92
139
|
end
|
93
140
|
end # def load_package_info
|
@@ -101,25 +148,32 @@ class FPM::Package::Python < FPM::Package
|
|
101
148
|
if name.start_with?("python")
|
102
149
|
# If the python package is called "python-foo" strip the "python-" part while
|
103
150
|
# prepending the package name prefix.
|
104
|
-
return [attributes[:
|
151
|
+
return [attributes[:python_package_name_prefix], name.gsub(/^python-/, "")].join("-")
|
105
152
|
else
|
106
|
-
return [attributes[:
|
153
|
+
return [attributes[:python_package_name_prefix], name].join("-")
|
107
154
|
end
|
108
155
|
end # def fix_name
|
109
156
|
|
157
|
+
# Install this package to the staging directory
|
110
158
|
def install_to_staging(setup_py)
|
111
159
|
dir = File.dirname(setup_py)
|
112
160
|
|
113
161
|
# Some setup.py's assume $PWD == current directory of setup.py, so let's
|
114
162
|
# chdir first.
|
115
163
|
::Dir.chdir(dir) do
|
164
|
+
|
165
|
+
# Install with a specific prefix if requested
|
116
166
|
if attributes[:prefix]
|
117
167
|
safesystem(attributes[:python_bin], "setup.py", "install", "--prefix",
|
118
168
|
File.join(staging_path, attributes[:prefix]))
|
119
169
|
else
|
170
|
+
# Otherwise set the root in staging_path
|
171
|
+
# TODO(sissel): there needs to be a way to force
|
120
172
|
safesystem(attributes[:python_bin], "setup.py", "install", "--root",
|
121
173
|
staging_path)
|
122
174
|
end
|
123
175
|
end
|
124
176
|
end # def install_to_staging
|
177
|
+
|
178
|
+
public(:input)
|
125
179
|
end # class FPM::Package::Python
|
data/lib/fpm/package/rpm.rb
CHANGED
@@ -67,7 +67,6 @@ class FPM::Package::RPM < FPM::Package
|
|
67
67
|
|
68
68
|
self.architecture = tags[:arch]
|
69
69
|
self.category = tags[:group]
|
70
|
-
self.config_files = config_files
|
71
70
|
self.description = tags[:description]
|
72
71
|
self.epoch = (tags[:epoch] || [nil]).first # for some reason epoch is an array
|
73
72
|
self.iteration = tags[:release]
|
@@ -78,16 +77,28 @@ class FPM::Package::RPM < FPM::Package
|
|
78
77
|
self.vendor = tags[:vendor]
|
79
78
|
self.version = tags[:version]
|
80
79
|
|
81
|
-
|
80
|
+
self.scripts[:before_install] = tags[:prein]
|
81
|
+
self.scripts[:after_install] = tags[:postin]
|
82
|
+
self.scripts[:before_remove] = tags[:preun]
|
83
|
+
self.scripts[:after_remove] = tags[:postun]
|
84
|
+
# TODO(sissel): prefix these scripts above with a shebang line if there isn't one?
|
85
|
+
# Also taking into account the value of tags[preinprog] etc, something like:
|
86
|
+
# #!#{tags[:preinprog]}
|
87
|
+
# #{tags[prein]}
|
82
88
|
# TODO(sissel): put 'trigger scripts' stuff into attributes
|
83
|
-
# TODO(sissel): support provides
|
84
|
-
# TODO(sissel): support conflicts
|
85
|
-
# TODO(sissel): support replaces
|
86
89
|
|
87
90
|
self.dependencies += rpm.requires.collect do |name, operator, version|
|
88
91
|
[name, operator, version].join(" ")
|
89
92
|
end
|
93
|
+
self.conflicts += rpm.conflicts.collect do |name, operator, version|
|
94
|
+
[name, operator, version].join(" ")
|
95
|
+
end
|
96
|
+
self.provides += rpm.provides.collect do |name, operator, version|
|
97
|
+
[name, operator, version].join(" ")
|
98
|
+
end
|
90
99
|
#input.replaces += replaces
|
100
|
+
|
101
|
+
self.config_files += rpm.config_files
|
91
102
|
|
92
103
|
# Extract to the staging directory
|
93
104
|
rpm.extract(staging_path)
|
@@ -112,11 +123,6 @@ class FPM::Package::RPM < FPM::Package
|
|
112
123
|
edit_file(specfile) if attributes[:edit?]
|
113
124
|
|
114
125
|
args << specfile
|
115
|
-
#if defines.empty?
|
116
|
-
#args = prefixargs + spec
|
117
|
-
#else
|
118
|
-
#args = prefixargs + defines.collect{ |define| ["--define", define] }.flatten + spec
|
119
|
-
#end
|
120
126
|
|
121
127
|
@logger.info("Running rpmbuild", :args => args)
|
122
128
|
safesystem(*args)
|
@@ -129,5 +135,10 @@ class FPM::Package::RPM < FPM::Package
|
|
129
135
|
@logger.log("Created rpm", :path => output_path)
|
130
136
|
end # def output
|
131
137
|
|
132
|
-
|
138
|
+
def to_s(format=nil)
|
139
|
+
return super("NAME-VERSION-ITERATION.ARCH.TYPE") if format.nil?
|
140
|
+
return super(format)
|
141
|
+
end # def to_s
|
142
|
+
|
143
|
+
public(:input, :output, :converted_from, :architecture, :to_s)
|
133
144
|
end # class FPM::Package::RPM
|
data/templates/rpm.erb
CHANGED
@@ -31,6 +31,9 @@ Requires: <%= req %>
|
|
31
31
|
<% provides.each do |prov| -%>
|
32
32
|
Provides: <%= prov %>
|
33
33
|
<% end -%>
|
34
|
+
<% conflicts.each do |conflict| -%>
|
35
|
+
Conflicts: <%= conflict %>
|
36
|
+
<% end -%>
|
34
37
|
<% replaces.each do |repl| -%>
|
35
38
|
<%# The closes equivalent in RPM to "replaces" is "Obsoletes" -%>
|
36
39
|
Obsoletes: <%= repl %>
|
@@ -63,36 +66,39 @@ fi
|
|
63
66
|
%clean
|
64
67
|
# noop
|
65
68
|
|
66
|
-
<% if scripts[
|
69
|
+
<% if scripts[:before_install] -%>
|
67
70
|
%pre
|
68
|
-
<%=
|
71
|
+
<%= scripts[:before_install] %>
|
69
72
|
|
70
73
|
<% end -%>
|
71
|
-
<% if scripts[
|
74
|
+
<% if scripts[:after_install] -%>
|
72
75
|
%post
|
73
|
-
<%=
|
76
|
+
<%= scripts[:after_install] %>
|
74
77
|
|
75
78
|
<% end -%>
|
76
|
-
<% if scripts[
|
79
|
+
<% if scripts[:before_remove] -%>
|
77
80
|
%preun
|
78
|
-
<%=
|
81
|
+
<%= scripts[:before_remove] %>
|
79
82
|
|
80
83
|
<% end -%>
|
81
|
-
<% if scripts[
|
84
|
+
<% if scripts[:after_remove] -%>
|
82
85
|
%postun
|
83
|
-
<%=
|
86
|
+
<%= scripts[:after_remove] %>
|
84
87
|
|
85
88
|
<% end -%>
|
86
89
|
%files
|
87
90
|
%defattr(-,root,root,-)
|
88
91
|
<%# Output config files and then regular files. -%>
|
89
|
-
|
90
|
-
|
92
|
+
<% config_files.each do |path| -%>
|
93
|
+
%config <%= path %>
|
94
|
+
<% end -%>
|
95
|
+
<%# list only files, not directories? -%>
|
91
96
|
<%=
|
92
|
-
# Reject directories
|
93
|
-
# paths with spaces are quoted. I hate rpm so much.
|
97
|
+
# Reject directories or config files already listed, then prefix files with
|
98
|
+
# "/", then make sure paths with spaces are quoted. I hate rpm so much.
|
94
99
|
files.reject { |f| File.directory?(File.join(staging_path, f)) } \
|
95
100
|
.collect { |f| "/#{f}" } \
|
101
|
+
.reject { |f| config_files.include?(f) } \
|
96
102
|
.collect { |f| f[/\s/] and "\"#{f}\"" or f } \
|
97
103
|
.join("\n")
|
98
104
|
%>
|
metadata
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fpm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
5
|
-
prerelease:
|
4
|
+
version: 0.4.0
|
5
|
+
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Jordan Sissel
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-03-
|
12
|
+
date: 2012-03-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: json
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,43 +21,63 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: cabin
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
35
|
- - ~>
|
31
36
|
- !ruby/object:Gem::Version
|
32
|
-
version: 0.4.
|
37
|
+
version: 0.4.3
|
33
38
|
type: :runtime
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 0.4.3
|
36
46
|
- !ruby/object:Gem::Dependency
|
37
47
|
name: backports
|
38
|
-
requirement:
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
39
49
|
none: false
|
40
50
|
requirements:
|
41
|
-
- - =
|
51
|
+
- - '='
|
42
52
|
- !ruby/object:Gem::Version
|
43
53
|
version: 2.3.0
|
44
54
|
type: :runtime
|
45
55
|
prerelease: false
|
46
|
-
version_requirements:
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - '='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 2.3.0
|
47
62
|
- !ruby/object:Gem::Dependency
|
48
63
|
name: arr-pm
|
49
|
-
requirement:
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
50
65
|
none: false
|
51
66
|
requirements:
|
52
|
-
- -
|
67
|
+
- - ~>
|
53
68
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
69
|
+
version: 0.0.7
|
55
70
|
type: :runtime
|
56
71
|
prerelease: false
|
57
|
-
version_requirements:
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 0.0.7
|
58
78
|
- !ruby/object:Gem::Dependency
|
59
79
|
name: clamp
|
60
|
-
requirement:
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
61
81
|
none: false
|
62
82
|
requirements:
|
63
83
|
- - ! '>='
|
@@ -65,10 +85,15 @@ dependencies:
|
|
65
85
|
version: '0'
|
66
86
|
type: :runtime
|
67
87
|
prerelease: false
|
68
|
-
version_requirements:
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
69
94
|
- !ruby/object:Gem::Dependency
|
70
95
|
name: rush
|
71
|
-
requirement:
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
72
97
|
none: false
|
73
98
|
requirements:
|
74
99
|
- - ! '>='
|
@@ -76,10 +101,15 @@ dependencies:
|
|
76
101
|
version: '0'
|
77
102
|
type: :development
|
78
103
|
prerelease: false
|
79
|
-
version_requirements:
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
80
110
|
- !ruby/object:Gem::Dependency
|
81
111
|
name: rspec
|
82
|
-
requirement:
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
83
113
|
none: false
|
84
114
|
requirements:
|
85
115
|
- - ! '>='
|
@@ -87,18 +117,28 @@ dependencies:
|
|
87
117
|
version: '0'
|
88
118
|
type: :development
|
89
119
|
prerelease: false
|
90
|
-
version_requirements:
|
91
|
-
- !ruby/object:Gem::Dependency
|
92
|
-
name: insist
|
93
|
-
requirement: &14148140 !ruby/object:Gem::Requirement
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
121
|
none: false
|
95
122
|
requirements:
|
96
123
|
- - ! '>='
|
97
124
|
- !ruby/object:Gem::Version
|
98
125
|
version: '0'
|
99
|
-
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: insist
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ~>
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: 0.0.3
|
134
|
+
type: :development
|
100
135
|
prerelease: false
|
101
|
-
version_requirements:
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ~>
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: 0.0.3
|
102
142
|
description: Convert directories, rpms, python eggs, rubygems, and more to rpms, debs,
|
103
143
|
solaris packages and more. Win at package management without wasting pointless hours
|
104
144
|
debugging bad rpm specs!
|
@@ -155,12 +195,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
155
195
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
156
196
|
none: false
|
157
197
|
requirements:
|
158
|
-
- - ! '
|
198
|
+
- - ! '>='
|
159
199
|
- !ruby/object:Gem::Version
|
160
|
-
version:
|
200
|
+
version: '0'
|
161
201
|
requirements: []
|
162
202
|
rubyforge_project:
|
163
|
-
rubygems_version: 1.8.
|
203
|
+
rubygems_version: 1.8.18
|
164
204
|
signing_key:
|
165
205
|
specification_version: 3
|
166
206
|
summary: fpm - package building and mangling
|