fig 0.1.73 → 0.1.75

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 (50) hide show
  1. data/Changes +75 -0
  2. data/lib/fig.rb +1 -1
  3. data/lib/fig/command.rb +36 -12
  4. data/lib/fig/command/action.rb +1 -1
  5. data/lib/fig/command/action/dump_package_definition_parsed.rb +4 -6
  6. data/lib/fig/command/action/run_command_statement.rb +3 -2
  7. data/lib/fig/command/options.rb +12 -3
  8. data/lib/fig/command/options/parser.rb +2 -0
  9. data/lib/fig/command/package_loader.rb +1 -0
  10. data/lib/fig/config_file_error.rb +1 -1
  11. data/lib/fig/grammar/base.rb +214 -0
  12. data/lib/fig/grammar/base.treetop +29 -0
  13. data/lib/fig/grammar/v0.rb +1493 -0
  14. data/lib/fig/grammar/v0.treetop +167 -0
  15. data/lib/fig/grammar/v1.rb +1478 -0
  16. data/lib/fig/grammar/v1.treetop +174 -0
  17. data/lib/fig/grammar/version.rb +144 -0
  18. data/lib/fig/grammar/version.treetop +22 -0
  19. data/lib/fig/grammar/version_identification.rb +113 -0
  20. data/lib/fig/grammar/version_identification.treetop +27 -0
  21. data/lib/fig/log4r_config_error.rb +1 -1
  22. data/lib/fig/no_such_package_config_error.rb +1 -1
  23. data/lib/fig/not_found_error.rb +7 -0
  24. data/lib/fig/operating_system.rb +31 -20
  25. data/lib/fig/package.rb +8 -3
  26. data/lib/fig/package_definition_text_assembler.rb +88 -0
  27. data/lib/fig/package_descriptor_parse_error.rb +1 -1
  28. data/lib/fig/parser.rb +115 -29
  29. data/lib/fig/parser_package_build_state.rb +38 -11
  30. data/lib/fig/repository.rb +5 -8
  31. data/lib/fig/repository_package_publisher.rb +114 -96
  32. data/lib/fig/runtime_environment.rb +42 -14
  33. data/lib/fig/statement.rb +133 -0
  34. data/lib/fig/statement/archive.rb +6 -4
  35. data/lib/fig/statement/asset.rb +28 -34
  36. data/lib/fig/statement/command.rb +6 -2
  37. data/lib/fig/statement/configuration.rb +4 -12
  38. data/lib/fig/statement/grammar_version.rb +22 -0
  39. data/lib/fig/statement/include.rb +5 -6
  40. data/lib/fig/statement/override.rb +6 -3
  41. data/lib/fig/statement/path.rb +12 -2
  42. data/lib/fig/statement/resource.rb +8 -8
  43. data/lib/fig/statement/retrieve.rb +11 -3
  44. data/lib/fig/statement/set.rb +12 -2
  45. data/lib/fig/unparser.rb +127 -0
  46. data/lib/fig/unparser/v0.rb +84 -0
  47. data/lib/fig/unparser/v1.rb +77 -0
  48. data/lib/fig/url.rb +7 -0
  49. metadata +139 -25
  50. data/lib/fig/grammar.treetop +0 -147
@@ -9,6 +9,7 @@ require 'fig/statement/include'
9
9
  require 'fig/statement/path'
10
10
  require 'fig/statement/set'
11
11
  require 'fig/user_input_error'
12
+ require 'fig/unparser/v0'
12
13
 
13
14
  module Fig; end
14
15
 
@@ -106,19 +107,25 @@ class Fig::RuntimeEnvironment
106
107
  return
107
108
  end
108
109
 
109
- def execute_config(base_package, descriptor, args, &block)
110
+ def execute_config(base_package, base_config, descriptor, args, &block)
110
111
  config_name =
