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
|
require 'open-uri'
class Downloader
class GNU < self
def self.download(name, *rest)
super("http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=#{name};hb=HEAD", name, *rest)
end
end
class RubyGems < self
def self.download(name, *rest)
super("https://rubygems.org/downloads/#{name}", name, *rest)
end
end
Gems = RubyGems
class Unicode < self
def self.download(name, *rest)
super("http://www.unicode.org/Public/UCD/latest/ucd/#{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 :unicode, 'UnicodeData.txt', 'enc/unicode/data'
def self.download(url, name, dir = nil, ims = true)
file = dir ? File.join(dir, name) : name
return true if ims.nil? and File.exist?(file)
url = URI(url)
if $VERBOSE
$stdout.print "downloading #{name} ... "
$stdout.flush
end
begin
data = url.read(http_options(file, 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
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 e.class, "failed to download #{name}\n#{e.message}: #{url}", e.backtrace
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-/
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
$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
|