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.
Files changed (55) hide show
  1. data/Changes +58 -1
  2. data/bin/fig +1 -1
  3. data/lib/fig.rb +1 -1
  4. data/lib/fig/command.rb +3 -3
  5. data/lib/fig/command/action/dump_package_definition_parsed.rb +5 -4
  6. data/lib/fig/command/action/list_variables/all_configs.rb +2 -5
  7. data/lib/fig/command/action/publish_local.rb +1 -1
  8. data/lib/fig/command/action/role/list_variables_in_a_tree.rb +2 -5
  9. data/lib/fig/command/action/run_command_line.rb +10 -3
  10. data/lib/fig/command/action/run_command_statement.rb +1 -1
  11. data/lib/fig/command/options.rb +8 -7
  12. data/lib/fig/command/options/parser.rb +1 -1
  13. data/lib/fig/environment_variables/case_insensitive.rb +1 -1
  14. data/lib/fig/environment_variables/case_sensitive.rb +1 -1
  15. data/lib/fig/figrc.rb +10 -10
  16. data/lib/fig/{not_found_error.rb → file_not_found_error.rb} +1 -1
  17. data/lib/fig/grammar/v0.rb +174 -173
  18. data/lib/fig/grammar/v0.treetop +27 -21
  19. data/lib/fig/grammar/v1.rb +477 -171
  20. data/lib/fig/grammar/v1.treetop +34 -22
  21. data/lib/fig/operating_system.rb +139 -60
  22. data/lib/fig/package.rb +8 -4
  23. data/lib/fig/package_definition_text_assembler.rb +31 -23
  24. data/lib/fig/parser.rb +3 -5
  25. data/lib/fig/parser_package_build_state.rb +15 -14
  26. data/lib/fig/repository.rb +41 -28
  27. data/lib/fig/repository_package_publisher.rb +20 -25
  28. data/lib/fig/runtime_environment.rb +136 -87
  29. data/lib/fig/statement.rb +15 -116
  30. data/lib/fig/statement/archive.rb +6 -4
  31. data/lib/fig/statement/asset.rb +50 -35
  32. data/lib/fig/statement/command.rb +6 -2
  33. data/lib/fig/statement/configuration.rb +10 -2
  34. data/lib/fig/statement/environment_variable.rb +35 -0
  35. data/lib/fig/statement/grammar_version.rb +6 -2
  36. data/lib/fig/statement/include.rb +6 -2
  37. data/lib/fig/statement/override.rb +6 -2
  38. data/lib/fig/statement/path.rb +7 -8
  39. data/lib/fig/statement/resource.rb +7 -3
  40. data/lib/fig/statement/retrieve.rb +10 -2
  41. data/lib/fig/statement/set.rb +7 -8
  42. data/lib/fig/string_tokenizer.rb +195 -0
  43. data/lib/fig/tokenized_string.rb +22 -0
  44. data/lib/fig/tokenized_string/plain_segment.rb +24 -0
  45. data/lib/fig/tokenized_string/token.rb +18 -0
  46. data/lib/fig/unparser.rb +84 -1
  47. data/lib/fig/unparser/v0.rb +4 -0
  48. data/lib/fig/unparser/v1.rb +7 -7
  49. data/lib/fig/url.rb +12 -1
  50. data/lib/fig/{url_access_error.rb → url_access_disallowed_error.rb} +2 -2
  51. metadata +129 -128
  52. data/lib/fig/grammar/v0_asset_location.rb +0 -162
  53. data/lib/fig/grammar/v0_ish.rb +0 -1356
  54. data/lib/fig/grammar/v1_asset_location.rb +0 -162
  55. data/lib/fig/grammar/v2.rb +0 -1478
@@ -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
- def minimum_grammar_version_required()
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
- attr_reader :url
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
- @url = url
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
@@ -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 :url
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 [ url() ]
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?(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 in it, but not
36
- # going to fix this now.
37
- return url().split('/').last()
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
- def minimum_grammar_version_required()
41
- return 1 if url =~ /\s/
42
+ if Fig::URL.is_url? location
43
+ return CGI.unescape basename
44
+ end
42
45
 
43
- # Can't have octothorpes anywhere in v0 due to comment stripping via regex.
44
- return 1 if url =~ /#/
46
+ return basename
47
+ end
45
48
 
46
- # If we shouldn't glob, but we've got glob characters...
47
- return 1 if ! glob_if_not_url? && url =~ /[*?\[\]{}]/
49
+ def minimum_grammar_for_emitting_input()
50
+ return minimum_grammar_for_value location
51
+ end
48
52
 
49
- return 0
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
- module ClassMethods
55
- # Modifies the parameter to deal with quoting, escaping.
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
- if url =~ / ( ["<>|] ) /x
67
- yield %Q<contains a "#{$1}", which isn't permitted because Windows doesn't allow it in file names.>
68
- return
69
- end
62
+ if value =~ /\s/
63
+ return [1, 'contains whitespace']
64
+ end
70
65
 
71
- if url =~ / ( ' ) /x
72
- yield %Q<contains a "#{$1}", which isn't permitted to allow for future grammar expansion.>
73
- return
74
- end
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?(url)
92
+ if Fig::Parser.strict_keyword?(tokenized_string.to_expanded_string)
78
93
  yield 'is a keyword.'
79
94
  end
80
95
 
81
- return ! was_in_single_quotes
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 minimum_grammar_version_required()
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 minimum_grammar_version_required()
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 minimum_grammar_version_required()
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 minimum_grammar_version_required()
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 minimum_grammar_version_required()
41
- return 0
44
+ def minimum_grammar_for_publishing()
45
+ return [0]
42
46
  end
43
47
  end
@@ -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