fig 0.1.51 → 0.1.52

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,254 +1,476 @@
1
1
  require 'optparse'
2
+
2
3
  require 'fig/package'
3
- require 'fig/package/archive'
4
- require 'fig/package/include'
5
- require 'fig/package/path'
6
- require 'fig/package/resource'
7
- require 'fig/package/set'
4
+ require 'fig/packagedescriptor'
5
+ require 'fig/statement/archive'
6
+ require 'fig/statement/include'
7
+ require 'fig/statement/path'
8
+ require 'fig/statement/resource'
9
+ require 'fig/statement/set'
10
+
11
+ module Fig; end
8
12
 
9
13
  # Command-line processing.
14
+ class Fig::Options
15
+ USAGE = <<-EOF
10
16
 
17
+ Usage:
11
18
 
12
- module Fig
13
- def parse_descriptor(descriptor)
14
- # todo should use treetop for these:
15
- package_name = descriptor =~ /^([^:\/]+)/ ? $1 : nil
16
- config_name = descriptor =~ /:([^:\/]+)/ ? $1 : nil
17
- version_name = descriptor =~ /\/([^:\/]+)/ ? $1 : nil
18
- return package_name, config_name, version_name
19
- end
19
+ fig [...] [DESCRIPTOR] [--update | --update-if-missing] [-- COMMAND]
20
+
21
+ fig {--publish | --publish-local} DESCRIPTOR
22
+ [--resource PATH]
23
+ [--archive PATH]
24
+ [--include DESCRIPTOR]
25
+ [--force]
26
+ [...]
27
+
28
+ fig --clean DESCRIPTOR [...]
29
+
30
+ fig --get VARIABLE [DESCRIPTOR] [...]
31
+ fig --list-configs [DESCRIPTOR] [...]
32
+ fig --list-dependencies [--list-tree] [--list-all-configs] [DESCRIPTOR] [...]
33
+ fig {--list-local | --list-remote} [...]
34
+
35
+ fig {--version | --help}
36
+
37
+ Not yet implemented:
38
+ fig --list-variables [--list-tree] [--list-all-configs] [DESCRIPTOR] [...]
39
+
40
+ A DESCRIPTOR looks like <package name>[/<version>][:<config>] e.g. "foo",
41
+ "foo/1.2.3", and "foo/1.2.3:default". Whether ":<config>" and "/<version>" are
42
+ required or allowed is dependent upon what your are doing
43
+
44
+ Standard options (represented as "[...]" above):
20
45
 
21
- USAGE = <<EOF
46
+ [--set VARIABLE=VALUE]
47
+ [--append VARIABLE=VALUE]
48
+ [--file PATH] [--no-file]
49
+ [--config CONFIG]
50
+ [--login]
51
+ [--log-level LEVEL] [--log-config PATH]
52
+ [--figrc PATH] [--no-figrc]
22
53
 
23
- Usage: fig [--update | --update-if-missing] [--file <path>] [--set <VAR=value>] [--config <config>] [--login] [--log-level <level>] [--log-config <path>] [--figrc <path>] [--no-figrc] [-- <command>]
24
- fig [--publish | --publish-local] [--append <VAR=val>] [--resource <fullpath>] [--include <package name/version>] [--force] [--no-file] [--archive <path>] [--file] [--set <VAR=value>] [--config <config>] [--login] [--log-level <level>] [--log-config <path>] [--figrc <path>] [--no-figrc]
25
- fig [--set <VAR=value>] [--get <VAR> | --list-configs <package name>/<version> | --list | --list-remote | --clean <package name/version> | --version] [--log-level <level>] [--log-config <path>] [--figrc <path>] [--no-figrc] [-- <command>]
26
- fig [<package name>/<version>] [--log-level <level>] [--log-config <path>] [--figrc <path>] [--no-figrc]
54
+ Environment variables:
27
55
 