111
- descriptor.config || find_config_name_in_package(descriptor.name)
112
-
113
- name = descriptor.name || base_package.name
114
- package = lookup_package(
115
- name,
116
- descriptor.version,
117
- Fig::IncludeBacktrace.new(
118
- nil,
119
- Fig::PackageDescriptor.new(name, descriptor.version, config_name)
112
+ determine_config_to_executed(base_package, base_config, descriptor)
113
+
114
+ package = nil
115
+
116
+ if descriptor
117
+ name = descriptor.name || base_package.name
118
+ package = lookup_package(
119
+ name,
120
+ descriptor.version,
121
+ Fig::IncludeBacktrace.new(
122
+ nil,
123
+ Fig::PackageDescriptor.new(name, descriptor.version, config_name)
124
+ )
120
125
  )
121
- )
126
+ else
127
+ package = base_package
128
+ end
122
129
 
123
130
  command_statement = package[config_name].command_statement
124
131
  if command_statement
@@ -148,7 +155,9 @@ class Fig::RuntimeEnvironment
148
155
  when Fig::Statement::Command
149
156
  # Skip - has no effect on environment.
150
157
  else
151
- raise "Unexpected statement in a config block: #{statement.unparse('')}"
158
+ unparser = Fig::Unparser::V0.new :emit_as_to_be_published
159
+ text = unparser.unparse([statement]).strip
160
+ raise "Unexpected statement in a config block: #{text}"
152
161
  end
153
162
 
154
163
  return
@@ -191,8 +200,10 @@ class Fig::RuntimeEnvironment
191
200
 
192
201
  statement = @retrieves[name]
193
202
  if statement.loaded_but_not_referenced?
203
+ unparser = Fig::Unparser::V0.new :emit_as_to_be_published
204
+ text = unparser.unparse([statement]).strip
194
205
  Fig::Logging.warn \
195
- %Q<The #{name} variable was never referenced or didn't need expansion, so "#{statement.unparse('')}"#{statement.position_string} was ignored.>
206
+ %Q<The #{name} variable was never referenced or didn't need expansion, so "#{text}"#{statement.position_string} was ignored.>
196
207
  end
197
208
  end
198
209
  end
@@ -264,12 +275,29 @@ class Fig::RuntimeEnvironment
264
275
  return package
265
276
  end
266
277
 
267
- def find_config_name_in_package(name)
278
+ def determine_config_to_executed(base_package, base_config, descriptor)
279
+ return base_config if base_config
280
+
281
+ if descriptor
282
+ return descriptor.config if descriptor.config
283
+
284
+ config_name = find_config_name_in_package_named(descriptor.name)
285
+ return config_name if config_name
286
+ end
287
+
288
+ return find_config_name_in_package(base_package)
289
+ end
290
+
291
+ def find_config_name_in_package_named(name)
268
292
  package = get_package(name)
269
293
  if not package
270
294
  return Fig::Package::DEFAULT_CONFIG
271
295
  end
272
296
 
297
+ return find_config_name_in_package(package)
298
+ end
299
+
300
+ def find_config_name_in_package(package)
273
301
  return package.primary_config_name || Fig::Package::DEFAULT_CONFIG
274
302
  end
275
303
 
@@ -1,3 +1,7 @@
1
+ # coding: utf-8
2
+
3
+ require 'set'
4
+
1
5
  module Fig; end
2
6
 
3
7
  # A statement within a package definition file (package.fig).
@@ -22,6 +26,121 @@ class Fig::Statement
22
26
  return description
23
27
  end
24
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
+
25
144
  # This mess of getting these as a single array necessary is due to
26
145
  # limitations of the "*" array splat operator in ruby v1.8.
27
146
  def initialize(line_column, source_description)
@@ -37,6 +156,14 @@ class Fig::Statement
37
156
  return
38
157
  end
39
158
 
159
+ def unparse_as_version(unparser)
160
+ raise NotImplementedError
161
+ end
162
+
163
+ def minimum_grammar_version_required()
164
+ raise NotImplementedError
165
+ end
166
+
40
167
  def urls()
41
168
  return []
42
169
  end
@@ -45,6 +172,10 @@ class Fig::Statement
45
172
  return false
46
173
  end
47
174
 
175
+ def is_environment_variable?()
176
+ return false
177
+ end
178
+
48
179
  # Returns a representation of the position of this statement, if the position
49
180
  # is known, empty string otherwise. This is written with the idea that you
50
181
  # can do something like "puts %Q<Found a
@@ -56,3 +187,5 @@ class Fig::Statement
56
187
  )
57
188
  end
58
189
  end
190
+
191
+ # vim: set fileencoding=utf8 :
@@ -2,6 +2,7 @@ require 'fig/statement'
2
2
  require 'fig/statement/asset'
3
3
 
4
4
  module Fig; end
5
+ class Fig::Statement; end
5
6
 
6
7
  # Specifies an archive file (possibly via a URL) that is part of a package.
7
8
  #
@@ -11,17 +12,18 @@ class Fig::Statement::Archive < Fig::Statement
11
12
 
12
13
  attr_reader :url
13
14
 
14
- def initialize(line_column, source_description, url)
15
+ def initialize(line_column, source_description, url, glob_if_not_url)
15
16
  super(line_column, source_description)
16
17
 
17
- set_up_url(url)
18
+ @url = url
19
+ @glob_if_not_url = glob_if_not_url
18
20
  end
19
21
 
20
22
  def asset_name()
21
23
  return standard_asset_name()
22
24
  end
23
25
 
24
- def unparse(indent)
25
- %Q<#{indent}archive "#{url}">
26
+ def unparse_as_version(unparser)
27
+ return unparser.archive(self)
26
28
  end
27
29
  end
@@ -1,18 +1,22 @@
1
1
  require 'fig/parser'
2
+ require 'fig/statement'
3
+ require 'fig/url'
2
4
 
3
5
  module Fig; end
4
6
  class Fig::Statement; end
5
7
 
6
8
  # Some sort of file to be included in a package.
7
9
  module Fig::Statement::Asset
