| 877 | } |
| 878 | |
| 879 | function readWorktrees(projectRoot) { |
| 880 | if (!hasGitContext(projectRoot)) return []; |
| 881 | try { |
| 882 | const output = execFileSync('git', ['worktree', 'list', '--porcelain'], { |
| 883 | cwd: projectRoot, |
| 884 | encoding: 'utf8', |
| 885 | stdio: ['ignore', 'pipe', 'ignore'], |
| 886 | }); |
| 887 | const blocks = output.split(/\r?\n\r?\n/).map((block) => block.trim()).filter(Boolean); |
| 888 | return blocks.map((block) => { |
| 889 | const lines = block.split(/\r?\n/); |
| 890 | const first = lines[0] || ''; |
| 891 | return { |
| 892 | path: first.replace(/^worktree\s+/, ''), |
| 893 | branch: (lines.find((line) => line.startsWith('branch ')) || '').replace(/^branch refs\/heads\//, '').replace(/^branch\s+/, '') || 'detached', |
| 894 | bare: lines.includes('bare'), |
| 895 | }; |
| 896 | }); |
| 897 | } catch { |
| 898 | return []; |
| 899 | } |
| 900 | } |
| 901 | |
| 902 | function readGitStatus(projectRoot) { |
| 903 | if (!hasGitContext(projectRoot)) { |
| 904 | return { |