diff --git a/SourcerySwift/Sources/SwiftTemplate.swift b/SourcerySwift/Sources/SwiftTemplate.swift index 2720b6289..a46ecc27c 100644 --- a/SourcerySwift/Sources/SwiftTemplate.swift +++ b/SourcerySwift/Sources/SwiftTemplate.swift @@ -202,16 +202,13 @@ open class SwiftTemplate { Log.verbose("Reusing built SwiftTemplate binary for SwiftTemplate with cache key: \(hash)...") } else { Log.verbose("Building new SwiftTemplate binary for SwiftTemplate...") - try? cachePath.delete() // clear old cache - try cachePath.mkdir() do { - try build().move(binaryPath) + let path = try build() + try? cachePath.delete() // clear old cache + try? cachePath.mkdir() + try? path.move(binaryPath) } catch let error as NSError { - if error.domain == "NSCocoaErrorDomain", error.code == 516 { - Log.warning("This error can be ignored: Attempt to copy `SwiftTemplate` binary to \(binaryPath) failed. Probably multiple Sourcery processes trying to cache into the same directory.") - } else { - throw error - } + throw error } } } else { diff --git a/SourceryTests/Generating/SwiftTemplateSpecs.swift b/SourceryTests/Generating/SwiftTemplateSpecs.swift index aaf317ccb..3bb26a126 100644 --- a/SourceryTests/Generating/SwiftTemplateSpecs.swift +++ b/SourceryTests/Generating/SwiftTemplateSpecs.swift @@ -199,14 +199,8 @@ class SwiftTemplateTests: QuickSpec { } context("with existing cache") { - // beforeEach { - - // } - context("and missing build dir") { -#if canImport(ObjectiveC) expect { try Sourcery(cacheDisabled: false).processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), usingTemplates: Paths(include: [templatePath]), output: output, baseIndentation: 0) }.toNot(throwError()) -#endif expect((try? (outputDir + Sourcery().generatedPath(for: templatePath)).read(.utf8))).to(equal(expectedResult)) guard let buildDir = NSURL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("SwiftTemplate").map({ Path($0.path) }) else { fail("Could not create buildDir path") @@ -228,6 +222,37 @@ class SwiftTemplateTests: QuickSpec { let result = (try? (outputDir + Sourcery().generatedPath(for: templatePath)).read(.utf8)) expect(result).to(equal(expectedResult)) } + + it("generates the code asynchronously without throwing error") { + let iterations = 2 + let paths = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true) as [String] + let path = paths[0] + let caches = Path(path) + Path("Sourcery") + try? caches.delete() + @Sendable func generateCode() async throws -> Int { + expect { try Sourcery(cacheDisabled: false).processFiles(.sources(Paths(include: [Stubs.sourceDirectory])), usingTemplates: Paths(include: [templatePath]), output: output, baseIndentation: 0) }.toNot(throwError()) + let result = (try? (outputDir + Sourcery().generatedPath(for: templatePath)).read(.utf8)) + expect(result).to(equal(expectedResult)) + return 1 + } + let semaphore = DispatchSemaphore(value: 0) + Task { + _ = try await withThrowingTaskGroup(of: Int.self) { taskGroup in + for _ in 0 ..< iterations { + taskGroup.addTask { + try await generateCode() + } + } + var counter = 0 + for try await _ in taskGroup { + counter += 1 + } + return counter + } + semaphore.signal() + } + semaphore.wait() + } } }