From b2726e618ff7538d9e00193ad3e2ec45931765c1 Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Sun, 17 May 2026 10:08:55 +0200 Subject: [PATCH 1/5] Refine comment --- Sources/ZIPFoundation/FileManager+ZIP.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/ZIPFoundation/FileManager+ZIP.swift b/Sources/ZIPFoundation/FileManager+ZIP.swift index 816cc28d..4ee34fa3 100644 --- a/Sources/ZIPFoundation/FileManager+ZIP.swift +++ b/Sources/ZIPFoundation/FileManager+ZIP.swift @@ -205,7 +205,7 @@ extension FileManager { try self.setSymlinkModificationDate(modificationDate, ofItemAtURL: url) #else - // Bionic and Windows lack a fully equivalent symlink-targeted + // Some platforms lack a fully equivalent symlink-targeted // `lutimes`; leave this codepath as a no-op there. return #endif From d2e97a02d550188a3252e64cc1541d651893afd2 Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Sun, 17 May 2026 10:20:18 +0200 Subject: [PATCH 2/5] Move symlink date test case into a new Darwin+Linux test group --- Sources/ZIPFoundation/FileManager+ZIP.swift | 2 ++ .../ZIPFoundationFileAttributeTests.swift | 4 +++- Tests/ZIPFoundationTests/ZIPFoundationTests.swift | 14 +++++++++++--- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/Sources/ZIPFoundation/FileManager+ZIP.swift b/Sources/ZIPFoundation/FileManager+ZIP.swift index 4ee34fa3..90e6eed1 100644 --- a/Sources/ZIPFoundation/FileManager+ZIP.swift +++ b/Sources/ZIPFoundation/FileManager+ZIP.swift @@ -223,7 +223,9 @@ extension FileManager { throw POSIXError(errno, path: url.path) } } +#endif +#if os(macOS) || os(iOS) || os(tvOS) || os(visionOS) || os(watchOS) || os(Linux) func setSymlinkModificationDate(_ modificationDate: Date, ofItemAtURL url: URL) throws { let fileSystemRepresentation = self.fileSystemRepresentation(withPath: url.path) var fileStat = stat() diff --git a/Tests/ZIPFoundationTests/ZIPFoundationFileAttributeTests.swift b/Tests/ZIPFoundationTests/ZIPFoundationFileAttributeTests.swift index b16df683..bc59f7f0 100644 --- a/Tests/ZIPFoundationTests/ZIPFoundationFileAttributeTests.swift +++ b/Tests/ZIPFoundationTests/ZIPFoundationFileAttributeTests.swift @@ -68,7 +68,7 @@ extension ZIPFoundationTests { } func testSymlinkModificationDateTransferErrorConditions() { -#if os(macOS) || os(iOS) || os(tvOS) || os(visionOS) || os(watchOS) +#if os(macOS) || os(iOS) || os(tvOS) || os(visionOS) || os(watchOS) || os(Linux) let fileManager = FileManager() var assetURL = self.resourceURL(for: #function, pathExtension: "png") let tempPath = NSTemporaryDirectory() @@ -76,6 +76,7 @@ extension ZIPFoundationTests { nonExistantURL.appendPathComponent("invalid.path") XCTAssertPOSIXError(try fileManager.setSymlinkModificationDate(Date(), ofItemAtURL: nonExistantURL), throwsErrorWithCode: .ENOENT) +#if os(macOS) || os(iOS) || os(tvOS) || os(visionOS) || os(watchOS) var resourceValues = URLResourceValues() resourceValues.isUserImmutable = true try? assetURL.setResourceValues(resourceValues) @@ -85,6 +86,7 @@ extension ZIPFoundationTests { } XCTAssertPOSIXError(try fileManager.setSymlinkModificationDate(Date(), ofItemAtURL: assetURL), throwsErrorWithCode: .EPERM) +#endif #endif } diff --git a/Tests/ZIPFoundationTests/ZIPFoundationTests.swift b/Tests/ZIPFoundationTests/ZIPFoundationTests.swift index d454fdb4..305f3484 100644 --- a/Tests/ZIPFoundationTests/ZIPFoundationTests.swift +++ b/Tests/ZIPFoundationTests/ZIPFoundationTests.swift @@ -255,7 +255,7 @@ extension ZIPFoundationTests { ("testFileModificationDate", testFileModificationDate), ("testFileModificationDateHelperMethods", testFileModificationDateHelperMethods), ("testInvalidSymlinkCompressionMethodErrorConditions", testInvalidSymlinkCompressionMethodErrorConditions) - ] + zip64Tests + darwinOnlyTests + swift5OnlyTests + ] + zip64Tests + darwinOnlyTests + posixOnlyTests + swift5OnlyTests } static var zip64Tests: [(String, (ZIPFoundationTests) -> () throws -> Void)] { @@ -318,8 +318,16 @@ extension ZIPFoundationTests { // Fails for Swift < 4.2 on Linux. We can re-enable that when we drop Swift 4.x support ("testZipItemErrorConditions", testZipItemErrorConditions), // Applying permissions on symlinks is only relevant on Darwin platforms - ("testSymlinkPermissionsTransferErrorConditions", testSymlinkPermissionsTransferErrorConditions), - // Applying file modification dates is currently unsupported in corelibs Foundation + ("testSymlinkPermissionsTransferErrorConditions", testSymlinkPermissionsTransferErrorConditions) + ] + #else + return [] + #endif + } + + static var posixOnlyTests: [(String, (ZIPFoundationTests) -> () throws -> Void)] { + #if os(macOS) || os(iOS) || os(tvOS) || os(visionOS) || os(watchOS) || os(Linux) + return [ ("testSymlinkModificationDateTransferErrorConditions", testSymlinkModificationDateTransferErrorConditions) ] #else From 02cef17d5e57027e556055fb8d087b5f463fb209 Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Sun, 17 May 2026 10:28:14 +0200 Subject: [PATCH 3/5] Move missing attribute check into symlink modification date test case --- .../ZIPFoundationFileAttributeTests.swift | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Tests/ZIPFoundationTests/ZIPFoundationFileAttributeTests.swift b/Tests/ZIPFoundationTests/ZIPFoundationFileAttributeTests.swift index bc59f7f0..143431f9 100644 --- a/Tests/ZIPFoundationTests/ZIPFoundationFileAttributeTests.swift +++ b/Tests/ZIPFoundationTests/ZIPFoundationFileAttributeTests.swift @@ -59,12 +59,6 @@ extension ZIPFoundationTests { XCTAssertPOSIXError(try fileManager.setAttributes([.posixPermissions: permissions], ofItemAtURL: nonExistantURL, traverseLink: false), throwsErrorWithCode: .ENOENT) - XCTAssertSwiftError(try fileManager.setAttributes([.posixPermissions: permissions], - ofItemAtURL: assetURL, traverseLink: false), - throws: Entry.EntryError.missingModificationDateAttributeError) - XCTAssertPOSIXError( try fileManager.setAttributes([.posixPermissions: permissions, .modificationDate: Date()], - ofItemAtURL: nonExistantURL, traverseLink: false), - throwsErrorWithCode: .ENOENT) } func testSymlinkModificationDateTransferErrorConditions() { @@ -74,8 +68,15 @@ extension ZIPFoundationTests { let tempPath = NSTemporaryDirectory() var nonExistantURL = URL(fileURLWithPath: tempPath) nonExistantURL.appendPathComponent("invalid.path") + let requiredPermissions = NSNumber(value: Int16(0o753)) + XCTAssertSwiftError(try fileManager.setAttributes([.posixPermissions: requiredPermissions], + ofItemAtURL: assetURL, traverseLink: false), + throws: Entry.EntryError.missingModificationDateAttributeError) XCTAssertPOSIXError(try fileManager.setSymlinkModificationDate(Date(), ofItemAtURL: nonExistantURL), throwsErrorWithCode: .ENOENT) + XCTAssertPOSIXError( try fileManager.setAttributes([.posixPermissions: requiredPermissions, .modificationDate: Date()], + ofItemAtURL: nonExistantURL, traverseLink: false), + throwsErrorWithCode: .ENOENT) #if os(macOS) || os(iOS) || os(tvOS) || os(visionOS) || os(watchOS) var resourceValues = URLResourceValues() resourceValues.isUserImmutable = true From 57ac6e2c4e6c1ef55dea546217777b3ad05cb658 Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Sun, 17 May 2026 10:31:47 +0200 Subject: [PATCH 4/5] Cleanup --- .../ZIPFoundationFileAttributeTests.swift | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Tests/ZIPFoundationTests/ZIPFoundationFileAttributeTests.swift b/Tests/ZIPFoundationTests/ZIPFoundationFileAttributeTests.swift index 143431f9..32c67b14 100644 --- a/Tests/ZIPFoundationTests/ZIPFoundationFileAttributeTests.swift +++ b/Tests/ZIPFoundationTests/ZIPFoundationFileAttributeTests.swift @@ -54,10 +54,10 @@ extension ZIPFoundationTests { throws: Entry.EntryError.missingPermissionsAttributeError) let permissions = NSNumber(value: Int16(0o753)) let tempPath = NSTemporaryDirectory() - var nonExistantURL = URL(fileURLWithPath: tempPath) - nonExistantURL.appendPathComponent("invalid.path") + var nonExistentURL = URL(fileURLWithPath: tempPath) + nonExistentURL.appendPathComponent("invalid.path") XCTAssertPOSIXError(try fileManager.setAttributes([.posixPermissions: permissions], - ofItemAtURL: nonExistantURL, traverseLink: false), + ofItemAtURL: nonExistentURL, traverseLink: false), throwsErrorWithCode: .ENOENT) } @@ -66,16 +66,16 @@ extension ZIPFoundationTests { let fileManager = FileManager() var assetURL = self.resourceURL(for: #function, pathExtension: "png") let tempPath = NSTemporaryDirectory() - var nonExistantURL = URL(fileURLWithPath: tempPath) - nonExistantURL.appendPathComponent("invalid.path") - let requiredPermissions = NSNumber(value: Int16(0o753)) - XCTAssertSwiftError(try fileManager.setAttributes([.posixPermissions: requiredPermissions], + var nonExistentURL = URL(fileURLWithPath: tempPath) + nonExistentURL.appendPathComponent("invalid.path") + let providedPermissions = NSNumber(value: Int16(0o753)) + XCTAssertSwiftError(try fileManager.setAttributes([.posixPermissions: providedPermissions], ofItemAtURL: assetURL, traverseLink: false), throws: Entry.EntryError.missingModificationDateAttributeError) - XCTAssertPOSIXError(try fileManager.setSymlinkModificationDate(Date(), ofItemAtURL: nonExistantURL), + XCTAssertPOSIXError(try fileManager.setSymlinkModificationDate(Date(), ofItemAtURL: nonExistentURL), throwsErrorWithCode: .ENOENT) - XCTAssertPOSIXError( try fileManager.setAttributes([.posixPermissions: requiredPermissions, .modificationDate: Date()], - ofItemAtURL: nonExistantURL, traverseLink: false), + XCTAssertPOSIXError(try fileManager.setAttributes([.posixPermissions: providedPermissions, .modificationDate: Date()], + ofItemAtURL: nonExistentURL, traverseLink: false), throwsErrorWithCode: .ENOENT) #if os(macOS) || os(iOS) || os(tvOS) || os(visionOS) || os(watchOS) var resourceValues = URLResourceValues() @@ -107,8 +107,8 @@ extension ZIPFoundationTests { XCTAssertCocoaError(try FileManager.fileModificationDateTimeForItem(at: nonFileURL), throwsErrorWithCode: CocoaError.fileReadNoSuchFile) - let nonExistantURL = URL(fileURLWithPath: "/nonexistant") - XCTAssertCocoaError(try FileManager.fileModificationDateTimeForItem(at: nonExistantURL), + let nonExistentURL = URL(fileURLWithPath: "/nonexistant") + XCTAssertCocoaError(try FileManager.fileModificationDateTimeForItem(at: nonExistentURL), throwsErrorWithCode: CocoaError.fileReadNoSuchFile) let msDOSDate = Date(timeIntervalSince1970: TimeInterval(Int.min)).fileModificationDate XCTAssert(msDOSDate == 0) @@ -121,14 +121,14 @@ extension ZIPFoundationTests { } func testFileSizeHelperMethods() { - let nonExistantURL = URL(fileURLWithPath: "/nonexistant") - XCTAssertCocoaError(try FileManager.fileSizeForItem(at: nonExistantURL), + let nonExistentURL = URL(fileURLWithPath: "/nonexistant") + XCTAssertCocoaError(try FileManager.fileSizeForItem(at: nonExistentURL), throwsErrorWithCode: CocoaError.fileReadNoSuchFile) } func testFileTypeHelperMethods() { - let nonExistantURL = URL(fileURLWithPath: "/nonexistant") - XCTAssertCocoaError(try FileManager.typeForItem(at: nonExistantURL), + let nonExistentURL = URL(fileURLWithPath: "/nonexistant") + XCTAssertCocoaError(try FileManager.typeForItem(at: nonExistentURL), throwsErrorWithCode: CocoaError.fileReadNoSuchFile) guard let nonFileURL = URL(string: "https://www.peakstep.com") else { XCTFail("Failed to create test URL."); return From 66e42dde85cd1784b5cc6c2ec4912a63f3d4bb01 Mon Sep 17 00:00:00 2001 From: Thomas Zoechling Date: Sun, 17 May 2026 10:37:28 +0200 Subject: [PATCH 5/5] Swiftlint --- .../ZIPFoundationFileAttributeTests.swift | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Tests/ZIPFoundationTests/ZIPFoundationFileAttributeTests.swift b/Tests/ZIPFoundationTests/ZIPFoundationFileAttributeTests.swift index 32c67b14..69638204 100644 --- a/Tests/ZIPFoundationTests/ZIPFoundationFileAttributeTests.swift +++ b/Tests/ZIPFoundationTests/ZIPFoundationFileAttributeTests.swift @@ -74,9 +74,17 @@ extension ZIPFoundationTests { throws: Entry.EntryError.missingModificationDateAttributeError) XCTAssertPOSIXError(try fileManager.setSymlinkModificationDate(Date(), ofItemAtURL: nonExistentURL), throwsErrorWithCode: .ENOENT) - XCTAssertPOSIXError(try fileManager.setAttributes([.posixPermissions: providedPermissions, .modificationDate: Date()], - ofItemAtURL: nonExistentURL, traverseLink: false), - throwsErrorWithCode: .ENOENT) + XCTAssertPOSIXError( + try fileManager.setAttributes( + [ + .posixPermissions: providedPermissions, + .modificationDate: Date() + ], + ofItemAtURL: nonExistentURL, + traverseLink: false + ), + throwsErrorWithCode: .ENOENT + ) #if os(macOS) || os(iOS) || os(tvOS) || os(visionOS) || os(watchOS) var resourceValues = URLResourceValues() resourceValues.isUserImmutable = true