feat(git): /git overview page and diff viewer
Add git module with repo status overview (/git) and per-repo detail page (/git/[repo]) featuring a color-coded diff viewer (+ green, - red). Reads repo paths from REPO_PATHS env var, calls ops-agent git_status and git_diff commands. Status badges: clean (green), dirty (orange), behind-origin (blue). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
4821d29670
commit
9e08a7c31f
5 changed files with 513 additions and 0 deletions
46
lib/parse-git.ts
Normal file
46
lib/parse-git.ts
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
export interface RepoStatus {
|
||||
branch: string
|
||||
/** Number of commits ahead of upstream (undefined if no upstream) */
|
||||
ahead?: number
|
||||
/** Number of commits behind upstream (undefined if no upstream) */
|
||||
behind?: number
|
||||
/** True when there are uncommitted changes */
|
||||
dirty: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses `git status --short --branch` output into a RepoStatus.
|
||||
*
|
||||
* First line format: ## main...origin/main [ahead N, behind M]
|
||||
* Remaining lines: XY path (presence means dirty)
|
||||
*/
|
||||
export function parseGitStatus(output: string): RepoStatus {
|
||||
const lines = output.trim().split('\n').filter(Boolean)
|
||||
|
||||
let branch = 'unknown'
|
||||
let ahead: number | undefined
|
||||
let behind: number | undefined
|
||||
let dirty = false
|
||||
|
||||
for (const line of lines) {
|
||||
if (line.startsWith('## ')) {
|
||||
const rest = line.slice(3)
|
||||
// "No commits yet on main" or "HEAD (no branch)"
|
||||
const trackMatch = rest.match(/^([^.]+)\.\.\.(\S+)/)
|
||||
if (trackMatch) {
|
||||
branch = trackMatch[1]
|
||||
} else {
|
||||
branch = rest.split(' ')[0]
|
||||
}
|
||||
const aheadMatch = rest.match(/ahead (\d+)/)
|
||||
const behindMatch = rest.match(/behind (\d+)/)
|
||||
if (aheadMatch) ahead = parseInt(aheadMatch[1], 10)
|
||||
if (behindMatch) behind = parseInt(behindMatch[1], 10)
|
||||
} else {
|
||||
// Any non-header line means there are changes
|
||||
dirty = true
|
||||
}
|
||||
}
|
||||
|
||||
return { branch, ahead, behind, dirty }
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue