From a98cf2cc5c01143cdf646036817735efbfa437fc Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Sat, 8 Jun 2024 08:59:56 +0200 Subject: [PATCH 01/33] Prefer non-optional String->Data conversion --- Sources/ZIPFoundation/Archive+Helpers.swift | 3 +-- .../ZIPFoundationEntryTests+ZIP64.swift | 18 ++++++------- .../ZIPFoundationEntryTests.swift | 6 ++--- ...PFoundationErrorConditionTests+ZIP64.swift | 26 +++++++++---------- .../ZIPFoundationFileAttributeTests.swift | 4 +-- .../ZIPFoundationFileManagerTests.swift | 2 +- .../ZIPFoundationMemoryTests.swift | 14 +++++----- 7 files changed, 32 insertions(+), 41 deletions(-) diff --git a/Sources/ZIPFoundation/Archive+Helpers.swift b/Sources/ZIPFoundation/Archive+Helpers.swift index 3b89e0e5..faebd6bc 100644 --- a/Sources/ZIPFoundation/Archive+Helpers.swift +++ b/Sources/ZIPFoundation/Archive+Helpers.swift @@ -77,8 +77,7 @@ extension Archive { size: (uncompressed: UInt64, compressed: UInt64), checksum: CRC32, modificationDateTime: (UInt16, UInt16)) throws -> LocalFileHeader { // We always set Bit 11 in generalPurposeBitFlag, which indicates an UTF-8 encoded path. - guard let fileNameData = path.data(using: .utf8) else { throw ArchiveError.invalidEntryPath } - + let fileNameData = Data(path.utf8) var uncompressedSizeOfLFH = UInt32(0) var compressedSizeOfLFH = UInt32(0) var extraFieldLength = UInt16(0) diff --git a/Tests/ZIPFoundationTests/ZIPFoundationEntryTests+ZIP64.swift b/Tests/ZIPFoundationTests/ZIPFoundationEntryTests+ZIP64.swift index ea0e7a52..1206e8c7 100644 --- a/Tests/ZIPFoundationTests/ZIPFoundationEntryTests+ZIP64.swift +++ b/Tests/ZIPFoundationTests/ZIPFoundationEntryTests+ZIP64.swift @@ -67,7 +67,7 @@ extension ZIPFoundationTests { 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] let zip64DataDescriptor = Entry.ZIP64DataDescriptor(data: Data(zip64DDBytes), additionalDataProvider: {_ -> Data in - return Data() }) + return Data() }) XCTAssertEqual(zip64DataDescriptor?.uncompressedSize, 10) XCTAssertEqual(zip64DataDescriptor?.compressedSize, 10) } @@ -85,13 +85,11 @@ extension ZIPFoundationTests { 0xb0, 0x11, 0x00, 0x00, 0x00, 0x00] guard let cds = Entry.CentralDirectoryStructure(data: Data(cdsBytes), additionalDataProvider: { count -> Data in - guard let name = "/".data(using: .utf8) else { - throw AdditionalDataError.encodingError - } - let extra = name + Data(extraFieldBytesIncludingSizeFields) - XCTAssert(count == extra.count) - return extra - }) else { + let name = Data("/".utf8) + let extra = name + Data(extraFieldBytesIncludingSizeFields) + XCTAssert(count == extra.count) + return extra + }) else { XCTFail("Failed to read central directory structure."); return } XCTAssertNotNil(cds.extraFields) @@ -104,8 +102,8 @@ extension ZIPFoundationTests { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] guard let lfh = Entry.LocalFileHeader(data: Data(lfhBytes), additionalDataProvider: { _ -> Data in - return Data() - }) else { + return Data() + }) else { XCTFail("Failed to read local file header."); return } guard let entry = Entry(centralDirectoryStructure: cds, localFileHeader: lfh) else { diff --git a/Tests/ZIPFoundationTests/ZIPFoundationEntryTests.swift b/Tests/ZIPFoundationTests/ZIPFoundationEntryTests.swift index c19fa182..64bc5d94 100644 --- a/Tests/ZIPFoundationTests/ZIPFoundationEntryTests.swift +++ b/Tests/ZIPFoundationTests/ZIPFoundationEntryTests.swift @@ -159,16 +159,14 @@ extension ZIPFoundationTests { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x11, 0x00, 0x00, 0x00, 0x00] let cds = Entry.CentralDirectoryStructure(data: Data(cdsBytes)) { _ -> Data in - guard let pathData = "/".data(using: .utf8) else { throw AdditionalDataError.encodingError } - return pathData + return Data("/".utf8) } let lfhBytes: [UInt8] = [0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x08, 0x08, 0x00, 0xab, 0x85, 0x77, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00] let lfh = Entry.LocalFileHeader(data: Data(lfhBytes)) { _ -> Data in - guard let pathData = "/".data(using: .utf8) else { throw AdditionalDataError.encodingError } - return pathData + return Data("/".utf8) } guard let central = cds else { XCTFail("Failed to read central directory structure.") diff --git a/Tests/ZIPFoundationTests/ZIPFoundationErrorConditionTests+ZIP64.swift b/Tests/ZIPFoundationTests/ZIPFoundationErrorConditionTests+ZIP64.swift index e77eedbd..9a22204e 100644 --- a/Tests/ZIPFoundationTests/ZIPFoundationErrorConditionTests+ZIP64.swift +++ b/Tests/ZIPFoundationTests/ZIPFoundationErrorConditionTests+ZIP64.swift @@ -19,10 +19,10 @@ extension ZIPFoundationTests { numberOfEntries: 0) XCTAssertSwiftError( try archive.writeEndOfCentralDirectory(centralDirectoryStructure: makeMockCentralDirectory()!, - startOfCentralDirectory: 0, - startOfEndOfCentralDirectory: 0, - operation: .add), - throws: Archive.ArchiveError.invalidCentralDirectorySize) + startOfCentralDirectory: 0, + startOfEndOfCentralDirectory: 0, + operation: .add), + throws: Archive.ArchiveError.invalidCentralDirectorySize) } func testWriteEOCDWithTooLargeCentralDirectoryOffset() { @@ -31,10 +31,10 @@ extension ZIPFoundationTests { numberOfEntries: .max) XCTAssertSwiftError( try archive.writeEndOfCentralDirectory(centralDirectoryStructure: makeMockCentralDirectory()!, - startOfCentralDirectory: 0, - startOfEndOfCentralDirectory: 0, - operation: .add), - throws: Archive.ArchiveError.invalidCentralDirectoryEntryCount) + startOfCentralDirectory: 0, + startOfEndOfCentralDirectory: 0, + operation: .add), + throws: Archive.ArchiveError.invalidCentralDirectoryEntryCount) } // MARK: - Helper @@ -65,12 +65,10 @@ extension ZIPFoundationTests { 0xb0, 0x11, 0x00, 0x00, 0x00, 0x00] guard let cds = Entry.CentralDirectoryStructure(data: Data(cdsBytes), additionalDataProvider: { count -> Data in - guard let pathData = "/".data(using: .utf8) else { - throw AdditionalDataError.encodingError - } - XCTAssert(count == pathData.count) - return pathData - }) else { + let pathData = Data("/".utf8) + XCTAssert(count == pathData.count) + return pathData + }) else { XCTFail("Failed to read central directory structure.") return nil } diff --git a/Tests/ZIPFoundationTests/ZIPFoundationFileAttributeTests.swift b/Tests/ZIPFoundationTests/ZIPFoundationFileAttributeTests.swift index c0927825..ebea946f 100644 --- a/Tests/ZIPFoundationTests/ZIPFoundationFileAttributeTests.swift +++ b/Tests/ZIPFoundationTests/ZIPFoundationFileAttributeTests.swift @@ -22,9 +22,7 @@ extension ZIPFoundationTests { 0xb0, 0x11, 0x00, 0x00, 0x00, 0x00] guard let cds = Entry.CentralDirectoryStructure(data: Data(cdsBytes), additionalDataProvider: { count -> Data in - guard let pathData = "/".data(using: .utf8) else { - throw AdditionalDataError.encodingError - } + let pathData = Data("/".utf8) XCTAssert(count == pathData.count) return pathData }) else { diff --git a/Tests/ZIPFoundationTests/ZIPFoundationFileManagerTests.swift b/Tests/ZIPFoundationTests/ZIPFoundationFileManagerTests.swift index a2c13514..691ce705 100755 --- a/Tests/ZIPFoundationTests/ZIPFoundationFileManagerTests.swift +++ b/Tests/ZIPFoundationTests/ZIPFoundationFileManagerTests.swift @@ -156,7 +156,7 @@ extension ZIPFoundationTests { let linkArchive = try XCTUnwrap(try? Archive(url: linkArchiveURL, accessMode: .create)) try? linkArchive.addEntry(with: "link", type: .symlink, uncompressedSize: Int64(4), provider: { (_, _) -> Data in - return linkTarget.data(using: .utf8) ?? Data() + return Data(linkTarget.utf8) }) try? fileManager.unzipItem(at: linkArchiveURL, to: destinationURL, allowUncontainedSymlinks: true) XCTAssert(fileManager.itemExists(at: destinationURL.appendingPathComponent("link"))) diff --git a/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift b/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift index 7f8c1314..beffe0ed 100644 --- a/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift +++ b/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift @@ -153,7 +153,7 @@ extension ZIPFoundationTests { } func testReadOnlyFile() { - let file = MemoryFile(data: "ABCDEabcde".data(using: .utf8)!).open(mode: "r") + let file = MemoryFile(data: Data("ABCDEabcde".utf8)).open(mode: "r") var chars: [UInt8] = [0, 0, 0] XCTAssertEqual(fread(&chars, 1, 2, file), 2) XCTAssertEqual(String(Unicode.Scalar(chars[0])), "A") @@ -171,7 +171,7 @@ extension ZIPFoundationTests { } func testReadOnlySlicedFile() { - let originalData = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".data(using: .utf8)! + let originalData = Data("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".utf8) let slice = originalData[10.. Date: Sat, 8 Jun 2024 09:15:26 +0200 Subject: [PATCH 02/33] Disable erroneous swiftlint rule --- Sources/ZIPFoundation/Archive+Reading.swift | 1 + Tests/ZIPFoundationTests/ZIPFoundationFileManagerTests.swift | 1 + 2 files changed, 2 insertions(+) diff --git a/Sources/ZIPFoundation/Archive+Reading.swift b/Sources/ZIPFoundation/Archive+Reading.swift index 216ad5c7..a0e2fe70 100644 --- a/Sources/ZIPFoundation/Archive+Reading.swift +++ b/Sources/ZIPFoundation/Archive+Reading.swift @@ -55,6 +55,7 @@ extension Archive { throw CocoaError(.fileWriteFileExists, userInfo: [NSFilePathErrorKey: url.path]) } let consumer = { (data: Data) in + // swiftlint:disable:next non_optional_string_data_conversion guard let linkPath = String(data: data, encoding: .utf8) else { throw ArchiveError.invalidEntryPath } let parentURL = url.deletingLastPathComponent() diff --git a/Tests/ZIPFoundationTests/ZIPFoundationFileManagerTests.swift b/Tests/ZIPFoundationTests/ZIPFoundationFileManagerTests.swift index 691ce705..83ae9a2d 100755 --- a/Tests/ZIPFoundationTests/ZIPFoundationFileManagerTests.swift +++ b/Tests/ZIPFoundationTests/ZIPFoundationFileManagerTests.swift @@ -276,6 +276,7 @@ private struct ZIPInfo: Hashable { unzipTask.standardError = pipe unzipTask.launch() let unzipOutputData = pipe.fileHandleForReading.readDataToEndOfFile() + // swiftlint:disable:next non_optional_string_data_conversion let unzipOutput = String(data: unzipOutputData, encoding: .utf8)! unzipTask.waitUntilExit() return unzipOutput.split(whereSeparator: \.isNewline) From cc2711da11744edb2bd2f4b2c0205bb720d5dc33 Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Sat, 8 Jun 2024 09:28:18 +0200 Subject: [PATCH 03/33] Whitespace --- Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift b/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift index beffe0ed..5ed350d9 100644 --- a/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift +++ b/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift @@ -143,7 +143,7 @@ extension ZIPFoundationTests { #if os(macOS) || os(iOS) || os(tvOS) || os(visionOS) || os(watchOS) let archiveCreation = { self.XCTAssertSwiftError(try Archive(data: data, accessMode: .read), - throws: Archive.ArchiveError.unreadableArchive) + throws: Archive.ArchiveError.unreadableArchive) } self.runWithoutMemory { From aa0bf78f7bd1f35e1e54d072ac4969a2572d0ce4 Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Sat, 8 Jun 2024 13:02:43 +0200 Subject: [PATCH 04/33] Add a merge step to convert raw code coverage profile data --- .github/workflows/llvm-cov.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/llvm-cov.yml b/.github/workflows/llvm-cov.yml index 9d02bba0..b19856e8 100644 --- a/.github/workflows/llvm-cov.yml +++ b/.github/workflows/llvm-cov.yml @@ -12,5 +12,6 @@ jobs: steps: - uses: actions/checkout@v2 - run: swift test -c release -Xswiftc -enable-testing --enable-code-coverage + - run: find .build/release/codecov/ -name "*.profraw" -print0 | xargs -0 xcrun llvm-profdata merge -sparse -o .build/release/codecov/default.profdata - run: xcrun llvm-cov export -summary-only -ignore-filename-regex 'ZIPFoundationTests|.*Deprecated.*$' .build/release/ZIPFoundationPackageTests.xctest/Contents/MacOS/ZIPFoundationPackageTests -instr-profile .build/release/codecov/default.profdata > .build/coverage.json - run: (cat .build/coverage.json|jq '.data[0]["totals"]["lines"]["percent"]' | grep -Eq "100") && { exit 0; } || { echo 'Please make sure that the test suite covers all framework code paths.'; exit 1; } From d3dda5e9340b00336b48ac94dab563d74d05e37a Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Sat, 8 Jun 2024 13:17:57 +0200 Subject: [PATCH 05/33] Whitespace --- .github/workflows/llvm-cov.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/llvm-cov.yml b/.github/workflows/llvm-cov.yml index b19856e8..4af68777 100644 --- a/.github/workflows/llvm-cov.yml +++ b/.github/workflows/llvm-cov.yml @@ -12,6 +12,6 @@ jobs: steps: - uses: actions/checkout@v2 - run: swift test -c release -Xswiftc -enable-testing --enable-code-coverage - - run: find .build/release/codecov/ -name "*.profraw" -print0 | xargs -0 xcrun llvm-profdata merge -sparse -o .build/release/codecov/default.profdata + - run: find .build/release/codecov/ -name "*.profraw" -print0 | xargs -0 xcrun llvm-profdata merge -sparse -o .build/release/codecov/default.profdata - run: xcrun llvm-cov export -summary-only -ignore-filename-regex 'ZIPFoundationTests|.*Deprecated.*$' .build/release/ZIPFoundationPackageTests.xctest/Contents/MacOS/ZIPFoundationPackageTests -instr-profile .build/release/codecov/default.profdata > .build/coverage.json - run: (cat .build/coverage.json|jq '.data[0]["totals"]["lines"]["percent"]' | grep -Eq "100") && { exit 0; } || { echo 'Please make sure that the test suite covers all framework code paths.'; exit 1; } From 58fffc6fb73e3cbe5814ab152a86934468b701ca Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Sat, 8 Jun 2024 13:21:15 +0200 Subject: [PATCH 06/33] Remove custom codecov merge step --- .github/workflows/llvm-cov.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/llvm-cov.yml b/.github/workflows/llvm-cov.yml index 4af68777..9d02bba0 100644 --- a/.github/workflows/llvm-cov.yml +++ b/.github/workflows/llvm-cov.yml @@ -12,6 +12,5 @@ jobs: steps: - uses: actions/checkout@v2 - run: swift test -c release -Xswiftc -enable-testing --enable-code-coverage - - run: find .build/release/codecov/ -name "*.profraw" -print0 | xargs -0 xcrun llvm-profdata merge -sparse -o .build/release/codecov/default.profdata - run: xcrun llvm-cov export -summary-only -ignore-filename-regex 'ZIPFoundationTests|.*Deprecated.*$' .build/release/ZIPFoundationPackageTests.xctest/Contents/MacOS/ZIPFoundationPackageTests -instr-profile .build/release/codecov/default.profdata > .build/coverage.json - run: (cat .build/coverage.json|jq '.data[0]["totals"]["lines"]["percent"]' | grep -Eq "100") && { exit 0; } || { echo 'Please make sure that the test suite covers all framework code paths.'; exit 1; } From c008da14483d90427fd21761184167ab230f3508 Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Sat, 8 Jun 2024 13:23:54 +0200 Subject: [PATCH 07/33] Revert "Remove custom codecov merge step" This reverts commit 58fffc6fb73e3cbe5814ab152a86934468b701ca. --- .github/workflows/llvm-cov.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/llvm-cov.yml b/.github/workflows/llvm-cov.yml index 9d02bba0..4af68777 100644 --- a/.github/workflows/llvm-cov.yml +++ b/.github/workflows/llvm-cov.yml @@ -12,5 +12,6 @@ jobs: steps: - uses: actions/checkout@v2 - run: swift test -c release -Xswiftc -enable-testing --enable-code-coverage + - run: find .build/release/codecov/ -name "*.profraw" -print0 | xargs -0 xcrun llvm-profdata merge -sparse -o .build/release/codecov/default.profdata - run: xcrun llvm-cov export -summary-only -ignore-filename-regex 'ZIPFoundationTests|.*Deprecated.*$' .build/release/ZIPFoundationPackageTests.xctest/Contents/MacOS/ZIPFoundationPackageTests -instr-profile .build/release/codecov/default.profdata > .build/coverage.json - run: (cat .build/coverage.json|jq '.data[0]["totals"]["lines"]["percent"]' | grep -Eq "100") && { exit 0; } || { echo 'Please make sure that the test suite covers all framework code paths.'; exit 1; } From a6c23ca080fe8de7d38db93ad98843f82fad4275 Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Sun, 9 Jun 2024 07:51:58 +0200 Subject: [PATCH 08/33] Avoid optional FILE pointers when opening memory archives --- Sources/ZIPFoundation/Archive+BackingConfiguration.swift | 5 +---- Sources/ZIPFoundation/Archive+MemoryFile.swift | 8 +++++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Sources/ZIPFoundation/Archive+BackingConfiguration.swift b/Sources/ZIPFoundation/Archive+BackingConfiguration.swift index 167cbd7c..4fb9848d 100644 --- a/Sources/ZIPFoundation/Archive+BackingConfiguration.swift +++ b/Sources/ZIPFoundation/Archive+BackingConfiguration.swift @@ -90,10 +90,7 @@ extension Archive { case .update: posixMode = "rb+" } let memoryFile = MemoryFile(data: data) - guard let archiveFile = memoryFile.open(mode: posixMode) else { - throw ArchiveError.unreadableArchive - } - + let archiveFile = memoryFile.open(mode: posixMode) switch mode { case .read: guard let (eocdRecord, zip64EOCD) = Archive.scanForEndOfCentralDirectoryRecord(in: archiveFile) else { diff --git a/Sources/ZIPFoundation/Archive+MemoryFile.swift b/Sources/ZIPFoundation/Archive+MemoryFile.swift index 8d01536f..736ca9d3 100644 --- a/Sources/ZIPFoundation/Archive+MemoryFile.swift +++ b/Sources/ZIPFoundation/Archive+MemoryFile.swift @@ -22,6 +22,7 @@ extension Archive { } class MemoryFile { + private(set) var data: Data private var offset = 0 @@ -29,14 +30,14 @@ class MemoryFile { self.data = data } - func open(mode: String) -> FILEPointer? { + func open(mode: String) -> FILEPointer { let cookie = Unmanaged.passRetained(self) let writable = mode.count > 0 && (mode.first! != "r" || mode.last! == "+") let append = mode.count > 0 && mode.first! == "a" #if os(macOS) || os(iOS) || os(tvOS) || os(visionOS) || os(watchOS) || os(Android) let result = writable - ? funopen(cookie.toOpaque(), readStub, writeStub, seekStub, closeStub) - : funopen(cookie.toOpaque(), readStub, nil, seekStub, closeStub) + ? funopen(cookie.toOpaque(), readStub, writeStub, seekStub, closeStub)! + : funopen(cookie.toOpaque(), readStub, nil, seekStub, closeStub)! #else let stubs = cookie_io_functions_t(read: readStub, write: writeStub, seek: seekStub, close: closeStub) let result = fopencookie(cookie.toOpaque(), mode, stubs) @@ -49,6 +50,7 @@ class MemoryFile { } private extension MemoryFile { + func readData(buffer: UnsafeMutableRawBufferPointer) -> Int { let size = min(buffer.count, data.count-offset) let start = data.startIndex From f61266573dd8a4645298e0658c228251b29f6f6a Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Sun, 9 Jun 2024 07:53:07 +0200 Subject: [PATCH 09/33] Remove unreliable low-memory allocator test helper --- Sources/ZIPFoundation/Archive.swift | 5 +-- .../ZIPFoundationMemoryTests.swift | 43 +++---------------- .../ZIPFoundationTests.swift | 9 ---- 3 files changed, 8 insertions(+), 49 deletions(-) diff --git a/Sources/ZIPFoundation/Archive.swift b/Sources/ZIPFoundation/Archive.swift index 8e79794c..989d2913 100644 --- a/Sources/ZIPFoundation/Archive.swift +++ b/Sources/ZIPFoundation/Archive.swift @@ -192,10 +192,7 @@ public final class Archive: Sequence { /// - The backing `data` _must_ contain a valid ZIP archive for `AccessMode.read` and `AccessMode.update`. /// - The backing `data` _must_ be empty (or omitted) for `AccessMode.create`. public init(data: Data = Data(), accessMode mode: AccessMode, pathEncoding: String.Encoding? = nil) throws { - guard let url = URL(string: "\(memoryURLScheme)://") else { - throw ArchiveError.unreadableArchive - } - + let url = URL(string: "\(memoryURLScheme)://")! self.url = url self.accessMode = mode self.pathEncoding = pathEncoding diff --git a/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift b/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift index 5ed350d9..c4f73278 100644 --- a/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift +++ b/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift @@ -108,48 +108,19 @@ extension ZIPFoundationTests { XCTFail("Failed to remove entry from memory archive with error : \(error)") } XCTAssert(archive.checkIntegrity()) - // Trigger the code path that is taken if funopen() fails - // We can only do this on Apple platforms - #if os(macOS) || os(iOS) || os(tvOS) || os(visionOS) || os(watchOS) - let entryRemoval = { - self.XCTAssertSwiftError(try archive.remove(entryToRemove), - throws: Archive.ArchiveError.unreadableArchive) - } - self.runWithoutMemory { - try? entryRemoval() - } - let data = Data.makeRandomData(size: 1024) - let emptyArchive = try Archive(accessMode: .create) - let replacementArchive = try Archive(data: data, accessMode: .create) - // Trigger the error code path that is taken when no temporary archive - // can be created during replacement - replacementArchive.memoryFile = nil - let archiveReplacement = { - self.XCTAssertSwiftError(try emptyArchive.replaceCurrentArchive(with: replacementArchive), - throws: Archive.ArchiveError.unwritableArchive) - } - self.runWithoutMemory { - try? archiveReplacement() - } - #endif } func testMemoryArchiveErrorConditions() throws { let data = Data.makeRandomData(size: 1024) XCTAssertSwiftError(try Archive(data: data, accessMode: .read), throws: Archive.ArchiveError.missingEndOfCentralDirectoryRecord) - // Trigger the code path that is taken if funopen() fails - // We can only do this on Apple platforms - #if os(macOS) || os(iOS) || os(tvOS) || os(visionOS) || os(watchOS) - let archiveCreation = { - self.XCTAssertSwiftError(try Archive(data: data, accessMode: .read), - throws: Archive.ArchiveError.unreadableArchive) - } - - self.runWithoutMemory { - try? archiveCreation() - } - #endif + let archive = self.memoryArchive(for: #function, mode: .create) + let replacementArchive = self.memoryArchive(for: #function, mode: .read) + replacementArchive.memoryFile = nil + XCTAssertSwiftError( + try archive.replaceCurrentArchive(with: replacementArchive), + throws: Archive.ArchiveError.unwritableArchive + ) } func testReadOnlyFile() { diff --git a/Tests/ZIPFoundationTests/ZIPFoundationTests.swift b/Tests/ZIPFoundationTests/ZIPFoundationTests.swift index 6c244617..d75e79bb 100644 --- a/Tests/ZIPFoundationTests/ZIPFoundationTests.swift +++ b/Tests/ZIPFoundationTests/ZIPFoundationTests.swift @@ -154,15 +154,6 @@ class ZIPFoundationTests: XCTestCase { try handler() } - func runWithoutMemory(handler: () -> Void) { - #if os(macOS) || os(iOS) || os(tvOS) || os(visionOS) || os(watchOS) - let systemAllocator = CFAllocatorGetDefault().takeUnretainedValue() - CFAllocatorSetDefault(kCFAllocatorNull) - defer { CFAllocatorSetDefault(systemAllocator) } - handler() - #endif - } - // MARK: - ZIP64 Helpers // It's not practical to create compressed files that exceed the size limit every time for test, From ce0d91445209ed7fecea427449bb8cbafcde9419 Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Sun, 9 Jun 2024 07:53:48 +0200 Subject: [PATCH 10/33] Improve ZIP64 field extraction --- Sources/ZIPFoundation/Entry+ZIP64.swift | 31 +++++++++++-------------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/Sources/ZIPFoundation/Entry+ZIP64.swift b/Sources/ZIPFoundation/Entry+ZIP64.swift index dec18688..88bce895 100644 --- a/Sources/ZIPFoundation/Entry+ZIP64.swift +++ b/Sources/ZIPFoundation/Entry+ZIP64.swift @@ -16,8 +16,8 @@ protocol ExtensibleDataField { } extension Entry { + enum EntryError: Error { - case invalidDataError case missingPermissionsAttributeError case missingModificationDateAttributeError } @@ -63,6 +63,7 @@ extension Entry.CentralDirectoryStructure { } extension Entry.ZIP64ExtendedInformation { + enum Field { case uncompressedSize case compressedSize @@ -105,29 +106,23 @@ extension Entry.ZIP64ExtendedInformation { init?(data: Data, fields: [Field]) { let headerLength = 4 guard fields.reduce(0, { $0 + $1.size }) + headerLength == data.count else { return nil } + var readOffset = headerLength - func value(of field: Field) throws -> T where T: BinaryInteger { - if fields.contains(field) { - defer { - readOffset += MemoryLayout.size - } - guard readOffset + field.size <= data.count else { - throw Entry.EntryError.invalidDataError - } + func value(of field: Field) -> T where T: BinaryInteger { + if fields.contains(field), readOffset + field.size <= data.count { + defer { readOffset += MemoryLayout.size } + return data.scanValue(start: readOffset) } else { return 0 } } - do { - dataSize = data.scanValue(start: 2) - uncompressedSize = try value(of: .uncompressedSize) - compressedSize = try value(of: .compressedSize) - relativeOffsetOfLocalHeader = try value(of: .relativeOffsetOfLocalHeader) - diskNumberStart = try value(of: .diskNumberStart) - } catch { - return nil - } + + self.dataSize = data.scanValue(start: 2) + self.uncompressedSize = try value(of: .uncompressedSize) + self.compressedSize = try value(of: .compressedSize) + self.relativeOffsetOfLocalHeader = try value(of: .relativeOffsetOfLocalHeader) + self.diskNumberStart = try value(of: .diskNumberStart) } init?(zip64ExtendedInformation: Entry.ZIP64ExtendedInformation?, offset: UInt64) { From 4b0bad74119ada02cdae3c265fba2a3ed370c988 Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Sun, 9 Jun 2024 07:55:44 +0200 Subject: [PATCH 11/33] Add test resource --- .../testMemoryArchiveErrorConditions.zip | Bin 0 -> 6546 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Tests/ZIPFoundationTests/Resources/testMemoryArchiveErrorConditions.zip diff --git a/Tests/ZIPFoundationTests/Resources/testMemoryArchiveErrorConditions.zip b/Tests/ZIPFoundationTests/Resources/testMemoryArchiveErrorConditions.zip new file mode 100644 index 0000000000000000000000000000000000000000..9ced9c619ea18673fb46ec7c3aadae49130b25ad GIT binary patch literal 6546 zcmeHMJxc>Y5S=xrMr~3kSRN=?C`wAZQ_ezz5D3_+rZTISMGGxOSf6TTeam z{h-~d61{CaZR_R+o?wipd68;u(m2E?3Wx%tfG8je{1*kVXS3xO3`#BvhytR(KmlGK zTqH)%V#lCfI*{or0FaOI+EC^@1#?`Bp2dzqcwovRlV>S?m}zbW-;6 zp={5}-cXe89qqe1oRnu!a#27O7*!x=J`246?;(x3|BsU7OB4_V{*(gB@hko=reycl z)Z}=tb&*bx5<{#GM>cW@zz1)|_{-54{4SS(p2dzq)WGB*pk> WySHH3xs^-PGwg8idj&q}CGZ;;#%Tfo literal 0 HcmV?d00001 From 6a58e768c3712875e85311a1fddd12fe6f3abe73 Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Sun, 9 Jun 2024 08:00:23 +0200 Subject: [PATCH 12/33] Swiftlint --- Sources/ZIPFoundation/Entry+ZIP64.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Sources/ZIPFoundation/Entry+ZIP64.swift b/Sources/ZIPFoundation/Entry+ZIP64.swift index 88bce895..57704509 100644 --- a/Sources/ZIPFoundation/Entry+ZIP64.swift +++ b/Sources/ZIPFoundation/Entry+ZIP64.swift @@ -106,7 +106,7 @@ extension Entry.ZIP64ExtendedInformation { init?(data: Data, fields: [Field]) { let headerLength = 4 guard fields.reduce(0, { $0 + $1.size }) + headerLength == data.count else { return nil } - + var readOffset = headerLength func value(of field: Field) -> T where T: BinaryInteger { if fields.contains(field), readOffset + field.size <= data.count { @@ -119,10 +119,10 @@ extension Entry.ZIP64ExtendedInformation { } self.dataSize = data.scanValue(start: 2) - self.uncompressedSize = try value(of: .uncompressedSize) - self.compressedSize = try value(of: .compressedSize) - self.relativeOffsetOfLocalHeader = try value(of: .relativeOffsetOfLocalHeader) - self.diskNumberStart = try value(of: .diskNumberStart) + self.uncompressedSize = value(of: .uncompressedSize) + self.compressedSize = value(of: .compressedSize) + self.relativeOffsetOfLocalHeader = value(of: .relativeOffsetOfLocalHeader) + self.diskNumberStart = value(of: .diskNumberStart) } init?(zip64ExtendedInformation: Entry.ZIP64ExtendedInformation?, offset: UInt64) { From 7b3dd0fd439afef8b470c722f1415f2554822ac9 Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Sun, 9 Jun 2024 08:08:07 +0200 Subject: [PATCH 13/33] Fix Linux build --- Sources/ZIPFoundation/Archive+MemoryFile.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/ZIPFoundation/Archive+MemoryFile.swift b/Sources/ZIPFoundation/Archive+MemoryFile.swift index 736ca9d3..430826d1 100644 --- a/Sources/ZIPFoundation/Archive+MemoryFile.swift +++ b/Sources/ZIPFoundation/Archive+MemoryFile.swift @@ -40,7 +40,7 @@ class MemoryFile { : funopen(cookie.toOpaque(), readStub, nil, seekStub, closeStub)! #else let stubs = cookie_io_functions_t(read: readStub, write: writeStub, seek: seekStub, close: closeStub) - let result = fopencookie(cookie.toOpaque(), mode, stubs) + let result = fopencookie(cookie.toOpaque(), mode, stubs)! #endif if append { fseeko(result, 0, SEEK_END) From 8a0e219535a46a36282ea08df84a48a1cce1817c Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Sun, 9 Jun 2024 08:36:04 +0200 Subject: [PATCH 14/33] Refactor memory file opening --- .../Archive+BackingConfiguration.swift | 8 +-- .../ZIPFoundation/Archive+MemoryFile.swift | 52 +++++++++---------- Sources/ZIPFoundation/Archive.swift | 2 + .../ZIPFoundationMemoryTests.swift | 20 +++---- .../ZIPFoundationTests.swift | 1 - 5 files changed, 33 insertions(+), 50 deletions(-) diff --git a/Sources/ZIPFoundation/Archive+BackingConfiguration.swift b/Sources/ZIPFoundation/Archive+BackingConfiguration.swift index 4fb9848d..d39b4720 100644 --- a/Sources/ZIPFoundation/Archive+BackingConfiguration.swift +++ b/Sources/ZIPFoundation/Archive+BackingConfiguration.swift @@ -83,14 +83,8 @@ extension Archive { #if swift(>=5.0) static func makeBackingConfiguration(for data: Data, mode: AccessMode) throws -> BackingConfiguration { - let posixMode: String - switch mode { - case .read: posixMode = "rb" - case .create: posixMode = "wb+" - case .update: posixMode = "rb+" - } let memoryFile = MemoryFile(data: data) - let archiveFile = memoryFile.open(mode: posixMode) + let archiveFile = memoryFile.open(mode: mode) switch mode { case .read: guard let (eocdRecord, zip64EOCD) = Archive.scanForEndOfCentralDirectoryRecord(in: archiveFile) else { diff --git a/Sources/ZIPFoundation/Archive+MemoryFile.swift b/Sources/ZIPFoundation/Archive+MemoryFile.swift index 430826d1..2d7060ec 100644 --- a/Sources/ZIPFoundation/Archive+MemoryFile.swift +++ b/Sources/ZIPFoundation/Archive+MemoryFile.swift @@ -17,39 +17,35 @@ extension Archive { #if swift(>=5.0) extension Archive { - /// Returns a `Data` object containing a representation of the receiver. - public var data: Data? { return self.memoryFile?.data } -} -class MemoryFile { + class MemoryFile { - private(set) var data: Data - private var offset = 0 + private(set) var data: Data + private var offset = 0 - init(data: Data = Data()) { - self.data = data - } + init(data: Data = Data()) { + self.data = data + } - func open(mode: String) -> FILEPointer { - let cookie = Unmanaged.passRetained(self) - let writable = mode.count > 0 && (mode.first! != "r" || mode.last! == "+") - let append = mode.count > 0 && mode.first! == "a" - #if os(macOS) || os(iOS) || os(tvOS) || os(visionOS) || os(watchOS) || os(Android) - let result = writable - ? funopen(cookie.toOpaque(), readStub, writeStub, seekStub, closeStub)! - : funopen(cookie.toOpaque(), readStub, nil, seekStub, closeStub)! - #else - let stubs = cookie_io_functions_t(read: readStub, write: writeStub, seek: seekStub, close: closeStub) - let result = fopencookie(cookie.toOpaque(), mode, stubs)! - #endif - if append { - fseeko(result, 0, SEEK_END) + func open(mode: AccessMode) -> FILEPointer { + let cookie = Unmanaged.passRetained(self) + #if os(macOS) || os(iOS) || os(tvOS) || os(visionOS) || os(watchOS) || os(Android) + let result = mode.isWritable + ? funopen(cookie.toOpaque(), readStub, writeStub, seekStub, closeStub)! + : funopen(cookie.toOpaque(), readStub, nil, seekStub, closeStub)! + #else + let stubs = cookie_io_functions_t(read: readStub, write: writeStub, seek: seekStub, close: closeStub) + let result = fopencookie(cookie.toOpaque(), mode, stubs)! + #endif + return result } - return result } + + /// Returns a `Data` object containing a representation of the receiver. + public var data: Data? { return self.memoryFile?.data } } -private extension MemoryFile { +private extension Archive.MemoryFile { func readData(buffer: UnsafeMutableRawBufferPointer) -> Int { let size = min(buffer.count, data.count-offset) @@ -90,13 +86,13 @@ private extension MemoryFile { } } -private func fileFromCookie(cookie: UnsafeRawPointer) -> MemoryFile { - return Unmanaged.fromOpaque(cookie).takeUnretainedValue() +private func fileFromCookie(cookie: UnsafeRawPointer) -> Archive.MemoryFile { + return Unmanaged.fromOpaque(cookie).takeUnretainedValue() } private func closeStub(_ cookie: UnsafeMutableRawPointer?) -> Int32 { if let cookie = cookie { - Unmanaged.fromOpaque(cookie).release() + Unmanaged.fromOpaque(cookie).release() } return 0 } diff --git a/Sources/ZIPFoundation/Archive.swift b/Sources/ZIPFoundation/Archive.swift index 989d2913..89b71c11 100644 --- a/Sources/ZIPFoundation/Archive.swift +++ b/Sources/ZIPFoundation/Archive.swift @@ -102,6 +102,8 @@ public final class Archive: Sequence { case read /// Indicates that a newly instantiated `Archive` should update an existing backing file. case update + + var isWritable: Bool { self != .read } } /// The version of an `Archive` diff --git a/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift b/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift index c4f73278..d076be8c 100644 --- a/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift +++ b/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift @@ -124,7 +124,7 @@ extension ZIPFoundationTests { } func testReadOnlyFile() { - let file = MemoryFile(data: Data("ABCDEabcde".utf8)).open(mode: "r") + let file = Archive.MemoryFile(data: Data("ABCDEabcde".utf8)).open(mode: .read) var chars: [UInt8] = [0, 0, 0] XCTAssertEqual(fread(&chars, 1, 2, file), 2) XCTAssertEqual(String(Unicode.Scalar(chars[0])), "A") @@ -144,7 +144,7 @@ extension ZIPFoundationTests { func testReadOnlySlicedFile() { let originalData = Data("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".utf8) let slice = originalData[10.. () throws -> Void)] { #if swift(>=5.0) return [ - ("testAppendFile", testAppendFile), ("testCreateArchiveAddUncompressedEntryToMemory", testCreateArchiveAddUncompressedEntryToMemory), ("testCreateArchiveAddCompressedEntryToMemory", testCreateArchiveAddCompressedEntryToMemory), ("testUpdateArchiveRemoveUncompressedEntryFromMemory", testUpdateArchiveRemoveUncompressedEntryFromMemory), From f4d22b808b65a3a041e494e1fc2a6cf8de8902dc Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Sun, 9 Jun 2024 08:41:20 +0200 Subject: [PATCH 15/33] Fix Linux build --- Sources/ZIPFoundation/Archive+MemoryFile.swift | 2 +- Sources/ZIPFoundation/Archive.swift | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Sources/ZIPFoundation/Archive+MemoryFile.swift b/Sources/ZIPFoundation/Archive+MemoryFile.swift index 2d7060ec..246c8d00 100644 --- a/Sources/ZIPFoundation/Archive+MemoryFile.swift +++ b/Sources/ZIPFoundation/Archive+MemoryFile.swift @@ -35,7 +35,7 @@ extension Archive { : funopen(cookie.toOpaque(), readStub, nil, seekStub, closeStub)! #else let stubs = cookie_io_functions_t(read: readStub, write: writeStub, seek: seekStub, close: closeStub) - let result = fopencookie(cookie.toOpaque(), mode, stubs)! + let result = fopencookie(cookie.toOpaque(), mode.posixMode, stubs)! #endif return result } diff --git a/Sources/ZIPFoundation/Archive.swift b/Sources/ZIPFoundation/Archive.swift index 89b71c11..e3839456 100644 --- a/Sources/ZIPFoundation/Archive.swift +++ b/Sources/ZIPFoundation/Archive.swift @@ -104,6 +104,14 @@ public final class Archive: Sequence { case update var isWritable: Bool { self != .read } + + var posixMode: String { + switch self { + case .read: return "rb" + case .create: return "wb+" + case .update: return "rb+" + } + } } /// The version of an `Archive` From fbb037a0861c7996129bddabf8bc98701356a3b1 Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Sun, 9 Jun 2024 08:43:52 +0200 Subject: [PATCH 16/33] Cleanup --- Sources/ZIPFoundation/Archive+MemoryFile.swift | 12 ++++++++++++ Sources/ZIPFoundation/Archive.swift | 8 -------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Sources/ZIPFoundation/Archive+MemoryFile.swift b/Sources/ZIPFoundation/Archive+MemoryFile.swift index 246c8d00..e869f73b 100644 --- a/Sources/ZIPFoundation/Archive+MemoryFile.swift +++ b/Sources/ZIPFoundation/Archive+MemoryFile.swift @@ -122,6 +122,18 @@ private func seekStub(_ cookie: UnsafeMutableRawPointer?, } #else + +extension Archive.AccessMode { + + var posixMode: String { + switch self { + case .read: return "rb" + case .create: return "wb+" + case .update: return "rb+" + } + } +} + private func readStub(_ cookie: UnsafeMutableRawPointer?, _ bytePtr: UnsafeMutablePointer?, _ count: Int) -> Int { diff --git a/Sources/ZIPFoundation/Archive.swift b/Sources/ZIPFoundation/Archive.swift index e3839456..89b71c11 100644 --- a/Sources/ZIPFoundation/Archive.swift +++ b/Sources/ZIPFoundation/Archive.swift @@ -104,14 +104,6 @@ public final class Archive: Sequence { case update var isWritable: Bool { self != .read } - - var posixMode: String { - switch self { - case .read: return "rb" - case .create: return "wb+" - case .update: return "rb+" - } - } } /// The version of an `Archive` From b0c350e3ca89d20a2ed81869ef31763d99cadc0d Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Sun, 9 Jun 2024 10:29:44 +0200 Subject: [PATCH 17/33] Merge workflows into one --- .github/workflows/CI.yml | 50 +++++++++++++++++++++++++++++++++ .github/workflows/llvm-cov.yml | 17 ----------- .github/workflows/swift.yml | 31 -------------------- .github/workflows/swiftlint.yml | 18 ------------ 4 files changed, 50 insertions(+), 66 deletions(-) create mode 100644 .github/workflows/CI.yml delete mode 100644 .github/workflows/llvm-cov.yml delete mode 100644 .github/workflows/swift.yml delete mode 100644 .github/workflows/swiftlint.yml diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml new file mode 100644 index 00000000..eefab1c9 --- /dev/null +++ b/.github/workflows/CI.yml @@ -0,0 +1,50 @@ +name: SwiftLint + +on: + pull_request: + paths: + - '.github/workflows/swiftlint.yml' + - '.swiftlint.yml' + - '**/*.swift' + +jobs: + SwiftLint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: SwiftLint + uses: norio-nomura/action-swiftlint@3.2.1 + with: + args: --strict + + Xcode: + strategy: + matrix: + xcode_version: ['13.3.1', '13.4', '14.0.1', '14.1', '14.2'] + runs-on: macos-12 + env: + DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode_version }}.app + steps: + - uses: actions/checkout@v2 + - run: swift -version + - run: swift test -c release -Xswiftc -enable-testing + + Linux: + strategy: + matrix: + tag: ['5.1', '5.2', '5.3', '5.4', '5.5', '5.6', '5.7', '5.8'] + runs-on: ubuntu-latest + container: + image: swift:${{ matrix.tag }} + steps: + - uses: actions/checkout@v2 + - run: swift test -c release -Xswiftc -enable-testing + + Coverage: + runs-on: macos-latest + steps: + - uses: actions/checkout@v2 + - run: swift test -c release -Xswiftc -enable-testing --enable-code-coverage + - run: find .build/release/codecov/ -name "*.profraw" -print0 | xargs -0 xcrun llvm-profdata merge -sparse -o .build/release/codecov/default.profdata + - run: xcrun llvm-cov export -summary-only -ignore-filename-regex 'ZIPFoundationTests|.*Deprecated.*$' .build/release/ZIPFoundationPackageTests.xctest/Contents/MacOS/ZIPFoundationPackageTests -instr-profile .build/release/codecov/default.profdata > .build/coverage.json + - run: (cat .build/coverage.json|jq '.data[0]["totals"]["lines"]["percent"]' | grep -Eq "100") && { exit 0; } || { echo 'Please make sure that the test suite covers all framework code paths.'; exit 1; } diff --git a/.github/workflows/llvm-cov.yml b/.github/workflows/llvm-cov.yml deleted file mode 100644 index 4af68777..00000000 --- a/.github/workflows/llvm-cov.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: Coverage - -on: - push: - branches: [development] - pull_request: - branches: [development] - -jobs: - Coverage: - runs-on: macos-latest - steps: - - uses: actions/checkout@v2 - - run: swift test -c release -Xswiftc -enable-testing --enable-code-coverage - - run: find .build/release/codecov/ -name "*.profraw" -print0 | xargs -0 xcrun llvm-profdata merge -sparse -o .build/release/codecov/default.profdata - - run: xcrun llvm-cov export -summary-only -ignore-filename-regex 'ZIPFoundationTests|.*Deprecated.*$' .build/release/ZIPFoundationPackageTests.xctest/Contents/MacOS/ZIPFoundationPackageTests -instr-profile .build/release/codecov/default.profdata > .build/coverage.json - - run: (cat .build/coverage.json|jq '.data[0]["totals"]["lines"]["percent"]' | grep -Eq "100") && { exit 0; } || { echo 'Please make sure that the test suite covers all framework code paths.'; exit 1; } diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml deleted file mode 100644 index 2b08431b..00000000 --- a/.github/workflows/swift.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Swift - -on: - push: - branches: [development] - pull_request: - branches: [development] - -jobs: - Xcode: - strategy: - matrix: - xcode_version: ['13.3.1', '13.4', '14.0.1', '14.1', '14.2'] - runs-on: macos-12 - env: - DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode_version }}.app - steps: - - uses: actions/checkout@v2 - - run: swift -version - - run: swift test -c release -Xswiftc -enable-testing - - Linux: - strategy: - matrix: - tag: ['5.1', '5.2', '5.3', '5.4', '5.5', '5.6', '5.7', '5.8'] - runs-on: ubuntu-latest - container: - image: swift:${{ matrix.tag }} - steps: - - uses: actions/checkout@v2 - - run: swift test -c release -Xswiftc -enable-testing diff --git a/.github/workflows/swiftlint.yml b/.github/workflows/swiftlint.yml deleted file mode 100644 index 5818a7fb..00000000 --- a/.github/workflows/swiftlint.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: SwiftLint - -on: - pull_request: - paths: - - '.github/workflows/swiftlint.yml' - - '.swiftlint.yml' - - '**/*.swift' - -jobs: - SwiftLint: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: SwiftLint - uses: norio-nomura/action-swiftlint@3.2.1 - with: - args: --strict \ No newline at end of file From ebf55de8d24a959f58d0618b074c2f783bf756e4 Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Sun, 9 Jun 2024 10:41:22 +0200 Subject: [PATCH 18/33] Debug Linux test suite --- .../ZIPFoundationMemoryTests.swift | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift b/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift index d076be8c..6f9dfd77 100644 --- a/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift +++ b/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift @@ -114,13 +114,13 @@ extension ZIPFoundationTests { let data = Data.makeRandomData(size: 1024) XCTAssertSwiftError(try Archive(data: data, accessMode: .read), throws: Archive.ArchiveError.missingEndOfCentralDirectoryRecord) - let archive = self.memoryArchive(for: #function, mode: .create) - let replacementArchive = self.memoryArchive(for: #function, mode: .read) - replacementArchive.memoryFile = nil - XCTAssertSwiftError( - try archive.replaceCurrentArchive(with: replacementArchive), - throws: Archive.ArchiveError.unwritableArchive - ) +// let archive = self.memoryArchive(for: #function, mode: .create) +// let replacementArchive = self.memoryArchive(for: #function, mode: .read) +// replacementArchive.memoryFile = nil +// XCTAssertSwiftError( +// try archive.replaceCurrentArchive(with: replacementArchive), +// throws: Archive.ArchiveError.unwritableArchive +// ) } func testReadOnlyFile() { From 53a16770d01b0235a33e8faa474b1b80dd00d029 Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Sun, 9 Jun 2024 10:59:13 +0200 Subject: [PATCH 19/33] Debug Linux test --- .../ZIPFoundation/Archive+MemoryFile.swift | 1 + Sources/ZIPFoundation/Archive.swift | 4 ++-- .../ZIPFoundationMemoryTests.swift | 19 +++++++++---------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Sources/ZIPFoundation/Archive+MemoryFile.swift b/Sources/ZIPFoundation/Archive+MemoryFile.swift index e869f73b..08ae82a9 100644 --- a/Sources/ZIPFoundation/Archive+MemoryFile.swift +++ b/Sources/ZIPFoundation/Archive+MemoryFile.swift @@ -98,6 +98,7 @@ private func closeStub(_ cookie: UnsafeMutableRawPointer?) -> Int32 { } #if os(macOS) || os(iOS) || os(tvOS) || os(visionOS) || os(watchOS) || os(Android) + private func readStub(_ cookie: UnsafeMutableRawPointer?, _ bytePtr: UnsafeMutablePointer?, _ count: Int32) -> Int32 { diff --git a/Sources/ZIPFoundation/Archive.swift b/Sources/ZIPFoundation/Archive.swift index 89b71c11..53d3950b 100644 --- a/Sources/ZIPFoundation/Archive.swift +++ b/Sources/ZIPFoundation/Archive.swift @@ -176,7 +176,7 @@ public final class Archive: Sequence { setvbuf(self.archiveFile, nil, _IOFBF, Int(defaultPOSIXBufferSize)) } -#if swift(>=5.0) + #if swift(>=5.0) var memoryFile: MemoryFile? /// Initializes a new in-memory ZIP `Archive`. @@ -204,7 +204,7 @@ public final class Archive: Sequence { self.endOfCentralDirectoryRecord = config.endOfCentralDirectoryRecord self.zip64EndOfCentralDirectory = config.zip64EndOfCentralDirectory } -#endif + #endif deinit { fclose(self.archiveFile) diff --git a/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift b/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift index 6f9dfd77..eb24b943 100644 --- a/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift +++ b/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift @@ -114,13 +114,13 @@ extension ZIPFoundationTests { let data = Data.makeRandomData(size: 1024) XCTAssertSwiftError(try Archive(data: data, accessMode: .read), throws: Archive.ArchiveError.missingEndOfCentralDirectoryRecord) -// let archive = self.memoryArchive(for: #function, mode: .create) -// let replacementArchive = self.memoryArchive(for: #function, mode: .read) -// replacementArchive.memoryFile = nil -// XCTAssertSwiftError( -// try archive.replaceCurrentArchive(with: replacementArchive), -// throws: Archive.ArchiveError.unwritableArchive -// ) + let archive = self.memoryArchive(for: #function, mode: .create) + let replacementArchive = self.memoryArchive(for: #function, mode: .read) + //replacementArchive.memoryFile = nil + XCTAssertSwiftError( + try archive.replaceCurrentArchive(with: replacementArchive), + throws: Archive.ArchiveError.unwritableArchive + ) } func testReadOnlyFile() { @@ -192,9 +192,8 @@ extension ZIPFoundationTests { sourceArchiveURL.appendPathExtension("zip") do { let data = mode == .create ? Data() : try Data(contentsOf: sourceArchiveURL) - let archive = try Archive(data: data, accessMode: mode, - pathEncoding: pathEncoding) - return archive + return try Archive(data: data, accessMode: mode, + pathEncoding: pathEncoding) } catch { XCTFail("Failed to open memory archive for '\(sourceArchiveURL.lastPathComponent)'") type(of: self).tearDown() From 45cb00bb6a021188f3b61172bfdc6a16fa3986fb Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Sun, 9 Jun 2024 11:10:03 +0200 Subject: [PATCH 20/33] Debug Linux test --- .../ZIPFoundationTests/ZIPFoundationMemoryTests.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift b/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift index eb24b943..a99885d0 100644 --- a/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift +++ b/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift @@ -116,11 +116,11 @@ extension ZIPFoundationTests { throws: Archive.ArchiveError.missingEndOfCentralDirectoryRecord) let archive = self.memoryArchive(for: #function, mode: .create) let replacementArchive = self.memoryArchive(for: #function, mode: .read) - //replacementArchive.memoryFile = nil - XCTAssertSwiftError( - try archive.replaceCurrentArchive(with: replacementArchive), - throws: Archive.ArchiveError.unwritableArchive - ) + replacementArchive.memoryFile = nil +// XCTAssertSwiftError( +// try archive.replaceCurrentArchive(with: replacementArchive), +// throws: Archive.ArchiveError.unwritableArchive +// ) } func testReadOnlyFile() { From bc263d8252130d9562a1b8a3bb843fb0f2d07c31 Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Sun, 9 Jun 2024 22:51:41 +0200 Subject: [PATCH 21/33] Refactor archive file handle closing --- .../ZIPFoundation/Archive+MemoryFile.swift | 22 +++++++++---------- Sources/ZIPFoundation/Archive+Writing.swift | 2 +- Sources/ZIPFoundation/Archive.swift | 6 ++++- .../ZIPFoundationMemoryTests.swift | 8 +++---- 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/Sources/ZIPFoundation/Archive+MemoryFile.swift b/Sources/ZIPFoundation/Archive+MemoryFile.swift index 08ae82a9..519fd936 100644 --- a/Sources/ZIPFoundation/Archive+MemoryFile.swift +++ b/Sources/ZIPFoundation/Archive+MemoryFile.swift @@ -50,25 +50,25 @@ private extension Archive.MemoryFile { func readData(buffer: UnsafeMutableRawBufferPointer) -> Int { let size = min(buffer.count, data.count-offset) let start = data.startIndex - data.copyBytes(to: buffer.bindMemory(to: UInt8.self), from: start+offset.. Int { - let start = data.startIndex - if offset < data.count && offset+buffer.count > data.count { - data.removeSubrange(start+offset.. self.data.count { + self.data.removeSubrange(start+self.offset.. data.count { - data.append(Data(count: offset-data.count)) + self.data.append(Data(count: self.offset-self.data.count)) } - if offset == data.count { - data.append(buffer.bindMemory(to: UInt8.self)) + if self.offset == self.data.count { + self.data.append(buffer.bindMemory(to: UInt8.self)) } else { - let start = data.startIndex // May have changed in earlier mutation - data.replaceSubrange(start+offset..=5.0) guard let data = archive.data else { @@ -246,6 +245,7 @@ extension Archive { #endif let fileSystemRepresentation = fileManager.fileSystemRepresentation(withPath: self.url.path) guard let file = fopen(fileSystemRepresentation, "rb+") else { throw ArchiveError.unreadableArchive } + self.archiveFile = file } } diff --git a/Sources/ZIPFoundation/Archive.swift b/Sources/ZIPFoundation/Archive.swift index 53d3950b..9be7e411 100644 --- a/Sources/ZIPFoundation/Archive.swift +++ b/Sources/ZIPFoundation/Archive.swift @@ -131,7 +131,11 @@ public final class Archive: Sequence { public let url: URL /// Access mode for an archive file. public let accessMode: AccessMode - var archiveFile: FILEPointer + var archiveFile: FILEPointer { + willSet { + fclose(self.archiveFile) + } + } var endOfCentralDirectoryRecord: EndOfCentralDirectoryRecord var zip64EndOfCentralDirectory: ZIP64EndOfCentralDirectory? var pathEncoding: String.Encoding? diff --git a/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift b/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift index a99885d0..057065d4 100644 --- a/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift +++ b/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift @@ -117,10 +117,10 @@ extension ZIPFoundationTests { let archive = self.memoryArchive(for: #function, mode: .create) let replacementArchive = self.memoryArchive(for: #function, mode: .read) replacementArchive.memoryFile = nil -// XCTAssertSwiftError( -// try archive.replaceCurrentArchive(with: replacementArchive), -// throws: Archive.ArchiveError.unwritableArchive -// ) + XCTAssertSwiftError( + try archive.replaceCurrentArchive(with: replacementArchive), + throws: Archive.ArchiveError.unwritableArchive + ) } func testReadOnlyFile() { From a0770368a1642ed044af22a8d986fac86e60083c Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Sun, 9 Jun 2024 23:07:12 +0200 Subject: [PATCH 22/33] Swiftlint --- Sources/ZIPFoundation/Archive+MemoryFile.swift | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Sources/ZIPFoundation/Archive+MemoryFile.swift b/Sources/ZIPFoundation/Archive+MemoryFile.swift index 519fd936..286e424f 100644 --- a/Sources/ZIPFoundation/Archive+MemoryFile.swift +++ b/Sources/ZIPFoundation/Archive+MemoryFile.swift @@ -66,7 +66,10 @@ private extension Archive.MemoryFile { self.data.append(buffer.bindMemory(to: UInt8.self)) } else { let start = self.data.startIndex // May have changed in earlier mutation - self.data.replaceSubrange(start+self.offset.. Date: Sun, 9 Jun 2024 23:21:41 +0200 Subject: [PATCH 23/33] Doc comment --- Sources/ZIPFoundation/Archive.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Sources/ZIPFoundation/Archive.swift b/Sources/ZIPFoundation/Archive.swift index 9be7e411..29daf33a 100644 --- a/Sources/ZIPFoundation/Archive.swift +++ b/Sources/ZIPFoundation/Archive.swift @@ -103,6 +103,7 @@ public final class Archive: Sequence { /// Indicates that a newly instantiated `Archive` should update an existing backing file. case update + /// Indicates that the archive can be written to. var isWritable: Bool { self != .read } } From e01c8ddb7c5db38f96a5ec9503b17fe47fafefa4 Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Sun, 9 Jun 2024 23:45:54 +0200 Subject: [PATCH 24/33] Improve coverage --- Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift b/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift index 057065d4..5dae6909 100644 --- a/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift +++ b/Tests/ZIPFoundationTests/ZIPFoundationMemoryTests.swift @@ -121,6 +121,15 @@ extension ZIPFoundationTests { try archive.replaceCurrentArchive(with: replacementArchive), throws: Archive.ArchiveError.unwritableArchive ) + + var noEndOfCentralDirectoryArchiveURL = ZIPFoundationTests.tempZipDirectoryURL + noEndOfCentralDirectoryArchiveURL.appendPathComponent(ProcessInfo.processInfo.globallyUniqueString) + let fullPermissionAttributes = [FileAttributeKey.posixPermissions: NSNumber(value: defaultFilePermissions)] + FileManager().createFile(atPath: noEndOfCentralDirectoryArchiveURL.path, contents: nil, + attributes: fullPermissionAttributes) + let noEOCDArchiveData = try Data(contentsOf: noEndOfCentralDirectoryArchiveURL) + XCTAssertSwiftError(try Archive(data: noEOCDArchiveData, accessMode: .update), + throws: Archive.ArchiveError.missingEndOfCentralDirectoryRecord) } func testReadOnlyFile() { From f27f12a008abdbee72e48caa350bd2db1e928334 Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Sun, 9 Jun 2024 23:50:19 +0200 Subject: [PATCH 25/33] Improve coverage --- Tests/ZIPFoundationTests/ZIPFoundationErrorConditionTests.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Tests/ZIPFoundationTests/ZIPFoundationErrorConditionTests.swift b/Tests/ZIPFoundationTests/ZIPFoundationErrorConditionTests.swift index b0f90355..311c51d5 100644 --- a/Tests/ZIPFoundationTests/ZIPFoundationErrorConditionTests.swift +++ b/Tests/ZIPFoundationTests/ZIPFoundationErrorConditionTests.swift @@ -14,6 +14,7 @@ extension ZIPFoundationTests { func testArchiveReadErrorConditions() { let nonExistantURL = URL(fileURLWithPath: "/nothing") + XCTAssertPOSIXError(try Archive(url: nonExistantURL, accessMode: .read), throwsErrorWithCode: .ENOENT) XCTAssertPOSIXError(try Archive(url: nonExistantURL, accessMode: .update), throwsErrorWithCode: .ENOENT) let processInfo = ProcessInfo.processInfo let fileManager = FileManager() From a5177fe8d54af20dca443de68708d2822d0ef920 Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Mon, 10 Jun 2024 09:44:02 +0200 Subject: [PATCH 26/33] Increase coverage --- Sources/ZIPFoundation/Archive.swift | 9 +++------ .../Resources/testArchiveReadErrorConditions.zip | Bin 0 -> 6546 bytes .../ZIPFoundationErrorConditionTests.swift | 3 +++ 3 files changed, 6 insertions(+), 6 deletions(-) create mode 100644 Tests/ZIPFoundationTests/Resources/testArchiveReadErrorConditions.zip diff --git a/Sources/ZIPFoundation/Archive.swift b/Sources/ZIPFoundation/Archive.swift index 29daf33a..3f4f438a 100644 --- a/Sources/ZIPFoundation/Archive.swift +++ b/Sources/ZIPFoundation/Archive.swift @@ -297,14 +297,11 @@ public final class Archive: Sequence { private static func scanForZIP64EndOfCentralDirectory(in file: FILEPointer, eocdOffset: UInt64) -> ZIP64EndOfCentralDirectory? { - guard UInt64(ZIP64EndOfCentralDirectoryLocator.size) < eocdOffset else { - return nil - } + guard UInt64(ZIP64EndOfCentralDirectoryLocator.size) < eocdOffset else { return nil } + let locatorOffset = eocdOffset - UInt64(ZIP64EndOfCentralDirectoryLocator.size) + guard UInt64(ZIP64EndOfCentralDirectoryRecord.size) < locatorOffset else { return nil } - guard UInt64(ZIP64EndOfCentralDirectoryRecord.size) < locatorOffset else { - return nil - } let recordOffset = locatorOffset - UInt64(ZIP64EndOfCentralDirectoryRecord.size) guard let locator: ZIP64EndOfCentralDirectoryLocator = Data.readStruct(from: file, at: locatorOffset), let record: ZIP64EndOfCentralDirectoryRecord = Data.readStruct(from: file, at: recordOffset) else { diff --git a/Tests/ZIPFoundationTests/Resources/testArchiveReadErrorConditions.zip b/Tests/ZIPFoundationTests/Resources/testArchiveReadErrorConditions.zip new file mode 100644 index 0000000000000000000000000000000000000000..387ed8e81d686444860db56fe90ff4673a51b1b5 GIT binary patch literal 6546 zcmeHMJxc>Y5S=xrMr~3kSRN=?C`wAZQ_ezz5D3_+rZTISMGGxOSf6TTeam z{h-~d61{CaZR_R+o?wipd68;u(m2E?3Wx%tfG8je{1*kVXS3xO3`#BvhytR(KmlGK zTqH)%V#lCfI*{or0FaOI+EC^@1#?`Bp2dzqcwovRlV>S?m}zbW-;6 zp={5}-cXe89qqe1oRnu!a#27O7*!x=J`246?;(x3|BsU7OB4_V{*(gB@hko=reycl z)Z}=tb&*bx5<{#GM>cW@zz1)|_{-54{4SS(p2dzq)WGB*pk> XySHH3xs^-PGwg8idj&r666kyb7s_b{ literal 0 HcmV?d00001 diff --git a/Tests/ZIPFoundationTests/ZIPFoundationErrorConditionTests.swift b/Tests/ZIPFoundationTests/ZIPFoundationErrorConditionTests.swift index 311c51d5..07952dff 100644 --- a/Tests/ZIPFoundationTests/ZIPFoundationErrorConditionTests.swift +++ b/Tests/ZIPFoundationTests/ZIPFoundationErrorConditionTests.swift @@ -27,6 +27,9 @@ extension ZIPFoundationTests { XCTAssert(result == true) XCTAssertSwiftError(try Archive(url: noEndOfCentralDirectoryArchiveURL, accessMode: .read), throws: Archive.ArchiveError.missingEndOfCentralDirectoryRecord) + let invalidEndOfCentralDirectoryArchiveURL = self.resourceURL(for: #function, pathExtension: "zip") + XCTAssertSwiftError(try Archive(url: invalidEndOfCentralDirectoryArchiveURL, accessMode: .read), + throws: Archive.ArchiveError.missingEndOfCentralDirectoryRecord) self.runWithUnprivilegedGroup { var unreadableArchiveURL = ZIPFoundationTests.tempZipDirectoryURL unreadableArchiveURL.appendPathComponent(processInfo.globallyUniqueString) From 4adaa2cb6d655bfd0ecad8401a2190860536ab3c Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Mon, 10 Jun 2024 09:55:16 +0200 Subject: [PATCH 27/33] Swiftlint --- Sources/ZIPFoundation/Archive.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/ZIPFoundation/Archive.swift b/Sources/ZIPFoundation/Archive.swift index 3f4f438a..23b47664 100644 --- a/Sources/ZIPFoundation/Archive.swift +++ b/Sources/ZIPFoundation/Archive.swift @@ -298,7 +298,7 @@ public final class Archive: Sequence { private static func scanForZIP64EndOfCentralDirectory(in file: FILEPointer, eocdOffset: UInt64) -> ZIP64EndOfCentralDirectory? { guard UInt64(ZIP64EndOfCentralDirectoryLocator.size) < eocdOffset else { return nil } - + let locatorOffset = eocdOffset - UInt64(ZIP64EndOfCentralDirectoryLocator.size) guard UInt64(ZIP64EndOfCentralDirectoryRecord.size) < locatorOffset else { return nil } From c30176cbcd878f1e6f94f4f1ec35a4e673b88bc6 Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Mon, 10 Jun 2024 10:02:08 +0200 Subject: [PATCH 28/33] Change worfklow name --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index eefab1c9..c5b4703d 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -1,4 +1,4 @@ -name: SwiftLint +name: CI on: pull_request: From 111ace5b7d5ccb8d28e9a68ccbc742f8c2b1a9ec Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Mon, 10 Jun 2024 10:07:09 +0200 Subject: [PATCH 29/33] Exclude synthesised source bundle accessor from coverage calculation --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index c5b4703d..6323a484 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -46,5 +46,5 @@ jobs: - uses: actions/checkout@v2 - run: swift test -c release -Xswiftc -enable-testing --enable-code-coverage - run: find .build/release/codecov/ -name "*.profraw" -print0 | xargs -0 xcrun llvm-profdata merge -sparse -o .build/release/codecov/default.profdata - - run: xcrun llvm-cov export -summary-only -ignore-filename-regex 'ZIPFoundationTests|.*Deprecated.*$' .build/release/ZIPFoundationPackageTests.xctest/Contents/MacOS/ZIPFoundationPackageTests -instr-profile .build/release/codecov/default.profdata > .build/coverage.json + - run: xcrun llvm-cov export -summary-only -ignore-filename-regex 'ZIPFoundationTests|resource_bundle_accessor.swift|.*Deprecated.*$' .build/release/ZIPFoundationPackageTests.xctest/Contents/MacOS/ZIPFoundationPackageTests -instr-profile .build/release/codecov/default.profdata > .build/coverage.json - run: (cat .build/coverage.json|jq '.data[0]["totals"]["lines"]["percent"]' | grep -Eq "100") && { exit 0; } || { echo 'Please make sure that the test suite covers all framework code paths.'; exit 1; } From f0015e2feb58867b8da9d6a427c0dc6ad09d99ab Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Mon, 10 Jun 2024 10:55:30 +0200 Subject: [PATCH 30/33] Update testing matrix --- .github/workflows/CI.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 6323a484..3bc8fd57 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -20,8 +20,8 @@ jobs: Xcode: strategy: matrix: - xcode_version: ['13.3.1', '13.4', '14.0.1', '14.1', '14.2'] - runs-on: macos-12 + xcode_version: ['14.3.1', '15.0.1', '15.1', '15.2', '15.3', '15.4'] + runs-on: macos-latest env: DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode_version }}.app steps: From 1dc572206d2d25ebc092ef15cb6c5c2c19656896 Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Mon, 10 Jun 2024 11:13:19 +0200 Subject: [PATCH 31/33] Codestyle --- Sources/ZIPFoundation/FileManager+ZIP.swift | 12 ++++++------ Tests/ZIPFoundationTests/ZIPFoundationTests.swift | 1 + 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Sources/ZIPFoundation/FileManager+ZIP.swift b/Sources/ZIPFoundation/FileManager+ZIP.swift index b0bbf9bd..af2bbbd3 100644 --- a/Sources/ZIPFoundation/FileManager+ZIP.swift +++ b/Sources/ZIPFoundation/FileManager+ZIP.swift @@ -297,14 +297,14 @@ extension FileManager { guard fileManager.itemExists(at: url) else { throw CocoaError(.fileReadNoSuchFile, userInfo: [NSFilePathErrorKey: url.path]) } + let entryFileSystemRepresentation = fileManager.fileSystemRepresentation(withPath: url.path) - var fileStat = stat() - lstat(entryFileSystemRepresentation, &fileStat) - guard fileStat.st_size >= 0 else { - throw CocoaError(.fileReadTooLarge, userInfo: [NSFilePathErrorKey: url.path]) - } + var stat = stat() + lstat(entryFileSystemRepresentation, &stat) + guard stat.st_size >= 0 else { throw CocoaError(.fileReadTooLarge, userInfo: [NSFilePathErrorKey: url.path]) } + // `st_size` is a signed int value - return Int64(fileStat.st_size) + return Int64(stat.st_size) } class func typeForItem(at url: URL) throws -> Entry.EntryType { diff --git a/Tests/ZIPFoundationTests/ZIPFoundationTests.swift b/Tests/ZIPFoundationTests/ZIPFoundationTests.swift index a422a14b..ab5f35f2 100644 --- a/Tests/ZIPFoundationTests/ZIPFoundationTests.swift +++ b/Tests/ZIPFoundationTests/ZIPFoundationTests.swift @@ -369,6 +369,7 @@ extension Data { #if os(macOS) extension NSUserScriptTask { + static func makeVolumeCreationTask(at tempDir: URL, volumeName: String) throws -> NSUserScriptTask { let scriptURL = tempDir.appendingPathComponent("createVol.sh", isDirectory: false) let dmgURL = tempDir.appendingPathComponent(volumeName).appendingPathExtension("dmg") From 72af049c5d28f17829589057f8a37816bc76ea4f Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Mon, 10 Jun 2024 11:37:07 +0200 Subject: [PATCH 32/33] Rename var --- Sources/ZIPFoundation/FileManager+ZIP.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Sources/ZIPFoundation/FileManager+ZIP.swift b/Sources/ZIPFoundation/FileManager+ZIP.swift index af2bbbd3..227df282 100644 --- a/Sources/ZIPFoundation/FileManager+ZIP.swift +++ b/Sources/ZIPFoundation/FileManager+ZIP.swift @@ -299,12 +299,12 @@ extension FileManager { } let entryFileSystemRepresentation = fileManager.fileSystemRepresentation(withPath: url.path) - var stat = stat() - lstat(entryFileSystemRepresentation, &stat) - guard stat.st_size >= 0 else { throw CocoaError(.fileReadTooLarge, userInfo: [NSFilePathErrorKey: url.path]) } + var stats = stat() + lstat(entryFileSystemRepresentation, &stats) + guard stats.st_size >= 0 else { throw CocoaError(.fileReadTooLarge, userInfo: [NSFilePathErrorKey: url.path]) } // `st_size` is a signed int value - return Int64(stat.st_size) + return Int64(stats.st_size) } class func typeForItem(at url: URL) throws -> Entry.EntryType { From dcea71ae6bffbf7de49e7d53b28ce74e12bfd43b Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Mon, 10 Jun 2024 12:30:18 +0200 Subject: [PATCH 33/33] Update Linux test matrix --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 3bc8fd57..03eb3390 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -32,7 +32,7 @@ jobs: Linux: strategy: matrix: - tag: ['5.1', '5.2', '5.3', '5.4', '5.5', '5.6', '5.7', '5.8'] + tag: ['5.1', '5.2', '5.3', '5.4', '5.5', '5.6', '5.7', '5.8', '5.9', '5.10'] runs-on: ubuntu-latest container: image: swift:${{ matrix.tag }}