Class: Gem::MiniMirror::Fetcher

Inherits:
Object
  • Object
show all
Defined in:
lib/rubygems/mini_mirror/fetcher.rb

Defined Under Namespace

Classes: Error

Instance Method Summary collapse

Constructor Details

#initializeFetcher

Returns a new instance of Fetcher.



10
11
12
# File 'lib/rubygems/mini_mirror/fetcher.rb', line 10

def initialize
  @http = Net::HTTP::Persistent.new(self.class.name, :ENV)
end

Instance Method Details

#fetch(uri, path) ⇒ Object

Fetch a source path under the base uri, and put it in the same or given destination path under the base path.



16
17
18
19
20
21
22
23
24
25
# File 'lib/rubygems/mini_mirror/fetcher.rb', line 16

def fetch(uri, path)
  modified_time = File.exists?(path) && File.stat(path).mtime.rfc822

  req = Net::HTTP::Get.new URI.parse(uri).path
  req.add_field 'If-Modified-Since', modified_time if modified_time

  @http.request URI(uri), req do |resp|
    return handle_response(resp, path)
  end
end

#handle_response(resp, path) ⇒ Object

Handle an http response, follow redirects, etc. returns true if a file was downloaded, false if a 304. Raise Error on unknown responses.



29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/rubygems/mini_mirror/fetcher.rb', line 29

def handle_response(resp, path)
  case resp.code.to_i
  when 304
  when 302
    fetch resp['location'], path
  when 200
    write_file(resp, path)
  when 403, 404
    warn "#{resp.code} on #{File.basename(path)}"
  else
    raise Error, "unexpected response #{resp.inspect}"
  end
  # TODO rescue http errors and reraise cleanly
end

#write_file(resp, path) ⇒ Object

Efficiently writes an http response object to a particular path. If there is an error, it will remove the target file.



46
47
48
49
50
51
52
53
54
55
56
# File 'lib/rubygems/mini_mirror/fetcher.rb', line 46

def write_file(resp, path)
  FileUtils.mkdir_p File.dirname(path)
  File.open(path, 'wb') do |output|
    resp.read_body { |chunk| output << chunk }
  end
  true
ensure
  # cleanup incomplete files, rescue perm errors etc, they're being
  # raised already.
  File.delete(path) rescue nil if $!
end