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
@@ -0,0 +1,27 @@
1
+ # Treetop (http://treetop.rubyforge.org/) grammar for determining package
2
+ # definition versions.
3
+
4
+ require 'treetop'
5
+
6
+ require 'fig/grammar/base'
7
+ require 'fig/grammar/version'
8
+
9
+ module Fig
10
+ module Grammar
11
+ grammar VersionIdentification
12
+ include Fig::Grammar::Base
13
+ include Fig::Grammar::Version
14
+
15
+ rule everything
16
+ ws_or_comment* grammar_version:grammar_version? .* {
17
+ def get_grammar_version(build_state)
18
+ return if not grammar_version
19
+ return if grammar_version.text_value.empty?
20
+
21
+ return grammar_version.to_package_statement(build_state)
22
+ end
23
+ }
24
+ end
25
+ end
26
+ end
27
+ end
@@ -3,7 +3,7 @@ require 'fig/user_input_error'
3
3
  module Fig
4
4
  # A problem with configuring Log4r.
5
5
  class Log4rConfigError < UserInputError
6
- attr_accessor :config_file, :original_exception
6
+ attr_reader :config_file, :original_exception
7
7
 
8
8
  def initialize(config_file, original_exception)
9
9
  super(
@@ -4,7 +4,7 @@ require 'fig/user_input_error'
4
4
  module Fig
5
5
  # User specified a configuration for a Package that does not exist.
6
6
  class NoSuchPackageConfigError < UserInputError
7
- attr_accessor :descriptor
7
+ attr_reader :descriptor
8
8
 
9
9
  def initialize(message, descriptor)
10
10
  super(message)
@@ -3,5 +3,12 @@ module Fig
3
3
  # may not actually be a problem; i.e. this may be the result of an existence
4
4
  # test.
5
5
  class NotFoundError < StandardError
6
+ attr_reader :path
7
+
8
+ def initialize(message, path)
9
+ super(message)
10
+
11
+ @path = path
12
+ end
6
13
  end
7
14
  end
@@ -32,10 +32,12 @@ class Fig::OperatingSystem
32
32
  end
33
33
 
34
34
  def get_username()
35
+ # #ask() comes from highline
35
36
  @username ||= ask('Username: ') { |q| q.echo = true }
36
37
  end
37
38
 
38
39
  def get_password()
40
+ # #ask() comes from highline
39
41
  @password ||= ask('Password: ') { |q| q.echo = false }
40
42
  end
41
43
 
@@ -177,10 +179,10 @@ class Fig::OperatingSystem
177
179
  end
178
180
  rescue Net::FTPPermError => error
179
181
  Fig::Logging.debug error.message
180
- raise Fig::NotFoundError.new
182
+ raise Fig::NotFoundError.new error.message, url
181
183
  rescue SocketError => error
182
184
  Fig::Logging.debug error.message
183
- raise Fig::NotFoundError.new
185
+ raise Fig::NotFoundError.new error.message, url
184
186
  end
185
187
  when 'http'
186
188
  log_download(url, path)
@@ -191,10 +193,10 @@ class Fig::OperatingSystem
191
193
  download_via_http_get(url, file)
192
194
  rescue SystemCallError => error
193
195
  Fig::Logging.debug error.message
194
- raise Fig::NotFoundError.new
196
+ raise Fig::NotFoundError.new error.message, url
195
197
  rescue SocketError => error
196
198
  Fig::Logging.debug error.message
197
- raise Fig::NotFoundError.new
199
+ raise Fig::NotFoundError.new error.message, url
198
200
  end
199
201
  end
200
202
  when 'ssh'
@@ -208,8 +210,8 @@ class Fig::OperatingSystem
208
210
  begin
209
211
  FileUtils.cp(uri.path, path)
210
212
  return true
211
- rescue Errno::ENOENT
212
- raise Fig::NotFoundError.new
213
+ rescue Errno::ENOENT => error
214
+ raise Fig::NotFoundError.new error.message, url
213
215
  end
214
216
  else
215
217
  Fig::Logging.fatal "Unknown protocol: #{url}"
@@ -217,29 +219,36 @@ class Fig::OperatingSystem
217
219
  end
218
220
  end
219
221
 
220
- def download_resource(url, dir)
221
- FileUtils.mkdir_p(dir)
222
- download(url, File.join(dir, URI.parse(url).path.split('/').last))
223
- end
222
+ # Returns the basename and full path to the download.
223
+ def download_resource(url, download_directory)
224
+ FileUtils.mkdir_p(download_directory)
224
225
 
225
- def download_and_unpack_archive(url, dir)
226
- FileUtils.mkdir_p(dir)
227
226
  basename = URI.parse(url).path.split('/').last
228
- path = File.join(dir, basename)
227
+ path = File.join(download_directory, basename)
228
+
229
229
  download(url, path)
230
+
231
+ return basename, path
232
+ end
233
+
234
+ def download_and_unpack_archive(url, download_directory)
235
+ basename, path = download_resource(url, download_directory)
236
+
230
237
  case basename
231
238
  when /\.tar\.gz$/
232
- unpack_archive(dir, path)
239
+ unpack_archive(download_directory, path)
233
240
  when /\.tgz$/
234
- unpack_archive(dir, path)
241
+ unpack_archive(download_directory, path)
235
242
  when /\.tar\.bz2$/
236
- unpack_archive(dir, path)
243
+ unpack_archive(download_directory, path)
237
244
  when /\.zip$/
238
- unpack_archive(dir, path)
245
+ unpack_archive(download_directory, path)
239
246
  else
240
247
  Fig::Logging.fatal "Unknown archive type: #{basename}"
241
248
  raise Fig::NetworkError.new("Unknown archive type: #{basename}")
242
249
  end
250
+
251
+ return
243
252
  end
244
253
 
245
254
  def upload(local_file, remote_file)
@@ -429,7 +438,7 @@ class Fig::OperatingSystem
429
438
  return false
430
439
  when NOT_FOUND
431
440
  tempfile.delete
432
- raise Fig::NotFoundError.new
441
+ raise Fig::NotFoundError.new 'Remote path not found', path
433
442
  when SUCCESS
434
443
  FileUtils.mv(tempfile.path, path)
435
444
  return true
@@ -454,7 +463,7 @@ class Fig::OperatingSystem
454
463
  def download_via_http_get(uri_string, file, redirection_limit = 10)
455
464
  if redirection_limit < 1
456
465
  Fig::Logging.debug 'Too many HTTP redirects.'
457
- raise Fig::NotFoundError.new
466
+ raise Fig::NotFoundError.new 'Too many HTTP redirects.', uri_string
458
467
  end
459
468
 
460
469
  response = Net::HTTP.get_response(URI(uri_string))
@@ -468,7 +477,9 @@ class Fig::OperatingSystem
468
477
  download_via_http_get(location, file, limit - 1)
469
478
  else
470
479
  Fig::Logging.debug "Download failed: #{response.code} #{response.message}."
471
- raise Fig::NotFoundError.new
480
+ raise Fig::NotFoundError.new(
481
+ "Download failed: #{response.code} #{response.message}.", uri_string
482
+ )
472
483
  end
473
484
 
474
485
  return
@@ -16,11 +16,14 @@ module Fig; end
16
16
  class Fig::Package
17
17
  include Comparable
18
18
 
19
- UNPUBLISHED = '<unpublished>'
20
19
  DEFAULT_CONFIG = 'default'
21
20
 
22
- attr_reader :name, :version, :directory, :statements
23
- attr_accessor :backtrace, :unparsed_text
21
+ attr_reader :name
22
+ attr_reader :version
23
+ attr_reader :directory
24
+ attr_reader :statements
25
+ attr_accessor :backtrace
26
+ attr_accessor :unparsed_text
24
27
 
25
28
  def initialize(name, version, directory, statements)
26
29
  @name = name
@@ -151,6 +154,8 @@ class Fig::Package
151
154
 
152
155
  private
153
156
 
157
+ UNPUBLISHED = '<unpublished>'
158
+
154
159
  def compare_components(mine, others)
155
160
  if mine.nil?
156
161
  if others.nil?
@@ -0,0 +1,88 @@
1
+ require 'fig/unparser/v0'
2
+ require 'fig/unparser/v1'
3
+
4
+ module Fig; end
5
+
6
+ # Used for building packages for publishing.
7
+ class Fig::PackageDefinitionTextAssembler
8
+ attr_reader :input_statements
9
+ attr_reader :output_statements
10
+
11
+ def initialize()
12
+ @input_statements = []
13
+ @output_statements = []
14
+ @header_text = []
15
+ @footer_text = []
16
+
17
+ return
18
+ end
19
+
20
+ # Argument can either be a single Statement or an array of them.
21
+ def add_input(statements)
22
+ @input_statements << statements
23
+ @input_statements.flatten!
24
+
25
+ return
26
+ end
27
+
28
+ # Argument can either be a single Statement or an array of them.
29
+ def add_output(statements)
30
+ @output_statements << statements
31
+ @output_statements.flatten!
32
+
33
+ return
34
+ end
35
+
36
+ def asset_input_statements()
37
+ return @input_statements.select { |statement| statement.is_asset? }
38
+ end
39
+
40
+ # Argument can be a single string or an array of strings
41
+ def add_header(text)
42
+ @header_text << text
43
+
44
+ return
45
+ end
46
+
47
+ # Argument can be a single string or an array of strings
48
+ def add_footer(text)
49
+ @footer_text << text
50
+
51
+ return
52
+ end
53
+
54
+ def assemble_package_definition()
55
+ definition =
56
+ [@header_text, unparse_statements(), @footer_text].flatten.join("\n")
57
+ definition.gsub!(/\n{3,}/, "\n\n")
58
+ definition.strip!
59
+ definition << "\n"
60
+
61
+ return definition
62
+ end
63
+
64
+ private
65
+
66
+ def unparse_statements()
67
+ versions = @output_statements.map {|s| s.minimum_grammar_version_required}
68
+ version = versions.max || 0
69
+
70
+ unparser_class = nil
71
+ if version == 1
72
+ unparser_class = Fig::Unparser::V1
73
+ else
74
+ unparser_class = Fig::Unparser::V0
75
+ end
76
+
77
+ unparser = unparser_class.new :emit_as_to_be_published
78
+ text = unparser.unparse(@output_statements)
79
+
80
+ # TODO: Until v1 grammar handling is done, ensure we don't emit anything
81
+ # old fig versions cannot handle.
82
+ if version != 0
83
+ raise "Reached a point where something could not be represented by the current grammar. Bailing out.\n\nWould have attempted:\n#{text}"
84
+ end
85
+
86
+ return text
87
+ end
88
+ end
@@ -3,7 +3,7 @@ require 'fig/user_input_error'
3
3
  module Fig
4
4
  # Could not turn a string into a PackageDescriptor.
5
5
  class PackageDescriptorParseError < UserInputError
6
- attr_accessor :original_string
6
+ attr_reader :original_string
7
7
 
8
8
  def initialize(message, original_string)
9
9
  super(message)
@@ -1,12 +1,13 @@
1
1
  require 'set'
2
- require 'treetop'
3
2
 
4
- require 'fig/grammar' # this is grammar.treetop, not grammar.rb.
3
+ require 'fig/grammar/version_identification'
4
+ require 'fig/grammar/v0'
5
+ require 'fig/grammar/v1'
5
6
  require 'fig/logging'
6
7
  require 'fig/package_parse_error'
7
8
  require 'fig/parser_package_build_state'
8
- require 'fig/repository'
9
9
  require 'fig/statement'
10
+ require 'fig/url'
10
11
  require 'fig/url_access_error'
11
12
  require 'fig/user_input_error'
12
13
 
@@ -29,25 +30,114 @@ class Fig::Parser
29
30
  end
30
31
 
31
32
  def initialize(application_config, check_include_versions)
32
- # Fig::FigParser class is synthesized by Treetop.
33
- @treetop_parser = Fig::FigParser.new
34
33
  @application_config = application_config
35
34
  @check_include_versions = check_include_versions
36
35
  end
37
36
 
38
37
  def parse_package(descriptor, directory, source_description, unparsed_text)
39
- # Bye bye comments.
40
- stripped_text = unparsed_text.gsub(/#.*$/, '')
38
+ version = get_grammar_version(
39
+ descriptor, directory, source_description, unparsed_text
40
+ )
41
+
42
+ if version == 0
43
+ return parse_v0(descriptor, directory, source_description, unparsed_text)
44
+ end
45
+
46
+ return parse_v1(descriptor, directory, source_description, unparsed_text)
47
+ end
48
+
49
+ private
50
+
51
+ KEYWORDS = Set.new
52
+ KEYWORDS << 'add'
53
+ KEYWORDS << 'append'
54
+ KEYWORDS << 'archive'
55
+ KEYWORDS << 'command'
56
+ KEYWORDS << 'config'
57
+ KEYWORDS << 'end'
58
+ KEYWORDS << 'include'
59
+ KEYWORDS << 'override'
60
+ KEYWORDS << 'path'
61
+ KEYWORDS << 'resource'
62
+ KEYWORDS << 'retrieve'
63
+ KEYWORDS << 'set'
64
+
65
+
66
+ def get_grammar_version(
67
+ descriptor, directory, source_description, unparsed_text
68
+ )
69
+ version_parser = Fig::Grammar::VersionIdentificationParser.new()
70
+
71
+ extended_description =
72
+ extend_source_description(directory, source_description)
41
73
 
74
+ result = version_parser.parse(unparsed_text)
75
+ if result.nil?
76
+ raise_parse_error(version_parser, unparsed_text, extended_description)
77
+ end
78
+
79
+ statement = result.get_grammar_version(
80
+ Fig::ParserPackageBuildState.new(descriptor, extended_description)
81
+ )
82
+ return 0 if not statement
83
+
84
+ version = statement.version
85
+ # TODO: restore v1 grammar.
86
+ # if version > 1
87
+ if version > 0
88
+ raise Fig::PackageParseError.new(
89
+ %Q<Don't know how to parse grammar version #{version}#{statement.position_string()}.>
90
+ )
91
+ end
92
+
93
+ return version
94
+ end
95
+
96
+ def parse_v0(descriptor, directory, source_description, unparsed_text)
97
+ stripped_text = unparsed_text.gsub(/#.*$/, '') # Blech.
98
+
99
+ v0_parser = Fig::Grammar::V0Parser.new
100
+
101
+ return drive_parser(
102
+ v0_parser,
103
+ descriptor,
104
+ directory,
105
+ source_description,
106
+ unparsed_text,
107
+ stripped_text
108
+ )
109
+ end
110
+
111
+ def parse_v1(descriptor, directory, source_description, unparsed_text)
112
+ v1_parser = Fig::Grammar::V1Parser.new
113
+
114
+ return drive_parser(
115
+ v1_parser,
116
+ descriptor,
117
+ directory,
118
+ source_description,
119
+ unparsed_text,
120
+ unparsed_text
121
+ )
122
+ end
123
+
124
+ def drive_parser(
125
+ parser,
126
+ descriptor,
127
+ directory,
128
+ source_description,
129
+ unparsed_text, # Ugh. V0 strips comments via regex.
130
+ cleaned_text
131
+ )
42
132
  # Extra space at the end because most of the rules in the grammar require
43
133
  # trailing whitespace.
44
- result = @treetop_parser.parse(stripped_text + ' ')
134
+ result = parser.parse(cleaned_text + ' ')
45
135
 
46
136
  extended_description =
47
137
  extend_source_description(directory, source_description)
48
138
 
49
139
  if result.nil?
50
- raise_parse_error(extended_description)
140
+ raise_parse_error(parser, cleaned_text, extended_description)
51
141
  end
52
142
 
53
143
  package = result.to_package(
@@ -63,23 +153,6 @@ class Fig::Parser
63
153
  return package
64
154
  end
65
155
 
66
- private
67
-
68
- KEYWORDS = Set.new
69
- KEYWORDS << 'add'
70
- KEYWORDS << 'append'
71
- KEYWORDS << 'archive'
72
- KEYWORDS << 'command'
73
- KEYWORDS << 'config'
74
- KEYWORDS << 'end'
75
- KEYWORDS << 'include'
76
- KEYWORDS << 'override'
77
- KEYWORDS << 'path'
78
- KEYWORDS << 'resource'
79
- KEYWORDS << 'retrieve'
80
- KEYWORDS << 'set'
81
-
82
-
83
156
  def extend_source_description(directory, original_description)
84
157
  if original_description
85
158
  extended = original_description
@@ -93,9 +166,22 @@ class Fig::Parser
93
166
  return directory
94
167
  end
95
168
 
96
- def raise_parse_error(extended_description)
169
+ def raise_parse_error(treetop_parser, text, extended_description)
97
170
  message = extended_description
98
- message << ": #{@treetop_parser.failure_reason}"
171
+
172
+ failure_reason = treetop_parser.failure_reason
173
+ message << ": #{failure_reason}"
174
+ if message.sub!( / after\s*\z/, %q< after '>)
175
+ start = treetop_parser.failure_index - 20
176
+ if start < 0
177
+ start = 0
178
+ else
179
+ message << '...'
180
+ end
181
+
182
+ message << text[start, treetop_parser.failure_index]
183
+ message << %q<'>
184
+ end
99
185
 
100
186
  raise Fig::PackageParseError.new(message)
101
187
  end
@@ -107,7 +193,7 @@ class Fig::Parser
107
193
  package.walk_statements do |statement|
108
194
  statement.urls.each do |url|
109
195
  # collect all bad urls in bad_urls
110
- next if not Fig::Repository.is_url?(url)
196
+ next if not Fig::URL.is_url?(url)
111
197
  bad_urls << url if not @application_config.url_access_allowed?(url)
112
198
  end
113
199
  end