28
- Relevant env vars: FIG_REMOTE_URL (required), FIG_HOME (path to local repository cache, defaults
29
- to $HOME/.fighome).
56
+ FIG_REMOTE_URL (required),
57
+ FIG_HOME (path to local repository cache, defaults to $HOME/.fighome).
30
58
 
31
- EOF
59
+ EOF
32
60
 
33
61
  LOG_LEVELS = %w[ off fatal error warn info debug all ]
34
62
  LOG_ALIASES = { 'warning' => 'warn' }
35
63
 
36
- # Returns hash of option values, the remainders of argv, and an exit code if
37
- # full program processing occured in this method, otherwise nil.
38
- def parse_options(argv)
39
- options = {}
40
-
41
- parser = OptionParser.new do |opts|
42
- opts.banner = USAGE
43
- opts.on('-?', '-h','--help','display this help text') do
44
- puts opts.help
45
- puts "\n -- end of fig options; everything following is a command to run in the fig environment.\n\n"
46
- return nil, nil, 0
47
- end
64
+ attr_reader :shell_command
65
+ attr_reader :descriptor
66
+ attr_reader :exit_code
48
67
 
49
- opts.on('-v', '--version', 'Print fig version') do
50
- line = nil
68
+ def initialize(argv)
69
+ strip_shell_command(argv)
51
70
 
52
- begin
53
- File.open(
54
- "#{File.expand_path(File.dirname(__FILE__) + '/../../VERSION')}"
55
- ) do |file|
56
- line = file.gets
57
- end
58
- rescue
59
- $stderr.puts 'Could not retrieve version number. Something has mucked with your gem install.'
60
- return nil, nil, 1
61
- end
71
+ @options = {}
62
72
 
63
- if line !~ /\d+\.\d+\.\d+/
64
- $stderr.puts %Q<"#{line}" does not look like a version number. Something has mucked with your gem install.>
65
- return nil, nil, 1
66
- end
73
+ @options[:home] = ENV['FIG_HOME'] || File.expand_path('~/.fighome')
67
74
 
68
- puts File.basename($0) + ' v' + line
75
+ parser = new_parser()
69
76
 
70
- return nil, nil, 0
71
- end
77
+ # TODO: Need to catch the exception thrown from parser and retranslate into a fig exception
78
+ begin
79
+ parser.parse!(argv)
80
+ rescue OptionParser::MissingArgument => error
81
+ $stderr.puts "Please provide the #{error}."
82
+ @exit_code = 1
83
+ return
84
+ end
72
85
 
73
- options[:non_command_package_statements] = []
74
- opts.on(
75
- '-p',
76
- '--append VAR=VAL',
77
- 'append (actually, prepend) VAL to environment var VAR, delimited by separator'
78
- ) do |var_val|
79
- var, val = var_val.split('=')
80
- options[:non_command_package_statements] << Package::Path.new(var, val)
81
- end
86
+ if not exit_code.nil?
87
+ return
88
+ end
82
89
 
83
- options[:archives] = []
84
- opts.on(
85
- '--archive FULLPATH',
86
- 'include FULLPATH archive in package (when using --publish)'
87
- ) do |path|
88
- options[:archives] << Package::Archive.new(path)
89
- end
90
+ if argv.size > 1
91
+ $stderr.puts %q<Extra arguments. Should only have a package/version after all other options. Had "> + argv.join(%q<", ">) + %q<" left over.>
92
+ @exit_code = 1
93
+ return
94
+ end
90
95
 
91
- options[:cleans] = []
92
- opts.on('--clean PKG', 'remove package from $FIG_HOME') do |descriptor|
93
- options[:cleans] << descriptor
94
- end
96
+ package_text = argv.first
97
+ if package_text
98
+ @descriptor = Fig::PackageDescriptor.parse(package_text)
99
+ end
95
100
 
