(params: {
sourcePath: string;
executablePath: string;
sourceText?: string;
timeoutMs?: number;
})
| 78 | } |
| 79 | |
| 80 | async function ensureSwiftExecutable(params: { |
| 81 | sourcePath: string; |
| 82 | executablePath: string; |
| 83 | sourceText?: string; |
| 84 | timeoutMs?: number; |
| 85 | }): Promise<void> { |
| 86 | if (isExecutableFile(params.executablePath)) { |
| 87 | return; |
| 88 | } |
| 89 | |
| 90 | const executableDir = path.dirname(params.executablePath); |
| 91 | fs.mkdirSync(executableDir, { recursive: true }); |
| 92 | const lockDir = `${params.executablePath}.lock`; |
| 93 | const releaseLock = await acquireSwiftCacheLock( |
| 94 | lockDir, |
| 95 | params.executablePath, |
| 96 | params.timeoutMs ?? 120_000, |
| 97 | ); |
| 98 | if (!releaseLock) { |
| 99 | return; |
| 100 | } |
| 101 | |
| 102 | const tempDir = fs.mkdtempSync( |
| 103 | path.join(executableDir, `.${path.basename(params.executablePath)}.${process.pid}.`), |
| 104 | ); |
| 105 | const tempExecutablePath = path.join(tempDir, path.basename(params.executablePath)); |
| 106 | try { |
| 107 | if (isExecutableFile(params.executablePath)) { |
| 108 | return; |
| 109 | } |
| 110 | if (params.sourceText !== undefined && !fs.existsSync(params.sourcePath)) { |
| 111 | fs.mkdirSync(path.dirname(params.sourcePath), { recursive: true }); |
| 112 | fs.writeFileSync(params.sourcePath, params.sourceText); |
| 113 | } |
| 114 | await runCmd('xcrun', ['swiftc', params.sourcePath, '-o', tempExecutablePath], { |
| 115 | timeoutMs: params.timeoutMs ?? 120_000, |
| 116 | env: buildSwiftToolEnv(), |
| 117 | }); |
| 118 | fs.renameSync(tempExecutablePath, params.executablePath); |
| 119 | } finally { |
| 120 | fs.rmSync(tempDir, { recursive: true, force: true }); |
| 121 | await releaseLock(); |
| 122 | } |
| 123 | } |
| 124 | |
| 125 | async function acquireSwiftCacheLock( |
| 126 | lockDir: string, |
no test coverage detected