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.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELIST +661 -0
  3. data/CONTRIBUTORS +26 -0
  4. data/LICENSE +21 -0
  5. data/bin/fpm +8 -0
  6. data/lib/fpm.rb +20 -0
  7. data/lib/fpm/command.rb +648 -0
  8. data/lib/fpm/errors.rb +4 -0
  9. data/lib/fpm/namespace.rb +4 -0
  10. data/lib/fpm/package.rb +539 -0
  11. data/lib/fpm/package/apk.rb +510 -0
  12. data/lib/fpm/package/cpan.rb +405 -0
  13. data/lib/fpm/package/deb.rb +935 -0
  14. data/lib/fpm/package/dir.rb +221 -0
  15. data/lib/fpm/package/empty.rb +13 -0
  16. data/lib/fpm/package/freebsd.rb +147 -0
  17. data/lib/fpm/package/gem.rb +243 -0
  18. data/lib/fpm/package/npm.rb +120 -0
  19. data/lib/fpm/package/osxpkg.rb +165 -0
  20. data/lib/fpm/package/p5p.rb +124 -0
  21. data/lib/fpm/package/pacman.rb +403 -0
  22. data/lib/fpm/package/pear.rb +117 -0
  23. data/lib/fpm/package/pkgin.rb +35 -0
  24. data/lib/fpm/package/pleaserun.rb +63 -0
  25. data/lib/fpm/package/puppet.rb +120 -0
  26. data/lib/fpm/package/pyfpm/__init__.py +1 -0
  27. data/lib/fpm/package/pyfpm/get_metadata.py +104 -0
  28. data/lib/fpm/package/python.rb +318 -0
  29. data/lib/fpm/package/rpm.rb +593 -0
  30. data/lib/fpm/package/sh.rb +69 -0
  31. data/lib/fpm/package/solaris.rb +95 -0
  32. data/lib/fpm/package/tar.rb +86 -0
  33. data/lib/fpm/package/virtualenv.rb +164 -0
  34. data/lib/fpm/package/zip.rb +63 -0
  35. data/lib/fpm/rake_task.rb +60 -0
  36. data/lib/fpm/util.rb +358 -0
  37. data/lib/fpm/util/tar_writer.rb +80 -0
  38. data/lib/fpm/version.rb +3 -0
  39. data/templates/deb.erb +52 -0
  40. data/templates/deb/changelog.erb +5 -0
  41. data/templates/deb/ldconfig.sh.erb +13 -0
  42. data/templates/deb/postinst_upgrade.sh.erb +62 -0
  43. data/templates/deb/postrm_upgrade.sh.erb +46 -0
  44. data/templates/deb/preinst_upgrade.sh.erb +41 -0
  45. data/templates/deb/prerm_upgrade.sh.erb +39 -0
  46. data/templates/osxpkg.erb +11 -0
  47. data/templates/p5p_metadata.erb +12 -0
  48. data/templates/pacman.erb +47 -0
  49. data/templates/pacman/INSTALL.erb +41 -0
  50. data/templates/pleaserun/generate-cleanup.sh +17 -0
  51. data/templates/pleaserun/install-path.sh +17 -0
  52. data/templates/pleaserun/install.sh +117 -0
  53. data/templates/pleaserun/scripts/after-install.sh +4 -0
  54. data/templates/pleaserun/scripts/before-remove.sh +12 -0
  55. data/templates/puppet/package.pp.erb +34 -0
  56. data/templates/puppet/package/remove.pp.erb +13 -0
  57. data/templates/rpm.erb +260 -0
  58. data/templates/rpm/filesystem_list +14514 -0
  59. data/templates/sh.erb +369 -0
  60. data/templates/solaris.erb +15 -0
  61. metadata +322 -0
