fig 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/Changes +94 -0
  2. data/lib/fig.rb +1 -1
  3. data/lib/fig/command.rb +18 -7
  4. data/lib/fig/command/action/dump_package_definition_for_command_line.rb +2 -2
  5. data/lib/fig/command/action/dump_package_definition_parsed.rb +2 -2
  6. data/lib/fig/command/action/dump_package_definition_text.rb +2 -2
  7. data/lib/fig/command/action/source_package.rb +65 -0
  8. data/lib/fig/command/options.rb +64 -15
  9. data/lib/fig/command/options/parser.rb +24 -14
  10. data/lib/fig/command/package_applier.rb +32 -7
  11. data/lib/fig/command/package_loader.rb +16 -7
  12. data/lib/fig/external_program.rb +72 -0
  13. data/lib/fig/figrc.rb +1 -1
  14. data/lib/fig/grammar/v0.rb +2 -2
  15. data/lib/fig/grammar/v0.treetop +2 -2
  16. data/lib/fig/grammar/v1.rb +17 -1737
  17. data/lib/fig/grammar/v1.treetop +6 -217
  18. data/lib/fig/grammar/v1_base.rb +1750 -0
  19. data/lib/fig/grammar/v1_base.treetop +229 -0
  20. data/lib/fig/grammar/v2.rb +508 -0
  21. data/lib/fig/grammar/v2.treetop +65 -0
  22. data/lib/fig/grammar_monkey_patches.rb +7 -0
  23. data/lib/fig/no_such_package_config_error.rb +3 -1
  24. data/lib/fig/not_yet_parsed_package.rb +27 -0
  25. data/lib/fig/operating_system.rb +5 -5
  26. data/lib/fig/package.rb +20 -2
  27. data/lib/fig/package_definition_text_assembler.rb +2 -1
  28. data/lib/fig/package_descriptor.rb +11 -4
  29. data/lib/fig/parser.rb +44 -58
  30. data/lib/fig/parser_package_build_state.rb +39 -4
  31. data/lib/fig/protocol/file.rb +2 -2
  32. data/lib/fig/protocol/ftp.rb +15 -10
  33. data/lib/fig/protocol/http.rb +1 -1
  34. data/lib/fig/protocol/netrc_enabled.rb +29 -16
  35. data/lib/fig/protocol/sftp.rb +19 -12
  36. data/lib/fig/repository.rb +33 -21
  37. data/lib/fig/repository_package_publisher.rb +129 -8
  38. data/lib/fig/runtime_environment.rb +114 -28
  39. data/lib/fig/statement/include.rb +21 -4
  40. data/lib/fig/statement/include_file.rb +94 -0
  41. data/lib/fig/unparser.rb +15 -7
  42. data/lib/fig/unparser/v1.rb +2 -80
  43. data/lib/fig/unparser/v1_base.rb +85 -0
  44. data/lib/fig/unparser/v2.rb +55 -0
  45. data/lib/fig/working_directory_maintainer.rb +12 -0
  46. metadata +61 -51
