fig 0.1.73 → 0.1.75

Sign up to get free protection for your applications and to get access to all the features.
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