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
data/lib/fig/string_tokenizer.rb
CHANGED
@@ -1,11 +1,33 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
1
3
|
require 'fig/tokenized_string'
|
2
4
|
require 'fig/tokenized_string/plain_segment'
|
3
5
|
|
4
6
|
module Fig; end
|
5
7
|
|
6
8
|
class Fig::StringTokenizer
|
7
|
-
|
9
|
+
# subexpression_matchers is an array of hashes. Each hash is expected to
|
10
|
+
# contain two keys: :pattern and :action.
|
11
|
+
#
|
12
|
+
# The :pattern value needs to be a regular expression for the substring that
|
13
|
+
# needs special handling.
|
14
|
+
#
|
15
|
+
# The :action value needs to be a block that takes two parameters.
|
16
|
+
#
|
17
|
+
# The first parameter is the text that was matched and the second is the
|
18
|
+
# error block passed to #tokenize().
|
19
|
+
#
|
20
|
+
# On success the block returns either a String containing replacement text or
|
21
|
+
# a Fig::TokenizedString::Token representing the special handling of the
|
22
|
+
# consumed text. If there was a problem, then the error block should have
|
23
|
+
# been invoked and the block should return nil.
|
24
|
+
#
|
25
|
+
#
|
26
|
+
# metacharacters is a regular expression character class for characters that
|
27
|
+
# need to be escaped when un-single quoting a string.
|
28
|
+
def initialize(subexpression_matchers = [], metacharacters = '')
|
8
29
|
@subexpression_matchers = subexpression_matchers
|
30
|
+
@metacharacters = metacharacters
|
9
31
|
|
10
32
|
return
|
11
33
|
end
|
@@ -28,15 +50,11 @@ class Fig::StringTokenizer
|
|
28
50
|
|
29
51
|
return if @segments.empty?
|
30
52
|
|
31
|
-
return Fig::TokenizedString.new(@segments, @single_quoted)
|
53
|
+
return Fig::TokenizedString.new(@segments, @single_quoted, @metacharacters)
|
32
54
|
end
|
33
55
|
|
34
56
|
private
|
35
57
|
|
36
|
-
DEFAULT_SUBEXPRESSION_MATCHER = [
|
37
|
-
{ :pattern => %r<\@>, :action => lambda {|character| character} }
|
38
|
-
]
|
39
|
-
|
40
58
|
def strip_quotes_and_process_escapes()
|
41
59
|
if @string.length == 0
|
42
60
|
@single_quoted = false
|
@@ -60,13 +78,15 @@ class Fig::StringTokenizer
|
|
60
78
|
|
61
79
|
def strip_single_quotes_and_process_escapes()
|
62
80
|
return false if @string[0..0] != %q<'> && @string[-1..-1] != %q<'>
|
63
|
-
return false if @string =~ %r<
|
81
|
+
return false if @string =~ %r< # «\'» is legal
|
82
|
+
\A ( [^\\']* (?: \\{2} )* \\ ' )* \z
|
83
|
+
>x
|
64
84
|
|
65
85
|
if (
|
66
|
-
@string.length == 1
|
67
|
-
@string[0..0] != %q<'>
|
68
|
-
@string[-1..-1] != %q<'>
|
69
|
-
@string =~ %r< [^\\] (?: \\{2} )* \\ ' \z >x
|
86
|
+
@string.length == 1 ||
|
87
|
+
@string[0..0] != %q<'> ||
|
88
|
+
@string[-1..-1] != %q<'> ||
|
89
|
+
@string =~ %r< [^\\] (?: \\{2} )* (?: \\ | ' .* ) ' \z >x
|
70
90
|
)
|
71
91
|
@error_block.call 'has unbalanced single quotes.'
|
72
92
|
return
|
@@ -85,7 +105,8 @@ class Fig::StringTokenizer
|
|
85
105
|
end
|
86
106
|
|
87
107
|
def strip_double_quotes_and_process_escapes()
|
88
|
-
|
108
|
+
was_quoted = check_and_strip_double_quotes
|
109
|
+
return if was_quoted.nil?
|
89
110
|
|
90
111
|
if @string == %q<\\'>
|
91
112
|
@segments << Fig::TokenizedString::PlainSegment.new(%q<'>)
|
@@ -93,7 +114,7 @@ class Fig::StringTokenizer
|
|
93
114
|
return
|
94
115
|
end
|
95
116
|
|
96
|
-
generate_segments
|
117
|
+
generate_segments was_quoted
|
97
118
|
|
98
119
|
return
|
99
120
|
end
|
@@ -101,7 +122,7 @@ class Fig::StringTokenizer
|
|
101
122
|
def check_and_strip_double_quotes()
|
102
123
|
# We accept any unquoted single character at this point. Later validation
|
103
124
|
# will catch bad characters.
|
104
|
-
return
|
125
|
+
return false if @string =~ %r< \A \\ . \z >xm
|
105
126
|
|
106
127
|
if @string[0..0] == %q<">
|
107
128
|
if @string.length == 1 || @string[-1..-1] != %q<">
|
@@ -115,16 +136,18 @@ class Fig::StringTokenizer
|
|
115
136
|
end
|
116
137
|
|
117
138
|
@string.sub!( %r< \A " (.*) " \z >xm, '\1' )
|
139
|
+
|
140
|
+
return true
|
118
141
|
elsif @string =~ %r< (?: \A | [^\\] ) (?: \\{2} )* " \z >xm
|
119
142
|
@error_block.call \
|
120
143
|
%q<has unbalanced double quotes; it ends in a double quote when it didn't start with one.>
|
121
144
|
return
|
122
145
|
end
|
123
146
|
|
124
|
-
return
|
147
|
+
return false
|
125
148
|
end
|
126
149
|
|
127
|
-
def generate_segments()
|
150
|
+
def generate_segments(was_quoted)
|
128
151
|
plain_string = nil
|
129
152
|
|
130
153
|
while ! @string.empty?
|
@@ -135,13 +158,20 @@ class Fig::StringTokenizer
|
|
135
158
|
@error_block.call 'ends in an incomplete escape.'
|
136
159
|
return
|
137
160
|
end
|
138
|
-
|
161
|
+
subexpression_matched = subexpression_match(remainder)
|
162
|
+
return if subexpression_matched.nil?
|
163
|
+
if (
|
164
|
+
subexpression_matched ||
|
165
|
+
remainder[0..0] == %q<"> ||
|
166
|
+
! was_quoted && remainder[0..0] == %q<'>
|
167
|
+
)
|
139
168
|
plain_string ||= ''
|
140
169
|
plain_string << slashes
|
141
170
|
plain_string << remainder[0..0]
|
142
171
|
@string = remainder[1..-1] || ''
|
143
172
|
else
|
144
|
-
@error_block.call
|
173
|
+
@error_block.call \
|
174
|
+
"contains a bad escape sequence (\\#{remainder[0..0]})."
|
145
175
|
return
|
146
176
|
end
|
147
177
|
else
|
@@ -151,17 +181,23 @@ class Fig::StringTokenizer
|
|
151
181
|
end
|
152
182
|
else
|
153
183
|
replacement, remainder = subexpression_match @string
|
184
|
+
return if replacement.nil?
|
154
185
|
if replacement
|
155
186
|
if replacement.is_a? String
|
156
187
|
plain_string << replacement
|
157
188
|
else
|
158
|
-
|
159
|
-
|
189
|
+
if ! plain_string.nil?
|
190
|
+
@segments << Fig::TokenizedString::PlainSegment.new(plain_string)
|
191
|
+
plain_string = nil
|
192
|
+
end
|
193
|
+
@segments << replacement
|
160
194
|
end
|
161
195
|
@string = remainder
|
162
|
-
elsif @string =~ %r< \A
|
163
|
-
|
164
|
-
|
196
|
+
elsif @string =~ %r< \A " >xm
|
197
|
+
@error_block.call 'contains an unescaped double quote.'
|
198
|
+
return
|
199
|
+
elsif ! was_quoted && @string =~ %r< \A ' >xm
|
200
|
+
@error_block.call 'contains an unescaped single quote.'
|
165
201
|
return
|
166
202
|
else
|
167
203
|
plain_string ||= ''
|
@@ -185,11 +221,13 @@ class Fig::StringTokenizer
|
|
185
221
|
pattern = matcher[:pattern]
|
186
222
|
if sub_string =~ %r< \A ( #{pattern} ) >x
|
187
223
|
subexpression, remainder = $1, $'
|
188
|
-
replacement = matcher[:action].call subexpression
|
224
|
+
replacement = matcher[:action].call subexpression, @error_block
|
225
|
+
|
226
|
+
return if ! replacement
|
189
227
|
return [replacement, remainder]
|
190
228
|
end
|
191
229
|
end
|
192
230
|
|
193
|
-
return
|
231
|
+
return false
|
194
232
|
end
|
195
233
|
end
|
data/lib/fig/tokenized_string.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
module Fig; end
|
2
2
|
|
3
3
|
class Fig::TokenizedString
|
4
|
-
def initialize(segments, single_quoted)
|
5
|
-
@segments
|
6
|
-
@single_quoted
|
4
|
+
def initialize(segments, single_quoted, metacharacters)
|
5
|
+
@segments = segments
|
6
|
+
@single_quoted = single_quoted
|
7
|
+
@metacharacters = metacharacters
|
7
8
|
|
8
9
|
return
|
9
10
|
end
|
@@ -12,11 +13,36 @@ class Fig::TokenizedString
|
|
12
13
|
return @single_quoted
|
13
14
|
end
|
14
15
|
|
15
|
-
def
|
16
|
-
return
|
16
|
+
def can_be_single_quoted?()
|
17
|
+
return true if single_quoted?
|
18
|
+
return @segments.all? {|segment| segment.type.nil?}
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_expanded_string(&block)
|
22
|
+
return (
|
23
|
+
@segments.collect { |segment| segment.to_expanded_string(&block) }
|
24
|
+
).join ''
|
17
25
|
end
|
18
26
|
|
19
27
|
def to_escaped_string()
|
20
28
|
return ( @segments.collect {|segment| segment.to_escaped_string} ).join ''
|
21
29
|
end
|
30
|
+
|
31
|
+
def to_single_quoted_string()
|
32
|
+
return to_escaped_string if single_quoted?
|
33
|
+
|
34
|
+
return (
|
35
|
+
@segments.collect {|segment| segment.to_single_quoted_string}
|
36
|
+
).join ''
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_double_quotable_string()
|
40
|
+
return to_escaped_string if ! single_quoted?
|
41
|
+
|
42
|
+
return (
|
43
|
+
@segments.collect {
|
44
|
+
|segment| segment.to_double_quotable_string @metacharacters
|
45
|
+
}
|
46
|
+
).join ''
|
47
|
+
end
|
22
48
|
end
|
@@ -11,14 +11,44 @@ class Fig::TokenizedString::PlainSegment
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def type
|
14
|
-
return
|
14
|
+
return nil
|
15
15
|
end
|
16
16
|
|
17
|
-
def to_expanded_string()
|
17
|
+
def to_expanded_string(&block)
|
18
18
|
return @raw_value.gsub(%r< \\ (.) >xm, '\1')
|
19
19
|
end
|
20
20
|
|
21
21
|
def to_escaped_string()
|
22
22
|
return @raw_value
|
23
23
|
end
|
24
|
+
|
25
|
+
# Should not be invoked if original string was single quoted.
|
26
|
+
def to_single_quoted_string()
|
27
|
+
# Raw value will have come from a non-single quoted string, so we unescape
|
28
|
+
# everything (including backslashes) and then escape backslashes and single
|
29
|
+
# quotes (which cannot be escaped outside of single quotes).
|
30
|
+
return \
|
31
|
+
@raw_value.gsub(%r< \\ (.) >xm, '\1').gsub(%r< ([\\']) >xm, '\\\\\1')
|
32
|
+
end
|
33
|
+
|
34
|
+
# Should not be invoked if original string was not single quoted.
|
35
|
+
def to_double_quotable_string(metacharacters)
|
36
|
+
quoted_value = @raw_value.gsub %r< ( ["#{metacharacters}] ) >xm, '\\\\\1'
|
37
|
+
|
38
|
+
quoted_value.gsub!(
|
39
|
+
%r<
|
40
|
+
(
|
41
|
+
(?: ^ | [^\\] ) # New line or non-backslash
|
42
|
+
(\\{2})* # Even number of backslashes
|
43
|
+
)
|
44
|
+
|
45
|
+
# All single quotes must have been escaped. The important bit is to
|
46
|
+
# not lose escaped backslashes.
|
47
|
+
\\'
|
48
|
+
>xm,
|
49
|
+
%q<\1'>
|
50
|
+
)
|
51
|
+
|
52
|
+
return quoted_value
|
53
|
+
end
|
24
54
|
end
|
@@ -12,7 +12,19 @@ class Fig::TokenizedString::Token
|
|
12
12
|
return
|
13
13
|
end
|
14
14
|
|
15
|
+
def to_expanded_string(&block)
|
16
|
+
return block.call self
|
17
|
+
end
|
18
|
+
|
15
19
|
def to_escaped_string()
|
16
20
|
return raw_value
|
17
21
|
end
|
22
|
+
|
23
|
+
def to_double_quotable_string(metacharacters)
|
24
|
+
return raw_value
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_single_quoted_string()
|
28
|
+
raise NotImplementedError.new 'Cannot single-quote a token.'
|
29
|
+
end
|
18
30
|
end
|
data/lib/fig/unparser.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
# Note: we very specifically do not require the files containing the
|
2
|
+
# Unparser classes in order to avoid circular dependencies.
|
3
|
+
|
1
4
|
module Fig; end
|
2
5
|
|
3
6
|
module Fig::Unparser
|
@@ -7,8 +10,6 @@ module Fig::Unparser
|
|
7
10
|
def self.class_for_statements(
|
8
11
|
statements, emit_as_input_or_to_be_published_values
|
9
12
|
)
|
10
|
-
# Note: we very specifically do not require the files containing the
|
11
|
-
# Unparser classes in order to avoid circular dependencies.
|
12
13
|
statements = [statements].flatten
|
13
14
|
|
14
15
|
versions =
|
@@ -21,12 +22,6 @@ module Fig::Unparser
|
|
21
22
|
return Fig::Unparser::V0, explanations
|
22
23
|
end
|
23
24
|
|
24
|
-
# TODO: Until v1 grammar handling is done, ensure we don't emit anything
|
25
|
-
# old fig versions cannot handle.
|
26
|
-
if ! ENV['FIG_ALLOW_NON_V0_GRAMMAR']
|
27
|
-
raise 'Reached a point where something could not be represented by the v0 grammar. Bailing out.'
|
28
|
-
end
|
29
|
-
|
30
25
|
return Fig::Unparser::V1, explanations
|
31
26
|
end
|
32
27
|
|
@@ -44,8 +39,11 @@ module Fig::Unparser
|
|
44
39
|
private
|
45
40
|
|
46
41
|
def self.gather_versions(statements, emit_as_input_or_to_be_published_values)
|
42
|
+
all_statements = gather_all_statements statements
|
43
|
+
|
47
44
|
if emit_as_input_or_to_be_published_values == :emit_as_input
|
48
|
-
|
45
|
+
versions = []
|
46
|
+
return all_statements.map {
|
49
47
|
|statement|
|
50
48
|
|
51
49
|
self.expand_version_and_explanation(
|
@@ -54,7 +52,7 @@ module Fig::Unparser
|
|
54
52
|
}
|
55
53
|
end
|
56
54
|
|
57
|
-
return
|
55
|
+
return all_statements.map {
|
58
56
|
|statement|
|
59
57
|
|
60
58
|
self.expand_version_and_explanation(
|
@@ -63,6 +61,21 @@ module Fig::Unparser
|
|
63
61
|
}
|
64
62
|
end
|
65
63
|
|
64
|
+
def self.gather_all_statements(statements)
|
65
|
+
all_statements = []
|
66
|
+
statements.each do
|
67
|
+
|statement|
|
68
|
+
|
69
|
+
all_statements << statement
|
70
|
+
|
71
|
+
if statement.is_a? Fig::Statement::Configuration
|
72
|
+
all_statements << statement.statements
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
return all_statements.flatten
|
77
|
+
end
|
78
|
+
|
66
79
|
def self.expand_version_and_explanation(statement, version_info)
|
67
80
|
version, explanation = *version_info
|
68
81
|
if explanation.nil?
|
@@ -159,6 +172,8 @@ module Fig::Unparser
|
|
159
172
|
end
|
160
173
|
|
161
174
|
def path(statement)
|
175
|
+
# I'd really like to change this to "add", but because the command-line
|
176
|
+
# option is "--append", I'm not going to.
|
162
177
|
environment_variable(statement, 'append')
|
163
178
|
|
164
179
|
return
|
@@ -202,8 +217,8 @@ module Fig::Unparser
|
|
202
217
|
raise NotImplementedError
|
203
218
|
end
|
204
219
|
|
205
|
-
def add_indent()
|
206
|
-
@text << @indent_string *
|
220
|
+
def add_indent(indent_level = @indent_level)
|
221
|
+
@text << @indent_string * indent_level
|
207
222
|
|
208
223
|
return
|
209
224
|
end
|
data/lib/fig/unparser/v0.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'fig/package_descriptor'
|
2
1
|
require 'fig/unparser'
|
3
2
|
|
4
3
|
module Fig; end
|
@@ -25,7 +24,7 @@ class Fig::Unparser::V0
|
|
25
24
|
add_indent
|
26
25
|
|
27
26
|
@text << %q<command ">
|
28
|
-
@text << statement.command
|
27
|
+
@text << statement.command.first.to_double_quotable_string
|
29
28
|
@text << %Q<"\n>
|
30
29
|
|
31
30
|
return
|
@@ -44,9 +43,9 @@ class Fig::Unparser::V0
|
|
44
43
|
add_indent
|
45
44
|
|
46
45
|
@text << 'retrieve '
|
47
|
-
@text << statement.
|
46
|
+
@text << statement.variable
|
48
47
|
@text << '->'
|
49
|
-
@text << statement.
|
48
|
+
@text << statement.tokenized_path.to_double_quotable_string
|
50
49
|
@text << "\n"
|
51
50
|
|
52
51
|
return
|
@@ -80,7 +79,7 @@ class Fig::Unparser::V0
|
|
80
79
|
@text << ' '
|
81
80
|
@text << statement.name
|
82
81
|
@text << '='
|
83
|
-
@text << statement.
|
82
|
+
@text << statement.tokenized_value.to_double_quotable_string
|
84
83
|
@text << "\n"
|
85
84
|
|
86
85
|
return
|
data/lib/fig/unparser/v1.rb
CHANGED
@@ -22,10 +22,19 @@ class Fig::Unparser::V1
|
|
22
22
|
|
23
23
|
def command(statement)
|
24
24
|
add_indent
|
25
|
+
@text << %Q<command\n>
|
25
26
|
|
26
|
-
@
|
27
|
-
|
28
|
-
|
27
|
+
add_indent(@indent_level + 1)
|
28
|
+
statement.command.each do
|
29
|
+
|argument|
|
30
|
+
|
31
|
+
emit_tokenized_value argument
|
32
|
+
@text << ' '
|
33
|
+
end
|
34
|
+
|
35
|
+
@text << %Q<\n>
|
36
|
+
add_indent
|
37
|
+
@text << %Q<end\n>
|
29
38
|
|
30
39
|
return
|
31
40
|
end
|
@@ -38,6 +47,20 @@ class Fig::Unparser::V1
|
|
38
47
|
return
|
39
48
|
end
|
40
49
|
|
50
|
+
def retrieve(statement)
|
51
|
+
add_indent
|
52
|
+
|
53
|
+
@text << 'retrieve '
|
54
|
+
@text << statement.variable
|
55
|
+
@text << '->'
|
56
|
+
|
57
|
+
emit_tokenized_value statement.tokenized_path
|
58
|
+
|
59
|
+
@text << "\n"
|
60
|
+
|
61
|
+
return
|
62
|
+
end
|
63
|
+
|
41
64
|
def grammar_description()
|
42
65
|
return 'v1'
|
43
66
|
end
|
@@ -61,17 +84,31 @@ class Fig::Unparser::V1
|
|
61
84
|
end
|
62
85
|
|
63
86
|
def environment_variable(statement, keyword)
|
64
|
-
# TODO: temporarily hack v0 grammar in here so we can test asset
|
65
|
-
# statements; proper implementation once asset statements are done.
|
66
87
|
add_indent
|
67
88
|
|
68
89
|
@text << keyword
|
69
90
|
@text << ' '
|
70
91
|
@text << statement.name
|
71
92
|
@text << '='
|
72
|
-
|
93
|
+
|
94
|
+
emit_tokenized_value statement.tokenized_value
|
95
|
+
|
73
96
|
@text << "\n"
|
74
97
|
|
75
98
|
return
|
76
99
|
end
|
100
|
+
|
101
|
+
def emit_tokenized_value(tokenized_value)
|
102
|
+
if tokenized_value.can_be_single_quoted?
|
103
|
+
@text << %q<'>
|
104
|
+
@text << tokenized_value.to_single_quoted_string
|
105
|
+
@text << %q<'>
|
106
|
+
else
|
107
|
+
@text << %q<">
|
108
|
+
@text << tokenized_value.to_escaped_string
|
109
|
+
@text << %q<">
|
110
|
+
end
|
111
|
+
|
112
|
+
return
|
113
|
+
end
|
77
114
|
end
|