96
- options[:config] = 'default'
97
- opts.on(
98
- '-c',
99
- '--config CFG',
100
- %q<apply configuration CFG, default is 'default'>
101
- ) do |config|
102
- options[:config] = config
103
- end
101
+ return
102
+ end
104
103
 
105
- options[:package_config_file] = nil
106
- opts.on(
107
- '--file FILE',
108
- %q<read fig file FILE. Use '-' for stdin. See also --no-file>
109
- ) do |path|
110
- options[:package_config_file] = path
111
- end
104
+ def archives()
105
+ return @options[:archives]
106
+ end
112
107
 
113
- options[:force] = nil
114
- opts.on(
115
- '--force',
116
- 'force-overwrite existing version of a package to the remote repo'
117
- ) do |force|
118
- options[:force] = force
119
- end
108
+ def clean?()
109
+ return @options[:clean]
110
+ end
120
111
 
121
- options[:get] = nil
122
- opts.on(
123
- '-g',
124
- '--get VAR',
125
- 'print value of environment variable VAR'
126
- ) do |get|
127
- options[:get] = get
128
- end
112
+ def config()
113
+ return @options[:config]
114
+ end
129
115
 
130
- opts.on(
131
- '-i',
132
- '--include PKG',
133
- 'include PKG (with any variable prepends) in environment'
134
- ) do |descriptor|
135
- package_name, config_name, version_name = parse_descriptor(descriptor)
136
- options[:non_command_package_statements] << Package::Include.new(package_name, config_name, version_name, {})
137
- end
116
+ def figrc()
117
+ return @options[:figrc]
118
+ end
138
119
 
139
- options[:list] = false
140
- opts.on('--list', 'list packages in $FIG_HOME') do
141
- options[:list] = true
142
- end
120
+ def force?()
121
+ return @options[:force]
122
+ end
143
123
 
144
- options[:list_configs] = []
145
- opts.on(
146
- '--list-configs PKG', 'list configurations in package'
147
- ) do |descriptor|
148
- options[:list_configs] << descriptor
149
- end
124
+ def get()
125
+ return @options[:get]
126
+ end
150
127
 
151
- options[:list_remote] = false
152
- opts.on('--list-remote', 'list packages in remote repo') do
153
- options[:list_remote] = true
154
- end
128
+ def home()
129
+ return @options[:home]
130
+ end
155
131
 
156
- options[:login] = false
157
- opts.on(
158
- '-l', '--login', 'login to remote repo as a non-anonymous user'
159
- ) do
160
- options[:login] = true
161
- end
132
+ def listing()
133
+ return @options[:listing]
134
+ end
162
135
 
163
- opts.on(
164
- '--no-file', 'ignore package.fig file in current directory'
165
- ) do |path|
166
- options[:package_config_file] = :none
167
- end
136
+ def list_tree?()
137
+ return @options[:list_tree]
138
+ end
168
139
 
169
- options[:publish] = nil
170
- opts.on(
171
- '--publish PKG', 'install PKG in $FIG_HOME and in remote repo'
172
- ) do |publish|
173
- options[:publish] = publish
174
- end
140
+ def list_all_configs?()
141
+ return @options[:list_all_configs]
142
+ end
175
143
 
176
- options[:publish_local] = nil
177
- opts.on(
178
- '--publish-local PKG', 'install package only in $FIG_HOME'
179
- ) do |publish_local|
180
- options[:publish_local] = publish_local
181
- end
144
+ def log_config()
145
+ return @options[:log_config]
146
+ end
182
147
 
183
- options[:resources] =[]
184
- opts.on(
185
- '--resource FULLPATH',
186
- 'include FULLPATH resource in package (when using --publish)'
187
- ) do |path|
188
- options[:resources] << Package::Resource.new(path)
189
- end
148
+ def login?()
149
+ return @options[:login]
150
+ end
190
151
 
