fig 0.1.73 → 0.1.75
Sign up to get free protection for your applications and to get access to all the features.
- data/Changes +75 -0
- data/lib/fig.rb +1 -1
- data/lib/fig/command.rb +36 -12
- data/lib/fig/command/action.rb +1 -1
- data/lib/fig/command/action/dump_package_definition_parsed.rb +4 -6
- data/lib/fig/command/action/run_command_statement.rb +3 -2
- data/lib/fig/command/options.rb +12 -3
- data/lib/fig/command/options/parser.rb +2 -0
- data/lib/fig/command/package_loader.rb +1 -0
- data/lib/fig/config_file_error.rb +1 -1
- data/lib/fig/grammar/base.rb +214 -0
- data/lib/fig/grammar/base.treetop +29 -0
- data/lib/fig/grammar/v0.rb +1493 -0
- data/lib/fig/grammar/v0.treetop +167 -0
- data/lib/fig/grammar/v1.rb +1478 -0
- data/lib/fig/grammar/v1.treetop +174 -0
- data/lib/fig/grammar/version.rb +144 -0
- data/lib/fig/grammar/version.treetop +22 -0
- data/lib/fig/grammar/version_identification.rb +113 -0
- data/lib/fig/grammar/version_identification.treetop +27 -0
- data/lib/fig/log4r_config_error.rb +1 -1
- data/lib/fig/no_such_package_config_error.rb +1 -1
- data/lib/fig/not_found_error.rb +7 -0
- data/lib/fig/operating_system.rb +31 -20
- data/lib/fig/package.rb +8 -3
- data/lib/fig/package_definition_text_assembler.rb +88 -0
- data/lib/fig/package_descriptor_parse_error.rb +1 -1
- data/lib/fig/parser.rb +115 -29
- data/lib/fig/parser_package_build_state.rb +38 -11
- data/lib/fig/repository.rb +5 -8
- data/lib/fig/repository_package_publisher.rb +114 -96
- data/lib/fig/runtime_environment.rb +42 -14
- data/lib/fig/statement.rb +133 -0
- data/lib/fig/statement/archive.rb +6 -4
- data/lib/fig/statement/asset.rb +28 -34
- data/lib/fig/statement/command.rb +6 -2
- data/lib/fig/statement/configuration.rb +4 -12
- data/lib/fig/statement/grammar_version.rb +22 -0
- data/lib/fig/statement/include.rb +5 -6
- data/lib/fig/statement/override.rb +6 -3
- data/lib/fig/statement/path.rb +12 -2
- data/lib/fig/statement/resource.rb +8 -8
- data/lib/fig/statement/retrieve.rb +11 -3
- data/lib/fig/statement/set.rb +12 -2
- data/lib/fig/unparser.rb +127 -0
- data/lib/fig/unparser/v0.rb +84 -0
- data/lib/fig/unparser/v1.rb +77 -0
- data/lib/fig/url.rb +7 -0
- metadata +139 -25
- 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
|
-
|
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
|
-
|
7
|
+
attr_reader :descriptor
|
8
8
|
|
9
9
|
def initialize(message, descriptor)
|
10
10
|
super(message)
|
data/lib/fig/not_found_error.rb
CHANGED
data/lib/fig/operating_system.rb
CHANGED
@@ -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
|
-
|
221
|
-
|
222
|
-
|
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
|
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(
|
239
|
+
unpack_archive(download_directory, path)
|
233
240
|
when /\.tgz$/
|
234
|
-
unpack_archive(
|
241
|
+
unpack_archive(download_directory, path)
|
235
242
|
when /\.tar\.bz2$/
|
236
|
-
unpack_archive(
|
243
|
+
unpack_archive(download_directory, path)
|
237
244
|
when /\.zip$/
|
238
|
-
unpack_archive(
|
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
|
data/lib/fig/package.rb
CHANGED
@@ -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
|
23
|
-
|
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
|
-
|
6
|
+
attr_reader :original_string
|
7
7
|
|
8
8
|
def initialize(message, original_string)
|
9
9
|
super(message)
|
data/lib/fig/parser.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
require 'set'
|
2
|
-
require 'treetop'
|
3
2
|
|
4
|
-
require 'fig/grammar'
|
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
|
-
|
40
|
-
|
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 =
|
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
|
-
|
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::
|
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
|