1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
|
require "rubygems"
require "erb" # TODO(sissel): Move to the class that needs it.
require "fpm/namespace"
require "optparse"
require "ostruct"
require "fpm"
require "fpm/flags"
class FPM::Program
def initialize
@settings = OpenStruct.new
@settings.dependencies = []
@settings.exclude = [] # Paths to exclude in packaging
@settings.provides = []
@settings.replaces = []
@settings.conflicts = []
@settings.source = {} # source settings
@settings.target = {} # target settings
@settings.config_files ||= []
@settings.paths = [] # Paths to include in the package
# Maintainer scripts - https://github.com/jordansissel/fpm/issues/18
@settings.scripts ||= {}
@help = nil
end # def initialize
def run(args)
$: << File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))
inputs = options(args)
ok = true
if @settings.package_type.nil?
$stderr.puts "Missing package target type (no -t flag?)"
ok = false
end
if @settings.source_type.nil?
$stderr.puts "Missing package source type (no -s flag?)"
ok = false
end
paths = process_paths(remaining_args)
ok = false if paths == :errors
if !ok
$stderr.puts "There were errors; see above."
$stderr.puts
$stderr.puts @help
return 1
end
builder = FPM::Builder.new(@settings, paths)
builder.assemble!
puts "Created #{builder.output}"
return 0
end # def run
def process_paths(args)
paths_iolike = args
read_from_stdin = args.length == 1 && args.first == '-'
ok = true
if @settings.source[:inputs]
if read_from_stdin
$stderr.puts "Error: setting --inputs conflicts with passing '-' as the only argument"
ok = false
end
unless File.file?(@settings.source[:inputs])
$stderr.puts "Error: '#{@settings.source[:inputs]}' does not exist"
ok = false
end
end
return :errors if !ok
if read_from_stdin
paths_iolike = $stdin
end
if @settings.source[:inputs]
paths_iolike = File.open(@settings.source[:inputs], 'r')
end
paths = []
paths_iolike.each do |entry|
paths << entry.strip
end
paths_iolike.close if paths_iolike.respond_to?(:close)
paths
end # def process_paths
def options(args)
opts = OptionParser.new
default_options(opts)
# Add extra flags from plugins
FPM::Package::Gem.flags(FPM::Flags.new(opts, "gem", "gem only"), @settings)
FPM::Package::Python.flags(FPM::Flags.new(opts, "python", "python only"),
@settings)
#FPM::Package::Deb.flags(FPM::Flags.new(opts, "deb", "deb only"), @settings)
FPM::Package::Rpm.flags(FPM::Flags.new(opts, "rpm", "rpm only"), @settings)
# Process fpmrc first
fpmrc(opts)
# Proces normal flags now.
begin
remaining = opts.parse(args)
rescue OptionParser::MissingArgument, OptionParser::InvalidOption
$stderr.puts $!.to_s
$stderr.puts opts
exit 2
end
# need to print help in a different scope
@help = opts.help
return remaining
end # def options
def fpmrc(options)
# Skip if we have no HOME environment variable.
return if !ENV.include?("HOME")
rcpath = File.expand_path("~/.fpmrc")
return if !File.exists?(rcpath)
# fpmrc exists, read it as flags, one per line.
File.new(rcpath, "r").each do |line|
flag = line.chomp
begin
options.parse([flag])
rescue => e
$stderr.puts "Error parsing fpmrc (#{rcpath})"
raise e
end # begin
end # File.new
end # def fpmrc
def default_options(opts)
# TODO(sissel): Maybe this should be '-o OUTPUT' ?
opts.on("-p PACKAGEFILE", "--package PACKAGEFILE",
"The package file to manage") do |path|
if path =~ /^\//
@settings.package_path = path
else
@settings.package_path = "#{Dir.pwd}/#{path}"
end
end # --package
opts.on("-n PACKAGENAME", "--name PACKAGENAME",
"What name to give to the package") do |name|
@settings.package_name = name
end # --name
opts.on("-v VERSION", "--version VERSION",
"version to give the package") do |version|
@settings.version = version
end # --version
opts.on("--iteration ITERATION",
"(optional) Set the iteration value for this package ('release' for RPM).") do |iteration|
@settings.iteration = iteration
end # --iteration
opts.on("--epoch EPOCH",
"(optional) Set epoch value for this package.") do |epoch|
@settings.epoch = epoch
end # --epoch
opts.on("--license LICENSE", "(optional) Sets the license for this package.") do |license|
@settings.license = license
end # --license
opts.on("--vendor VENDOR", "(optional) Sets the vendor for this package.") do |vendor|
@settings.vendor = vendor
end # --vendor
opts.on("-d DEPENDENCY", "--depends DEPENDENCY") do |dep|
@settings.dependencies << dep
end # --depends
opts.on("--category SECTION_OR_GROUP") do |thing|
@settings.category = thing
end # --category
opts.on("--provides PROVIDES") do |thing|
@settings.provides << thing
end # --provides
opts.on("--conflicts CONFLICTS") do |thing|
@settings.conflicts << thing
end # --conflicts
opts.on("--replaces REPLACES") do |thing|
@settings.replaces << thing
end # --replaces
opts.on("--config-files PATH",
"(optional) Treat path as a configuration file. Uses conffiles in deb or %config in rpm. (/etc/package.conf)") do |thing|
@settings.config_files << thing
end
opts.on("-a ARCHITECTURE", "--architecture ARCHITECTURE") do |arch|
@settings.architecture = arch
end # --architecture
opts.on("-m MAINTAINER", "--maintainer MAINTAINER") do |maintainer|
@settings.maintainer = maintainer
end # --maintainer
opts.on("-C DIRECTORY", "Change directory before searching for files") do |dir|
@settings.chdir = dir
end # -C
opts.on("-t PACKAGE_TYPE", "the type of package you want to create") do |type|
@settings.package_type = type
end # -t
opts.on("-s SOURCE_TYPE", "what to build the package from") do |st|
@settings.source_type = st
end # -s
opts.on("-S PACKAGE_SUFFIX", "which suffix to append to package and dependencies") do |sfx|
@settings.suffix = sfx
end # -S
opts.on("--prefix PREFIX",
"A path to prefix files with when building the target package. This may not be necessary for all source types. For example, the 'gem' type will prefix with your gem directory (gem env | grep -A1 PATHS:)") do |prefix|
@settings.prefix = prefix
end # --prefix
opts.on("-e", "--edit", "Edit the specfile before building") do
@settings.edit = true
end # --edit
opts.on("-x PATTERN", "--exclude PATTERN",
"Exclude paths matching pattern (according to tar --exclude)") do |pattern|
@settings.exclude << pattern
end # -x / --exclude
opts.on("--post-install SCRIPTPATH",
"Add a post-install action. This script will be included in the" \
" resulting package") do |path|
@settings.scripts["post-install"] = File.expand_path(path)
end # --post-install
opts.on("--pre-install SCRIPTPATH",
"Add a pre-install action. This script will be included in the" \
" resulting package") do |path|
@settings.scripts["pre-install"] = File.expand_path(path)
end # --pre-install
opts.on("--pre-uninstall SCRIPTPATH",
"Add a pre-uninstall action. This script will be included in the" \
" resulting package") do |path|
@settings.scripts["pre-uninstall"] = File.expand_path(path)
end # --pre-uninstall
opts.on("--post-uninstall SCRIPTPATH",
"Add a post-uninstall action. This script will be included in the" \
" resulting package") do |path|
@settings.scripts["post-uninstall"] = File.expand_path(path)
end # --post-uninstall
opts.on("--description DESCRIPTION",
"Add a description for this package.") do |description|
@settings.description = description
end # --description
opts.on("--url URL",
"Add a url for this package.") do |url|
@settings.url = url
end # --url
opts.on("--inputs FILEPATH",
"The path to a file containing a newline-separated list of " \
"files and dirs to package.") do |path|
@settings.source[:inputs] = path
end
opts.separator "Pass - as the only argument to have the list of " \
"files and dirs read from STDIN " \
"(e.g. fpm -s dir -t deb - < FILELIST)"
end # def default_options
end # class FPM::Program
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|