initial commit [141.14.129.234,mike]

This commit is contained in:
2026-07-26 06:38:01 +02:00
commit 5562055695
20 changed files with 2898 additions and 0 deletions
+108
View File
@@ -0,0 +1,108 @@
package main
// overview.go — the `overview` command (also reachable as `status -a`): a
// one-line-per-project summary of every git project under BASE, showing the
// dirty state and how far each branch is ahead/behind its upstream.
import (
"fmt"
"os"
"strings"
)
// projStatus is the collected state of one project for the overview.
type projStatus struct {
name string
branch string
dirty bool
ahead, behind int
hasUpstream bool
}
// overviewAll prints a status summary for all git projects under BASE.
func overviewAll() {
entries, err := os.ReadDir(BASE)
if err != nil {
errorln("cannot read " + BASE + ": " + err.Error())
return
}
var rows []projStatus
width := 0
for _, e := range entries {
if !e.IsDir() || strings.HasPrefix(e.Name(), ".") {
continue
}
dir := BASE + "/" + e.Name()
if !isDir(dir + "/.git") {
continue
}
rows = append(rows, projectStatus(e.Name(), dir))
if len(e.Name()) > width {
width = len(e.Name())
}
}
if len(rows) == 0 {
fmt.Println(col(cGray, "no git projects under "+BASE))
return
}
dirtyN, syncN := 0, 0
for _, r := range rows {
fmt.Println(formatProjStatus(r, width))
if r.dirty {
dirtyN++
}
if r.hasUpstream && r.ahead == 0 && r.behind == 0 && !r.dirty {
syncN++
}
}
fmt.Printf("%s\n", col(cGray, fmt.Sprintf("%d projects · %d dirty · %d in sync", len(rows), dirtyN, syncN)))
}
// projectStatus gathers the git state of a single project directory.
func projectStatus(name, dir string) projStatus {
s := projStatus{name: name, branch: "-"}
if out, err := gitCapture(dir, "rev-parse", "--abbrev-ref", "HEAD"); err == nil {
s.branch = strings.TrimSpace(out)
}
if out, err := gitCapture(dir, "status", "--porcelain"); err == nil && strings.TrimSpace(out) != "" {
s.dirty = true
}
// left/right counts against the upstream: "<behind>\t<ahead>"
if out, err := gitCapture(dir, "rev-list", "--left-right", "--count", "@{upstream}...HEAD"); err == nil {
if _, e := fmt.Sscanf(strings.TrimSpace(out), "%d\t%d", &s.behind, &s.ahead); e == nil {
s.hasUpstream = true
}
}
return s
}
// formatProjStatus renders one aligned overview row.
func formatProjStatus(s projStatus, width int) string {
var marks []string
if s.dirty {
marks = append(marks, col(cYellow, "*"))
}
if s.ahead > 0 {
marks = append(marks, col(cGreen, fmt.Sprintf("↑%d", s.ahead)))
}
if s.behind > 0 {
marks = append(marks, col(cRed, fmt.Sprintf("↓%d", s.behind)))
}
state := strings.Join(marks, " ")
if state == "" {
if s.hasUpstream {
state = col(cGreen, "✓")
} else {
state = col(cGray, "✓ (no upstream)")
}
}
line := " " + col(cGreen, padRight(s.name, width+2)) + state
if s.branch != "master" && s.branch != "main" && s.branch != "-" {
line += col(cGray, " ("+s.branch+")")
}
return line
}