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
data/lib/fig/statement.rb
CHANGED
@@ -26,121 +26,6 @@ class Fig::Statement
|
|
26
26
|
return description
|
27
27
|
end
|
28
28
|
|
29
|
-
# Parameter will be modified.
|
30
|
-
#
|
31
|
-
# Takes a block that is invoked when there is an error. Block receives a
|
32
|
-
# single parameter of an error message that is the end of a statement
|
33
|
-
# describing the problem, with no leading space character. For example,
|
34
|
-
# given «'foo», the block will receive a message like 'has unbalanced single
|
35
|
-
# quotes.'.
|
36
|
-
#
|
37
|
-
# Returns whether parameter was single-quoted; if there was a parse error,
|
38
|
-
# then the return value will be nil (and the block will have been invoked).
|
39
|
-
def self.strip_quotes_and_process_escapes!(string, &error_block)
|
40
|
-
return false if string.length == 0
|
41
|
-
|
42
|
-
replaced_quotes = strip_single_quotes!(string, &error_block)
|
43
|
-
return true if replaced_quotes
|
44
|
-
return if replaced_quotes.nil?
|
45
|
-
|
46
|
-
return process_escapes_and_strip_double_quotes!(string, &error_block)
|
47
|
-
end
|
48
|
-
|
49
|
-
private
|
50
|
-
|
51
|
-
def self.strip_single_quotes!(string)
|
52
|
-
return false if string[0..0] != %q<'> && string[-1..-1] != %q<'>
|
53
|
-
|
54
|
-
if string.length == 1 || string[0..0] != %q<'> || string[-1..-1] != %q<'>
|
55
|
-
yield 'has unbalanced single quotes.'
|
56
|
-
return
|
57
|
-
end
|
58
|
-
|
59
|
-
if string =~ %r< \A ' [^']* ' .* ' \z >xs
|
60
|
-
yield %q<isn't permitted because it has a single quote inside single quotes.>
|
61
|
-
return
|
62
|
-
end
|
63
|
-
|
64
|
-
string.sub!(%r< \A ' (.*) ' \z >xs, '\1')
|
65
|
-
|
66
|
-
return true
|
67
|
-
end
|
68
|
-
|
69
|
-
ALLOWED_ESCAPED_CHARACTERS = Set.new
|
70
|
-
ALLOWED_ESCAPED_CHARACTERS << '\\'
|
71
|
-
ALLOWED_ESCAPED_CHARACTERS << %q<'>
|
72
|
-
ALLOWED_ESCAPED_CHARACTERS << %q<">
|
73
|
-
ALLOWED_ESCAPED_CHARACTERS << '@' # Environment variable package replacement
|
74
|
-
|
75
|
-
def self.process_escapes_and_strip_double_quotes!(string)
|
76
|
-
if string[0..0] == %q<"> && (string.length == 1 || string[-1..-1] != %q<">)
|
77
|
-
yield 'has unbalanced double quotes.'
|
78
|
-
return
|
79
|
-
end
|
80
|
-
|
81
|
-
new_string = ''
|
82
|
-
|
83
|
-
characters = string.each_char
|
84
|
-
initial_character = characters.next
|
85
|
-
last_character = nil
|
86
|
-
had_starting_quote = initial_character == %q<">
|
87
|
-
in_escape = initial_character == '\\'
|
88
|
-
if ! had_starting_quote && ! in_escape
|
89
|
-
new_string << initial_character
|
90
|
-
end
|
91
|
-
|
92
|
-
last_was_escaped = nil
|
93
|
-
loop do
|
94
|
-
last_character = character = characters.next
|
95
|
-
if in_escape
|
96
|
-
if ! ALLOWED_ESCAPED_CHARACTERS.include? character
|
97
|
-
yield "contains a bad escape sequence (\\#{character})."
|
98
|
-
return
|
99
|
-
end
|
100
|
-
|
101
|
-
new_string << character
|
102
|
-
in_escape = false
|
103
|
-
last_was_escaped = true
|
104
|
-
elsif character == %q<">
|
105
|
-
# If we're at the end of the string, we'll get bounced out of the loop
|
106
|
-
# by a StopIteration exception.
|
107
|
-
characters.next
|
108
|
-
yield 'has an unescaped double quote in the middle.'
|
109
|
-
return
|
110
|
-
elsif character == %q<'>
|
111
|
-
yield 'has an unescaped single quote in the middle.'
|
112
|
-
return
|
113
|
-
elsif character == '\\'
|
114
|
-
in_escape = true
|
115
|
-
# TODO: need an
|
116
|
-
# «elsif character == '@'»
|
117
|
-
# here to deal with package substitution in variable statements
|
118
|
-
else
|
119
|
-
new_string << character
|
120
|
-
last_was_escaped = false
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
if in_escape
|
125
|
-
yield 'ends in an incomplete escape sequence.'
|
126
|
-
return
|
127
|
-
elsif had_starting_quote
|
128
|
-
if last_was_escaped
|
129
|
-
yield 'has unbalanced double quotes (last quote was escaped).'
|
130
|
-
return
|
131
|
-
end
|
132
|
-
elsif ! last_was_escaped && ! had_starting_quote && last_character == %q<">
|
133
|
-
yield 'has unbalanced double quotes.'
|
134
|
-
return
|
135
|
-
end
|
136
|
-
|
137
|
-
string.replace(new_string)
|
138
|
-
|
139
|
-
return false
|
140
|
-
end
|
141
|
-
|
142
|
-
public
|
143
|
-
|
144
29
|
# This mess of getting these as a single array necessary is due to
|
145
30
|
# limitations of the "*" array splat operator in ruby v1.8.
|
146
31
|
def initialize(line_column, source_description)
|
@@ -151,6 +36,12 @@ class Fig::Statement
|
|
151
36
|
@source_description = source_description
|
152
37
|
end
|
153
38
|
|
39
|
+
# A name for this kind of Statement, usually a keyword for this statement as
|
40
|
+
# it appears in package definition files.
|
41
|
+
def statement_type()
|
42
|
+
raise NotImplementedError
|
43
|
+
end
|
44
|
+
|
154
45
|
# Block will receive a Statement.
|
155
46
|
def walk_statements(&block)
|
156
47
|
return
|
@@ -160,7 +51,15 @@ class Fig::Statement
|
|
160
51
|
raise NotImplementedError
|
161
52
|
end
|
162
53
|
|
163
|
-
|
54
|
+
# Returns a two element array containing the version and an explanation of
|
55
|
+
# why the version is necessary if the version is greater than 0.
|
56
|
+
def minimum_grammar_for_emitting_input()
|
57
|
+
raise NotImplementedError
|
58
|
+
end
|
59
|
+
|
60
|
+
# Returns a two element array containing the version and an explanation of
|
61
|
+
# why the version is necessary if the version is greater than 0.
|
62
|
+
def minimum_grammar_for_publishing()
|
164
63
|
raise NotImplementedError
|
165
64
|
end
|
166
65
|
|
@@ -10,15 +10,17 @@ class Fig::Statement; end
|
|
10
10
|
class Fig::Statement::Archive < Fig::Statement
|
11
11
|
include Fig::Statement::Asset
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
def initialize(line_column, source_description, url, glob_if_not_url)
|
13
|
+
def initialize(line_column, source_description, location, glob_if_not_url)
|
16
14
|
super(line_column, source_description)
|
17
15
|
|
18
|
-
@
|
16
|
+
@location = location
|
19
17
|
@glob_if_not_url = glob_if_not_url
|
20
18
|
end
|
21
19
|
|
20
|
+
def statement_type()
|
21
|
+
return 'archive'
|
22
|
+
end
|
23
|
+
|
22
24
|
def asset_name()
|
23
25
|
return standard_asset_name()
|
24
26
|
end
|
data/lib/fig/statement/asset.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
|
1
3
|
require 'fig/parser'
|
2
4
|
require 'fig/statement'
|
5
|
+
require 'fig/string_tokenizer'
|
3
6
|
require 'fig/url'
|
4
7
|
|
5
8
|
module Fig; end
|
@@ -7,7 +10,7 @@ class Fig::Statement; end
|
|
7
10
|
|
8
11
|
# Some sort of file to be included in a package.
|
9
12
|
module Fig::Statement::Asset
|
10
|
-
attr_reader :
|
13
|
+
attr_reader :location
|
11
14
|
|
12
15
|
def self.included(class_included_into)
|
13
16
|
class_included_into.extend(ClassMethods)
|
@@ -20,7 +23,7 @@ module Fig::Statement::Asset
|
|
20
23
|
end
|
21
24
|
|
22
25
|
def urls()
|
23
|
-
return [
|
26
|
+
return [location()]
|
24
27
|
end
|
25
28
|
|
26
29
|
def is_asset?()
|
@@ -28,57 +31,69 @@ module Fig::Statement::Asset
|
|
28
31
|
end
|
29
32
|
|
30
33
|
def requires_globbing?()
|
31
|
-
return glob_if_not_url? && ! Fig::URL.is_url?(
|
34
|
+
return glob_if_not_url? && ! Fig::URL.is_url?(location())
|
32
35
|
end
|
33
36
|
|
34
37
|
def standard_asset_name()
|
35
|
-
# Not so hot of an idea if the URL has query parameters
|
36
|
-
# going to fix this now.
|
37
|
-
|
38
|
-
end
|
38
|
+
# Not so hot of an idea if the location is a URL and has query parameters
|
39
|
+
# in it, but not going to fix this now.
|
40
|
+
basename = location().split('/').last
|
39
41
|
|
40
|
-
|
41
|
-
|
42
|
+
if Fig::URL.is_url? location
|
43
|
+
return CGI.unescape basename
|
44
|
+
end
|
42
45
|
|
43
|
-
|
44
|
-
|
46
|
+
return basename
|
47
|
+
end
|
45
48
|
|
46
|
-
|
47
|
-
return
|
49
|
+
def minimum_grammar_for_emitting_input()
|
50
|
+
return minimum_grammar_for_value location
|
51
|
+
end
|
48
52
|
|
49
|
-
|
53
|
+
def minimum_grammar_for_publishing()
|
54
|
+
return minimum_grammar_for_value asset_name
|
50
55
|
end
|
51
56
|
|
52
57
|
private
|
53
58
|
|
54
|
-
|
55
|
-
|
56
|
-
def validate_and_process_escapes_in_url!(url, &block)
|
57
|
-
was_in_single_quotes =
|
58
|
-
Fig::Statement.strip_quotes_and_process_escapes!(url, &block)
|
59
|
-
return if was_in_single_quotes.nil?
|
60
|
-
|
61
|
-
if url.include? '@'
|
62
|
-
yield %q<contains an "@", which isn't permitted in order to allow for package substitution.>
|
63
|
-
return
|
64
|
-
end
|
59
|
+
def minimum_grammar_for_value(value)
|
60
|
+
return [0] if value.nil?
|
65
61
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
end
|
62
|
+
if value =~ /\s/
|
63
|
+
return [1, 'contains whitespace']
|
64
|
+
end
|
70
65
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
66
|
+
# Can't have octothorpes anywhere in v0 due to comment stripping via
|
67
|
+
# regex.
|
68
|
+
if value =~ /#/
|
69
|
+
return [1, 'contains a "#" character']
|
70
|
+
end
|
71
|
+
|
72
|
+
if ! glob_if_not_url? && value =~ / ( [*?\[\]{}] ) /x
|
73
|
+
return [
|
74
|
+
1, %Q<contains a glob character ("#{$1}") which should not be globbed>
|
75
|
+
]
|
76
|
+
end
|
77
|
+
|
78
|
+
if value =~ / ( ["'<>|] ) /x
|
79
|
+
return [1, %Q<contains a "#{$1}" character>]
|
80
|
+
end
|
81
|
+
|
82
|
+
return [0]
|
83
|
+
end
|
84
|
+
|
85
|
+
module ClassMethods
|
86
|
+
def validate_and_process_escapes_in_location(location, &block)
|
87
|
+
tokenizer = Fig::StringTokenizer.new
|
88
|
+
tokenized_string = tokenizer.tokenize(location, &block)
|
89
|
+
return if ! tokenized_string
|
75
90
|
|
76
91
|
# "config" is a reasonable asset name, so we let that pass.
|
77
|
-
if Fig::Parser.strict_keyword?(
|
92
|
+
if Fig::Parser.strict_keyword?(tokenized_string.to_expanded_string)
|
78
93
|
yield 'is a keyword.'
|
79
94
|
end
|
80
95
|
|
81
|
-
return
|
96
|
+
return tokenized_string
|
82
97
|
end
|
83
98
|
end
|
84
99
|
end
|
@@ -13,11 +13,15 @@ class Fig::Statement::Command < Fig::Statement
|
|
13
13
|
@command = command
|
14
14
|
end
|
15
15
|
|
16
|
+
def statement_type()
|
17
|
+
return 'command'
|
18
|
+
end
|
19
|
+
|
16
20
|
def unparse_as_version(unparser)
|
17
21
|
return unparser.command(self)
|
18
22
|
end
|
19
23
|
|
20
|
-
def
|
21
|
-
return 0
|
24
|
+
def minimum_grammar_for_publishing()
|
25
|
+
return [0]
|
22
26
|
end
|
23
27
|
end
|
@@ -21,6 +21,10 @@ class Fig::Statement::Configuration < Fig::Statement
|
|
21
21
|
@statements = [overrides, others].flatten
|
22
22
|
end
|
23
23
|
|
24
|
+
def statement_type()
|
25
|
+
return 'config'
|
26
|
+
end
|
27
|
+
|
24
28
|
def command_statement
|
25
29
|
return statements.find do
|
26
30
|
|statement| statement.is_a?(Fig::Statement::Command)
|
@@ -39,7 +43,11 @@ class Fig::Statement::Configuration < Fig::Statement
|
|
39
43
|
return unparser.configuration(self)
|
40
44
|
end
|
41
45
|
|
42
|
-
def
|
43
|
-
return 0
|
46
|
+
def minimum_grammar_for_emitting_input()
|
47
|
+
return [0]
|
48
|
+
end
|
49
|
+
|
50
|
+
def minimum_grammar_for_publishing()
|
51
|
+
return [0]
|
44
52
|
end
|
45
53
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Fig; end
|
2
|
+
class Fig::Statement; end
|
3
|
+
|
4
|
+
# A statement that manipulates an environment variable.
|
5
|
+
module Fig::Statement::EnvironmentVariable
|
6
|
+
attr_reader :name, :value
|
7
|
+
|
8
|
+
def minimum_grammar_for_emitting_input()
|
9
|
+
return minimum_grammar()
|
10
|
+
end
|
11
|
+
|
12
|
+
def minimum_grammar_for_publishing()
|
13
|
+
return minimum_grammar()
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def minimum_grammar()
|
19
|
+
if value =~ /\s/
|
20
|
+
return [1, 'contains whitespace']
|
21
|
+
end
|
22
|
+
|
23
|
+
# Can't have octothorpes anywhere in v0 due to comment stripping via
|
24
|
+
# regex.
|
25
|
+
if value =~ /#/
|
26
|
+
return [1, 'contains a "#" character']
|
27
|
+
end
|
28
|
+
|
29
|
+
if value =~ / ( ["'] ) /x
|
30
|
+
return [1, %Q<contains a "#{$1}" character>]
|
31
|
+
end
|
32
|
+
|
33
|
+
return [0]
|
34
|
+
end
|
35
|
+
end
|
@@ -12,11 +12,15 @@ class Fig::Statement::GrammarVersion < Fig::Statement
|
|
12
12
|
@version = version
|
13
13
|
end
|
14
14
|
|
15
|
+
def statement_type()
|
16
|
+
return 'grammar'
|
17
|
+
end
|
18
|
+
|
15
19
|
def unparse_as_version(unparser)
|
16
20
|
return unparser.grammar_version(self)
|
17
21
|
end
|
18
22
|
|
19
|
-
def
|
20
|
-
return version
|
23
|
+
def minimum_grammar_for_publishing()
|
24
|
+
return [version]
|
21
25
|
end
|
22
26
|
end
|
@@ -23,6 +23,10 @@ class Fig::Statement::Include < Fig::Statement
|
|
23
23
|
@containing_package_descriptor = containing_package_descriptor
|
24
24
|
end
|
25
25
|
|
26
|
+
def statement_type()
|
27
|
+
return 'include'
|
28
|
+
end
|
29
|
+
|
26
30
|
def package_name
|
27
31
|
return @descriptor.name
|
28
32
|
end
|
@@ -66,8 +70,8 @@ class Fig::Statement::Include < Fig::Statement
|
|
66
70
|
return unparser.include(self)
|
67
71
|
end
|
68
72
|
|
69
|
-
def
|
70
|
-
return 0
|
73
|
+
def minimum_grammar_for_publishing()
|
74
|
+
return [0]
|
71
75
|
end
|
72
76
|
|
73
77
|
private
|
@@ -33,11 +33,15 @@ class Fig::Statement::Override < Fig::Statement
|
|
33
33
|
@version = version
|
34
34
|
end
|
35
35
|
|
36
|
+
def statement_type()
|
37
|
+
return 'override'
|
38
|
+
end
|
39
|
+
|
36
40
|
def unparse_as_version(unparser)
|
37
41
|
return unparser.override(self)
|
38
42
|
end
|
39
43
|
|
40
|
-
def
|
41
|
-
return 0
|
44
|
+
def minimum_grammar_for_publishing()
|
45
|
+
return [0]
|
42
46
|
end
|
43
47
|
end
|
data/lib/fig/statement/path.rb
CHANGED
@@ -1,10 +1,13 @@
|
|
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 specifies or modifies a path environment variable, e.g.
|
6
7
|
# "append", "path", "add" (though those are all synonyms).
|
7
8
|
class Fig::Statement::Path < Fig::Statement
|
9
|
+
include Fig::Statement::EnvironmentVariable
|
10
|
+
|
8
11
|
# We block single-quotes right now in order to allow for using them for
|
9
12
|
# quoting later.
|
10
13
|
VALUE_REGEX = %r< \A [^;:'"<>|\s]+ \z >x
|
@@ -27,8 +30,6 @@ class Fig::Statement::Path < Fig::Statement
|
|
27
30
|
return [variable, value]
|
28
31
|
end
|
29
32
|
|
30
|
-
attr_reader :name, :value
|
31
|
-
|
32
33
|
def initialize(line_column, source_description, name, value)
|
33
34
|
super(line_column, source_description)
|
34
35
|
|
@@ -36,6 +37,10 @@ class Fig::Statement::Path < Fig::Statement
|
|
36
37
|
@value = value
|
37
38
|
end
|
38
39
|
|
40
|
+
def statement_type()
|
41
|
+
return 'path'
|
42
|
+
end
|
43
|
+
|
39
44
|
def is_environment_variable?()
|
40
45
|
return true
|
41
46
|
end
|
@@ -43,10 +48,4 @@ class Fig::Statement::Path < Fig::Statement
|
|
43
48
|
def unparse_as_version(unparser)
|
44
49
|
return unparser.path(self)
|
45
50
|
end
|
46
|
-
|
47
|
-
def minimum_grammar_version_required()
|
48
|
-
# TODO: fix this once going through
|
49
|
-
# Statement.strip_quotes_and_process_escapes()
|
50
|
-
return 0
|
51
|
-
end
|
52
51
|
end
|