191
- opts.on(
192
- '-s', '--set VAR=VAL', 'set environment variable VAR to VAL'
193
- ) do |var_val|
194
- var, val = var_val.split('=')
195
- options[:non_command_package_statements] << Package::Set.new(var, val)
196
- end
152
+ def log_level()
153
+ return @options[:log_level]
154
+ end
197
155
 
198
- options[:update] = false
199
- opts.on(
200
- '-u',
201
- '--update',
202
- 'check remote repo for updates and download to $FIG_HOME as necessary'
203
- ) do
204
- options[:update] = true
205
- end
156
+ def no_figrc?()
157
+ return @options[:no_figrc]
158
+ end
206
159
 
207
- options[:update_if_missing] = false
208
- opts.on(
209
- '-m',
210
- '--update-if-missing',
211
- 'check remote repo for updates only if package missing from $FIG_HOME'
212
- ) do
213
- options[:update_if_missing] = true
214
- end
160
+ def non_command_package_statements()
161
+ return @options[:non_command_package_statements]
162
+ end
215
163
 
216
- opts.on(
217
- '--figrc PATH', 'add PATH to configuration used for Fig'
218
- ) do |path|
219
- options[:figrc] = path
220
- end
164
+ def package_config_file()
165
+ return @options[:package_config_file]
166
+ end
221
167
 
222
- opts.on('--no-figrc', 'ignore ~/.figrc') { options[:no_figrc] = true }
168
+ def publish?()
169
+ return @options[:publish]
170
+ end
171
+
172
+ def publish_local?()
173
+ return @options[:publish_local]
174
+ end
223
175
 
224
- opts.on(
225
- '--log-config PATH', 'use PATH file as configuration for Log4r'
226
- ) do |path|
227
- options[:log_config] = path
176
+ def publishing?()
177
+ return publish? || publish_local?
178
+ end
179
+
180
+ def resources()
181
+ return @options[:resources]
182
+ end
183
+
184
+ def update?()
185
+ return @options[:update]
186
+ end
187
+
188
+ def update_if_missing?()
189
+ return @options[:update_if_missing]
190
+ end
191
+
192
+ def updating?()
193
+ return update? || update_if_missing?
194
+ end
195
+
196
+ private
197
+
198
+ def strip_shell_command(argv)
199
+ argv.each_with_index do |arg, i|
200
+ if arg == '--'
201
+ @shell_command = argv[(i+1)..-1]
202
+ argv.slice!(i..-1)
203
+ break
228
204
  end
205
+ end
206
+
207
+ return
208
+ end
209
+
210
+ def new_parser
211
+ return OptionParser.new do |parser|
212
+ set_up_queries(parser)
213
+ set_up_commands(parser)
214
+ set_up_package_configuration_source(parser)
215
+ set_up_package_statements(parser)
216
+ set_up_remote_repository_access(parser)
217
+ set_up_program_configuration(parser)
218
+ end
219
+ end
220
+
221
+ def set_up_queries(parser)
222
+ parser.banner = USAGE
223
+ parser.on('-?', '-h','--help','display this help text') do
224
+ help(parser)
225
+ end
229
226
 
230
- level_list = LOG_LEVELS.join(', ')
231
- opts.on(
232
- '--log-level LEVEL',
233
- LOG_LEVELS,
234
- LOG_ALIASES,
235
- 'set logging level to LEVEL',
236
- " (#{level_list})"
237
- ) do |log_level|
238
- options[:log_level] = log_level
227
+ parser.on('-v', '--version', 'Print fig version') do
228
+ version()
229
+ end
230
+
231
+ parser.on(
232
+ '-g',
233
+ '--get VARIABLE',
234
+ 'print value of environment variable VARIABLE'
235
+ ) do |get|
236
+ @options[:get] = get
237
+ end
238
+
239
+ set_up_listings(parser)
240
+
241
+ return
242
+ end
243
+
244
+ def set_up_listings(parser)
245
+ option_mapping = {
246
+ :local_packages =>
247
+ [ '--list-local', '--list', 'list packages in $FIG_HOME' ],
248
+
249
+ :configs =>
250
+ ['--list-configs', 'list configurations'],
251
+
252
+ :dependencies =>
253
+ ['--list-dependencies', 'list package dependencies, recursively'],
254
+
255
+ :variables =>
256
+ [
257
+ '--list-variables',
258
+ 'list all variables defined/used by package and its dependencies'
259
+ ],
260
+
261
+ :remote_packages =>
262
+ ['--list-remote', 'list packages in remote repo']
263
+ }
264
+
265
+ option_mapping.each_pair do
266
+ | type, specification |
267
+
268
+ parser.on(*specification) do
269
+ @options[:listing] = type
239
270
  end
