Module: FileDependencies::File

Defined in:
lib/file-dependencies/file.rb

Overview

:nodoc:

Constant Summary collapse

SHA1_REGEXP =
/(\b[0-9a-f]{40}\b)/

Class Method Summary collapse

Class Method Details

.calculate_sha1(path) ⇒ Object


34
35
36
# File 'lib/file-dependencies/file.rb', line 34

def calculate_sha1(path)
  Digest::SHA1.file(path).hexdigest
end

.download(url, target) ⇒ Object


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
# File 'lib/file-dependencies/file.rb', line 47

def download(url, target)
  uri = URI(url)
  output = "#{target}/#{::File.basename(uri.path)}"
  tmp = "#{output}.tmp"
  Net::HTTP.start(uri.host, uri.port, :use_ssl => (uri.scheme == "https")) do |http|
    request = Net::HTTP::Get.new(uri.path)
    http.request(request) do |response|
      raise("HTTP fetch failed for #{url}. #{response}") unless [200, 301].include?(response.code.to_i)
      size = (response["content-length"].to_i || -1).to_f
      count = 0
      ::File.open(tmp, "w") do |fd|
        response.read_body do |chunk|
          fd.write(chunk)
          if size > 0 && $stdout.tty?
            count += chunk.bytesize
            $stdout.write(sprintf("\r%0.2f%%", count / size * 100))
          end
        end
      end
      $stdout.write("\r      \r") if $stdout.tty?
    end
  end

  ::File.rename(tmp, output)

  return output
rescue SocketError => e
  puts "Failure while downloading #{url}: #{e}"
  raise
ensure
  ::File.unlink(tmp) if ::File.exist?(tmp)
end

.fetch_file(url, sha1, target) ⇒ Object


39
40
41
42
43
44
# File 'lib/file-dependencies/file.rb', line 39

def fetch_file(url, sha1, target)
  puts "Downloading #{url}" if $DEBUG

  file = download(url, target)
  return file if validate_sha1(file, sha1)
end

.fetch_sha1(remote_sha1) ⇒ Object


12
13
14
15
16
17
18
19
20
21
# File 'lib/file-dependencies/file.rb', line 12

def fetch_sha1(remote_sha1)
  if URI(remote_sha1.to_s).scheme.nil?
    sha1 = remote_sha1
  else
    file = download(remote_sha1, Dir.tmpdir)
    sha1 = IO.read(file).gsub("\n", '')
  end
  raise("invalid SHA1 signature. Got '#{sha1}'") unless sha1.match(SHA1_REGEXP)
  sha1
end

.validate_sha1(local_file, remote_sha1) ⇒ Object


24
25
26
27
28
29
30
31
# File 'lib/file-dependencies/file.rb', line 24

def validate_sha1(local_file, remote_sha1)
  return true if remote_sha1 == 'none'
  sha1 = fetch_sha1(remote_sha1)
  local_sha1 = calculate_sha1(local_file)

  raise("SHA1 did not match. Expected #{sha1} but computed #{local_sha1}") if sha1 != local_sha1
  true
end