fig 0.1.38-java
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/LICENSE +27 -0
- data/README.md +229 -0
- data/bin/fig +190 -0
- data/bin/fig-download +20 -0
- data/lib/fig.rb +0 -0
- data/lib/fig/backtrace.rb +50 -0
- data/lib/fig/environment.rb +192 -0
- data/lib/fig/grammar.treetop +157 -0
- data/lib/fig/options.rb +106 -0
- data/lib/fig/os.rb +396 -0
- data/lib/fig/package.rb +220 -0
- data/lib/fig/parser.rb +27 -0
- data/lib/fig/repository.rb +241 -0
- data/lib/fig/retriever.rb +107 -0
- data/lib/fig/windows.rb +46 -0
- metadata +159 -0
data/lib/fig/os.rb
ADDED
@@ -0,0 +1,396 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
# Must specify absolute path of ::Archive when using
|
3
|
+
# this module to avoid conflicts with Fig::Package::Archive
|
4
|
+
require 'libarchive_ruby' unless RUBY_PLATFORM == 'java'
|
5
|
+
require 'uri'
|
6
|
+
require 'net/http'
|
7
|
+
require 'net/ssh'
|
8
|
+
require 'net/sftp'
|
9
|
+
require 'net/netrc'
|
10
|
+
require 'tempfile'
|
11
|
+
require 'highline/import'
|
12
|
+
|
13
|
+
module Fig
|
14
|
+
class NotFoundException < Exception
|
15
|
+
end
|
16
|
+
|
17
|
+
class OS
|
18
|
+
def initialize(login)
|
19
|
+
@login = login
|
20
|
+
@username = ENV["FIG_USERNAME"]
|
21
|
+
@password = ENV["FIG_PASSWORD"]
|
22
|
+
end
|
23
|
+
|
24
|
+
def get_username()
|
25
|
+
@username ||= ask("Username: ") { |q| q.echo = true }
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_password()
|
29
|
+
@password ||= ask("Password: ") { |q| q.echo = false }
|
30
|
+
end
|
31
|
+
|
32
|
+
def ftp_login(ftp, host)
|
33
|
+
if @login
|
34
|
+
rc = Net::Netrc.locate(host)
|
35
|
+
if rc
|
36
|
+
@username = rc.login
|
37
|
+
@password = rc.password
|
38
|
+
end
|
39
|
+
ftp.login(get_username, get_password)
|
40
|
+
else
|
41
|
+
ftp.login()
|
42
|
+
end
|
43
|
+
ftp.passive = true
|
44
|
+
end
|
45
|
+
|
46
|
+
def list(dir)
|
47
|
+
Dir.entries(dir) - ['.','..']
|
48
|
+
end
|
49
|
+
|
50
|
+
def exist?(path)
|
51
|
+
File.exist?(path)
|
52
|
+
end
|
53
|
+
|
54
|
+
def mtime(path)
|
55
|
+
File.mtime(path)
|
56
|
+
end
|
57
|
+
|
58
|
+
def read(path)
|
59
|
+
File.read(path)
|
60
|
+
end
|
61
|
+
|
62
|
+
def write(path, content)
|
63
|
+
File.open(path, "wb") { |f| f.binmode; f << content }
|
64
|
+
end
|
65
|
+
|
66
|
+
SUCCESS = 0
|
67
|
+
NOT_MODIFIED = 3
|
68
|
+
NOT_FOUND = 4
|
69
|
+
|
70
|
+
def download_list(url)
|
71
|
+
begin
|
72
|
+
uri = URI.parse(url)
|
73
|
+
rescue
|
74
|
+
$stderr.puts "Unable to parse url: '#{url}'"
|
75
|
+
exit 10
|
76
|
+
end
|
77
|
+
case uri.scheme
|
78
|
+
when "ftp"
|
79
|
+
ftp = Net::FTP.new(uri.host)
|
80
|
+
ftp_login(ftp, uri.host)
|
81
|
+
ftp.chdir(uri.path)
|
82
|
+
dirs = ftp.nlst
|
83
|
+
ftp.close
|
84
|
+
|
85
|
+
download_ftp_list(uri, dirs)
|
86
|
+
when "ssh"
|
87
|
+
packages = []
|
88
|
+
Net::SSH.start(uri.host, uri.user) do |ssh|
|
89
|
+
ls = ssh.exec!("[ -d #{uri.path} ] && find #{uri.path}")
|
90
|
+
if not ls.nil?
|
91
|
+
ls = ls.gsub(uri.path + "/", "").gsub(uri.path, "").split("\n")
|
92
|
+
ls.each do |line|
|
93
|
+
parts = line.gsub(/\\/, '/').sub(/^\.\//, '').sub(/:$/, '').chomp().split('/')
|
94
|
+
packages << parts.join('/') if parts.size == 2
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
packages
|
99
|
+
else
|
100
|
+
$stderr.puts "Protocol not supported: #{url}"
|
101
|
+
exit 10
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def download_ftp_list(uri, dirs)
|
106
|
+
# Run a bunch of these in parallel since they're slow as hell
|
107
|
+
num_threads = (ENV["FIG_FTP_THREADS"] || "16").to_i
|
108
|
+
threads = []
|
109
|
+
all_packages = []
|
110
|
+
(0..num_threads-1).each { |num| all_packages[num] = [] }
|
111
|
+
(0..num_threads-1).each do |num|
|
112
|
+
threads << Thread.new do
|
113
|
+
packages = all_packages[num]
|
114
|
+
ftp = Net::FTP.new(uri.host)
|
115
|
+
ftp_login(ftp, uri.host)
|
116
|
+
ftp.chdir(uri.path)
|
117
|
+
pos = num
|
118
|
+
while pos < dirs.length
|
119
|
+
pkg = dirs[pos]
|
120
|
+
begin
|
121
|
+
ftp.nlst(dirs[pos]).each do |ver|
|
122
|
+
packages << pkg + '/' + ver
|
123
|
+
end
|
124
|
+
rescue Net::FTPPermError
|
125
|
+
# ignore
|
126
|
+
end
|
127
|
+
pos += num_threads
|
128
|
+
end
|
129
|
+
ftp.close
|
130
|
+
end
|
131
|
+
end
|
132
|
+
threads.each { |thread| thread.join }
|
133
|
+
all_packages.flatten.sort
|
134
|
+
end
|
135
|
+
|
136
|
+
def download(url, path)
|
137
|
+
FileUtils.mkdir_p(File.dirname(path))
|
138
|
+
uri = URI.parse(url)
|
139
|
+
case uri.scheme
|
140
|
+
when "ftp"
|
141
|
+
ftp = Net::FTP.new(uri.host)
|
142
|
+
ftp_login(ftp, uri.host)
|
143
|
+
begin
|
144
|
+
if File.exist?(path) && ftp.mtime(uri.path) <= File.mtime(path)
|
145
|
+
return false
|
146
|
+
else
|
147
|
+
$stderr.puts "downloading #{url}"
|
148
|
+
ftp.getbinaryfile(uri.path, path, 256*1024)
|
149
|
+
return true
|
150
|
+
end
|
151
|
+
rescue Net::FTPPermError
|
152
|
+
raise NotFoundException.new
|
153
|
+
end
|
154
|
+
when "http"
|
155
|
+
http = Net::HTTP.new(uri.host)
|
156
|
+
$stderr.puts "downloading #{url}"
|
157
|
+
File.open(path, "wb") do |file|
|
158
|
+
file.binmode
|
159
|
+
http.get(uri.path) do |block|
|
160
|
+
file.write(block)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
when "ssh"
|
164
|
+
# TODO need better way to do conditional download
|
165
|
+
# timestamp = `ssh #{uri.user + '@' if uri.user}#{uri.host} "ruby -e 'puts File.mtime(\\"#{uri.path}\\").to_i'"`.to_i
|
166
|
+
timestamp = File.exist?(path) ? File.mtime(path).to_i : 0
|
167
|
+
cmd = `which fig-download`.strip + " #{timestamp} #{uri.path}"
|
168
|
+
ssh_download(uri.user, uri.host, path, cmd)
|
169
|
+
else
|
170
|
+
$stderr.puts "Unknown protocol: #{url}"
|
171
|
+
exit 10
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def download_resource(url, dir)
|
176
|
+
FileUtils.mkdir_p(dir)
|
177
|
+
download(url, File.join(dir, URI.parse(url).path.split('/').last))
|
178
|
+
end
|
179
|
+
|
180
|
+
def download_archive(url, dir)
|
181
|
+
FileUtils.mkdir_p(dir)
|
182
|
+
basename = URI.parse(url).path.split('/').last
|
183
|
+
path = File.join(dir, basename)
|
184
|
+
download(url, path)
|
185
|
+
case basename
|
186
|
+
when /\.tar\.gz$/
|
187
|
+
unpack_archive(dir, path)
|
188
|
+
when /\.tgz$/
|
189
|
+
unpack_archive(dir, path)
|
190
|
+
when /\.tar\.bz2$/
|
191
|
+
unpack_archive(dir, path)
|
192
|
+
when /\.zip$/
|
193
|
+
unpack_archive(dir, path)
|
194
|
+
else
|
195
|
+
$stderr.puts "Unknown archive type: #{basename}"
|
196
|
+
exit 10
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def upload(local_file, remote_file, user)
|
201
|
+
puts "uploading #{local_file} to #{remote_file}"
|
202
|
+
uri = URI.parse(remote_file)
|
203
|
+
case uri.scheme
|
204
|
+
when "ssh"
|
205
|
+
ssh_upload(uri.user, uri.host, local_file, remote_file)
|
206
|
+
when "ftp"
|
207
|
+
# fail unless system "curl -T #{local_file} --create-dirs --ftp-create-dirs #{remote_file}"
|
208
|
+
require 'net/ftp'
|
209
|
+
ftp_uri = URI.parse(ENV["FIG_REMOTE_URL"])
|
210
|
+
ftp_root_path = ftp_uri.path
|
211
|
+
ftp_root_dirs = ftp_uri.path.split("/")
|
212
|
+
remote_publish_path = uri.path[0, uri.path.rindex("/")]
|
213
|
+
remote_publish_dirs = remote_publish_path.split("/")
|
214
|
+
# Use array subtraction to deduce which project/version folder to upload to,
|
215
|
+
# i.e. [1,2,3] - [2,3,4] = [1]
|
216
|
+
remote_project_dirs = remote_publish_dirs - ftp_root_dirs
|
217
|
+
Net::FTP.open(uri.host) do |ftp|
|
218
|
+
ftp_login(ftp, uri.host)
|
219
|
+
# Assume that the FIG_REMOTE_URL path exists.
|
220
|
+
ftp.chdir(ftp_root_path)
|
221
|
+
remote_project_dirs.each do |dir|
|
222
|
+
# Can't automatically create parent directories, so do it manually.
|
223
|
+
if ftp.nlst().index(dir).nil?
|
224
|
+
ftp.mkdir(dir)
|
225
|
+
ftp.chdir(dir)
|
226
|
+
else
|
227
|
+
ftp.chdir(dir)
|
228
|
+
end
|
229
|
+
end
|
230
|
+
ftp.putbinaryfile(local_file)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
def clear_directory(dir)
|
236
|
+
FileUtils.rm_rf(dir)
|
237
|
+
FileUtils.mkdir_p(dir)
|
238
|
+
end
|
239
|
+
|
240
|
+
def exec(dir,command)
|
241
|
+
Dir.chdir(dir) {
|
242
|
+
unless system command
|
243
|
+
$stderr.puts "Command failed"
|
244
|
+
exit 10
|
245
|
+
end
|
246
|
+
}
|
247
|
+
end
|
248
|
+
|
249
|
+
def copy(source, target, msg = nil)
|
250
|
+
if File.directory?(source)
|
251
|
+
FileUtils.mkdir_p(target)
|
252
|
+
Dir.foreach(source) do |child|
|
253
|
+
if child != "." and child != ".."
|
254
|
+
copy(File.join(source, child), File.join(target, child), msg)
|
255
|
+
end
|
256
|
+
end
|
257
|
+
else
|
258
|
+
if !File.exist?(target) || File.mtime(source) != File.mtime(target)
|
259
|
+
log_info "#{msg} #{target}" if msg
|
260
|
+
FileUtils.mkdir_p(File.dirname(target))
|
261
|
+
FileUtils.cp(source, target)
|
262
|
+
File.utime(File.atime(source), File.mtime(source), target)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
def move_file(dir, from, to)
|
268
|
+
Dir.chdir(dir) { FileUtils.mv(from, to, :force => true) }
|
269
|
+
end
|
270
|
+
|
271
|
+
def log_info(msg)
|
272
|
+
$stderr.puts msg
|
273
|
+
end
|
274
|
+
|
275
|
+
# Expects files_to_archive as an Array of filenames.
|
276
|
+
def create_archive(archive_name, files_to_archive)
|
277
|
+
if OS.java?
|
278
|
+
`tar czvf #{archive_name} #{files_to_archive.join(' ')}`
|
279
|
+
else
|
280
|
+
# TODO: Need to verify files_to_archive exists.
|
281
|
+
::Archive.write_open_filename(archive_name, ::Archive::COMPRESSION_GZIP, ::Archive::FORMAT_TAR) do |ar|
|
282
|
+
files_to_archive.each do |fn|
|
283
|
+
ar.new_entry do |entry|
|
284
|
+
entry.copy_stat(fn)
|
285
|
+
entry.pathname = fn
|
286
|
+
ar.write_header(entry)
|
287
|
+
if !entry.directory?
|
288
|
+
ar.write_data(open(fn) {|f| f.binmode; f.read })
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
# This method can handle the following archive types:
|
297
|
+
# .tar.bz2
|
298
|
+
# .tar.gz
|
299
|
+
# .tgz
|
300
|
+
# .zip
|
301
|
+
def unpack_archive(dir, file)
|
302
|
+
Dir.chdir(dir) do
|
303
|
+
if OS.java?
|
304
|
+
`tar xzvf #{file}`
|
305
|
+
else
|
306
|
+
::Archive.read_open_filename(file) do |ar|
|
307
|
+
while entry = ar.next_header
|
308
|
+
ar.extract(entry)
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
def self.windows?
|
316
|
+
Config::CONFIG['host_os'] =~ /mswin|mingw/
|
317
|
+
end
|
318
|
+
|
319
|
+
def self.java?
|
320
|
+
RUBY_PLATFORM == 'java'
|
321
|
+
end
|
322
|
+
|
323
|
+
def self.unix?
|
324
|
+
!windows?
|
325
|
+
end
|
326
|
+
|
327
|
+
def shell_exec(cmd)
|
328
|
+
if OS.windows?
|
329
|
+
Windows.shell_exec_windows(cmd)
|
330
|
+
else
|
331
|
+
shell_exec_unix(cmd)
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
private
|
336
|
+
|
337
|
+
def shell_exec_unix(cmd)
|
338
|
+
Kernel.exec(ENV['SHELL'], '-c', cmd.join(' '))
|
339
|
+
end
|
340
|
+
|
341
|
+
def shell_exec_windows(cmd)
|
342
|
+
#command = ["C:/WINDOWS/system32/cmd.exe", "/C", "call"] + cmd
|
343
|
+
command = ["cmd.exe", "/C"] + cmd
|
344
|
+
command = command.join(' ')
|
345
|
+
Kernel.exec(command)
|
346
|
+
end
|
347
|
+
|
348
|
+
# path = The local path the file should be downloaded to.
|
349
|
+
# cmd = The command to be run on the remote host.
|
350
|
+
def ssh_download(user, host, path, cmd)
|
351
|
+
return_code = nil
|
352
|
+
tempfile = Tempfile.new("tmp")
|
353
|
+
Net::SSH.start(host, user) do |ssh|
|
354
|
+
ssh.open_channel do |channel|
|
355
|
+
channel.exec(cmd)
|
356
|
+
channel.on_data() { |ch, data| tempfile << data }
|
357
|
+
channel.on_extended_data() { |ch, type, data| $stderr.puts "SSH Download ERROR: #{data}" }
|
358
|
+
channel.on_request("exit-status") { |ch, request|
|
359
|
+
return_code = request.read_long
|
360
|
+
}
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
tempfile.close()
|
365
|
+
|
366
|
+
case return_code
|
367
|
+
when NOT_MODIFIED
|
368
|
+
tempfile.delete
|
369
|
+
return false
|
370
|
+
when NOT_FOUND
|
371
|
+
tempfile.delete
|
372
|
+
$stderr.puts "File not found: #{path}"
|
373
|
+
exit 10
|
374
|
+
when SUCCESS
|
375
|
+
FileUtils.mv(tempfile.path, path)
|
376
|
+
return true
|
377
|
+
else
|
378
|
+
tempfile.delete
|
379
|
+
$stderr.puts "Unable to download file: #{return_code}"
|
380
|
+
exit 1
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
def ssh_upload(user, host, local_file, remote_file)
|
385
|
+
uri = URI.parse(remote_file)
|
386
|
+
dir = uri.path[0, uri.path.rindex('/')]
|
387
|
+
Net::SSH.start(host, user) do |ssh|
|
388
|
+
ssh.exec!("mkdir -p #{dir}")
|
389
|
+
end
|
390
|
+
Net::SFTP.start(host, user) do |sftp|
|
391
|
+
sftp.upload!(local_file, uri.path)
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
395
|
+
end
|
396
|
+
end
|
data/lib/fig/package.rb
ADDED
@@ -0,0 +1,220 @@
|
|
1
|
+
module Fig
|
2
|
+
class Package
|
3
|
+
attr_reader :package_name, :version_name, :directory, :statements
|
4
|
+
attr_accessor :backtrace
|
5
|
+
|
6
|
+
def initialize(package_name, version_name, directory, statements)
|
7
|
+
@package_name = package_name
|
8
|
+
@version_name = version_name
|
9
|
+
@directory = directory
|
10
|
+
@statements = statements
|
11
|
+
@backtrace = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](config_name)
|
15
|
+
@statements.each do |stmt|
|
16
|
+
return stmt if stmt.is_a?(Configuration) && stmt.name == config_name
|
17
|
+
end
|
18
|
+
$stderr.puts "Configuration not found: #{@package_name}/#{@version_name}:#{config_name}"
|
19
|
+
exit 10
|
20
|
+
end
|
21
|
+
|
22
|
+
def configs
|
23
|
+
@statements.select { |statement| statement.is_a?(Configuration) }
|
24
|
+
end
|
25
|
+
|
26
|
+
def retrieves
|
27
|
+
retrieves = {}
|
28
|
+
statements.each { |statement| retrieves[statement.var] = statement.path if statement.is_a?(Retrieve) }
|
29
|
+
retrieves
|
30
|
+
end
|
31
|
+
|
32
|
+
def archive_urls
|
33
|
+
@statements.select{|s| s.is_a?(Archive)}.map{|s|s.url}
|
34
|
+
end
|
35
|
+
|
36
|
+
def resource_urls
|
37
|
+
@statements.select{|s| s.is_a?(Resource)}.map{|s|s.url}
|
38
|
+
end
|
39
|
+
|
40
|
+
def unparse
|
41
|
+
@statements.map { |statement| statement.unparse('') }.join("\n")
|
42
|
+
end
|
43
|
+
|
44
|
+
def ==(other)
|
45
|
+
@package_name == other.package_name && @version_name == other.version_name && @statements.to_yaml == other.statements.to_yaml
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_s
|
49
|
+
@package_name + "/" + @version_name
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class Archive
|
54
|
+
attr_reader :url
|
55
|
+
|
56
|
+
def initialize(url)
|
57
|
+
@url = url
|
58
|
+
end
|
59
|
+
|
60
|
+
def unparse(indent)
|
61
|
+
"#{indent}archive \"#{url}\""
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class Resource
|
66
|
+
attr_reader :url
|
67
|
+
|
68
|
+
def initialize(url)
|
69
|
+
@url = url
|
70
|
+
end
|
71
|
+
|
72
|
+
def unparse(indent)
|
73
|
+
"#{indent}resource #{url}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class Retrieve
|
78
|
+
attr_reader :var, :path
|
79
|
+
|
80
|
+
def initialize(var, path)
|
81
|
+
@var = var
|
82
|
+
@path = path
|
83
|
+
end
|
84
|
+
|
85
|
+
def unparse(indent)
|
86
|
+
"#{indent}retrieve #{var}->#{path}"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
class Publish
|
91
|
+
attr_reader :local_name, :remote_name
|
92
|
+
|
93
|
+
def initialize(local_name, remote_name)
|
94
|
+
@local_name = local_name
|
95
|
+
@remote_name = remote_name
|
96
|
+
end
|
97
|
+
|
98
|
+
def unparse(indent)
|
99
|
+
"#{indent}publish #{@local_name}->#{@remote_name}"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
class Install
|
104
|
+
def initialize(statements)
|
105
|
+
@statements = statements
|
106
|
+
end
|
107
|
+
|
108
|
+
def unparse(indent)
|
109
|
+
prefix = "\n#{indent}install"
|
110
|
+
body = @statements.map { |statement| statement.unparse(indent+' ') }.join("\n")
|
111
|
+
suffix = "#{indent}end"
|
112
|
+
return [prefix, body, suffix].join("\n")
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
class Configuration
|
117
|
+
attr_reader :name, :statements
|
118
|
+
|
119
|
+
def initialize(name, statements)
|
120
|
+
@name = name
|
121
|
+
@statements = statements
|
122
|
+
end
|
123
|
+
|
124
|
+
def with_name(name)
|
125
|
+
Configuration.new(name, statements)
|
126
|
+
end
|
127
|
+
|
128
|
+
def commands
|
129
|
+
result = statements.select { |statement| statement.is_a?(Command) }
|
130
|
+
# if result.empty?
|
131
|
+
# raise "No commands found for config: #{@name}"
|
132
|
+
# end
|
133
|
+
result
|
134
|
+
end
|
135
|
+
|
136
|
+
def unparse(indent)
|
137
|
+
unparse_statements(indent, "config #{@name}", @statements, "end")
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
class Path
|
142
|
+
attr_reader :name, :value
|
143
|
+
|
144
|
+
def initialize(name, value)
|
145
|
+
@name = name
|
146
|
+
@value = value
|
147
|
+
end
|
148
|
+
|
149
|
+
def unparse(indent)
|
150
|
+
"#{indent}append #{name}=#{value}"
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
class Set
|
155
|
+
attr_reader :name, :value
|
156
|
+
|
157
|
+
def initialize(name, value)
|
158
|
+
@name = name
|
159
|
+
@value = value
|
160
|
+
end
|
161
|
+
|
162
|
+
def unparse(indent)
|
163
|
+
"#{indent}set #{name}=#{value}"
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
class Include
|
168
|
+
attr_reader :package_name, :config_name, :version_name, :overrides
|
169
|
+
|
170
|
+
def initialize(package_name, config_name, version_name, overrides)
|
171
|
+
@package_name = package_name
|
172
|
+
@config_name = config_name
|
173
|
+
@version_name = version_name
|
174
|
+
@overrides = overrides
|
175
|
+
end
|
176
|
+
|
177
|
+
def unparse(indent)
|
178
|
+
descriptor = ""
|
179
|
+
descriptor += @package_name if @package_name
|
180
|
+
descriptor += "/#{@version_name}" if @version_name
|
181
|
+
descriptor += ":#{@config_name}" if @config_name
|
182
|
+
@overrides.each do |override|
|
183
|
+
descriptor += override.unparse
|
184
|
+
end
|
185
|
+
return "#{indent}include #{descriptor}"
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
class Override
|
190
|
+
attr_reader :package_name, :version_name
|
191
|
+
|
192
|
+
def initialize(package_name, version_name)
|
193
|
+
@package_name = package_name
|
194
|
+
@version_name = version_name
|
195
|
+
end
|
196
|
+
|
197
|
+
def unparse()
|
198
|
+
return " override " + @package_name + "/" + @version_name
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
class Command
|
203
|
+
attr_reader :command
|
204
|
+
|
205
|
+
def initialize(command)
|
206
|
+
@command = command
|
207
|
+
end
|
208
|
+
|
209
|
+
def unparse(indent)
|
210
|
+
"#{indent}command \"#{@command}\""
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
end
|
215
|
+
|
216
|
+
def unparse_statements(indent, prefix, statements, suffix)
|
217
|
+
body = @statements.map { |statement| statement.unparse(indent+' ') }.join("\n")
|
218
|
+
return ["\n#{indent}#{prefix}", body, "#{indent}#{suffix}"].join("\n")
|
219
|
+
end
|
220
|
+
|