Remove checksum from downloader and replace with FileChecksum

Remove checksum implementation within the Util::Downloader and
relocate it into the FileChecksum helper class. Update Downloader
to use FileChecksum.
This commit is contained in:
Chris Roberts 2019-10-04 14:12:56 -07:00
parent 7fb81bcea1
commit 9ee5ce4817
2 changed files with 42 additions and 38 deletions

View File

@ -8,6 +8,7 @@ require "vagrant/util/busy"
require "vagrant/util/platform"
require "vagrant/util/subprocess"
require "vagrant/util/curl_helper"
require "vagrant/util/file_checksum"
module Vagrant
module Util
@ -21,15 +22,6 @@ module Vagrant
# Vagrant/1.7.4 (+https://www.vagrantup.com; ruby2.1.0)
USER_AGENT = "Vagrant/#{VERSION} (+https://www.vagrantup.com; #{RUBY_ENGINE}#{RUBY_VERSION}) #{ENV['VAGRANT_USER_AGENT_PROVISIONAL_STRING']}".freeze
# Supported file checksum
CHECKSUM_MAP = {
:md5 => Digest::MD5,
:sha1 => Digest::SHA1,
:sha256 => Digest::SHA256,
:sha384 => Digest::SHA384,
:sha512 => Digest::SHA512
}.freeze
# Hosts that do not require notification on redirect
SILENCED_HOSTS = [
"vagrantcloud.com".freeze,
@ -76,7 +68,7 @@ module Vagrant
:sha256 => options[:sha256],
:sha384 => options[:sha384],
:sha512 => options[:sha512]
}
}.compact
end
# This executes the actual download, downloading the source file
@ -172,36 +164,23 @@ module Vagrant
# @option checksums [String] :sha1 Compare SHA1 checksum
# @return [Boolean]
def validate_download!(source, path, checksums)
CHECKSUM_MAP.each do |type, klass|
if checksums[type]
result = checksum_file(klass, path)
@logger.debug("Validating checksum (#{type}) for #{source}. " \
"expected: #{checksums[type]} actual: #{result}")
if checksums[type] != result
raise Errors::DownloaderChecksumError.new(
source: source,
path: path,
type: type,
expected_checksum: checksums[type],
actual_checksum: result
)
end
checksums.each do |type, expected|
actual = FileChecksum.new(path, type).checksum
@logger.debug("Validating checksum (#{type}) for #{source}. " \
"expected: #{expected} actual: #{actual}")
if actual.casecmp(expected) != 0
raise Errors::DownloaderChecksumError.new(
source: source,
path: path,
type: type,
expected_checksum: expected,
actual_checksum: actual
)
end
end
true
end
# Generate checksum on given file
#
# @param digest_class [Class] Digest class to use for generating checksum
# @param path [String, Pathname] Path to file
# @return [String] hexdigest result
def checksum_file(digest_class, path)
digester = digest_class.new
digester.file(path)
digester.hexdigest
end
def execute_curl(options, subprocess_options, &data_proc)
options = options.dup
options << subprocess_options

View File

@ -10,13 +10,27 @@ end
class FileChecksum
BUFFER_SIZE = 1024 * 8
# Supported file checksum
CHECKSUM_MAP = {
:md5 => Digest::MD5,
:sha1 => Digest::SHA1,
:sha256 => Digest::SHA256,
:sha384 => Digest::SHA384,
:sha512 => Digest::SHA512
}.freeze
# Initializes an object to calculate the checksum of a file. The given
# ``digest_klass`` should implement the ``DigestClass`` interface. Note
# that the built-in Ruby digest classes duck type this properly:
# Digest::MD5, Digest::SHA1, etc.
def initialize(path, digest_klass)
@digest_klass = digest_klass
@path = path
if digest_klass.is_a?(Class)
@digest_klass = digest_klass
else
@digest_klass = load_digest(digest_klass)
end
@path = path
end
# This calculates the checksum of the file and returns it as a
@ -40,6 +54,17 @@ class FileChecksum
end
end
return digest.hexdigest
digest.hexdigest
end
private
def load_digest(type)
digest = CHECKSUM_MAP[type.to_s.to_sym]
if digest.nil?
raise Errors::BoxChecksumInvalidType,
type: type.to_s
end
digest
end
end