* Resolve git repository root and relative path from any directory within a repo
(directory: string)
| 380 | * Resolve git repository root and relative path from any directory within a repo |
| 381 | */ |
| 382 | async function resolveGitInfo(directory: string): Promise<{ repoRoot: string; relativePath: string }> { |
| 383 | const startTime = Date.now() |
| 384 | |
| 385 | // Validate directory exists |
| 386 | if (!fs.existsSync(directory)) { |
| 387 | throw new Error(`Directory does not exist: ${directory}`) |
| 388 | } |
| 389 | |
| 390 | // Get repository root |
| 391 | const rootResult = await execGit(["rev-parse", "--show-toplevel"], directory) |
| 392 | if (!rootResult.success) { |
| 393 | throw new Error(`Not a git repository: ${directory}`) |
| 394 | } |
| 395 | const repoRoot = rootResult.stdout.trim() |
| 396 | |
| 397 | // Get relative path from root (empty string if at root) |
| 398 | const prefixResult = await execGit(["rev-parse", "--show-prefix"], directory) |
| 399 | let relativePath = "" |
| 400 | if (prefixResult.success && prefixResult.stdout.trim()) { |
| 401 | // Remove trailing slash if present |
| 402 | relativePath = prefixResult.stdout.trim().replace(/\/$/, "") |
| 403 | } |
| 404 | |
| 405 | logger.info(`[Git:resolveGitInfo] Resolved: ${directory} -> root=${repoRoot}, relative=${relativePath || "(root)"}`, JSON.stringify({ |
| 406 | duration: Date.now() - startTime, |
| 407 | })) |
| 408 | |
| 409 | return { repoRoot, relativePath } |
| 410 | } |
| 411 | |
| 412 | /** |
| 413 | * Execute git command with error handling |
no test coverage detected