1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
|
#!/usr/bin/ruby
# Used to download, extract and patch extension libraries (extlibs)
# for Ruby. See common.mk for Ruby's usage.
require 'digest'
require_relative 'downloader'
require_relative 'lib/colorize'
class ExtLibs
def initialize
@colorize = Colorize.new
end
def cache_file(url, cache_dir)
Downloader.cache_file(url, nil, :cache_dir => cache_dir)
end
def do_download(url, cache_dir)
Downloader.download(url, nil, nil, nil, :cache_dir => cache_dir)
end
def do_checksum(cache, chksums)
chksums.each do |sum|
name, sum = sum.split(/:/)
if $VERBOSE
$stdout.print "checking #{name} of #{cache} ..."
$stdout.flush
end
hd = Digest(name.upcase).file(cache).hexdigest
if $VERBOSE
$stdout.print " "
$stdout.puts hd == sum ? @colorize.pass("OK") : @colorize.fail("NG")
$stdout.flush
end
unless hd == sum
raise "checksum mismatch: #{cache}, #{name}:#{hd}, expected #{sum}"
end
end
end
def do_extract(cache, dir)
if $VERBOSE
$stdout.puts "extracting #{cache} into #{dir}"
$stdout.flush
end
ext = File.extname(cache)
case ext
when '.gz', '.tgz'
f = IO.popen(["gzip", "-dc", cache])
cache = cache.chomp('.gz')
when '.bz2', '.tbz'
f = IO.popen(["bzip2", "-dc", cache])
cache = cache.chomp('.bz2')
when '.xz', '.txz'
f = IO.popen(["xz", "-dc", cache])
cache = cache.chomp('.xz')
else
inp = cache
end
inp ||= f.binmode
ext = File.extname(cache)
case ext
when '.tar', /\A\.t[gbx]z\z/
pid = Process.spawn("tar", "xpf", "-", in: inp, chdir: dir)
when '.zip'
pid = Process.spawn("unzip", inp, "-d", dir)
end
f.close if f
Process.wait(pid)
$?.success? or raise "failed to extract #{cache}"
end
def do_patch(dest, patch, args)
if $VERBOSE
$stdout.puts "applying #{patch} under #{dest}"
$stdout.flush
end
Process.wait(Process.spawn("patch", "-d", dest, "-i", patch, *args))
$?.success? or raise "failed to patch #{patch}"
end
def do_command(mode, dest, url, cache_dir, chksums)
extracted = false
base = /.*(?=\.tar(?:\.\w+)?\z)/
case mode
when :download
cache = do_download(url, cache_dir)
do_checksum(cache, chksums)
when :extract
cache = cache_file(url, cache_dir)
target = File.join(dest, File.basename(cache)[base])
unless File.directory?(target)
do_checksum(cache, chksums)
extracted = do_extract(cache, dest)
end
when :all
cache = do_download(url, cache_dir)
target = File.join(dest, File.basename(cache)[base])
unless File.directory?(target)
do_checksum(cache, chksums)
extracted = do_extract(cache, dest)
end
end
extracted
end
def run(argv)
cache_dir = nil
mode = :all
until argv.empty?
case argv[0]
when '--download'
mode = :download
when '--extract'
mode = :extract
when '--patch'
mode = :patch
when '--all'
mode = :all
when '--cache'
argv.shift
cache_dir = argv[0]
when /\A--cache=/
cache_dir = $'
when '--'
argv.shift
break
when /\A-/
warn "unknown option: #{argv[0]}"
return false
else
break
end
argv.shift
end
success = true
argv.each do |dir|
Dir.glob("#{dir}/**/extlibs") do |list|
if $VERBOSE
$stdout.puts "downloading for #{list}"
$stdout.flush
end
extracted = false
dest = File.dirname(list)
url = chksums = nil
IO.foreach(list) do |line|
line.sub!(/\s*#.*/, '')
if chksums
chksums.concat(line.split)
elsif /^\t/ =~ line
if extracted and (mode == :all or mode == :patch)
patch, *args = line.split
do_patch(dest, patch, args)
end
next
else
url, *chksums = line.split(' ')
end
if chksums.last == '\\'
chksums.pop
next
end
next unless url
begin
extracted = do_command(mode, dest, url, cache_dir, chksums)
rescue => e
warn e.inspect
success = false
end
url = chksums = nil
end
end
end
success
end
def self.run(argv)
self.new.run(argv)
end
end
if $0 == __FILE__
exit ExtLibs.run(ARGV)
end
|