Skip to content

cli: etchy log — per-commit layer changes over a git range - #481

Open
Cimos wants to merge 1 commit into
mainfrom
cimos-etchy-log-git-range
Open

Cimos wants to merge 1 commit into
mainfrom
cimos-etchy-log-git-range

Conversation

@Cimos

@Cimos Cimos commented Nov 6, 2026

Copy link
Copy Markdown
Owner

Fixes #424. Part of #418.

What

etchy log <RANGE> [SUBDIR] [--format summary|md|json] [--max-commits N] walks git rev-list --first-parent <RANGE> -- <SUBDIR> and diffs each commit against its first parent, printing per commit which layers changed with added/removed mm² and region counts.

Design calls (user unavailable — documented here)

  • Same path as two-ref mode: load_board_git (git blob reader → shared BoardBuilder loader, One board loader for CLI and viewer #464) → compare_detailed; the warning assembly was extracted into report_with_load_warnings and the non-UTF-8 [SUBDIR] check (cli: non-UTF-8 filenames collapse to an empty label and classify as Other #299) into git_subdir, both shared with run. No checkout. etchy-core untouched apart from making report::md_code_span public (used to keep commit subjects inert in Markdown, report: warnings embed raw filenames unescaped in the Markdown posted as a PR comment #298).
  • Merges: diffed against the first parent (shows everything the merge brought into the first-parent line). Parents are read with git show -s --format=%P (real parents, not pathspec-simplified ones).
  • Pack missing on one side: reported as pack: added/removed (diff vs an empty board → every layer added-layer/removed-layer), never skipped.
  • Unparseable commit: exit 2, error names the commit (commit <sha12>: …).
  • Exit codes: 0 no commit changed a layer · 1 any did · 2 error. No gate flags in log (kept localised; layer change = report.any_changes()), so drill-count-only changes follow whatever Count a drill-table hole count change as a diff (#456) #476 decides for the two-ref mode later.
  • Cap: --max-commits default 200; rev-list asks for N+1 and more than N is an error, never truncation.
  • Order: newest first like git log; internally walked oldest-first so a parent's board is reused from a one-entry cache keyed by the ls-tree listing (blob ids).
  • Dispatch: log is intercepted before the two-revision parser (which takes bare positional paths). A directory literally named log must be written ./log; a stderr note says so when ./log exists. Top-level --help mentions the subcommand.
  • A <RANGE> starting with - is refused (never reaches git as an option).

Tests

crates/etchy-cli/tests/log_cli.rs builds a temp repo from the demo pack: pack added (root), notes-only (unchanged), README outside the pack (not listed), rev B (changed), top silk removed, pack removed; plus cap, empty range, bad range, option-like range, and an unparseable commit. fmt, clippy -D warnings (with and without pdf), and cargo test -p etchy-cli pass.

Docs

README, site/docs.html, REQUIREMENTS CLI-14, CHANGELOG [Unreleased].

Walks first-parent commits touching the fab pack and diffs each against its
first parent via the shared git reader, board loader and compare path.
Summary/Markdown/JSON output; pack added/removed reported; unparseable commits
fail loud naming the commit; --max-commits caps the walk loudly.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 6, 2026 12:08

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The review found an issue that should be addressed before approval.

2 open issues
What changed in this PR

Adds etchy log to inspect per-commit PCB layer changes over a Git range, reusing the existing board loader and diff engine without a checkout.

Changes:

  • Adds first-parent history traversal with summary, Markdown, and JSON output.
  • Introduces a commit cap, named commit errors, and pack addition/removal reporting.
  • Adds CLI integration tests and documents the command.
File Description
site/​docs.html Documents history usage, output, and exit codes.
README.md Adds a quick-start history example.
docs/​REQUIREMENTS.md Records the CLI-14 history contract.
crates/​etchy-core/​src/​report.rs Exposes the Markdown code-span helper.
crates/​etchy-cli/​tests/​log_cli.rs Tests history output, limits, and error handling.
crates/​etchy-cli/​src/​main.rs Dispatches log and extracts shared helpers.
crates/​etchy-cli/​src/​log.rs Implements history traversal, comparison, and formatting.
CHANGELOG.md Announces the new history command.

Review effort: Balanced

Comment on lines +201 to +205
let pack = match (&old, &new) {
(None, Some(_)) => PackChange::Added,
(Some(_), None) => PackChange::Removed,
_ => PackChange::Present,
};
let old = old.unwrap_or_else(|| empty.clone());
let new = new.unwrap_or(empty);

let diff = compare_detailed(&old.0, &new.0).context("comparing with the first parent")?;

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

etchy log: per-commit layer changes over a git range

2 participants