diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9ffdddd..aec8653 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,6 +26,6 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v3 - name: Run tests run: docker run -v "$PWD":/host -w /host swift:5.10.0-amazonlinux2 swift test diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index d2317e4..92abe4e 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -27,7 +27,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v3 with: # Fetch all history to ensure the version number (tag) is resolved to create the # version info during the build step. diff --git a/Sources/DocUploadBundle/DocUploadBundle.swift b/Sources/DocUploadBundle/DocUploadBundle.swift index f9b1f09..b962dbe 100644 --- a/Sources/DocUploadBundle/DocUploadBundle.swift +++ b/Sources/DocUploadBundle/DocUploadBundle.swift @@ -110,7 +110,14 @@ public struct DocUploadBundle { let metadataURL = URL(fileURLWithPath: "\(workDir)/metadata.json") try JSONEncoder().encode(metadata).write(to: metadataURL) - try Zipper.zip(paths: [metadataURL, URL(fileURLWithPath: sourcePath)], to: archiveURL, method: method) + switch method { + case .library, .zipTool(workingDirectory: .some(_)): + try Zipper.zip(paths: [metadataURL, URL(fileURLWithPath: sourcePath)], to: archiveURL, method: method) + + case .zipTool(.none): + // By default, run the zip tool in the working directory + try Zipper.zip(paths: [metadataURL, URL(fileURLWithPath: sourcePath)], to: archiveURL, method: .zipTool(workingDirectory: workDir)) + } return archiveURL.path } diff --git a/Sources/DocUploadBundle/Zipper.swift b/Sources/DocUploadBundle/Zipper.swift index 24de978..fac49a4 100644 --- a/Sources/DocUploadBundle/Zipper.swift +++ b/Sources/DocUploadBundle/Zipper.swift @@ -21,37 +21,20 @@ public enum Zipper { public static func zip(paths inputPaths: [URL], to outputPath: URL, method: Method = .library) throws { switch method { case .library: - do { - try Zip.zipFiles(paths: inputPaths, zipFilePath: outputPath, password: nil, progress: nil) - } catch let error as ZipError { - switch error { - case .fileNotFound: throw Error.fileNotFound - case .unzipFail: throw Error.unzipFail - case .zipFail: throw Error.zipFail - } - } - catch { - throw Error.generic(reason: "\(error)") - } + do { try Zip.zipFiles(paths: inputPaths, zipFilePath: outputPath, password: nil, progress: nil) } + catch ZipError.fileNotFound { throw Error.fileNotFound } + catch ZipError.unzipFail { throw Error.unzipFail } + catch ZipError.zipFail { throw Error.zipFail } + catch { throw Error.generic(reason: "\(error)") } - case .zipTool: + case let .zipTool(cwd): do { - try withTempDir { tempDir in - let tempURL = URL(fileURLWithPath: tempDir) - // Copy inputs to tempDir - for source in inputPaths { - let target = tempURL.appendingPathComponent(source.lastPathComponent) - try FileManager.default.copyItem(at: source, to: target) - } - - // Run zip - let process = Process() - process.executableURL = zip - process.arguments = ["-q", "-r", outputPath.path] + inputPaths.map(\.lastPathComponent) - process.currentDirectoryURL = tempURL - try process.run() - process.waitUntilExit() - } + let process = Process() + process.executableURL = zip + process.arguments = ["-q", "-r", outputPath.path] + inputPaths.map(\.lastPathComponent) + process.currentDirectoryURL = cwd.map(URL.init(fileURLWithPath:)) + try process.run() + process.waitUntilExit() } catch { throw Error.generic(reason: "\(error)") } @@ -59,25 +42,18 @@ public enum Zipper { } public static func unzip(from inputPath: URL, to outputPath: URL, fileOutputHandler: ((_ unzippedFile: URL) -> Void)? = nil) throws { - do { - try Zip.unzipFile(inputPath, destination: outputPath, overwrite: true, password: nil, fileOutputHandler: fileOutputHandler) - } catch let error as ZipError { - switch error { - case .fileNotFound: throw Error.fileNotFound - case .unzipFail: throw Error.unzipFail - case .zipFail: throw Error.zipFail - } - } - catch { - throw Error.generic(reason: "\(error)") - } + do { try Zip.unzipFile(inputPath, destination: outputPath, overwrite: true, password: nil, fileOutputHandler: fileOutputHandler) } + catch ZipError.fileNotFound { throw Error.fileNotFound } + catch ZipError.unzipFail { throw Error.unzipFail } + catch ZipError.zipFail { throw Error.zipFail } + catch { throw Error.generic(reason: "\(error)") } } static let zip = URL(fileURLWithPath: "/usr/bin/zip") public enum Method { case library - case zipTool + case zipTool(workingDirectory: String? = nil) } public enum Error: Swift.Error { diff --git a/Sources/DocUploadBundle/TempDir.swift b/Tests/DocUploadBundleTests/TempDir.swift similarity index 87% rename from Sources/DocUploadBundle/TempDir.swift rename to Tests/DocUploadBundleTests/TempDir.swift index 45990e9..734dd95 100644 --- a/Sources/DocUploadBundle/TempDir.swift +++ b/Tests/DocUploadBundleTests/TempDir.swift @@ -32,8 +32,3 @@ func withTempDir(body: (String) async throws -> T) async throws -> T { let tmp = try TempDir() return try await body(tmp.path) } - -func withTempDir(body: (String) throws -> T) throws -> T { - let tmp = try TempDir() - return try body(tmp.path) -} diff --git a/Tests/DocUploadBundleTests/ZipTests.swift b/Tests/DocUploadBundleTests/ZipTests.swift index b79ee51..c3866eb 100644 --- a/Tests/DocUploadBundleTests/ZipTests.swift +++ b/Tests/DocUploadBundleTests/ZipTests.swift @@ -21,7 +21,7 @@ final class ZipTests: XCTestCase { func test_unzip() async throws { // Test basic unzip behaviour we expect from the library we use - try withTempDir { tempDir in + try await withTempDir { tempDir in let tempURL = URL(fileURLWithPath: tempDir) let zipFile = fixtureUrl(for: "out.zip") let outDir = tempURL.appendingPathComponent("out") @@ -41,7 +41,7 @@ final class ZipTests: XCTestCase { func test_zip_roundtrip() async throws { // Test basic zip roundtrip - try withTempDir { tempDir in + try await withTempDir { tempDir in // temp let tempURL = URL(fileURLWithPath: tempDir) @@ -92,7 +92,7 @@ final class ZipTests: XCTestCase { try XCTSkipIf(!FileManager.default.fileExists(atPath: Zipper.zip.path)) // Test basic zip roundtrip with the shellTool method - try withTempDir { tempDir in + try await withTempDir { tempDir in // temp let tempURL = URL(fileURLWithPath: tempDir) @@ -117,7 +117,7 @@ final class ZipTests: XCTestCase { try "c".write(to: fileC, atomically: true, encoding: .utf8) let zipFile = tempURL.appendingPathComponent("out.zip") - try Zipper.zip(paths: [fileA, subdir], to: zipFile, method: .zipTool) + try Zipper.zip(paths: [fileA, subdir], to: zipFile, method: .zipTool(workingDirectory: tempDir)) XCTAssert(FileManager.default.fileExists(atPath: zipFile.path)) do { // unzip what we zipped and check results @@ -139,41 +139,4 @@ final class ZipTests: XCTestCase { } } - func test_zip_roundtrip_shellTool_relative_paths() async throws { - try XCTSkipIf(!FileManager.default.fileExists(atPath: Zipper.zip.path)) - - // Test basic zip roundtrip with the shellTool method and relative paths - try withTempDir { tempDir in - // DocBundle components - // metadataURL: tempDir/metadata.json - // sourceURL: tempDir/.docs/owner/repo/ref - // should be zipped as - // - metadata.json - // - ref - // at the top level as relative paths. - let tempURL = URL(fileURLWithPath: tempDir) - let metadataURL = tempURL.appendingPathComponent("metadata.json") - try "metadata".write(to: metadataURL, atomically: true, encoding: .utf8) - let sourceURL = tempURL.appendingPathComponent("docs/owner/repo/ref") - try FileManager.default.createDirectory(at: sourceURL, withIntermediateDirectories: true) - let indexHTML = sourceURL.appendingPathComponent("index.html") - try "index".write(to: indexHTML, atomically: true, encoding: .utf8) - - // MUT - let zipFile = tempURL.appendingPathComponent("out.zip") - try Zipper.zip(paths: [metadataURL, sourceURL], to: zipFile, method: .zipTool) - - do { // validate - let unzipDir = tempURL.appendingPathComponent("unzip") - try Zipper.unzip(from: zipFile, to: unzipDir) - let metadataURL = unzipDir.appendingPathComponent("metadata.json") - let indexHTML = unzipDir.appendingPathComponent("ref/index.html") - XCTAssert(FileManager.default.fileExists(atPath: metadataURL.path)) - XCTAssert(FileManager.default.fileExists(atPath: indexHTML.path)) - XCTAssertEqual(try String(contentsOf: metadataURL), "metadata") - XCTAssertEqual(try String(contentsOf: indexHTML), "index") - } - } - } - }