10
+ attr_reader :url
11
+
8
12
  def self.included(class_included_into)
9
13
  class_included_into.extend(ClassMethods)
10
14
 
11
15
  return
12
16
  end
13
17
 
14
- def glob?()
15
- return @glob
18
+ def glob_if_not_url?()
19
+ return @glob_if_not_url
16
20
  end
17
21
 
18
22
  def urls()
@@ -23,44 +27,36 @@ module Fig::Statement::Asset
23
27
  return true
24
28
  end
25
29
 
30
+ def requires_globbing?()
31
+ return glob_if_not_url? && ! Fig::URL.is_url?(url())
32
+ end
33
+
26
34
  def standard_asset_name()
27
35
  # Not so hot of an idea if the URL has query parameters in it, but not
28
36
  # going to fix this now.
29
37
  return url().split('/').last()
30
38
  end
31
39
 
32
- private
40
+ def minimum_grammar_version_required()
41
+ return 1 if url =~ /\s/
33
42
 
34
- def set_up_url(url)
35
- # Damn you Ruby 1.8!!!!
36
- if url[0..0] == '"'
37
- @url = url[1..-2]
38
- @glob = true
39
- else
40
- @url = url
41
- @glob = false
42
- end
43
+ # Can't have octothorpes anywhere in v0 due to comment stripping via regex.
44
+ return 1 if url =~ /#/
43
45
 
44
- return
45
- end
46
+ # If we shouldn't glob, but we've got glob characters...
47
+ return 1 if ! glob_if_not_url? && url =~ /[*?\[\]{}]/
46
48
 
47
- module ClassMethods
48
- def validate_url(url)
49
- # Damn you Ruby 1.8!!!!
50
- if url[0..0] == '"' && url[-1..-1] != '"' ||
51
- url[0..0] != '"' && url[-1..-1] == '"'
52
- yield 'has unbalanced quotes.'
53
- return
54
- end
49
+ return 0
50
+ end
55
51
 
56
- if url[0..0] == '"'
57
- if url.length < 3
58
- yield 'is empty'
59
- return
60
- end
52
+ private
61
53
 
62
- url = url[1..-2]
63
- end
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?
64
60
 
65
61
  if url.include? '@'
66
62
  yield %q<contains an "@", which isn't permitted in order to allow for package substitution.>
@@ -72,10 +68,8 @@ module Fig::Statement::Asset
72
68
  return
73
69
  end
74
70
 
75
- if url =~ / \s /x
76
- # We may need to allow a space character in the future, but this will
77
- # require a change to the grammar.
78
- yield %q<contains whitespace.>
71
+ if url =~ / ( ' ) /x
72
+ yield %Q<contains a "#{$1}", which isn't permitted to allow for future grammar expansion.>
79
73
  return
80
74
  end
81
75
 
@@ -84,7 +78,7 @@ module Fig::Statement::Asset
84
78
  yield 'is a keyword.'
85
79
  end
86
80
 
87
- return
81
+ return ! was_in_single_quotes
88
82
  end
89
83
  end
90
84
  end
@@ -13,7 +13,11 @@ class Fig::Statement::Command < Fig::Statement
13
13
  @command = command
14
14
  end
15
15
 
16
- def unparse(indent)
17
- %Q<#{indent}command "#{@command}">
16
+ def unparse_as_version(unparser)
17
+ return unparser.command(self)
18
+ end
19
+
20
+ def minimum_grammar_version_required()
21
+ return 0
18
22
  end
19
23
  end
@@ -35,19 +35,11 @@ class Fig::Statement::Configuration < Fig::Statement
35
35
  end
36
36
  end
37
37
 
38
- def unparse(indent)
39
- unparse_statements(indent, "config #{@name}", @statements, 'end')
38
+ def unparse_as_version(unparser)
39
+ return unparser.configuration(self)
40
40
  end
41
41
 
42
- private
43
-
44
- def unparse_statements(indent, prefix, statements, suffix)
45
- body =
46
- @statements.map {|statement| statement.unparse(indent + ' ') }.join("\n")
47
- if body.length > 0
48
- body << "\n"
49
- end
50
-
51
- return "\n#{indent}#{prefix}\n#{body}#{indent}#{suffix}"
42
+ def minimum_grammar_version_required()
43
+ return 0
52
44
  end
53
45
  end
@@ -0,0 +1,22 @@
1
+ require 'fig/statement'
2
+
3
+ module Fig; end
4
+
5
+ # A statement that declares the syntax that a package is to be serialized in.
6
+ class Fig::Statement::GrammarVersion < Fig::Statement
7
+ attr_reader :version
8
+
9
+ def initialize(line_column, source_description, version)
10
+ super(line_column, source_description)
11
+
12
+ @version = version
13
+ end
14
+
15
+ def unparse_as_version(unparser)
16
+ return unparser.grammar_version(self)
17
+ end
18
+
19
+ def minimum_grammar_version_required()
20
+ return version
21
+ end
22
+ end