data/CONTRIBUTORS ADDED
@@ -0,0 +1,26 @@
1
+ The following awesome folks have contributed ideas,
2
+ bug reports, code, or other to fpm:
3
+
4
+ anthezium
5
+ Curt Micol
6
+ Jeanine Adkisson
7
+ Jordan Sissel
8
+ Marc Fournier
9
+ Michael Blume
10
+ Pierre-Yves Ritschard
11
+ sabowski
12
+ Thomas Haggett
13
+ Pieter Loubser
14
+ Aleix Conchillo Flaqué (github: aconchillo)
15
+ Luke Macken (github: lmacken)
16
+ Matt Blair (github: mblair)
17
+ Thomas Meson (github: zllak)
18
+ Oliver Hookins (github: ohookins)
19
+ llasram
20
+ sbuss
21
+ Brett Gailey (github: dnbert)
22
+ Daniel Haskin (github: djhaskin987)
23
+
24
+ If you have contributed (bug reports, feature requests, help in IRC, blog
25
+ posts, code, etc) and aren't listed here, please let me know if you wish to be
26
+ added!
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ (This is an MIT-style license)
2
+
3
+ Copyright (c) 2011-2016 Jordan Sissel and contributors.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/bin/fpm ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "rubygems"
4
+ $: << File.join(File.dirname(__FILE__), "..", "lib")
5
+ require "fpm"
6
+ require "fpm/command"
7
+
8
+ exit(FPM::Command.run || 0)
data/lib/fpm.rb ADDED
@@ -0,0 +1,20 @@
1
+ require "fpm/namespace"
2
+
3
+ require "fpm/package"
4
+ require "fpm/package/dir"
5
+ require "fpm/package/gem"
6
+ require "fpm/package/deb"
7
+ require "fpm/package/npm"
8
+ require "fpm/package/rpm"
9
+ require "fpm/package/tar"
10
+ require "fpm/package/cpan"
11
+ require "fpm/package/pear"
12
+ require "fpm/package/empty"
13
+ require "fpm/package/puppet"
14
+ require "fpm/package/python"
15
+ require "fpm/package/osxpkg"
16
+ require "fpm/package/solaris"
17
+ require "fpm/package/p5p"
18
+ require "fpm/package/pkgin"
19
+ require "fpm/package/freebsd"
20
+ require "fpm/package/apk"
@@ -0,0 +1,648 @@
1
+ require "rubygems"
2
+ require "fpm/namespace"
3
+ require "fpm/version"
4
+ require "fpm/util"
5
+ require "clamp"
6
+ require "ostruct"
7
+ require "fpm"
8
+ require "tmpdir" # for Dir.tmpdir
9
+
10
+ if $DEBUG
11
+ Cabin::Channel.get(Kernel).subscribe($stdout)
12
+ Cabin::Channel.get(Kernel).level = :debug
13
+ end
14
+
15
+ Dir[File.join(File.dirname(__FILE__), "package", "*.rb")].each do |plugin|
16
+ Cabin::Channel.get(Kernel).info("Loading plugin", :path => plugin)
17
+
18
+ require "fpm/package/#{File.basename(plugin)}"
19
+ end
20
+
21
+
22
+ # The main fpm command entry point.
23
+ class FPM::Command < Clamp::Command
24
+ include FPM::Util
25
+
26
+ def help(*args)
27
+ lines = [
28
+ "Intro:",
29
+ "",
30
+ " This is fpm version #{FPM::VERSION}",
31
+ "",
32
+ " If you think something is wrong, it's probably a bug! :)",
33
+ " Please file these here: https://github.com/jordansissel/fpm/issues",
34
+ "",
35
+ " You can find support on irc (#fpm on freenode irc) or via email with",
36
+ " fpm-users@googlegroups.com",
37
+ "",
38
+ "Loaded package types:",
39
+ ]
40
+ FPM::Package.types.each do |name, _|
41
+ lines.push(" - #{name}")
42
+ end
43
+ lines.push("")
44
+ lines.push(super)
45
+ return lines.join("\n")
46
+ end # def help
47
+
48
+ option "-t", "OUTPUT_TYPE",
49
+ "the type of package you want to create (deb, rpm, solaris, etc)",
50
+ :attribute_name => :output_type
51
+ option "-s", "INPUT_TYPE",
52
+ "the package type to use as input (gem, rpm, python, etc)",
53
+ :attribute_name => :input_type
54
+ option "-C", "CHDIR",
55
+ "Change directory to here before searching for files",
56
+ :attribute_name => :chdir
57
+ option "--prefix", "PREFIX",
58
+ "A path to prefix files with when building the target package. This may " \
59
+ "not be necessary for all input packages. For example, the 'gem' type " \
60
+ "will prefix with your gem directory automatically."
61
+ option ["-p", "--package"], "OUTPUT", "The package file path to output."
62
+ option ["-f", "--force"], :flag, "Force output even if it will overwrite an " \
63
+ "existing file", :default => false
64
+ option ["-n", "--name"], "NAME", "The name to give to the package"
65
+
66
+ loglevels = %w(error warn info debug)
67
+ option "--log", "LEVEL", "Set the log level. Values: #{loglevels.join(", ")}.",
68
+ :attribute_name => :log_level do |val|
69
+ val.downcase.tap do |v|
70
+ if !loglevels.include?(v)
71
+ raise FPM::Package::InvalidArgument, "Invalid log level, #{v.inspect}. Must be one of: #{loglevels.join(", ")}"
72
+ end
73
+ end
74
+ end # --log
75
+ option "--verbose", :flag, "Enable verbose output"
76
+ option "--debug", :flag, "Enable debug output"
77
+ option "--debug-workspace", :flag, "Keep any file workspaces around for " \
78
+ "debugging. This will disable automatic cleanup of package staging and " \
79
+ "build paths. It will also print which directories are available."
80
+ option ["-v", "--version"], "VERSION", "The version to give to the package",
81
+ :default => 1.0
82
+ option "--iteration", "ITERATION",
83
+ "The iteration to give to the package. RPM calls this the 'release'. " \
84
+ "FreeBSD calls it 'PORTREVISION'. Debian calls this 'debian_revision'"
85
+ option "--epoch", "EPOCH",
86
+ "The epoch value for this package. RPM and Debian calls this 'epoch'. " \
87
+ "FreeBSD calls this 'PORTEPOCH'"
88
+ option "--license", "LICENSE",
89
+ "(optional) license name for this package"
90
+ option "--vendor", "VENDOR",
91
+ "(optional) vendor name for this package"
92
+ option "--category", "CATEGORY",
93
+ "(optional) category this package belongs to", :default => "none"
94
+ option ["-d", "--depends"], "DEPENDENCY",
95
+ "A dependency. This flag can be specified multiple times. Value is " \
96
+ "usually in the form of: -d 'name' or -d 'name > version'",
97
+ :multivalued => true, :attribute_name => :dependencies
98
+
99
+ option "--no-depends", :flag, "Do not list any dependencies in this package",
100
+ :default => false
101
+
102
+ option "--no-auto-depends", :flag, "Do not list any dependencies in this " \
103
+ "package automatically", :default => false
104
+
105
+ option "--provides", "PROVIDES",
106
+ "What this package provides (usually a name). This flag can be " \
107
+ "specified multiple times.", :multivalued => true,
108
+ :attribute_name => :provides
109
+ option "--conflicts", "CONFLICTS",
110
+ "Other packages/versions this package conflicts with. This flag can be " \
111
+ "specified multiple times.", :multivalued => true,
112
+ :attribute_name => :conflicts
113
+ option "--replaces", "REPLACES",
114
+ "Other packages/versions this package replaces. Equivalent of rpm's 'Obsoletes'. " \
115
+ "This flag can be specified multiple times.", :multivalued => true,
116
+ :attribute_name => :replaces
117
+
118
+ option "--config-files", "CONFIG_FILES",
119
+ "Mark a file in the package as being a config file. This uses 'conffiles'" \
120
+ " in debs and %config in rpm. If you have multiple files to mark as " \
121
+ "configuration files, specify this flag multiple times. If argument is " \
122
+ "directory all files inside it will be recursively marked as config files.",
123
+ :multivalued => true, :attribute_name => :config_files
124
+ option "--directories", "DIRECTORIES", "Recursively mark a directory as being owned " \
125
+ "by the package. Use this flag multiple times if you have multiple directories " \
126
+ "and they are not under the same parent directory ", :multivalued => true,
127
+ :attribute_name => :directories
128
+ option ["-a", "--architecture"], "ARCHITECTURE",
129
+ "The architecture name. Usually matches 'uname -m'. For automatic values," \
130
+ " you can use '-a all' or '-a native'. These two strings will be " \
131
+ "translated into the correct value for your platform and target package type."
132
+ option ["-m", "--maintainer"], "MAINTAINER",
133
+ "The maintainer of this package.",
134
+ :default => "<#{ENV["USER"]}@#{Socket.gethostname}>"
135
+ option ["-S", "--package-name-suffix"], "PACKAGE_NAME_SUFFIX",
136
+ "a name suffix to append to package and dependencies."
137
+ option ["-e", "--edit"], :flag,
138
+ "Edit the package spec before building.", :default => false
139
+
140
+ excludes = []
141
+ option ["-x", "--exclude"], "EXCLUDE_PATTERN",
142
+ "Exclude paths matching pattern (shell wildcard globs valid here). " \
143
+ "If you have multiple file patterns to exclude, specify this flag " \
144
+ "multiple times.", :attribute_name => :excludes do |val|
145
+ excludes << val
146
+ next excludes
147
+ end # -x / --exclude
148
+
149
+ option "--exclude-file", "EXCLUDE_PATH",
150
+ "The path to a file containing a newline-sparated list of "\
151
+ "patterns to exclude from input."
152
+
153
+ option "--description", "DESCRIPTION", "Add a description for this package." \
154
+ " You can include '\\n' sequences to indicate newline breaks.",
155
+ :default => "no description"
156
+ option "--url", "URI", "Add a url for this package.",
157
+ :default => "http://example.com/no-uri-given"
158
+ option "--inputs", "INPUTS_PATH",
159
+ "The path to a file containing a newline-separated list of " \
160
+ "files and dirs to use as input."
161
+
162
+ option "--post-install", "FILE",
163
+ "(DEPRECATED, use --after-install) A script to be run after " \
164
+ "package installation" do |val|
165
+ @after_install = File.expand_path(val) # Get the full path to the script
166
+ end # --post-install (DEPRECATED)
167
+ option "--pre-install", "FILE",
168
+ "(DEPRECATED, use --before-install) A script to be run before " \
169
+ "package installation" do |val|
170
+ @before_install = File.expand_path(val) # Get the full path to the script
171
+ end # --pre-install (DEPRECATED)
172
+ option "--post-uninstall", "FILE",
173
+ "(DEPRECATED, use --after-remove) A script to be run after " \
174
+ "package removal" do |val|
175
+ @after_remove = File.expand_path(val) # Get the full path to the script
176
+ end # --post-uninstall (DEPRECATED)
177
+ option "--pre-uninstall", "FILE",
178
+ "(DEPRECATED, use --before-remove) A script to be run before " \
179
+ "package removal" do |val|
180
+ @before_remove = File.expand_path(val) # Get the full path to the script
181
+ end # --pre-uninstall (DEPRECATED)
182
+
183
+ option "--after-install", "FILE",
184
+ "A script to be run after package installation" do |val|
185
+ File.expand_path(val) # Get the full path to the script
186
+ end # --after-install
187
+ option "--before-install", "FILE",
188
+ "A script to be run before package installation" do |val|
189
+ File.expand_path(val) # Get the full path to the script
190
+ end # --before-install
191
+ option "--after-remove", "FILE",
192
+ "A script to be run after package removal" do |val|
193
+ File.expand_path(val) # Get the full path to the script
194
+ end # --after-remove
195
+ option "--before-remove", "FILE",
196
+ "A script to be run before package removal" do |val|
197
+ File.expand_path(val) # Get the full path to the script
198
+ end # --before-remove
199
+ option "--after-upgrade", "FILE",
200
+ "A script to be run after package upgrade. If not specified,\n" \
201
+ "--before-install, --after-install, --before-remove, and \n" \
202
+ "--after-remove will behave in a backwards-compatible manner\n" \
203
+ "(they will not be upgrade-case aware).\n" \
204
+ "Currently only supports deb, rpm and pacman packages." do |val|
205
+ File.expand_path(val) # Get the full path to the script
206
+ end # --after-upgrade
207
+ option "--before-upgrade", "FILE",
208
+ "A script to be run before package upgrade. If not specified,\n" \
209
+ "--before-install, --after-install, --before-remove, and \n" \
210
+ "--after-remove will behave in a backwards-compatible manner\n" \
211
+ "(they will not be upgrade-case aware).\n" \
212
+ "Currently only supports deb, rpm and pacman packages." do |val|
213
+ File.expand_path(val) # Get the full path to the script
214
+ end # --before-upgrade
215
+
216
+ option "--template-scripts", :flag,
217
+ "Allow scripts to be templated. This lets you use ERB to template your " \
218
+ "packaging scripts (for --after-install, etc). For example, you can do " \
219
+ "things like <%= name %> to get the package name. For more information, " \
220
+ "see the fpm wiki: " \
221
+ "https://github.com/jordansissel/fpm/wiki/Script-Templates"
222
+
223
+ option "--template-value", "KEY=VALUE",
224
+ "Make 'key' available in script templates, so <%= key %> given will be " \
225
+ "the provided value. Implies --template-scripts",
226
+ :multivalued => true do |kv|
227
+ @template_scripts = true
228
+ next kv.split("=", 2)
229
+ end
230
+
231
+ option "--workdir", "WORKDIR",
232
+ "The directory you want fpm to do its work in, where 'work' is any file " \
233
+ "copying, downloading, etc. Roughly any scratch space fpm needs to build " \
234
+ "your package.", :default => Dir.tmpdir
235
+
236
+ parameter "[ARGS] ...",
237
+ "Inputs to the source package type. For the 'dir' type, this is the files" \
238
+ " and directories you want to include in the package. For others, like " \
239
+ "'gem', it specifies the packages to download and use as the gem input",
240
+ :attribute_name => :args
241
+
242
+ FPM::Package.types.each do |name, klass|
243
+ klass.apply_options(self)
244
+ end
245
+
246
+ # A new FPM::Command
247
+ def initialize(*args)
248
+ super(*args)
249
+ @conflicts = []
250
+ @replaces = []
251
+ @provides = []
252
+ @dependencies = []
253
+ @config_files = []
254
+ @directories = []
255
+ end # def initialize
256
+
257
+ # Execute this command. See Clamp::Command#execute and Clamp's documentation
258
+ def execute
259
+ # Short-circuit if someone simply runs `fpm --version`
260
+ if ARGV == [ "--version" ]
261
+ puts FPM::VERSION
262
+ return 0
263
+ end
264
+
265
+ logger.level = :warn
266
+ logger.level = :info if verbose? # --verbose
267
+ logger.level = :debug if debug? # --debug
268
+ if log_level
269
+ logger.level = log_level.to_sym
270
+ end
271
+
272
+
273
+ if (stray_flags = args.grep(/^-/); stray_flags.any?)
274
+ logger.warn("All flags should be before the first argument " \
275
+ "(stray flags found: #{stray_flags}")
276
+ end
277
+
278
+ # Some older behavior, if you specify:
279
+ # 'fpm -s dir -t ... -C somepath'
280
+ # fpm would assume you meant to add '.' to the end of the commandline.
281
+ # Let's hack that. https://github.com/jordansissel/fpm/issues/187
282
+ if input_type == "dir" and args.empty? and !chdir.nil?
283
+ logger.info("No args, but -s dir and -C are given, assuming '.' as input")
284
+ args << "."
285
+ end
286
+
287
+ logger.info("Setting workdir", :workdir => workdir)
288
+ ENV["TMP"] = workdir
289
+
290
+ validator = Validator.new(self)
291
+ if !validator.ok?
292
+ validator.messages.each do |message|
293
+ logger.warn(message)
294
+ end
295
+
296
+ logger.fatal("Fix the above problems, and you'll be rolling packages in no time!")
297
+ return 1
298
+ end
299
+ input_class = FPM::Package.types[input_type]
300
+ output_class = FPM::Package.types[output_type]
301
+
302
+ input = input_class.new
303
+
304
+ # Merge in package settings.
305
+ # The 'settings' stuff comes in from #apply_options, which goes through
306
+ # all the options defined in known packages and puts them into our command.
307
+ # Flags in packages defined as "--foo-bar" become named "--<packagetype>-foo-bar"
308
+ # They are stored in 'settings' as :gem_foo_bar.
309
+ input.attributes ||= {}
310
+
311
+ # Iterate over all the options and set their values in the package's
312
+ # attribute hash.
313
+ #
314
+ # Things like '--foo-bar' will be available as pkg.attributes[:foo_bar]
315
+ self.class.declared_options.each do |option|
316
+ option.attribute_name.tap do |attr|
317
+ next if attr == "help"
318
+ # clamp makes option attributes available as accessor methods
319
+ # --foo-bar is available as 'foo_bar'. Put these in the package
320
+ # attributes hash. (See FPM::Package#attributes)
321
+ #
322
+ # In the case of 'flag' options, the accessor is actually 'foo_bar?'
323
+ # instead of just 'foo_bar'
324
+
325
+ # If the instance variable @{attr} is defined, then
326
+ # it means the flag was given on the command line.
327
+ flag_given = instance_variable_defined?("@#{attr}")
328
+ input.attributes["#{attr}_given?".to_sym] = flag_given
329
+ attr = "#{attr}?" if !respond_to?(attr) # handle boolean :flag cases
330
+ input.attributes[attr.to_sym] = send(attr) if respond_to?(attr)
331
+ logger.debug("Setting attribute", attr.to_sym => send(attr))
332
+ end
333
+ end
334
+
335
+ if input_type == "pleaserun"
336
+ # Special case for pleaserun that all parameters are considered the 'command'
337
+ # to run through pleaserun.
338
+ input.input(args)
339
+ else
340
+ # Each remaining command line parameter is used as an 'input' argument.
341
+ # For directories, this means paths. For things like gem and python, this
342
+ # means package name or paths to the packages (rails, foo-1.0.gem, django,
343
+ # bar/setup.py, etc)
344
+ args.each do |arg|
345
+ input.input(arg)
346
+ end
347
+ end
348
+
349
+ # If --inputs was specified, read it as a file.
350
+ if !inputs.nil?
351
+ if !File.exists?(inputs)
352
+ logger.fatal("File given for --inputs does not exist (#{inputs})")
353
+ return 1
354
+ end
355
+
356
+ # Read each line as a path
357
+ File.new(inputs, "r").each_line do |line|
358
+ # Handle each line as if it were an argument
359
+ input.input(line.strip)
360
+ end
361
+ end
362
+
363
+ # If --exclude-file was specified, read it as a file and append to
364
+ # the exclude pattern list.
365
+ if !exclude_file.nil?
366
+ if !File.exists?(exclude_file)
367
+ logger.fatal("File given for --exclude-file does not exist (#{exclude_file})")
368
+ return 1
369
+ end
370
+
371
+ # Ensure hash is initialized
372
+ input.attributes[:excludes] ||= []
373
+
374
+ # Read each line as a path
375
+ File.new(exclude_file, "r").each_line do |line|
376
+ # Handle each line as if it were an argument
377
+ input.attributes[:excludes] << line.strip
378
+ end
379
+ end
380
+
381
+ # Override package settings if they are not the default flag values
382
+ # the below proc essentially does:
383
+ #
384
+ # if someflag != default_someflag
385
+ # input.someflag = someflag
386
+ # end
387
+ set = proc do |object, attribute|
388
+ # if the package's attribute is currently nil *or* the flag setting for this
389
+ # attribute is non-default, use the value.
390
+ if object.send(attribute).nil? || send(attribute) != send("default_#{attribute}")
391
+ logger.info("Setting from flags: #{attribute}=#{send(attribute)}")
392
+ object.send("#{attribute}=", send(attribute))
393
+ end
394
+ end
395
+ set.call(input, :architecture)
396
+ set.call(input, :category)
397
+ set.call(input, :description)
398
+ set.call(input, :epoch)
399
+ set.call(input, :iteration)
400
+ set.call(input, :license)
401
+ set.call(input, :maintainer)
402
+ set.call(input, :name)
403
+ set.call(input, :url)
404
+ set.call(input, :vendor)
405
+ set.call(input, :version)
406
+
407
+ input.conflicts += conflicts
408
+ input.dependencies += dependencies
409
+ input.provides += provides
410
+ input.replaces += replaces
411
+ input.config_files += config_files
412
+ input.directories += directories
413
+
414
+ h = {}
415
+ attrs.each do | e |
416
+
417
+ s = e.split(':', 2)
418
+ h[s.last] = s.first
419
+ end
420
+
421
+ input.attrs = h
422
+
423
+ script_errors = []
424
+ setscript = proc do |scriptname|
425
+ # 'self.send(scriptname) == self.before_install == --before-install
426
+ # Gets the path to the script
427
+ path = self.send(scriptname)
428
+ # Skip scripts not set
429
+ next if path.nil?
430
+
431
+ if !File.exists?(path)
432
+ logger.error("No such file (for #{scriptname.to_s}): #{path.inspect}")
433
+ script_errors << path
434
+ end
435
+
436
+ # Load the script into memory.
437
+ input.scripts[scriptname] = File.read(path)
438
+ end
439
+
440
+ setscript.call(:before_install)
441
+ setscript.call(:after_install)
442
+ setscript.call(:before_remove)
443
+ setscript.call(:after_remove)
444
+ setscript.call(:before_upgrade)
445
+ setscript.call(:after_upgrade)
446
+
447
+ # Bail if any setscript calls had errors. We don't need to log
448
+ # anything because we've already logged the error(s) above.
449
+ return 1 if script_errors.any?
450
+
451
+ # Validate the package
452
+ if input.name.nil? or input.name.empty?
453
+ logger.fatal("No name given for this package (set name with '-n', " \
454
+ "for example, '-n packagename')")
455
+ return 1
456
+ end
457
+
458
+ # Convert to the output type
459
+ output = input.convert(output_class)
460
+
461
+ # Provide any template values as methods on the package.
462
+ if template_scripts?
463
+ template_value_list.each do |key, value|
464
+ (class << output; self; end).send(:define_method, key) { value }
465
+ end
466
+ end
467
+
468
+ # Write the output somewhere, package can be nil if no --package is specified,
469
+ # and that's OK.
470
+
471
+ # If the package output (-p flag) is a directory, write to the default file name
472
+ # but inside that directory.
473
+ if ! package.nil? && File.directory?(package)
474
+ package_file = File.join(package, output.to_s)
475
+ else
476
+ package_file = output.to_s(package)
477
+ end
478
+
479
+ begin
480
+ output.output(package_file)
481
+ rescue FPM::Package::FileAlreadyExists => e
482
+ logger.fatal(e.message)
483
+ return 1
484
+ rescue FPM::Package::ParentDirectoryMissing => e
485
+ logger.fatal(e.message)
486
+ return 1
487
+ end
488
+
489
+ logger.log("Created package", :path => package_file)
490
+ return 0
491
+ rescue FPM::Util::ExecutableNotFound => e
492
+ logger.error("Need executable '#{e}' to convert #{input_type} to #{output_type}")
493
+ return 1
494
+ rescue FPM::InvalidPackageConfiguration => e
495
+ logger.error("Invalid package configuration: #{e}")
496
+ return 1
497
+ rescue FPM::Util::ProcessFailed => e
498
+ logger.error("Process failed: #{e}")
499
+ return 1
500
+ ensure
501
+ if debug_workspace?
502
+ # only emit them if they have files
503
+ [input, output].each do |plugin|
504
+ next if plugin.nil?
505
+ [:staging_path, :build_path].each do |pathtype|
506
+ path = plugin.send(pathtype)
507
+ next unless Dir.open(path).to_a.size > 2
508
+ logger.log("plugin directory", :plugin => plugin.type, :pathtype => pathtype, :path => path)
509
+ end
510
+ end
511
+ else
512
+ input.cleanup unless input.nil?
513
+ output.cleanup unless output.nil?
514
+ end
515
+ end # def execute
516
+
517
+ def run(*run_args)
518
+ logger.subscribe(STDOUT)
519
+
520
+ # fpm initialization files, note the order of the following array is
521
+ # important, try .fpm in users home directory first and then the current
522
+ # directory
523
+ rc_files = [ ".fpm" ]
524
+ rc_files << File.join(ENV["HOME"], ".fpm") if ENV["HOME"]
525
+
526
+ rc_args = []
527
+
528
+ if ENV["FPMOPTS"]
529
+ logger.warn("Loading flags from FPMOPTS environment variable")
530
+ rc_args.push(*Shellwords.shellsplit(ENV["FPMOPTS"]))
531
+ end
532
+
533
+ rc_files.each do |rc_file|
534
+ if File.readable? rc_file
535
+ logger.warn("Loading flags from rc file #{rc_file}")
536
+ rc_args.push(*Shellwords.shellsplit(File.read(rc_file)))
537
+ end
538
+ end
539
+
540
+ flags = []
541
+ args = []
542
+ while rc_args.size > 0 do
543
+ arg = rc_args.shift
544
+ opt = self.class.find_option(arg)
545
+ if opt and not opt.flag?
546
+ flags.push(arg)
547
+ flags.push(rc_args.shift)
548
+ elsif opt or arg[0] == "-"
549
+ flags.push(arg)
550
+ else
551
+ args.push(arg)
552
+ end
553
+ end
554
+
555
+ logger.warn("Additional options: #{flags.join " "}") if flags.size > 0
556
+ logger.warn("Additional arguments: #{args.join " "}") if args.size > 0
557
+
558
+ ARGV.unshift(*flags)
559
+ ARGV.push(*args)
560
+ super(*run_args)
561
+ rescue FPM::Package::InvalidArgument => e
562
+ logger.error("Invalid package argument: #{e}")
563
+ return 1
564
+ end # def run
565
+
566
+ # A simple flag validator
567
+ #
568
+ # The goal of this class is to ensure the flags and arguments given
569
+ # are a valid configuration.
570
+ class Validator
571
+ include FPM::Util
572
+ private
573
+
574
+ def initialize(command)
575
+ @command = command
576
+ @valid = true
577
+ @messages = []
578
+
579
+ validate
580
+ end # def initialize
581
+
582
+ def ok?
583
+ return @valid
584
+ end # def ok?
585
+
586
+ def validate
587
+ # Make sure the user has passed '-s' and '-t' flags
588
+ mandatory(@command.input_type,
589
+ "Missing required -s flag. What package source did you want?")
590
+ mandatory(@command.output_type,
591
+ "Missing required -t flag. What package output did you want?")
592
+
593
+ # Verify the types requested are valid
594
+ types = FPM::Package.types.keys.sort
595
+ @command.input_type.tap do |val|
596
+ next if val.nil?
597
+ mandatory(FPM::Package.types.include?(val),
598
+ "Invalid input package -s flag) type #{val.inspect}. " \
599
+ "Expected one of: #{types.join(", ")}")
600
+ end
601
+
602
+ @command.output_type.tap do |val|
603
+ next if val.nil?
604
+ mandatory(FPM::Package.types.include?(val),
605
+ "Invalid output package (-t flag) type #{val.inspect}. " \
606
+ "Expected one of: #{types.join(", ")}")
607
+ end
608
+
609
+ @command.dependencies.tap do |dependencies|
610
+ # Verify dependencies don't include commas (#257)
611
+ dependencies.each do |dep|
612
+ next unless dep.include?(",")
613
+ splitdeps = dep.split(/\s*,\s*/)
614
+ @messages << "Dependencies should not " \
615
+ "include commas. If you want to specify multiple dependencies, use " \
616
+ "the '-d' flag multiple times. Example: " + \
617
+ splitdeps.map { |d| "-d '#{d}'" }.join(" ")
618
+ end
619
+ end
620
+
621
+ if @command.inputs
622
+ mandatory(@command.input_type == "dir", "--inputs is only valid with -s dir")
623
+ end
624
+
625
+ mandatory(@command.args.any? || @command.inputs || @command.input_type == 'empty',
626
+ "No parameters given. You need to pass additional command " \
627
+ "arguments so that I know what you want to build packages " \
628
+ "from. For example, for '-s dir' you would pass a list of " \
629
+ "files and directories. For '-s gem' you would pass a one" \
630
+ " or more gems to package from. As a full example, this " \
631
+ "will make an rpm of the 'json' rubygem: " \
632
+ "`fpm -s gem -t rpm json`")
633
+ end # def validate
634
+
635
+ def mandatory(value, message)
636
+ if value.nil? or !value
637
+ @messages << message
638
+ @valid = false
639
+ end
640
+ end # def mandatory
641
+
642
+ def messages
643
+ return @messages
644
+ end # def messages
645
+
646
+ public(:initialize, :ok?, :messages)
647
+ end # class Validator
648
+ end # class FPM::Program