fig 0.1.77 → 0.1.79
Sign up to get free protection for your applications and to get access to all the features.
- data/Changes +58 -1
- data/bin/fig +1 -1
- data/lib/fig.rb +1 -1
- data/lib/fig/command.rb +3 -3
- data/lib/fig/command/action/dump_package_definition_parsed.rb +5 -4
- data/lib/fig/command/action/list_variables/all_configs.rb +2 -5
- data/lib/fig/command/action/publish_local.rb +1 -1
- data/lib/fig/command/action/role/list_variables_in_a_tree.rb +2 -5
- data/lib/fig/command/action/run_command_line.rb +10 -3
- data/lib/fig/command/action/run_command_statement.rb +1 -1
- data/lib/fig/command/options.rb +8 -7
- data/lib/fig/command/options/parser.rb +1 -1
- data/lib/fig/environment_variables/case_insensitive.rb +1 -1
- data/lib/fig/environment_variables/case_sensitive.rb +1 -1
- data/lib/fig/figrc.rb +10 -10
- data/lib/fig/{not_found_error.rb → file_not_found_error.rb} +1 -1
- data/lib/fig/grammar/v0.rb +174 -173
- data/lib/fig/grammar/v0.treetop +27 -21
- data/lib/fig/grammar/v1.rb +477 -171
- data/lib/fig/grammar/v1.treetop +34 -22
- data/lib/fig/operating_system.rb +139 -60
- data/lib/fig/package.rb +8 -4
- data/lib/fig/package_definition_text_assembler.rb +31 -23
- data/lib/fig/parser.rb +3 -5
- data/lib/fig/parser_package_build_state.rb +15 -14
- data/lib/fig/repository.rb +41 -28
- data/lib/fig/repository_package_publisher.rb +20 -25
- data/lib/fig/runtime_environment.rb +136 -87
- data/lib/fig/statement.rb +15 -116
- data/lib/fig/statement/archive.rb +6 -4
- data/lib/fig/statement/asset.rb +50 -35
- data/lib/fig/statement/command.rb +6 -2
- data/lib/fig/statement/configuration.rb +10 -2
- data/lib/fig/statement/environment_variable.rb +35 -0
- data/lib/fig/statement/grammar_version.rb +6 -2
- data/lib/fig/statement/include.rb +6 -2
- data/lib/fig/statement/override.rb +6 -2
- data/lib/fig/statement/path.rb +7 -8
- data/lib/fig/statement/resource.rb +7 -3
- data/lib/fig/statement/retrieve.rb +10 -2
- data/lib/fig/statement/set.rb +7 -8
- data/lib/fig/string_tokenizer.rb +195 -0
- data/lib/fig/tokenized_string.rb +22 -0
- data/lib/fig/tokenized_string/plain_segment.rb +24 -0
- data/lib/fig/tokenized_string/token.rb +18 -0
- data/lib/fig/unparser.rb +84 -1
- data/lib/fig/unparser/v0.rb +4 -0
- data/lib/fig/unparser/v1.rb +7 -7
- data/lib/fig/url.rb +12 -1
- data/lib/fig/{url_access_error.rb → url_access_disallowed_error.rb} +2 -2
- metadata +129 -128
- data/lib/fig/grammar/v0_asset_location.rb +0 -162
- data/lib/fig/grammar/v0_ish.rb +0 -1356
- data/lib/fig/grammar/v1_asset_location.rb +0 -162
- data/lib/fig/grammar/v2.rb +0 -1478
@@ -11,15 +11,19 @@ class Fig::Statement; end
|
|
11
11
|
class Fig::Statement::Resource < Fig::Statement
|
12
12
|
include Fig::Statement::Asset
|
13
13
|
|
14
|
-
def initialize(line_column, source_description,
|
14
|
+
def initialize(line_column, source_description, location, glob_if_not_url)
|
15
15
|
super(line_column, source_description)
|
16
16
|
|
17
|
-
@
|
17
|
+
@location = location
|
18
18
|
@glob_if_not_url = glob_if_not_url
|
19
19
|
end
|
20
20
|
|
21
|
+
def statement_type()
|
22
|
+
return 'resource'
|
23
|
+
end
|
24
|
+
|
21
25
|
def asset_name()
|
22
|
-
if Fig::URL.is_url?(
|
26
|
+
if Fig::URL.is_url?(location())
|
23
27
|
return standard_asset_name()
|
24
28
|
end
|
25
29
|
|
@@ -27,6 +27,10 @@ class Fig::Statement::Retrieve < Fig::Statement
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
+
def statement_type()
|
31
|
+
return 'retrieve'
|
32
|
+
end
|
33
|
+
|
30
34
|
def loaded_but_not_referenced?()
|
31
35
|
return added_to_environment? && ! referenced?
|
32
36
|
end
|
@@ -51,7 +55,11 @@ class Fig::Statement::Retrieve < Fig::Statement
|
|
51
55
|
return unparser.retrieve(self)
|
52
56
|
end
|
53
57
|
|
54
|
-
def
|
55
|
-
return 0
|
58
|
+
def minimum_grammar_for_emitting_input()
|
59
|
+
return [0]
|
60
|
+
end
|
61
|
+
|
62
|
+
def minimum_grammar_for_publishing()
|
63
|
+
return [0]
|
56
64
|
end
|
57
65
|
end
|
data/lib/fig/statement/set.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
1
|
require 'fig/statement'
|
2
|
+
require 'fig/statement/environment_variable'
|
2
3
|
|
3
4
|
module Fig; end
|
4
5
|
|
5
6
|
# A statement that sets the value of an environment variable.
|
6
7
|
class Fig::Statement::Set < Fig::Statement
|
8
|
+
include Fig::Statement::EnvironmentVariable
|
9
|
+
|
7
10
|
# We block quotes right now in order to allow for using them for
|
8
11
|
# quoting later.
|
9
12
|
VALUE_REGEX = %r< \A [^\s\\'"]* \z >x
|
@@ -26,8 +29,6 @@ class Fig::Statement::Set < Fig::Statement
|
|
26
29
|
return [variable, value]
|
27
30
|
end
|
28
31
|
|
29
|
-
attr_reader :name, :value
|
30
|
-
|
31
32
|
def initialize(line_column, source_description, name, value)
|
32
33
|
super(line_column, source_description)
|
33
34
|
|
@@ -35,6 +36,10 @@ class Fig::Statement::Set < Fig::Statement
|
|
35
36
|
@value = value
|
36
37
|
end
|
37
38
|
|
39
|
+
def statement_type()
|
40
|
+
return 'set'
|
41
|
+
end
|
42
|
+
|
38
43
|
def is_environment_variable?()
|
39
44
|
return true
|
40
45
|
end
|
@@ -42,10 +47,4 @@ class Fig::Statement::Set < Fig::Statement
|
|
42
47
|
def unparse_as_version(unparser)
|
43
48
|
return unparser.set(self)
|
44
49
|
end
|
45
|
-
|
46
|
-
def minimum_grammar_version_required()
|
47
|
-
# TODO: fix this once going through
|
48
|
-
# Statement.strip_quotes_and_process_escapes()
|
49
|
-
return 0
|
50
|
-
end
|
51
50
|
end
|
@@ -0,0 +1,195 @@
|
|
1
|
+
require 'fig/tokenized_string'
|
2
|
+
require 'fig/tokenized_string/plain_segment'
|
3
|
+
|
4
|
+
module Fig; end
|
5
|
+
|
6
|
+
class Fig::StringTokenizer
|
7
|
+
def initialize(subexpression_matchers = DEFAULT_SUBEXPRESSION_MATCHER)
|
8
|
+
@subexpression_matchers = subexpression_matchers
|
9
|
+
|
10
|
+
return
|
11
|
+
end
|
12
|
+
|
13
|
+
# Takes a block that is invoked when there is an error. Block receives a
|
14
|
+
# single parameter of an error message that is the end of a statement
|
15
|
+
# describing the problem, with no leading space character. For example,
|
16
|
+
# given «'foo», the block will receive a message like 'has unbalanced single
|
17
|
+
# quotes.'.
|
18
|
+
#
|
19
|
+
# Returns the TokenizedString; if there was a parse error, then the return
|
20
|
+
# value will be nil (and the block will have been invoked).
|
21
|
+
def tokenize(string, &error_block)
|
22
|
+
@string = string.clone
|
23
|
+
@error_block = error_block
|
24
|
+
@single_quoted = nil
|
25
|
+
@segments = []
|
26
|
+
|
27
|
+
strip_quotes_and_process_escapes
|
28
|
+
|
29
|
+
return if @segments.empty?
|
30
|
+
|
31
|
+
return Fig::TokenizedString.new(@segments, @single_quoted)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
DEFAULT_SUBEXPRESSION_MATCHER = [
|
37
|
+
{ :pattern => %r<\@>, :action => lambda {|character| character} }
|
38
|
+
]
|
39
|
+
|
40
|
+
def strip_quotes_and_process_escapes()
|
41
|
+
if @string.length == 0
|
42
|
+
@single_quoted = false
|
43
|
+
@segments << Fig::TokenizedString::PlainSegment.new('')
|
44
|
+
|
45
|
+
return
|
46
|
+
end
|
47
|
+
|
48
|
+
@single_quoted = strip_single_quotes_and_process_escapes
|
49
|
+
return if @single_quoted.nil?
|
50
|
+
if @single_quoted
|
51
|
+
@segments << Fig::TokenizedString::PlainSegment.new(@string.clone)
|
52
|
+
|
53
|
+
return
|
54
|
+
end
|
55
|
+
|
56
|
+
strip_double_quotes_and_process_escapes
|
57
|
+
|
58
|
+
return
|
59
|
+
end
|
60
|
+
|
61
|
+
def strip_single_quotes_and_process_escapes()
|
62
|
+
return false if @string[0..0] != %q<'> && @string[-1..-1] != %q<'>
|
63
|
+
return false if @string =~ %r< \A (?: \\{2} )* \\ ' \z >x # «\'» is legal
|
64
|
+
|
65
|
+
if (
|
66
|
+
@string.length == 1 ||
|
67
|
+
@string[0..0] != %q<'> ||
|
68
|
+
@string[-1..-1] != %q<'> ||
|
69
|
+
@string =~ %r< [^\\] (?: \\{2} )* \\ ' \z >x
|
70
|
+
)
|
71
|
+
@error_block.call 'has unbalanced single quotes.'
|
72
|
+
return
|
73
|
+
end
|
74
|
+
|
75
|
+
if @string =~ %r< [^\\] (?: \\{2} )*? \\ ([^\\']) >x
|
76
|
+
@error_block.call(
|
77
|
+
"contains a bad escape sequence (\\#{$1}) inside single quotes."
|
78
|
+
)
|
79
|
+
return
|
80
|
+
end
|
81
|
+
|
82
|
+
@string.sub!( %r< \A ' (.*) ' \z >xm, '\1')
|
83
|
+
|
84
|
+
return true
|
85
|
+
end
|
86
|
+
|
87
|
+
def strip_double_quotes_and_process_escapes()
|
88
|
+
return if ! check_and_strip_double_quotes
|
89
|
+
|
90
|
+
if @string == %q<\\'>
|
91
|
+
@segments << Fig::TokenizedString::PlainSegment.new(%q<'>)
|
92
|
+
|
93
|
+
return
|
94
|
+
end
|
95
|
+
|
96
|
+
generate_segments
|
97
|
+
|
98
|
+
return
|
99
|
+
end
|
100
|
+
|
101
|
+
def check_and_strip_double_quotes()
|
102
|
+
# We accept any unquoted single character at this point. Later validation
|
103
|
+
# will catch bad characters.
|
104
|
+
return true if @string =~ %r< \A \\ . \z >xm
|
105
|
+
|
106
|
+
if @string[0..0] == %q<">
|
107
|
+
if @string.length == 1 || @string[-1..-1] != %q<">
|
108
|
+
@error_block.call 'has unbalanced double quotes.'
|
109
|
+
return
|
110
|
+
end
|
111
|
+
if @string =~ %r< [^\\] (?: \\{2} )*? \\ " \z >xm
|
112
|
+
@error_block.call \
|
113
|
+
'has unbalanced double quotes; the trailing double quote is escaped.'
|
114
|
+
return
|
115
|
+
end
|
116
|
+
|
117
|
+
@string.sub!( %r< \A " (.*) " \z >xm, '\1' )
|
118
|
+
elsif @string =~ %r< (?: \A | [^\\] ) (?: \\{2} )* " \z >xm
|
119
|
+
@error_block.call \
|
120
|
+
%q<has unbalanced double quotes; it ends in a double quote when it didn't start with one.>
|
121
|
+
return
|
122
|
+
end
|
123
|
+
|
124
|
+
return true
|
125
|
+
end
|
126
|
+
|
127
|
+
def generate_segments()
|
128
|
+
plain_string = nil
|
129
|
+
|
130
|
+
while ! @string.empty?
|
131
|
+
if @string =~ %r< \A (\\+) ([^\\] .*)? \z >xm
|
132
|
+
slashes, remainder = $1, $2
|
133
|
+
if slashes.length % 2 == 1
|
134
|
+
if remainder.nil?
|
135
|
+
@error_block.call 'ends in an incomplete escape.'
|
136
|
+
return
|
137
|
+
end
|
138
|
+
if subexpression_match(remainder) || remainder[0..0] == %q<">
|
139
|
+
plain_string ||= ''
|
140
|
+
plain_string << slashes
|
141
|
+
plain_string << remainder[0..0]
|
142
|
+
@string = remainder[1..-1] || ''
|
143
|
+
else
|
144
|
+
@error_block.call "contains a bad escape sequence (\\#{$1})."
|
145
|
+
return
|
146
|
+
end
|
147
|
+
else
|
148
|
+
plain_string ||= ''
|
149
|
+
plain_string << slashes
|
150
|
+
@string = remainder
|
151
|
+
end
|
152
|
+
else
|
153
|
+
replacement, remainder = subexpression_match @string
|
154
|
+
if replacement
|
155
|
+
if replacement.is_a? String
|
156
|
+
plain_string << replacement
|
157
|
+
else
|
158
|
+
@segments << Fig::TokenizedString::PlainSegment.new(plain_string)
|
159
|
+
plain_string = nil
|
160
|
+
end
|
161
|
+
@string = remainder
|
162
|
+
elsif @string =~ %r< \A (["']) >xm # Fix single quotes in quoted strings
|
163
|
+
quote_name = $1 == %q<'> ? 'single' : 'double'
|
164
|
+
@error_block.call "contains an unescaped #{quote_name} quote."
|
165
|
+
return
|
166
|
+
else
|
167
|
+
plain_string ||= ''
|
168
|
+
plain_string << @string[0..0]
|
169
|
+
@string = @string[1..-1] || ''
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
if plain_string
|
175
|
+
@segments << Fig::TokenizedString::PlainSegment.new(plain_string)
|
176
|
+
end
|
177
|
+
|
178
|
+
return
|
179
|
+
end
|
180
|
+
|
181
|
+
def subexpression_match(sub_string)
|
182
|
+
@subexpression_matchers.each do
|
183
|
+
|matcher|
|
184
|
+
|
185
|
+
pattern = matcher[:pattern]
|
186
|
+
if sub_string =~ %r< \A ( #{pattern} ) >x
|
187
|
+
subexpression, remainder = $1, $'
|
188
|
+
replacement = matcher[:action].call subexpression
|
189
|
+
return [replacement, remainder]
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
return
|
194
|
+
end
|
195
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Fig; end
|
2
|
+
|
3
|
+
class Fig::TokenizedString
|
4
|
+
def initialize(segments, single_quoted)
|
5
|
+
@segments = segments
|
6
|
+
@single_quoted = single_quoted
|
7
|
+
|
8
|
+
return
|
9
|
+
end
|
10
|
+
|
11
|
+
def single_quoted?()
|
12
|
+
return @single_quoted
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_expanded_string()
|
16
|
+
return ( @segments.collect {|segment| segment.to_expanded_string} ).join ''
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_escaped_string()
|
20
|
+
return ( @segments.collect {|segment| segment.to_escaped_string} ).join ''
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Fig; end
|
2
|
+
class Fig::TokenizedString; end
|
3
|
+
|
4
|
+
class Fig::TokenizedString::PlainSegment
|
5
|
+
attr_reader :raw_value
|
6
|
+
|
7
|
+
def initialize(raw_value)
|
8
|
+
@raw_value = raw_value
|
9
|
+
|
10
|
+
return
|
11
|
+
end
|
12
|
+
|
13
|
+
def type
|
14
|
+
return :plain_segment
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_expanded_string()
|
18
|
+
return @raw_value.gsub(%r< \\ (.) >xm, '\1')
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_escaped_string()
|
22
|
+
return @raw_value
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Fig; end
|
2
|
+
class Fig::TokenizedString; end
|
3
|
+
|
4
|
+
class Fig::TokenizedString::Token
|
5
|
+
attr_reader :type
|
6
|
+
attr_reader :raw_value
|
7
|
+
|
8
|
+
def initialize(type, raw_value)
|
9
|
+
@type = type
|
10
|
+
@raw_value = raw_value
|
11
|
+
|
12
|
+
return
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_escaped_string()
|
16
|
+
return raw_value
|
17
|
+
end
|
18
|
+
end
|
data/lib/fig/unparser.rb
CHANGED
@@ -1,7 +1,86 @@
|
|
1
1
|
module Fig; end
|
2
2
|
|
3
3
|
module Fig::Unparser
|
4
|
+
# Determine the class of Unparser necessary for a set of Statements; the
|
5
|
+
# parameter can be a single statement or multiple. Returns both the class
|
6
|
+
# and a list of explanations of why the class was picked.
|
7
|
+
def self.class_for_statements(
|
8
|
+
statements, emit_as_input_or_to_be_published_values
|
9
|
+
)
|
10
|
+
# Note: we very specifically do not require the files containing the
|
11
|
+
# Unparser classes in order to avoid circular dependencies.
|
12
|
+
statements = [statements].flatten
|
13
|
+
|
14
|
+
versions =
|
15
|
+
self.gather_versions statements, emit_as_input_or_to_be_published_values
|
16
|
+
version = (versions.map {|version_info| version_info[0]}).max || 0
|
17
|
+
explanations = (versions.collect {|v| v[1]}).reject {|e| e.nil?}
|
18
|
+
|
19
|
+
case version
|
20
|
+
when 0
|
21
|
+
return Fig::Unparser::V0, explanations
|
22
|
+
end
|
23
|
+
|
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
|
+
return Fig::Unparser::V1, explanations
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.determine_version_and_unparse(
|
34
|
+
statements, emit_as_input_or_to_be_published_values
|
35
|
+
)
|
36
|
+
unparser_class, explanations = self.class_for_statements(
|
37
|
+
statements, emit_as_input_or_to_be_published_values
|
38
|
+
)
|
39
|
+
unparser = unparser_class.new emit_as_input_or_to_be_published_values
|
40
|
+
|
41
|
+
return (unparser.unparse [statements].flatten), explanations
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def self.gather_versions(statements, emit_as_input_or_to_be_published_values)
|
47
|
+
if emit_as_input_or_to_be_published_values == :emit_as_input
|
48
|
+
return statements.map {
|
49
|
+
|statement|
|
50
|
+
|
51
|
+
self.expand_version_and_explanation(
|
52
|
+
statement, statement.minimum_grammar_for_emitting_input
|
53
|
+
)
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
return statements.map {
|
58
|
+
|statement|
|
59
|
+
|
60
|
+
self.expand_version_and_explanation(
|
61
|
+
statement, statement.minimum_grammar_for_publishing
|
62
|
+
)
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.expand_version_and_explanation(statement, version_info)
|
67
|
+
version, explanation = *version_info
|
68
|
+
if explanation.nil?
|
69
|
+
return [version]
|
70
|
+
end
|
71
|
+
|
72
|
+
return [
|
73
|
+
version,
|
74
|
+
"Grammar v#{version} is required because the #{statement.statement_type} statement#{statement.position_string} #{explanation}."
|
75
|
+
]
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
public
|
80
|
+
|
4
81
|
def unparse(statements)
|
82
|
+
# It's double dispatch time!
|
83
|
+
|
5
84
|
@text = ''
|
6
85
|
@indent_level = @initial_indent_level
|
7
86
|
|
@@ -101,6 +180,10 @@ module Fig::Unparser
|
|
101
180
|
return
|
102
181
|
end
|
103
182
|
|
183
|
+
def grammar_description
|
184
|
+
raise NotImplementedError
|
185
|
+
end
|
186
|
+
|
104
187
|
private
|
105
188
|
|
106
189
|
def asset(keyword, statement)
|
@@ -109,7 +192,7 @@ module Fig::Unparser
|
|
109
192
|
|
110
193
|
def asset_path(statement)
|
111
194
|
if @emit_as_input_or_to_be_published_values == :emit_as_input
|
112
|
-
return statement.
|
195
|
+
return statement.location
|
113
196
|
end
|
114
197
|
|
115
198
|
return statement.asset_name
|