(repoPath: string)
| 33 | } |
| 34 | |
| 35 | async function getRepoStatus(repoPath: string): Promise<RepoStatus> { |
| 36 | const name = repoPath.split('/').pop() || repoPath; |
| 37 | |
| 38 | try { |
| 39 | // Get branch |
| 40 | const { stdout: branch } = await execAsync(`cd "${repoPath}" && git rev-parse --abbrev-ref HEAD 2>/dev/null`).catch(() => ({ stdout: 'unknown' })); |
| 41 | |
| 42 | // Get ahead/behind |
| 43 | let ahead = 0, behind = 0; |
| 44 | try { |
| 45 | const { stdout: abStr } = await execAsync(`cd "${repoPath}" && git rev-list --left-right --count HEAD...@{upstream} 2>/dev/null`).catch(() => ({ stdout: '0\t0' })); |
| 46 | const parts = abStr.trim().split('\t'); |
| 47 | ahead = parseInt(parts[0]) || 0; |
| 48 | behind = parseInt(parts[1]) || 0; |
| 49 | } catch {} |
| 50 | |
| 51 | // Get status |
| 52 | const { stdout: statusOut } = await execAsync(`cd "${repoPath}" && git status --porcelain 2>/dev/null`).catch(() => ({ stdout: '' })); |
| 53 | const lines = statusOut.trim().split('\n').filter(Boolean); |
| 54 | |
| 55 | const staged: string[] = []; |
| 56 | const unstaged: string[] = []; |
| 57 | const untracked: string[] = []; |
| 58 | |
| 59 | for (const line of lines) { |
| 60 | const xy = line.slice(0, 2); |
| 61 | const file = line.slice(3); |
| 62 | const x = xy[0]; // staged |
| 63 | const y = xy[1]; // unstaged |
| 64 | |
| 65 | if (x !== ' ' && x !== '?') staged.push(file); |
| 66 | if (y !== ' ' && y !== '?') unstaged.push(file); |
| 67 | if (xy === '??') untracked.push(file); |
| 68 | } |
| 69 | |
| 70 | // Last commit |
| 71 | let lastCommit = null; |
| 72 | try { |
| 73 | const { stdout: commitOut } = await execAsync(`cd "${repoPath}" && git log -1 --format="%H|%s|%an|%ar" 2>/dev/null`); |
| 74 | const parts = commitOut.trim().split('|'); |
| 75 | if (parts.length >= 4) { |
| 76 | lastCommit = { hash: parts[0].slice(0, 8), message: parts[1], author: parts[2], date: parts[3] }; |
| 77 | } |
| 78 | } catch {} |
| 79 | |
| 80 | // Remote URL |
| 81 | let remoteUrl = ''; |
| 82 | try { |
| 83 | const { stdout: remote } = await execAsync(`cd "${repoPath}" && git remote get-url origin 2>/dev/null`); |
| 84 | remoteUrl = remote.trim(); |
| 85 | } catch {} |
| 86 | |
| 87 | return { |
| 88 | name, |
| 89 | path: repoPath, |
| 90 | branch: branch.trim(), |
| 91 | ahead, |
| 92 | behind, |
nothing calls this directly
no outgoing calls
no test coverage detected