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