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