Skip to content

Commit 0d24882

Browse files
committed
fix(git-extract): use repo-root-relative paths for git commands
1 parent 6d7afab commit 0d24882

1 file changed

Lines changed: 33 additions & 12 deletions

File tree

packages/cli/src/utils/git-extract.ts

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,18 @@ import * as path from 'node:path';
1010
import { extract } from '@openpkg-ts/sdk';
1111
import { normalize } from '@openpkg-ts/spec';
1212

13+
/**
14+
* Get the git repository root directory.
15+
*/
16+
function getGitRoot(cwd: string): string {
17+
return execSync('git rev-parse --show-toplevel', {
18+
encoding: 'utf-8',
19+
cwd,
20+
timeout: 5000,
21+
stdio: ['pipe', 'pipe', 'pipe'],
22+
}).trim();
23+
}
24+
1325
/**
1426
* List all source files tracked at a given ref under a directory prefix.
1527
*/
@@ -74,9 +86,11 @@ export async function extractSpecFromRef(
7486
entry: string,
7587
cwd = process.cwd(),
7688
): Promise<ReturnType<typeof normalize>> {
77-
// Resolve entry relative to cwd
78-
const relEntry = path.relative(cwd, path.resolve(cwd, entry));
79-
const entryDir = path.dirname(relEntry);
89+
// Git paths are always repo-root-relative, so resolve against git root
90+
const gitRoot = getGitRoot(cwd);
91+
const absEntry = path.resolve(cwd, entry);
92+
const repoRelEntry = path.relative(gitRoot, absEntry);
93+
const entryDir = path.dirname(repoRelEntry);
8094

8195
// Determine source prefix to checkout (the directory containing the entry)
8296
// For monorepos: packages/sdk/src/index.ts → packages/sdk/
@@ -86,17 +100,15 @@ export async function extractSpecFromRef(
86100
const tmpDir = mkdtempSync(path.join(os.tmpdir(), 'drift-git-'));
87101

88102
try {
89-
// List and checkout all source files at ref
103+
// List and checkout all source files at ref (paths must be repo-root-relative)
90104
const prefixes = srcPrefix === '.' ? [''] : [srcPrefix];
91-
// Always include root config files
92105
const rootFiles = ['tsconfig.json', 'tsconfig.base.json', 'package.json'];
93106

94107
for (const prefix of prefixes) {
95-
const files = listFilesAtRef(ref, prefix || '.', cwd);
108+
const files = listFilesAtRef(ref, prefix || '.', gitRoot);
96109
for (const file of files) {
97-
// Only checkout .ts/.tsx/.json files
98110
if (!file.match(/\.(ts|tsx|json|js|mjs|cjs)$/)) continue;
99-
const content = getFileAtRef(ref, file, cwd);
111+
const content = getFileAtRef(ref, file, gitRoot);
100112
if (content === null) continue;
101113
const destPath = path.join(tmpDir, file);
102114
mkdirSync(path.dirname(destPath), { recursive: true });
@@ -108,7 +120,7 @@ export async function extractSpecFromRef(
108120
for (const rootFile of rootFiles) {
109121
const dest = path.join(tmpDir, rootFile);
110122
if (!existsSync(dest)) {
111-
const content = getFileAtRef(ref, rootFile, cwd);
123+
const content = getFileAtRef(ref, rootFile, gitRoot);
112124
if (content) {
113125
writeFileSync(dest, content);
114126
}
@@ -122,9 +134,18 @@ export async function extractSpecFromRef(
122134
symlinkSync(nmSrc, nmDest, 'dir');
123135
}
124136

137+
// Also try root node_modules if cwd differs from git root
138+
if (cwd !== gitRoot) {
139+
const rootNm = path.join(gitRoot, 'node_modules');
140+
const rootNmDest = path.join(tmpDir, 'node_modules');
141+
if (existsSync(rootNm) && !existsSync(rootNmDest)) {
142+
symlinkSync(rootNm, rootNmDest, 'dir');
143+
}
144+
}
145+
125146
// If entry is inside a nested package, also symlink its node_modules
126147
if (srcPrefix !== '.') {
127-
const nestedNm = path.join(cwd, srcPrefix, 'node_modules');
148+
const nestedNm = path.join(gitRoot, srcPrefix, 'node_modules');
128149
const nestedDest = path.join(tmpDir, srcPrefix, 'node_modules');
129150
if (existsSync(nestedNm) && !existsSync(nestedDest)) {
130151
symlinkSync(nestedNm, nestedDest, 'dir');
@@ -139,9 +160,9 @@ export async function extractSpecFromRef(
139160
}
140161

141162
// Extract
142-
const entryFile = path.join(tmpDir, relEntry);
163+
const entryFile = path.join(tmpDir, repoRelEntry);
143164
if (!existsSync(entryFile)) {
144-
throw new Error(`Entry file not found at ref ${ref}: ${relEntry}`);
165+
throw new Error(`Entry file not found at ref ${ref}: ${repoRelEntry}`);
145166
}
146167

147168
const result = await extract({ entryFile });

0 commit comments

Comments
 (0)