Go to file
dimitar ae23019277 feat: phase 1 — repository discovery and status scanning
Implement the core data layer that everything else builds on: walking a
parent directory for Git repositories and snapshotting each repository's
state via porcelain commands.

Domain model (pkg/status):
- RepoStatus enum with zero value = StatusUnknown (invalid/unset), covering
  clean / modified / ahead / behind / diverged / detached / bare / error
- RepoInfo snapshot: path, name, remote URL, branch, detached flag, staged /
  modified / untracked file lists, ahead/behind counts, stash count, error
- ScanResult with computed Summary counters and NeedsAttention filter

Git wrapper (internal/git):
- Executor built with functional options (binary, timeout, env), defaults to
  "git" with a 10s per-command timeout so a hung repository can never stall
  a scan; context cancellation honoured via exec.CommandContext
- Status() validates with rev-parse --is-bare-repository (bare repos are
  reported as StatusBare and skipped), then parses `git status
  --porcelain=v2 --branch -z`
- Parsing uses the NUL-separated v2 format so paths with spaces, quotes,
  and tabs survive verbatim (no C-quoting to decode); rename records (type
  2) and ahead/behind lines (# branch.ab) are handled, unknown tokens are
  ignored for forward compatibility
- Best-effort remote URL (git config --get-regexp) and stash count

Discovery (internal/scanner/discover.go):
- WalkDir-based traversal that never descends into .git internals
- Detects working trees via .git directory or .git pointer file (linked
  worktrees, submodule checkouts) and bare repos via a *.git directory
  carrying its own HEAD/objects/refs
- WithExclude glob patterns (matched against full path and base name) and
  WithMaxDepth depth limiting as functional options
- Walk errors (e.g. permission denied) are aggregated and returned
  alongside partial results via errors.Join; cancellation is propagated

Scanner (internal/scanner/scanner.go):
- Concurrent status scanning with a bounded worker pool (errgroup +
  SetLimit, default 8 workers)
- Per-repo failures become StatusError entries instead of aborting the
  pass; a cancelled context aborts the whole scan

Testing:
- Table-driven parser tests with canned NUL-separated porcelain output
- Integration tests against a real git binary (clean / modified / staged /
  stashed / detached / bare / non-repo)
- Discovery tests over a fixture tree with nested repos, a bare repo, a
  linked worktree, and an exclusion target
- Scanner tests for mixed success/failure, bounded concurrency, and
  cancellation; everything runs under -race

Note: LastFetch from the original plan was dropped — the only reliable
source is a reflog of the remote-tracking ref, which does not exist on
fresh clones, so it would always be misleading. The model remains
extensible if a fetch-history feature is wanted later.
2026-08-02 08:35:41 +02:00
.github/workflows feat: phase 0 — project scaffolding and build tooling 2026-08-02 08:30:23 +02:00
cmd/gitflow feat: phase 0 — project scaffolding and build tooling 2026-08-02 08:30:23 +02:00
internal feat: phase 1 — repository discovery and status scanning 2026-08-02 08:35:41 +02:00
pkg/status feat: phase 1 — repository discovery and status scanning 2026-08-02 08:35:41 +02:00
.gitignore feat: phase 0 — project scaffolding and build tooling 2026-08-02 08:30:23 +02:00
.golangci.yml feat: phase 0 — project scaffolding and build tooling 2026-08-02 08:30:23 +02:00
go.mod feat: phase 1 — repository discovery and status scanning 2026-08-02 08:35:41 +02:00
go.sum feat: phase 1 — repository discovery and status scanning 2026-08-02 08:35:41 +02:00
implementation.md docs 2026-08-02 08:25:09 +02:00
Makefile feat: phase 0 — project scaffolding and build tooling 2026-08-02 08:30:23 +02:00
readme.md docs 2026-08-02 08:25:09 +02:00

git flow is CLI app writen go.

App will explore [] all git repos leaving on our machine. it will ask for parent directory. will scan status of our repos and present it to the user. app will scan repos in set interval [and present findings, integrated ai agent will suggest next steps/actions]