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
@@ -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