From 59935710884a3fd9b067170ddad3154557014d92 Mon Sep 17 00:00:00 2001 From: Nikolay Edigaryev Date: Wed, 12 Aug 2026 16:47:54 +0100 Subject: [PATCH] Hash files in chunks --- Sources/tart/OCI/Digest.swift | 13 ++++++++++++- Tests/TartTests/DigestTests.swift | 9 +++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/Sources/tart/OCI/Digest.swift b/Sources/tart/OCI/Digest.swift index 51c4201..5fb8d92 100644 --- a/Sources/tart/OCI/Digest.swift +++ b/Sources/tart/OCI/Digest.swift @@ -7,6 +7,8 @@ enum DigestError: Error { } class Digest { + static let fileReadChunkSize = 4 * 1024 * 1024 + var hash: SHA256 = SHA256() func update(_ data: Data) { @@ -22,7 +24,16 @@ class Digest { } static func hash(_ url: URL) throws -> String { - hash(try Data(contentsOf: url)) + let fh = try FileHandle(forReadingFrom: url) + defer { try? fh.close() } + + let digest = Digest() + + while let data = try fh.read(upToCount: fileReadChunkSize), !data.isEmpty { + digest.update(data) + } + + return digest.finalize() } static func hash(_ url: URL, offset: UInt64, size: UInt64) throws -> String { diff --git a/Tests/TartTests/DigestTests.swift b/Tests/TartTests/DigestTests.swift index 1c6fa56..9fedb4d 100644 --- a/Tests/TartTests/DigestTests.swift +++ b/Tests/TartTests/DigestTests.swift @@ -21,4 +21,13 @@ final class DigestTests: XCTestCase { XCTAssertEqual(Digest.hash(data), "sha256:d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592") } + + func testFileHashingReadsMultipleChunks() throws { + let data = Data(repeating: 0xab, count: Digest.fileReadChunkSize + 1) + let url = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString) + try data.write(to: url) + defer { try? FileManager.default.removeItem(at: url) } + + XCTAssertEqual(try Digest.hash(url), Digest.hash(data)) + } }