271
+ end
272
+
273
+ parser.on('--list-tree', 'for listings, output a tree instead of a list') do
274
+ @options[:list_tree] = true
275
+ end
276
+
277
+ parser.on('--list-all-configs', 'for listings, follow all configurations of the base package') do
278
+ @options[:list_all_configs] = true
279
+ end
280
+
281
+ return
282
+ end
283
+
284
+ def set_up_commands(parser)
285
+ parser.on('--clean', 'remove package from $FIG_HOME') do
286
+ @options[:clean] = true
287
+ end
288
+
289
+ parser.on(
290
+ '--publish', 'install package in $FIG_HOME and in remote repo'
291
+ ) do |publish|
292
+ @options[:publish] = true
293
+ end
294
+
295
+ parser.on(
296
+ '--publish-local', 'install package only in $FIG_HOME'
297
+ ) do |publish_local|
298
+ @options[:publish_local] = true
299
+ end
300
+
301
+ return
302
+ end
303
+
304
+ def set_up_package_configuration_source(parser)
305
+ parser.on(
306
+ '-c',
307
+ '--config CONFIG',
308
+ %q<apply configuration CONFIG, default is "default">
309
+ ) do |config|
310
+ @options[:config] = config
311
+ end
312
+
313
+ @options[:package_config_file] = nil
314
+ parser.on(
315
+ '--file FILE',
316
+ %q<read fig file FILE. Use '-' for stdin. See also --no-file>
317
+ ) do |path|
318
+ @options[:package_config_file] = path
319
+ end
320
+
321
+ parser.on(
322
+ '--no-file', 'ignore package.fig file in current directory'
323
+ ) do |path|
324
+ @options[:package_config_file] = :none
325
+ end
326
+
327
+ return
328
+ end
329
+
330
+ def set_up_package_statements(parser)
331
+ @options[:non_command_package_statements] = []
332
+ parser.on(
333
+ '-p',
334
+ '--append VARIABLE=VALUE',
335
+ 'append (actually, prepend) VALUE to environment variable VARIABLE, delimited by separator'
336
+ ) do |var_val|
337
+ var, val = var_val.split('=')
338
+ @options[:non_command_package_statements] << Fig::Statement::Path.new(var, val)
339
+ end
340
+
341
+ parser.on(
342
+ '-i',
343
+ '--include DESCRIPTOR',
344
+ 'include package/version:config specified in DESCRIPTOR (with any variable prepends) in environment'
345
+ ) do |descriptor|
346
+ @options[:non_command_package_statements] <<
347
+ Fig::Statement::Include.new(Fig::PackageDescriptor.parse(descriptor), {})
348
+ end
240
349
 
241
- options[:home] = ENV['FIG_HOME'] || File.expand_path('~/.fighome')
350
+ parser.on(
351
+ '-s', '--set VARIABLE=VALUE', 'set environment variable VARIABLE to VALUE'
352
+ ) do |var_val|
353
+ var, val = var_val.split('=')
354
+ @options[:non_command_package_statements] << Fig::Statement::Set.new(var, val)
242
355
  end
243
356
 
