summaryrefslogtreecommitdiff
path: root/tool/extlibs.rb
blob: 6323d8fdcd1cbb4c91ddd2f41f0115b87d8649f9 (plain)
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
#!/usr/bin/ruby
require 'fileutils'
require 'digest'
require_relative 'downloader'

cache_dir = ".downloaded-cache"
FileUtils.mkdir_p(cache_dir)

def do_download(url, base, cache_dir)
  Downloader.download(url, base, cache_dir, nil)
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 hd == sum
      if $VERBOSE
        $stdout.puts " OK"
        $stdout.flush
      end
    else
      if $VERBOSE
        $stdout.puts " NG"
        $stdout.flush
      end
      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

case ARGV[0]
when '--download'
  mode = :download
  ARGV.shift
when '--extract'
  mode = :extract
  ARGV.shift
when '--patch'
  mode = :patch
  ARGV.shift
when '--all'
  mode = :all
  ARGV.shift
else
  mode = :all
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)
    IO.foreach(list) do |line|
      line.sub!(/\s*#.*/, '')
      if /^\t/ =~ line
        if extracted and (mode == :all or mode == :patch)
          patch, *args = line.split
          do_patch(dest, patch, args)
        end
        next
      end
      url, *chksums = line.split(' ')
      next unless url
      extracted = false
      base = File.basename(url)
      cache = File.join(cache_dir, base)
      target = File.join(dest, base[/.*(?=\.tar(?:\.\w+)?\z)/])
      begin
        case mode
        when :download
          do_download(url, base, cache_dir)
          do_checksum(cache, chksums)
        when :extract
          unless File.directory?(target)
            do_checksum(cache, chksums)
            extracted = do_extract(cache, dest)
          end
        when :all
          do_download(url, base, cache_dir)
          unless File.directory?(target)
            do_checksum(cache, chksums)
            extracted = do_extract(cache, dest)
          end
        end
      rescue => e
        warn e.inspect
        success = false
      end
    end
  end
end

exit(success)