c9ff44298c
4 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
| c9ff44298c |
feat: phase 3 — presentation layer (table, JSON, compact)
Replace the interim renderers with a dedicated presenter package that
formats scan results in three ways.
Presenter (internal/presenter):
- Formatter interface with Present()/For() dispatch on format name:
table, json, compact
- TableFormatter: aligned tabwriter table with REPOSITORY / BRANCH /
STATUS / AHEAD-BEHIND / CHANGES / STASH columns, per-repo change
summaries like "2M 1U", error details inline, and a colored summary
line ("N repos | N clean | N need attention | N errors")
- JSONFormatter: indented document with scanned_at, parent_dir, repos,
and an aggregate summary for scripting; statuses render as string
labels ("modified") instead of raw integers
- CompactFormatter: one line per repo with color-coded status symbols
(✓ ✗ ↑ ↓ ⇄ ◉ ▢ !) plus branch, ahead/behind, and change counts
- Color handling: auto/always/never modes, TTY detection, and the
NO_COLOR convention (explicit --color=always still wins); paths have
$HOME collapsed to "~" in table and compact views
Domain model (pkg/status):
- JSON tags on RepoInfo/ScanResult/Summary for clean field names
- RepoStatus now marshals to its string label and unmarshals from both
string labels and numeric values, so JSON output round-trips
Configuration (internal/config):
- New --color flag (auto/always/never) validated in Load and included in
the config dump; keyed as "color" in viper
CLI (cmd/gitflow):
- scan now routes through presenter.Present with the resolved color mode;
the interim renderers are removed
Testing:
- Table content (columns, change summaries, error text, summary line) and
absence of escape codes with ColorNever
- ColorAlways emits ANSI codes even under NO_COLOR; auto stays clean on
non-terminal writers
- JSON decodes back into the domain types (string statuses round-trip)
- Compact symbols and counts; unknown formats rejected
- RepoStatus JSON round trip covers every status
Verified: go build, go vet, go test -race, gofmt clean; manual smoke of
table / compact / forced-color / JSON output against a scratch directory.
|
|||
| d52e0715f2 |
feat: phase 2 — CLI commands and configuration resolution
Add the Cobra-based command surface and the flag/env/config-file resolution layer that all commands share. Configuration (internal/config): - Load() resolves settings with the documented precedence flags > env > config file > defaults, via viper: GITFLOW_-prefixed env vars with dot-to-underscore mapping, plus ~/.gitflow.yaml (or $GITFLOW_CONFIG) - RegisterFlags/NewFlagSet own the flag definitions so every command and the tests share a single source of truth - Config/Validate/Dump cover dir, interval, format (table/json/compact), exclude globs, max depth, worker count, and the AI block (enabled, provider, model, api_key_env, base_url); ConfigFile records the loaded path; Dump renders the effective config as human-readable YAML with the interval as a duration string App orchestration (internal/app): - New() validates the configuration at the boundary (fail fast) - ScanOnce() runs discovery then a concurrent status scan, warning on stderr and continuing when discovery is only partially successful (e.g. permission-denied subtrees), and bundles everything into a ScanResult CLI (cmd/gitflow): - root command with scan / config / version subcommands - scan: resolves config, prompts for the parent directory when stdin is a TTY and --dir was not given (per the README), runs a single pass, and renders the result — interim plain/JSON output until phase 3 lands the presenter package - config: prints the effective configuration - version: prints the build version (ldflags-injectable) - signalContext() wires SIGINT/SIGTERM into a cancellable context for graceful shutdown Testing: - config: defaults, flag overrides, env overrides, flag-beats-env precedence, config file loading (including duration and slice values), GITFLOW_CONFIG path override, validation failures, and Dump output - app: config validation on New, end-to-end ScanOnce over a real temp repo, and missing-directory errors Verified: go build, go vet, go test -race, gofmt clean; manual smoke of `gitflow version`, `gitflow config`, and `gitflow scan -d <dir>` against a scratch directory with a dirty repo. |
|||
| 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. |
|||
| 9761adf3f9 |
feat: phase 0 — project scaffolding and build tooling
Bootstrap the gitflow module so subsequent phases build on a verified, linted foundation. - go.mod: initialize module gitea.oblak.solutions/dimitar/gitFlow at go 1.24 - cmd/gitflow/main.go: minimal entrypoint that prints the version string; this is a placeholder that Phase 2 (CLI & config) replaces with Cobra - internal/version: version metadata injectable at build time via ldflags, with a Makefile target wiring VERSION through - Makefile: build / test / fmt / vet / lint / install / clean targets with ldflags version injection - .golangci.yml: enable errcheck, govet, staticcheck, gosimple, ineffassign, unused, misspell, gofmt, goimports - .github/workflows/ci.yml: GitHub Actions CI running build + vet + tests (with -race) across Go 1.24/1.26, plus a golangci-lint job - .gitignore: build artifacts, test outputs, editor cruft, and local config overrides (never committed) Verified locally: go build, go vet, gofmt clean, binary prints version. |