244
- # Need to catch the exception thrown from parser and retranslate into a fig exception
357
+ @options[:archives] = []
358
+ parser.on(
359
+ '--archive PATH',
360
+ 'include PATH archive in package (when using --publish)'
361
+ ) do |path|
362
+ @options[:archives] << Fig::Statement::Archive.new(path)
363
+ end
364
+
365
+ @options[:resources] =[]
366
+ parser.on(
367
+ '--resource PATH',
368
+ 'include PATH resource in package (when using --publish)'
369
+ ) do |path|
370
+ @options[:resources] << Fig::Statement::Resource.new(path)
371
+ end
372
+
373
+ return
374
+ end
375
+
376
+ def set_up_remote_repository_access(parser)
377
+ parser.on(
378
+ '-u',
379
+ '--update',
380
+ 'check remote repo for updates and download to $FIG_HOME as necessary'
381
+ ) do
382
+ @options[:update] = true
383
+ end
384
+
385
+ parser.on(
386
+ '-m',
387
+ '--update-if-missing',
388
+ 'check remote repo for updates only if package missing from $FIG_HOME'
389
+ ) do
390
+ @options[:update_if_missing] = true
391
+ end
392
+
393
+ parser.on(
394
+ '-l', '--login', 'login to remote repo as a non-anonymous user'
395
+ ) do
396
+ @options[:login] = true
397
+ end
398
+
399
+ @options[:force] = nil
400
+ parser.on(
401
+ '--force',
402
+ 'force-overwrite existing version of a package to the remote repo'
403
+ ) do |force|
404
+ @options[:force] = force
405
+ end
406
+
407
+ return
408
+ end
409
+
410
+ def set_up_program_configuration(parser)
411
+ parser.on(
412
+ '--figrc PATH', 'add PATH to configuration used for Fig'
413
+ ) do |path|
414
+ @options[:figrc] = path
415
+ end
416
+
417
+ parser.on('--no-figrc', 'ignore ~/.figrc') { @options[:no_figrc] = true }
418
+
419
+ parser.on(
420
+ '--log-config PATH', 'use PATH file as configuration for Log4r'
421
+ ) do |path|
422
+ @options[:log_config] = path
423
+ end
424
+
425
+ level_list = LOG_LEVELS.join(', ')
426
+ parser.on(
427
+ '--log-level LEVEL',
428
+ LOG_LEVELS,
429
+ LOG_ALIASES,
430
+ 'set logging level to LEVEL',
431
+ " (#{level_list})"
432
+ ) do |log_level|
433
+ @options[:log_level] = log_level
434
+ end
435
+
436
+ return
437
+ end
438
+
439
+ def help(parser)
440
+ puts parser.help
441
+ puts " -- end of fig options; anything after this is used as a command to run\n\n"
442
+
443
+ @exit_code = 0
444
+
445
+ return
446
+ end
447
+
448
+ def version()
449
+ line = nil
450
+
245
451
  begin
246
- parser.parse!(argv)
247
- rescue OptionParser::MissingArgument => error
248
- $stderr.puts "Please provide the #{error}."
249
- return nil, nil, 1
452
+ File.open(
453
+ "#{File.expand_path(File.dirname(__FILE__) + '/../../VERSION')}"
454
+ ) do |file|
455
+ line = file.gets
456
+ end
457
+ rescue
458
+ $stderr.puts 'Could not retrieve version number. Something has mucked with your fig install.'
459
+
460
+ @exit_code = 1
461
+ return
250
462
  end
251
463
 
252
- return options, argv, nil
464
+ if line !~ /\d+\.\d+\.\d+/
465
+ $stderr.puts %Q<"#{line}" does not look like a version number. Something has mucked with your fig install.>
466
+
467
+ @exit_code = 1
468
+ return
469
+ end
470
+
471
+ puts File.basename($0) + ' v' + line
472
+
473
+ @exit_code = 0
474
+ return
253
475
  end
254
476
  end