fig 0.1.77 → 0.1.79
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 +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
|