summaryrefslogtreecommitdiff
path: root/jni/ruby/tool/downloader.rb
diff options
context:
space:
mode:
authorJari Vetoniemi <jari.vetoniemi@indooratlas.com>2020-03-16 18:49:26 +0900
committerJari Vetoniemi <jari.vetoniemi@indooratlas.com>2020-03-30 00:39:06 +0900
commitfcbf63e62c627deae76c1b8cb8c0876c536ed811 (patch)
tree64cb17de3f41a2b6fef2368028fbd00349946994 /jni/ruby/tool/downloader.rb
Fresh start
Diffstat (limited to 'jni/ruby/tool/downloader.rb')
-rw-r--r--jni/ruby/tool/downloader.rb178
1 files changed, 178 insertions, 0 deletions
diff --git a/jni/ruby/tool/downloader.rb b/jni/ruby/tool/downloader.rb
new file mode 100644
index 0000000..8f169d5
--- /dev/null
+++ b/jni/ruby/tool/downloader.rb
@@ -0,0 +1,178 @@
+require 'open-uri'
+begin
+ require 'net/https'
+ $rubygems_schema = 'https'
+
+ # open-uri of ruby 2.2.0 accept an array of PEMs as ssl_ca_cert, but old
+ # versions are not. so, patching OpenSSL::X509::Store#add_file instead.
+ class OpenSSL::X509::Store
+ alias orig_add_file add_file
+ def add_file(pems)
+ Array(pems).each do |pem|
+ if File.directory?(pem)
+ add_path pem
+ else
+ orig_add_file pem
+ end
+ end
+ end
+ end
+ # since open-uri internally checks ssl_ca_cert by File.directory?, to allow
+ # accept an array.
+ class <<File
+ alias orig_directory? directory?
+ def File.directory? files
+ files.is_a?(Array) ? false : orig_directory?(files)
+ end
+ end
+rescue LoadError
+ $rubygems_schema = 'http'
+end
+
+class Downloader
+ class GNU < self
+ def self.download(name, *rest)
+ super("http://gcc.gnu.org/git/?p=gcc.git;a=blob_plain;f=#{name};hb=master", name, *rest)
+ end
+ end
+
+ class RubyGems < self
+ def self.download(name, dir = nil, ims = true, options = {})
+ options[:ssl_ca_cert] = Dir.glob(File.expand_path("../lib/rubygems/ssl_certs/*.pem", File.dirname(__FILE__)))
+ if $rubygems_schema != 'https'
+ warn "*** using http instead of https ***"
+ end
+ super("#{$rubygems_schema}://rubygems.org/downloads/#{name}", name, dir, ims, options)
+ end
+ end
+
+ Gems = RubyGems
+
+ class Unicode < self
+ def self.download(name, *rest)
+ super("http://www.unicode.org/Public/#{name}", name, *rest)
+ end
+ end
+
+ def self.mode_for(data)
+ /\A#!/ =~ data ? 0755 : 0644
+ end
+
+ def self.http_options(file, since)
+ options = {}
+ if since
+ case since
+ when true
+ since = (File.mtime(file).httpdate rescue nil)
+ when Time
+ since = since.httpdate
+ end
+ if since
+ options['If-Modified-Since'] = since
+ end
+ end
+ options
+ end
+
+ # Downloader.download(url, name, [dir, [ims]])
+ #
+ # Update a file from url if newer version is available.
+ # Creates the file if the file doesn't yet exist; however, the
+ # directory where the file is being created has to exist already.
+ # If +ims+ is false, always download url regardless of its last
+ # modified time.
+ #
+ # Example usage:
+ # download 'http://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt',
+ # 'UnicodeData.txt', 'enc/unicode/data'
+ def self.download(url, name, dir = nil, ims = true, options = {})
+ file = dir ? File.join(dir, File.basename(name)) : name
+ if ims.nil? and File.exist?(file)
+ if $VERBOSE
+ $stdout.puts "#{name} already exists"
+ $stdout.flush
+ end
+ return true
+ end
+ url = URI(url)
+ if $VERBOSE
+ $stdout.print "downloading #{name} ... "
+ $stdout.flush
+ end
+ begin
+ data = url.read(options.merge(http_options(file, ims.nil? ? true : ims)))
+ rescue OpenURI::HTTPError => http_error
+ if http_error.message =~ /^304 / # 304 Not Modified
+ if $VERBOSE
+ $stdout.puts "not modified"
+ $stdout.flush
+ end
+ return true
+ end
+ raise
+ rescue Timeout::Error
+ if ims.nil? and File.exist?(file)
+ puts "Request for #{url} timed out, using old version."
+ return true
+ end
+ raise
+ rescue SocketError
+ if ims.nil? and File.exist?(file)
+ puts "No network connection, unable to download #{url}, using old version."
+ return true
+ end
+ raise
+ end
+ mtime = nil
+ open(file, "wb", 0600) do |f|
+ f.write(data)
+ f.chmod(mode_for(data))
+ mtime = data.meta["last-modified"]
+ end
+ if mtime
+ mtime = Time.httpdate(mtime)
+ File.utime(mtime, mtime, file)
+ end
+ if $VERBOSE
+ $stdout.puts "done"
+ $stdout.flush
+ end
+ true
+ rescue => e
+ raise "failed to download #{name}\n#{e.message}: #{url}"
+ end
+end
+
+if $0 == __FILE__
+ ims = true
+ until ARGV.empty?
+ case ARGV[0]
+ when '-d'
+ destdir = ARGV[1]
+ ARGV.shift
+ when '-e'
+ ims = nil
+ when '-a'
+ ims = true
+ when /\A-/
+ abort "#{$0}: unknown option #{ARGV[0]}"
+ else
+ break
+ end
+ ARGV.shift
+ end
+ dl = Downloader.constants.find do |name|
+ ARGV[0].casecmp(name.to_s) == 0
+ end unless ARGV.empty?
+ $VERBOSE = true
+ if dl
+ dl = Downloader.const_get(dl)
+ ARGV.shift
+ ARGV.each do |name|
+ dl.download(name, destdir, ims)
+ end
+ else
+ abort "usage: #{$0} url name" unless ARGV.size == 2
+ Downloader.download(ARGV[0], ARGV[1], destdir, ims)
+ end
+end