Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

import Foundation
import Utils

public protocol ChecksumCalculatorProtocol {
func calculateChecksum(fileURL: URL) throws -> String
}

extension SHA256ChecksumCalculator: ChecksumCalculatorProtocol {}
47 changes: 47 additions & 0 deletions Sources/Utils/SHA256ChecksumCalculator.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import Crypto
import Foundation

public struct SHA256ChecksumCalculator {
public init() {}

public func calculateChecksum(fileURL: URL) throws -> String {
// Read the file in chunks to avoid RAM usage issues

let handle: FileHandle = try FileHandle(forReadingFrom: fileURL)
var hasher: SHA256 = SHA256()

#if os(macOS)

while autoreleasepool(invoking: {
let nextChunk = handle.readData(ofLength: 1024 * 1024)
guard !nextChunk.isEmpty else { return false }
hasher.update(data: nextChunk)
return true
}) {}

#elseif os(Linux)

var eof: Bool = false
var nextChunk: Data

while !eof {
nextChunk = handle.readData(ofLength: 1024 * 1024)
eof = nextChunk.isEmpty
if !eof {
hasher.update(data: nextChunk)
}
}

#endif

let digest: SHA256.Digest = hasher.finalize()

return digest.hexadecimalString
}
}

extension SHA256.Digest {
fileprivate var hexadecimalString: String {
map { String(format: "%02hhx", $0) }.joined()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import Foundation

@testable import BinaryDependencyManager
import Utils

/// Mock implementation for UnarchiverProtocol for use in unit tests.
class ChecksumCalculatorProtocolMock: ChecksumCalculatorProtocol {
/// Records the arguments with which unzip was called.
public private(set) var unzipCalls: [(archivePath: String, outputFilePath: String)] = []
/// If set, unzip will throw this error when called.
public var errorToThrow: Error?

public init(errorToThrow: Error? = nil) {
self.errorToThrow = errorToThrow
}

var checksums: [URL: String] = [:]
var checksumCalls: [URL] = []
public func calculateChecksum(fileURL: URL) throws -> String {
checksumCalls.append(fileURL)
if let errorToThrow {
throw errorToThrow
}
guard let checksum = checksums[fileURL] else {
throw GenericError("no checksum provided for \(fileURL.relativeFilePath)")
}
return checksum
}
}