|
1 | 1 | import { EventEmitter } from "node:events"; |
2 | 2 | import { mkdir, readFile, rm, writeFile, cp, stat, readdir, symlink, lstat } from "node:fs/promises"; |
3 | 3 | import { appendFileSync, existsSync } from "node:fs"; |
4 | | -import { dirname, join, resolve } from "node:path"; |
| 4 | +import { dirname, isAbsolute, join, resolve } from "node:path"; |
5 | 5 | import { execFile } from "node:child_process"; |
6 | 6 | import type { ChildProcess } from "node:child_process"; |
7 | 7 | import { |
@@ -77,6 +77,23 @@ async function execFileStdout(command: string, args: string[], cwd: string): Pro |
77 | 77 | }); |
78 | 78 | } |
79 | 79 |
|
| 80 | +async function ignoreWorkspaceEntry(workspacePath: string, entry: string): Promise<void> { |
| 81 | + try { |
| 82 | + const rawExcludePath = (await execFileStdout("git", ["rev-parse", "--git-path", "info/exclude"], workspacePath)).trim(); |
| 83 | + const excludePath = isAbsolute(rawExcludePath) ? rawExcludePath : join(workspacePath, rawExcludePath); |
| 84 | + await mkdir(dirname(excludePath), { recursive: true }); |
| 85 | + const current = existsSync(excludePath) ? await readFile(excludePath, "utf-8") : ""; |
| 86 | + const lines = current.split("\n").map((line) => line.trim()).filter(Boolean); |
| 87 | + if (lines.includes(entry) || lines.includes(`/${entry}`)) { |
| 88 | + return; |
| 89 | + } |
| 90 | + const next = current.endsWith("\n") || current.length === 0 ? `${current}/${entry}\n` : `${current}\n/${entry}\n`; |
| 91 | + await writeFile(excludePath, next); |
| 92 | + } catch { |
| 93 | + // Temp copies or non-git workspaces do not need git excludes. |
| 94 | + } |
| 95 | +} |
| 96 | + |
80 | 97 | async function copyRepoContents(sourceRepoPath: string, workspacePath: string): Promise<void> { |
81 | 98 | await mkdir(workspacePath, { recursive: true }); |
82 | 99 | for (const entry of await readdir(sourceRepoPath)) { |
@@ -126,6 +143,7 @@ async function linkSharedDependencies(sourceRepoPath: string, workspacePath: str |
126 | 143 |
|
127 | 144 | const relativeTarget = resolve(sourceNodeModules); |
128 | 145 | await symlink(relativeTarget, workspaceNodeModules, "dir"); |
| 146 | + await ignoreWorkspaceEntry(workspacePath, "node_modules"); |
129 | 147 | } |
130 | 148 |
|
131 | 149 | function safeWorkspaceName(workBranch: string): string { |
|
0 commit comments