@@ -0,0 +1,229 @@
1
+ # Reusable parts of Treetop (http://treetop.rubyforge.org/) grammar for package
2
+ # definitions in v1 format.
3
+
4
+ # Some aspects of this grammar are significantly dumber than they could be
5
+ # because:
6
+ #
7
+ # * We want to treat statements as identically as possible to their
8
+ # command-line equivalents.
9
+ # * Treetop parse errors are pretty inscrutable at times and we can make
10
+ # error messages clearer by validating a lot of the terminals ourselves.
11
+
12
+ require 'treetop'
13
+
14
+ module Fig
15
+ module Grammar
16
+ # Consumers of this need to mix in Fig::Grammar::Base and
17
+ # Fig::Grammar::Version and have a "rule config_statement".
18
+ grammar V1Base
19
+ # Shim between "package" and "package_statement" rules to allow the
20
+ # compiled v0 and v1 grammars to have the same interface.
21
+ rule package_statement_with_ws
22
+ package_statement:package_statement ws_or_comment+ {
23
+ def to_package_statement(build_state)
24
+ return package_statement.to_package_statement(build_state)
25
+ end
26
+ }
27
+ end
28
+
29
+ rule package_statement
30
+ archive / resource / retrieve / config
31
+ end
32
+
33
+ rule archive
34
+ statement_start:'archive'
35
+ ws_or_comment+
36
+ location:quoted_or_bare_string
37
+ {
38
+ def to_package_statement(build_state)
39
+ return build_state.new_asset_statement(
40
+ Statement::Archive, statement_start, location
41
+ )
42
+ end
43
+ }
44
+ end
45
+
46
+ rule resource
47
+ statement_start:'resource'
48
+ ws_or_comment+
49
+ location:quoted_or_bare_string
50
+ {
51
+ def to_package_statement(build_state)
52
+ return build_state.new_asset_statement(
53
+ Statement::Resource, statement_start, location
54
+ )
55
+ end
56
+ }
57
+ end
58
+
59
+ rule retrieve
60
+ statement_start:'retrieve'
61
+ ws_or_comment+
62
+ variable:environment_variable_name '->' path:quoted_or_bare_string
63
+ {
64
+ def to_package_statement(build_state)
65
+ return build_state.new_retrieve_statement(
66
+ statement_start, variable, path
67
+ )
68
+ end
69
+ }
70
+ end
71
+
72
+ rule config
73
+ statement_start:'config'
74
+ ws_or_comment+
75
+ config_name
76
+ ws_or_comment+
77
+ statements:config_statement_with_ws*
78
+ 'end'
79
+ {
80
+ def to_package_statement(build_state)
81
+ return build_state.new_configuration_statement(
82
+ statement_start, config_name, statements
83
+ )
84
+ end
85
+ }
86
+ end
87
+
88
+ # Shim between "config" and "config_statement" rules to allow the
89
+ # compiled v0 and v1 grammars to have the same interface.
90
+ rule config_statement_with_ws
91
+ config_statement:config_statement ws_or_comment+ {
92
+ def to_config_statement(build_state)
93
+ return config_statement.to_config_statement(build_state)
94
+ end
95
+ }
96
+ end
97
+
98
+ # Need rule config_statement
99
+
100
+ rule include
101
+ statement_start:'include' ws_or_comment+ descriptor_string {
102
+ def to_config_statement(build_state)
103
+ return build_state.new_include_statement(
104
+ statement_start, descriptor_string
105
+ )
106
+ end
107
+ }
108
+ end
109
+
110
+ rule override
111
+ statement_start:'override' ws_or_comment+ descriptor_string {
112
+ def to_config_statement(build_state)
113
+ return build_state.new_override_statement(
114
+ statement_start, descriptor_string
115
+ )
116
+ end
117
+ }
118
+ end
119
+
120
+ rule set
121
+ statement_start:'set' ws_or_comment+ environment_variable_name_value {
122
+ def to_config_statement(build_state)
123
+ return build_state.new_environment_variable_statement(
124
+ Statement::Set, statement_start, environment_variable_name_value
125
+ )
126
+ end
127
+ }
128
+ end
129
+
130
+ rule path
131
+ statement_start:('add' / 'append' / 'path')
132
+ ws_or_comment+
133
+ environment_variable_name_value
134
+ {
135
+ def to_config_statement(build_state)
136
+ return build_state.new_environment_variable_statement(
137
+ Statement::Path, statement_start, environment_variable_name_value
138
+ )
139
+ end
140
+ }
141
+ end
142
+
143
+ rule command
144
+ statement_start:'command'
145
+ ws_or_comment+
146
+ command_line
147
+ ws_or_comment+
148
+ 'end'
149
+ {
150
+ def to_config_statement(build_state)
151
+ return build_state.new_v1_command_statement(
152
+ statement_start, gather_command_argument_nodes(command_line)
153
+ )
154
+ end
155
+
156
+ def gather_command_argument_nodes(node, arguments = [])
157
+ if node.respond_to? 'quoted_or_bare_string?'
158
+ arguments << node
159
+ return arguments
160
+ end
161
+
162
+ return arguments if not node.elements
163
+
164
+ node.elements.each do
165
+ |element|
166
+ gather_command_argument_nodes(element, arguments)
167
+ end
168
+
169
+ return arguments
170
+ end
171
+ }
172
+ end
173
+
174
+ rule command_line
175
+ quoted_or_bare_string
176
+ ! { |sequence| sequence[-1].text_value == 'end' }
177
+ (
178
+ ws_or_comment+
179
+ quoted_or_bare_string
180
+ ! { |sequence| sequence[-1].text_value == 'end' }
181
+ )*
182
+ end
183
+
184
+ # Terminals
185
+
186
+ rule descriptor_string
187
+ [^\s#]+
188
+ end
189
+
190
+ rule config_name
191
+ [a-zA-Z0-9_.-]+
192
+ end
193
+
194
+ rule quoted_or_bare_string
195
+ # In order to deal with the hierarchy of nodes that the command_line
196
+ # rule above generates, we tag each of the expressions here so that
197
+ # they can be found in the syntax tree.
198
+ [^\s#\\"]* '"' ( [^"\\] / '\\' . )* '"'
199
+ { def quoted_or_bare_string?() return true end }
200
+
201
+ /
202
+
203
+ [^\s#\\']* "'" ( [^'\\] / '\\' . )* "'"
204
+ { def quoted_or_bare_string?() return true end }
205
+
206
+ /
207
+
208
+ [^\s#]+
209
+ { def quoted_or_bare_string?() return true end }
210
+ end
211
+
212
+ rule environment_variable_name
213
+ [a-zA-Z0-9_]+
214
+ end
215
+
216
+ rule environment_variable_name_value
217
+ # This is like quoted_or_bare_string, but allows for the unquoted
218
+ # variable name followed by equals sign prior to the quotation marks
219
+ # coming in.
220
+ #
221
+ # Should result in somewhat reasonable handling by Treetop when
222
+ # encountering mis-quoted constructs.
223
+ [^\s#\\'"]* '"' ( [^"\\] / '\\' . )* '"' /
224
+ [^\s#\\'"]* "'" ( [^'\\] / '\\' . )* "'" /
225
+ [^\s#]+
226
+ end
227
+ end
228
+ end
229
+ end
@@ -0,0 +1,508 @@
1
+ # Autogenerated from a Treetop grammar. Edits may be lost.
2
+
3
+
4
+ # Treetop (http://treetop.rubyforge.org/) grammar for package definitions in v2
5
+ # format.
6
+
7
+ require 'treetop'
8
+
9
+ require 'fig/grammar/base'
10
+ require 'fig/grammar/v1_base'
11
+ require 'fig/grammar/version'
12
+
13
+ module Fig
14
+ module Grammar
15
+ module V2
16
+ include Treetop::Runtime
17
+
18
+ def root
19
+ @root ||= :package
20
+ end
21
+
22
+ include Fig::Grammar::Base
23
+
24
+ include Fig::Grammar::Version
25
+
26
+ include Fig::Grammar::V1Base
27
+
28
+ module Package0
29
+ def optional_ws_or_comment1
30
+ elements[0]
31
+ end
32
+
33
+ def grammar_version
34
+ elements[1]
35
+ end
36
+
37
+ def statements
38
+ elements[2]
39
+ end
40
+
41
+ def optional_ws_or_comment2
42
+ elements[3]
43
+ end
44
+ end
45
+
46
+ module Package1
47
+ def to_package(unparsed_package, build_state)
48
+ return build_state.new_package_statement(
49
+ unparsed_package, grammar_version, statements
50
+ )
51
+ end
52
+ end
53
+
54
+ def _nt_package
55
+ start_index = index
56
+ if node_cache[:package].has_key?(index)
57
+ cached = node_cache[:package][index]
58
+ if cached
59
+ cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
60
+ @index = cached.interval.end
61
+ end
62
+ return cached
63
+ end
64
+
65
+ i0, s0 = index, []
66
+ r1 = _nt_optional_ws_or_comment
67
+ s0 << r1
68
+ if r1
69
+ r3 = _nt_grammar_version
70
+ if r3
71
+ r2 = r3
72
+ else
73
+ r2 = instantiate_node(SyntaxNode,input, index...index)
74
+ end
75
+ s0 << r2
76
+ if r2
77
+ s4, i4 = [], index
78
+ loop do
79
+ r5 = _nt_package_statement_with_ws
80
+ if r5
81
+ s4 << r5
82
+ else
83
+ break
84
+ end
85
+ end
86
+ r4 = instantiate_node(SyntaxNode,input, i4...index, s4)
87
+ s0 << r4
88
+ if r4
89
+ r6 = _nt_optional_ws_or_comment
90
+ s0 << r6
91
+ end
92
+ end
93
+ end
94
+ if s0.last
95
+ r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
96
+ r0.extend(Package0)
97
+ r0.extend(Package1)
98
+ else
99
+ @index = i0
100
+ r0 = nil
101
+ end
102
+
103
+ node_cache[:package][start_index] = r0
104
+
105
+ r0
106
+ end
107
+
108
+ def _nt_config_statement
109
+ start_index = index
110
+ if node_cache[:config_statement].has_key?(index)
111
+ cached = node_cache[:config_statement][index]
112
+ if cached
113
+ cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
114
+ @index = cached.interval.end
115
+ end
116
+ return cached
117
+ end
118
+
119
+ i0 = index
120
+ r1 = _nt_override
121
+ if r1
122
+ r0 = r1
123
+ else
124
+ r2 = _nt_include
125
+ if r2
126
+ r0 = r2
127
+ else
128
+ r3 = _nt_include_file
129
+ if r3
130
+ r0 = r3
131
+ else
132
+ r4 = _nt_command
133
+ if r4
134
+ r0 = r4
135
+ else
136
+ r5 = _nt_path
137
+ if r5
138
+ r0 = r5
139
+ else
140
+ r6 = _nt_set
141
+ if r6
142
+ r0 = r6
143
+ else
144
+ @index = i0
145
+ r0 = nil
146
+ end
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
152
+
153
+ node_cache[:config_statement][start_index] = r0
154
+
155
+ r0
156
+ end
157
+
158
+ module IncludeFile0
159
+ def config_name
160
+ elements[1]
161
+ end
162
+ end
163
+
164
+ module IncludeFile1
165
+ def statement_start
166
+ elements[0]
167
+ end
168
+
169
+ def path
170
+ elements[2]
171
+ end
172
+
173
+ def config
174
+ elements[3]
175
+ end
176
+ end
177
+
178
+ module IncludeFile2
179
+ def to_config_statement(build_state)
180
+ config_name = nil
181
+ if config.respond_to? :config_name
182
+ config_name = config.config_name
183
+ end
184
+
185
+ return build_state.new_include_file_statement(
186
+ statement_start, path, config_name
187
+ )
188
+ end
189
+ end
190
+
191
+ def _nt_include_file
192
+ start_index = index
193
+ if node_cache[:include_file].has_key?(index)
194
+ cached = node_cache[:include_file][index]
195
+ if cached
196
+ cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
197
+ @index = cached.interval.end
198
+ end
199
+ return cached
200
+ end
201
+
202
+ i0, s0 = index, []
203
+ if has_terminal?('include-file', false, index)
204
+ r1 = instantiate_node(SyntaxNode,input, index...(index + 12))
205
+ @index += 12
206
+ else
207
+ terminal_parse_failure('include-file')
208
+ r1 = nil
209
+ end
210
+ s0 << r1
211
+ if r1
212
+ s2, i2 = [], index
213
+ loop do
214
+ r3 = _nt_ws_or_comment
215
+ if r3
216
+ s2 << r3
217
+ else
218
+ break
219
+ end
220
+ end
221
+ if s2.empty?
222
+ @index = i2
223
+ r2 = nil
224
+ else
225
+ r2 = instantiate_node(SyntaxNode,input, i2...index, s2)
226
+ end
227
+ s0 << r2
228
+ if r2
229
+ r4 = _nt_file_path
230
+ s0 << r4
231
+ if r4
232
+ i6, s6 = index, []
233
+ if has_terminal?(':', false, index)
234
+ r7 = instantiate_node(SyntaxNode,input, index...(index + 1))
235
+ @index += 1
236
+ else
237
+ terminal_parse_failure(':')
238
+ r7 = nil
239
+ end
240
+ s6 << r7
241
+ if r7
242
+ r8 = _nt_config_name
243
+ s6 << r8
244
+ end
245
+ if s6.last
246
+ r6 = instantiate_node(SyntaxNode,input, i6...index, s6)
247
+ r6.extend(IncludeFile0)
248
+ else
249
+ @index = i6
250
+ r6 = nil
251
+ end
252
+ if r6
253
+ r5 = r6
254
+ else
255
+ r5 = instantiate_node(SyntaxNode,input, index...index)
256
+ end
257
+ s0 << r5
258
+ end
259
+ end
260
+ end
261
+ if s0.last
262
+ r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
263
+ r0.extend(IncludeFile1)
264
+ r0.extend(IncludeFile2)
265
+ else
266
+ @index = i0
267
+ r0 = nil
268
+ end
269
+
270
+ node_cache[:include_file][start_index] = r0
271
+
272
+ r0
273
+ end
274
+
275
+ module FilePath0
276
+ end
277
+
278
+ module FilePath1
279
+ end
280
+
281
+ module FilePath2
282
+ end
283
+
284
+ module FilePath3
285
+ end
286
+
287
+ def _nt_file_path
288
+ start_index = index
289
+ if node_cache[:file_path].has_key?(index)
290
+ cached = node_cache[:file_path][index]
291
+ if cached
292
+ cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
293
+ @index = cached.interval.end
294
+ end
295
+ return cached
296
+ end
297
+
298
+ i0 = index
299
+ i1, s1 = index, []
300
+ if has_terminal?('"', false, index)
301
+ r2 = instantiate_node(SyntaxNode,input, index...(index + 1))
302
+ @index += 1
303
+ else
304
+ terminal_parse_failure('"')
305
+ r2 = nil
306
+ end
307
+ s1 << r2
308
+ if r2
309
+ s3, i3 = [], index
310
+ loop do
311
+ i4 = index
312
+ if has_terminal?('\G[^"\\\\]', true, index)
313
+ r5 = true
314
+ @index += 1
315
+ else
316
+ r5 = nil
317
+ end
318
+ if r5
319
+ r4 = r5
320
+ else
321
+ i6, s6 = index, []
322
+ if has_terminal?('\\', false, index)
323
+ r7 = instantiate_node(SyntaxNode,input, index...(index + 1))
324
+ @index += 1
325
+ else
326
+ terminal_parse_failure('\\')
327
+ r7 = nil
328
+ end
329
+ s6 << r7
330
+ if r7
331
+ if index < input_length
332
+ r8 = instantiate_node(SyntaxNode,input, index...(index + 1))
333
+ @index += 1
334
+ else
335
+ terminal_parse_failure("any character")
336
+ r8 = nil
337
+ end
338
+ s6 << r8
339
+ end
340
+ if s6.last
341
+ r6 = instantiate_node(SyntaxNode,input, i6...index, s6)
342
+ r6.extend(FilePath0)
343
+ else
344
+ @index = i6
345
+ r6 = nil
346
+ end
347
+ if r6
348
+ r4 = r6
349
+ else
350
+ @index = i4
351
+ r4 = nil
352
+ end
353
+ end
354
+ if r4
355
+ s3 << r4
356
+ else
357
+ break
358
+ end
359
+ end
360
+ r3 = instantiate_node(SyntaxNode,input, i3...index, s3)
361
+ s1 << r3
362
+ if r3
363
+ if has_terminal?('"', false, index)
364
+ r9 = instantiate_node(SyntaxNode,input, index...(index + 1))
365
+ @index += 1
366
+ else
367
+ terminal_parse_failure('"')
368
+ r9 = nil
369
+ end
370
+ s1 << r9
371
+ end
372
+ end
373
+ if s1.last
374
+ r1 = instantiate_node(SyntaxNode,input, i1...index, s1)
375
+ r1.extend(FilePath1)
376
+ else
377
+ @index = i1
378
+ r1 = nil
379
+ end
380
+ if r1
381
+ r0 = r1
382
+ else
383
+ i10, s10 = index, []
384
+ if has_terminal?("'", false, index)
385
+ r11 = instantiate_node(SyntaxNode,input, index...(index + 1))
386
+ @index += 1
387
+ else
388
+ terminal_parse_failure("'")
389
+ r11 = nil
390
+ end
391
+ s10 << r11
392
+ if r11
393
+ s12, i12 = [], index
394
+ loop do
395
+ i13 = index
396
+ if has_terminal?('\G[^\'\\\\]', true, index)
397
+ r14 = true
398
+ @index += 1
399
+ else
400
+ r14 = nil
401
+ end
402
+ if r14
403
+ r13 = r14
404
+ else
405
+ i15, s15 = index, []
406
+ if has_terminal?('\\', false, index)
407
+ r16 = instantiate_node(SyntaxNode,input, index...(index + 1))
408
+ @index += 1
409
+ else
410
+ terminal_parse_failure('\\')
411
+ r16 = nil
412
+ end
413
+ s15 << r16
414
+ if r16
415
+ if index < input_length
416
+ r17 = instantiate_node(SyntaxNode,input, index...(index + 1))
417
+ @index += 1
418
+ else
419
+ terminal_parse_failure("any character")
420
+ r17 = nil
421
+ end
422
+ s15 << r17
423
+ end
424
+ if s15.last
425
+ r15 = instantiate_node(SyntaxNode,input, i15...index, s15)
426
+ r15.extend(FilePath2)
427
+ else
428
+ @index = i15
429
+ r15 = nil
430
+ end
431
+ if r15
432
+ r13 = r15
433
+ else
434
+ @index = i13
435
+ r13 = nil
436
+ end
437
+ end
438
+ if r13
439
+ s12 << r13
440
+ else
441
+ break
442
+ end
443
+ end
444
+ r12 = instantiate_node(SyntaxNode,input, i12...index, s12)
445
+ s10 << r12
446
+ if r12
447
+ if has_terminal?("'", false, index)
448
+ r18 = instantiate_node(SyntaxNode,input, index...(index + 1))
449
+ @index += 1
450
+ else
451
+ terminal_parse_failure("'")
452
+ r18 = nil
453
+ end
454
+ s10 << r18
455
+ end
456
+ end
457
+ if s10.last
458
+ r10 = instantiate_node(SyntaxNode,input, i10...index, s10)
459
+ r10.extend(FilePath3)
460
+ else
461
+ @index = i10
462
+ r10 = nil
463
+ end
464
+ if r10
465
+ r0 = r10
466
+ else
467
+ s19, i19 = [], index
468
+ loop do
469
+ if has_terminal?('\G[^\\s#:]', true, index)
470
+ r20 = true
471
+ @index += 1
472
+ else
473
+ r20 = nil
474
+ end
475
+ if r20
476
+ s19 << r20
477
+ else
478
+ break
479
+ end
480
+ end
481
+ if s19.empty?
482
+ @index = i19
483
+ r19 = nil
484
+ else
485
+ r19 = instantiate_node(SyntaxNode,input, i19...index, s19)
486
+ end
487
+ if r19
488
+ r0 = r19
489
+ else
490
+ @index = i0
491
+ r0 = nil
492
+ end
493
+ end
494
+ end
495
+
496
+ node_cache[:file_path][start_index] = r0
497
+
498
+ r0
499
+ end
500
+
501
+ end
502
+
503
+ class V2Parser < Treetop::Runtime::CompiledParser
504
+ include V2
505
+ end
506
+
507
+ end
508
+ end