fig 1.1.0 → 1.2.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.
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