fig 0.1.81 → 0.2.1
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.
- data/Changes +87 -0
- data/lib/fig.rb +1 -1
- data/lib/fig/command.rb +5 -0
- data/lib/fig/command/action/dump_package_definition_for_command_line.rb +62 -0
- data/lib/fig/command/action/dump_package_definition_parsed.rb +19 -2
- data/lib/fig/command/action/list_local.rb +9 -1
- data/lib/fig/command/action/list_remote.rb +9 -1
- data/lib/fig/command/action/role/list_variables_in_a_tree.rb +1 -1
- data/lib/fig/command/action/run_command_line.rb +1 -1
- data/lib/fig/command/action/run_command_statement.rb +4 -2
- data/lib/fig/command/options.rb +50 -18
- data/lib/fig/command/options/parser.rb +16 -15
- data/lib/fig/command/package_applier.rb +5 -3
- data/lib/fig/grammar/v0.rb +287 -289
- data/lib/fig/grammar/v0.treetop +66 -42
- data/lib/fig/grammar/v1.rb +629 -533
- data/lib/fig/grammar/v1.treetop +102 -39
- data/lib/fig/grammar_monkey_patches.rb +21 -0
- data/lib/fig/operating_system.rb +53 -36
- data/lib/fig/package_descriptor.rb +1 -12
- data/lib/fig/parser.rb +8 -33
- data/lib/fig/parser_package_build_state.rb +92 -31
- data/lib/fig/repository_package_publisher.rb +2 -2
- data/lib/fig/runtime_environment.rb +54 -120
- data/lib/fig/statement.rb +6 -6
- data/lib/fig/statement/asset.rb +1 -13
- data/lib/fig/statement/command.rb +47 -0
- data/lib/fig/statement/environment_variable.rb +64 -3
- data/lib/fig/statement/grammar_version.rb +4 -0
- data/lib/fig/statement/include.rb +4 -0
- data/lib/fig/statement/override.rb +4 -0
- data/lib/fig/statement/path.rb +40 -16
- data/lib/fig/statement/retrieve.rb +61 -5
- data/lib/fig/statement/set.rb +16 -19
- data/lib/fig/string_tokenizer.rb +63 -25
- data/lib/fig/tokenized_string.rb +31 -5
- data/lib/fig/tokenized_string/plain_segment.rb +32 -2
- data/lib/fig/tokenized_string/token.rb +12 -0
- data/lib/fig/unparser.rb +27 -12
- data/lib/fig/unparser/v0.rb +4 -5
- data/lib/fig/unparser/v1.rb +43 -6
- data/lib/fig/url.rb +13 -0
- metadata +44 -42
@@ -14,11 +14,10 @@ require 'fig/statement/set'
|
|
14
14
|
|
15
15
|
module Fig; end
|
16
16
|
|
17
|
+
# The state of a Package while it is being built by a Parser.
|
17
18
|
class Fig::ParserPackageBuildState
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
def initialize(descriptor, source_description)
|
19
|
+
def initialize(grammar_version, descriptor, source_description)
|
20
|
+
@grammar_version = grammar_version
|
22
21
|
@descriptor = descriptor
|
23
22
|
@source_description = source_description
|
24
23
|
end
|
@@ -40,7 +39,7 @@ class Fig::ParserPackageBuildState
|
|
40
39
|
location = node_location(node)
|
41
40
|
|
42
41
|
return Fig::Statement.position_description(
|
43
|
-
location[0], location[1], source_description
|
42
|
+
location[0], location[1], @source_description
|
44
43
|
)
|
45
44
|
end
|
46
45
|
|
@@ -64,8 +63,8 @@ class Fig::ParserPackageBuildState
|
|
64
63
|
end
|
65
64
|
|
66
65
|
return Fig::Package.new(
|
67
|
-
descriptor.name,
|
68
|
-
descriptor.version,
|
66
|
+
@descriptor.name,
|
67
|
+
@descriptor.version,
|
69
68
|
directory,
|
70
69
|
statement_objects
|
71
70
|
)
|
@@ -74,7 +73,7 @@ class Fig::ParserPackageBuildState
|
|
74
73
|
def new_grammar_version_statement(keyword_node, version_node)
|
75
74
|
return Fig::Statement::GrammarVersion.new(
|
76
75
|
node_location(keyword_node),
|
77
|
-
source_description,
|
76
|
+
@source_description,
|
78
77
|
version_node.text_value.to_i
|
79
78
|
)
|
80
79
|
end
|
@@ -94,26 +93,29 @@ class Fig::ParserPackageBuildState
|
|
94
93
|
location = tokenized_location.to_expanded_string
|
95
94
|
need_to_glob = ! tokenized_location.single_quoted?
|
96
95
|
return statement_class.new(
|
97
|
-
node_location(keyword_node), source_description, location, need_to_glob
|
96
|
+
node_location(keyword_node), @source_description, location, need_to_glob
|
98
97
|
)
|
99
98
|
end
|
100
99
|
|
101
100
|
def new_retrieve_statement(keyword_node, variable_name_node, path_node)
|
101
|
+
tokenized_path =
|
102
|
+
Fig::Statement::Retrieve.tokenize_path(path_node.text_value) do
|
103
|
+
|error_description|
|
104
|
+
|
105
|
+
raise_invalid_value_parse_error(
|
106
|
+
keyword_node, path_node, 'path', error_description
|
107
|
+
)
|
108
|
+
end
|
109
|
+
|
102
110
|
return Fig::Statement::Retrieve.new(
|
103
111
|
node_location(keyword_node),
|
104
|
-
source_description,
|
112
|
+
@source_description,
|
105
113
|
variable_name_node.text_value,
|
106
|
-
|
114
|
+
tokenized_path
|
107
115
|
)
|
108
116
|
end
|
109
117
|
|
110
118
|
def new_configuration_statement(keyword_node, name_node, statements)
|
111
|
-
if Fig::Parser.strict_keyword? name_node.text_value
|
112
|
-
raise_invalid_value_parse_error(
|
113
|
-
keyword_node, name_node, 'name', 'is a keyword.'
|
114
|
-
)
|
115
|
-
end
|
116
|
-
|
117
119
|
statement_objects = statements.elements.map do
|
118
120
|
|statement|
|
119
121
|
|
@@ -122,7 +124,7 @@ class Fig::ParserPackageBuildState
|
|
122
124
|
|
123
125
|
return Fig::Statement::Configuration.new(
|
124
126
|
node_location(keyword_node),
|
125
|
-
source_description,
|
127
|
+
@source_description,
|
126
128
|
name_node.text_value,
|
127
129
|
statement_objects
|
128
130
|
)
|
@@ -138,9 +140,9 @@ class Fig::ParserPackageBuildState
|
|
138
140
|
|
139
141
|
return Fig::Statement::Include.new(
|
140
142
|
node_location(keyword_node),
|
141
|
-
source_description,
|
143
|
+
@source_description,
|
142
144
|
include_descriptor,
|
143
|
-
descriptor
|
145
|
+
@descriptor
|
144
146
|
)
|
145
147
|
end
|
146
148
|
|
@@ -154,7 +156,7 @@ class Fig::ParserPackageBuildState
|
|
154
156
|
|
155
157
|
return Fig::Statement::Override.new(
|
156
158
|
node_location(keyword_node),
|
157
|
-
source_description,
|
159
|
+
@source_description,
|
158
160
|
override_descriptor.name,
|
159
161
|
override_descriptor.version
|
160
162
|
)
|
@@ -163,25 +165,55 @@ class Fig::ParserPackageBuildState
|
|
163
165
|
def new_environment_variable_statement(
|
164
166
|
statement_class, keyword_node, value_node
|
165
167
|
)
|
166
|
-
name
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
168
|
+
name = value = nil
|
169
|
+
|
170
|
+
if @grammar_version == 0
|
171
|
+
name, value = statement_class.parse_v0_name_value(value_node.text_value) {
|
172
|
+
|description|
|
173
|
+
raise_invalid_statement_parse_error(
|
174
|
+
keyword_node, value_node, description
|
175
|
+
)
|
176
|
+
}
|
177
|
+
else
|
178
|
+
name, value = statement_class.parse_name_value(value_node.text_value) {
|
179
|
+
|description|
|
180
|
+
raise_invalid_statement_parse_error(
|
181
|
+
keyword_node, value_node, description
|
182
|
+
)
|
183
|
+
}
|
184
|
+
end
|
185
|
+
|
172
186
|
return statement_class.new(
|
173
|
-
node_location(keyword_node), source_description, name, value
|
187
|
+
node_location(keyword_node), @source_description, name, value
|
174
188
|
)
|
175
189
|
end
|
176
190
|
|
177
|
-
def
|
191
|
+
def new_v0_command_statement(keyword_node, command_line_node)
|
192
|
+
tokenized_command =
|
193
|
+
Fig::Statement::Command.validate_and_process_escapes_in_argument(
|
194
|
+
command_line_node.text_value
|
195
|
+
) {
|
196
|
+
|description|
|
197
|
+
raise_invalid_statement_parse_error(
|
198
|
+
keyword_node, command_line_node, description
|
199
|
+
)
|
200
|
+
}
|
201
|
+
|
202
|
+
return Fig::Statement::Command.new(
|
203
|
+
node_location(keyword_node), @source_description, [tokenized_command]
|
204
|
+
)
|
205
|
+
end
|
206
|
+
|
207
|
+
def new_v1_command_statement(keyword_node, command_line)
|
178
208
|
return Fig::Statement::Command.new(
|
179
209
|
node_location(keyword_node),
|
180
|
-
source_description,
|
181
|
-
|
210
|
+
@source_description,
|
211
|
+
tokenize_v1_command_line(keyword_node, command_line)
|
182
212
|
)
|
183
213
|
end
|
184
214
|
|
215
|
+
private
|
216
|
+
|
185
217
|
def raise_invalid_value_parse_error(
|
186
218
|
keyword_node, value_node, value_name, description
|
187
219
|
)
|
@@ -189,4 +221,33 @@ class Fig::ParserPackageBuildState
|
|
189
221
|
%Q<Invalid #{value_name} for #{keyword_node.text_value} statement: "#{value_node.text_value}" #{description}#{node_location_description(value_node)}>
|
190
222
|
)
|
191
223
|
end
|
224
|
+
|
225
|
+
def raise_invalid_statement_parse_error(keyword_node, value_node, description)
|
226
|
+
raise Fig::PackageParseError.new(
|
227
|
+
%Q<Invalid #{keyword_node.text_value} statement: "#{value_node.text_value}" #{description}#{node_location_description(value_node)}>
|
228
|
+
)
|
229
|
+
end
|
230
|
+
|
231
|
+
def tokenize_v1_command_line(keyword_node, command_line)
|
232
|
+
tokenized_command_line = []
|
233
|
+
|
234
|
+
command_line.each do
|
235
|
+
|argument_node|
|
236
|
+
|
237
|
+
unparsed = argument_node.text_value
|
238
|
+
next if unparsed.empty?
|
239
|
+
|
240
|
+
tokenized_command_line <<
|
241
|
+
Fig::Statement::Command.validate_and_process_escapes_in_argument(
|
242
|
+
unparsed
|
243
|
+
) {
|
244
|
+
|description|
|
245
|
+
raise_invalid_statement_parse_error(
|
246
|
+
keyword_node, argument_node, description
|
247
|
+
)
|
248
|
+
}
|
249
|
+
end
|
250
|
+
|
251
|
+
return tokenized_command_line
|
252
|
+
end
|
192
253
|
end
|
@@ -113,8 +113,8 @@ class Fig::RepositoryPackagePublisher
|
|
113
113
|
add_unparsed_text()
|
114
114
|
|
115
115
|
file_content, explanations = @text_assembler.assemble_package_definition()
|
116
|
-
if Fig::Logging.
|
117
|
-
explanations.each {|explanation| Fig::Logging.
|
116
|
+
if Fig::Logging.info?
|
117
|
+
explanations.each {|explanation| Fig::Logging.info explanation}
|
118
118
|
end
|
119
119
|
|
120
120
|
begin
|
@@ -42,7 +42,7 @@ class Fig::RuntimeEnvironment
|
|
42
42
|
# Indicates that the values from a particular environment variable path
|
43
43
|
# should be copied to a local directory.
|
44
44
|
def add_retrieve(retrieve_statement)
|
45
|
-
name = retrieve_statement.
|
45
|
+
name = retrieve_statement.variable
|
46
46
|
if @retrieves.has_key?(name)
|
47
47
|
Fig::Logging.warn \
|
48
48
|
%q<About to overwrite "#{name}" retrieve path of "#{@retrieves[name].path}" with "#{retrieve_statement.path}".>
|
@@ -99,7 +99,7 @@ class Fig::RuntimeEnvironment
|
|
99
99
|
return
|
100
100
|
end
|
101
101
|
|
102
|
-
def
|
102
|
+
def expand_command_line(base_package, base_config, descriptor, command_line)
|
103
103
|
package, * =
|
104
104
|
determine_package_for_execution(base_package, base_config, descriptor)
|
105
105
|
|
@@ -108,14 +108,12 @@ class Fig::RuntimeEnvironment
|
|
108
108
|
|argument| expand_command_line_argument(argument, base_package)
|
109
109
|
}
|
110
110
|
|
111
|
-
@variables.with_environment
|
112
|
-
yield expanded_command_line
|
113
|
-
end
|
111
|
+
@variables.with_environment { yield expanded_command_line }
|
114
112
|
|
115
113
|
return
|
116
114
|
end
|
117
115
|
|
118
|
-
def
|
116
|
+
def expand_command_statement_from_config(
|
119
117
|
base_package, base_config, descriptor, extra_arguments, &block
|
120
118
|
)
|
121
119
|
package, config_name =
|
@@ -123,7 +121,7 @@ class Fig::RuntimeEnvironment
|
|
123
121
|
|
124
122
|
command_statement = package[config_name].command_statement
|
125
123
|
if command_statement
|
126
|
-
|
124
|
+
expand_command(command_statement, extra_arguments, package, &block)
|
127
125
|
else
|
128
126
|
raise Fig::UserInputError.new(
|
129
127
|
%Q<The "#{package.to_s}" package with the "#{config_name}" configuration does not contain a command.>
|
@@ -213,10 +211,12 @@ class Fig::RuntimeEnvironment
|
|
213
211
|
@variables[name] = expanded_value
|
214
212
|
|
215
213
|
if Fig::Logging.debug?
|
216
|
-
|
214
|
+
tokenized_value = statement.tokenized_value
|
215
|
+
escaped_value = tokenized_value.to_escaped_string
|
217
216
|
expanded_message =
|
218
|
-
expanded_value ==
|
219
|
-
|
217
|
+
expanded_value == escaped_value \
|
218
|
+
? '' \
|
219
|
+
: %Q< (expanded from "#{escaped_value}")>
|
220
220
|
|
221
221
|
Fig::Logging.debug(
|
222
222
|
%Q<Set #{name} to "#{expanded_value}"#{expanded_message}.>
|
@@ -234,10 +234,12 @@ class Fig::RuntimeEnvironment
|
|
234
234
|
@variables.prepend_variable(name, expanded_value)
|
235
235
|
|
236
236
|
if Fig::Logging.debug?
|
237
|
-
|
237
|
+
tokenized_value = statement.tokenized_value
|
238
|
+
escaped_value = tokenized_value.to_escaped_string
|
238
239
|
expanded_message =
|
239
|
-
expanded_value ==
|
240
|
-
|
240
|
+
expanded_value == escaped_value \
|
241
|
+
? '' \
|
242
|
+
: %Q< ("#{escaped_value}" expanded to "#{expanded_value}")>
|
241
243
|
|
242
244
|
Fig::Logging.debug(
|
243
245
|
%Q<Prepending to #{name} resulted in "#{@variables[name]}"#{expanded_message}.>
|
@@ -323,27 +325,29 @@ class Fig::RuntimeEnvironment
|
|
323
325
|
return package.primary_config_name || Fig::Package::DEFAULT_CONFIG
|
324
326
|
end
|
325
327
|
|
326
|
-
def
|
327
|
-
|
328
|
-
command
|
329
|
-
expand_command_line_argument(
|
330
|
-
|
331
|
-
package
|
332
|
-
)
|
328
|
+
def expand_command(command_statement, extra_arguments, package)
|
329
|
+
expanded_command_line =
|
330
|
+
[ command_statement.command, extra_arguments ].flatten.map {
|
331
|
+
|argument| expand_command_line_argument(argument, package)
|
332
|
+
}
|
333
333
|
|
334
|
-
|
334
|
+
if command_statement.command.size == 1
|
335
|
+
expanded_command_line = [ expanded_command_line.join(' ') ]
|
335
336
|
end
|
336
337
|
|
338
|
+
@variables.with_environment { yield expanded_command_line }
|
339
|
+
|
337
340
|
return
|
338
341
|
end
|
339
342
|
|
340
343
|
def expand_variable_as_path_and_process_retrieves(
|
341
344
|
statement, package, backtrace
|
342
345
|
)
|
343
|
-
|
346
|
+
tokenized_value = statement.tokenized_value
|
347
|
+
return tokenized_value.to_expanded_string { '@' } \
|
348
|
+
unless package && package.name
|
344
349
|
|
345
|
-
variable_value =
|
346
|
-
expand_at_signs_in_path(statement.value, package, backtrace)
|
350
|
+
variable_value = tokenized_value.to_expanded_string { package.directory }
|
347
351
|
|
348
352
|
return variable_value if not @retrieves.member?(statement.name)
|
349
353
|
|
@@ -399,112 +403,42 @@ class Fig::RuntimeEnvironment
|
|
399
403
|
return File.join(retrieve_path, File.basename(variable_value))
|
400
404
|
end
|
401
405
|
|
402
|
-
def
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
frontmatter, backslashes = $1, $2
|
420
|
-
|
421
|
-
replacement = backslashes.length % 2 == 1 ? '@' : package.directory
|
422
|
-
|
423
|
-
"#{frontmatter}#{backslashes}#{replacement}"
|
424
|
-
end
|
425
|
-
end
|
426
|
-
|
427
|
-
def expand_command_line_argument(argument, package)
|
428
|
-
package_substituted = expand_package_references(argument, package)
|
429
|
-
check_for_bad_escape(package_substituted, argument, package, nil)
|
430
|
-
|
431
|
-
return collapse_backslashes_for_escaped_at_signs(package_substituted)
|
432
|
-
end
|
433
|
-
|
434
|
-
def expand_package_references(argument, package)
|
435
|
-
return argument.gsub(
|
436
|
-
# TODO: Refactor package name regex into PackageDescriptor constant.
|
437
|
-
%r<
|
438
|
-
(?: ^ | \G) # Zero-width anchor.
|
439
|
-
( [^\\@]* ) # A bunch of not-slashes-or-at-signs
|
440
|
-
( \\* ) # Any leading backslashes
|
441
|
-
\@ # The package indicator
|
442
|
-
( [a-zA-Z0-9_.-]* ) # Package name
|
443
|
-
>x
|
444
|
-
) do |match|
|
445
|
-
frontmatter, backslashes, package_name = $1, $2, $3
|
446
|
-
|
447
|
-
expand_package_reference(
|
448
|
-
frontmatter, backslashes, package_name, package
|
449
|
-
)
|
450
|
-
end
|
451
|
-
end
|
452
|
-
|
453
|
-
def expand_package_reference(
|
454
|
-
frontmatter, backslashes, package_name, starting_package
|
455
|
-
)
|
456
|
-
if backslashes.length % 2 == 1
|
457
|
-
return "#{frontmatter}#{backslashes}@#{package_name}"
|
458
|
-
end
|
459
|
-
|
460
|
-
package = nil
|
461
|
-
if ! package_name.empty?
|
462
|
-
package = get_package(package_name)
|
463
|
-
if package.nil?
|
464
|
-
raise_repository_error(
|
465
|
-
%Q<Command-line referenced the "#{package_name}" package, which has not been referenced by any other package, so there's nothing to substitute with.>,
|
466
|
-
nil,
|
467
|
-
nil
|
468
|
-
)
|
406
|
+
def expand_command_line_argument(argument, starting_package)
|
407
|
+
return argument.to_expanded_string() do
|
408
|
+
|token|
|
409
|
+
|
410
|
+
package_name = token.raw_value
|
411
|
+
package = nil
|
412
|
+
if package_name.empty?
|
413
|
+
package = starting_package
|
414
|
+
else
|
415
|
+
package = get_package(package_name)
|
416
|
+
if package.nil?
|
417
|
+
raise_repository_error(
|
418
|
+
%Q<Command-line referenced the "#{package_name}" package, which has not been referenced by any other package, so there's nothing to substitute with.>,
|
419
|
+
nil,
|
420
|
+
nil
|
421
|
+
)
|
422
|
+
end
|
469
423
|
end
|
470
|
-
else
|
471
|
-
package = starting_package
|
472
|
-
end
|
473
|
-
|
474
|
-
if package && package.directory
|
475
|
-
return "#{frontmatter}#{backslashes}#{package.directory}"
|
476
|
-
end
|
477
424
|
|
478
|
-
|
479
|
-
|
425
|
+
if package && package.directory
|
426
|
+
next package.directory
|
427
|
+
end
|
480
428
|
|
481
|
-
|
482
|
-
# collapsing of escapes not done yet.
|
483
|
-
def check_for_bad_escape(substituted, original, package, backtrace)
|
484
|
-
if substituted =~ %r<
|
485
|
-
(?: ^ | [^\\]) # Start of line or non backslash
|
486
|
-
(?: \\{2})* # Even number of backslashes (including zero)
|
487
|
-
( \\ [^\\@] ) # A bad escape
|
488
|
-
>x
|
489
|
-
raise_repository_error(
|
490
|
-
%Q<Unknown escape "#{$1}" in "#{original}">, backtrace, package
|
491
|
-
)
|
429
|
+
next '@'
|
492
430
|
end
|
493
|
-
|
494
|
-
return
|
495
|
-
end
|
496
|
-
|
497
|
-
# After @ substitution, we need to get rid of the backslashes in front of
|
498
|
-
# any escaped @ signs.
|
499
|
-
def collapse_backslashes_for_escaped_at_signs(string)
|
500
|
-
return string.gsub(%r< \\ ([\\@]) >x, '\1')
|
501
431
|
end
|
502
432
|
|
503
433
|
def get_retrieve_path_with_substitution(variable_name, package)
|
504
434
|
retrieve_statement = @retrieves[variable_name]
|
505
435
|
retrieve_statement.referenced(true)
|
506
436
|
|
507
|
-
return retrieve_statement.
|
437
|
+
return retrieve_statement.tokenized_path.to_expanded_string() do
|
438
|
+
|token|
|
439
|
+
|
440
|
+
package.name
|
441
|
+
end
|
508
442
|
end
|
509
443
|
|
510
444
|
def raise_repository_error(message, backtrace, package)
|