|
| 1 | +# gitui — working notes for Claude |
| 2 | + |
| 3 | +gitui is a Rust TUI git client. Cargo **workspace**: root crate `gitui` (the `src/` TUI binary) + |
| 4 | +members `asyncgit` (git logic over `git2`/`gix`), `filetreelist`, `git2-hooks`, `git2-testing`, |
| 5 | +`scopetime`. MSRV **1.88** (`Cargo.toml` `rust-version`, `.clippy.toml` `msrv`, CI matrix — keep |
| 6 | +all three in sync if ever bumped). |
| 7 | + |
| 8 | +## Feedback loop (run these — the reviewer here does not read Rust, so tooling IS the review) |
| 9 | + |
| 10 | +- **Fast inner loop while editing:** `cargo check -p asyncgit` (backend) / `cargo check` (whole |
| 11 | + workspace). Never iterate with `--release` — LTO + `opt-level="z"` makes it very slow. |
| 12 | +- **Format before every check:** `cargo fmt`. Formatting is unusual (`rustfmt.toml`: |
| 13 | + `max_width = 70`, `hard_tabs = true`) — hand-written code almost never matches, and |
| 14 | + `cargo fmt -- --check` is a CI gate. |
| 15 | +- **Full gate before declaring done / committing:** `make check` |
| 16 | + = `fmt` (`cargo fmt -- --check`) + `clippy` (`cargo clippy --workspace --all-features`) + |
| 17 | + `test` (`cargo nextest run --workspace`) + `sort` (`tombi format --check`) + `deny` |
| 18 | + (`cargo deny check`). CI calls the same `make` targets, so green locally ≈ green CI. |
| 19 | +- **Subset fallback** if a tool is missing: `cargo fmt -- --check` + |
| 20 | + `cargo clippy --workspace --all-features` + `cargo test --workspace` (plain `cargo test` works; |
| 21 | + it just also runs doctests that nextest skips). |
| 22 | +- **Run a single crate's tests:** `cargo test -p asyncgit <name_filter>`. |
| 23 | + |
| 24 | +Required tooling: `cargo-nextest`, `cargo-deny`, `tombi` (installed via mise), plus `python`, |
| 25 | +`gpgsm`/`gpg`, `openssl`, `perl`, a C compiler (vendored OpenSSL + bundled libgit2 build from |
| 26 | +source on first compile — the first build is slow, later ones are cached). |
| 27 | + |
| 28 | +## Hard rules clippy enforces (these fail the build, not just warn) |
| 29 | + |
| 30 | +Crate roots carry `#![deny(clippy::all, perf, nursery, pedantic, cargo)]` plus bans below. |
| 31 | +- **No `unwrap` / `expect` / `panic!` in production code** — use `?`, `ok_or(...)`, |
| 32 | + `unwrap_or_default()`, `map_or(...)`. (`unwrap`/`expect` are fine in `#[cfg(test)]` code.) |
| 33 | +- `asyncgit` has `#![forbid(missing_docs)]` — **every `pub` item needs a `///` doc comment**. |
| 34 | +- `#![forbid(unsafe_code)]` in the binary crate. |
| 35 | + |
| 36 | +## Other gotchas |
| 37 | + |
| 38 | +- **UI output is snapshot-tested with `insta`** (`src/snapshots/*.snap`). If you change rendered |
| 39 | + output, tests fail with a diff — review and accept via `cargo insta review` / `cargo insta |
| 40 | + accept`, then commit the updated `.snap` files. (Install once: `cargo install cargo-insta`.) |
| 41 | +- **CHANGELOG.md** must gain an entry under `## Unreleased` (`Added`/`Changed`/`Fixes`) or the CI |
| 42 | + `log-test` job fails. Format: Keep-a-Changelog, with issue/PR links. |
| 43 | +- Only the `stable` and `1.88` CI rows gate (nightly is `continue-on-error`). `cargo +nightly |
| 44 | + udeps` runs in CI but not in `make check`, so **don't add unused dependencies**. |
| 45 | +- Production code never shells out to the `git` binary; use `git2`/`gix`. The only |
| 46 | + `Command::new("git")` calls live in test helpers (`debug_cmd_print` in `asyncgit/src/sync/mod.rs`). |
| 47 | + |
| 48 | +## Where things live (patterns to copy) |
| 49 | + |
| 50 | +- Sync git ops: `asyncgit/src/sync/<feature>.rs`, re-exported from `asyncgit/src/sync/mod.rs`. Each |
| 51 | + op: `pub fn f(repo_path: &RepoPath, ...) -> Result<T> { scope_time!("f"); let repo = |
| 52 | + repo(repo_path)?; ... }`. Test helpers (`repo_init`, `debug_cmd_print`) in `sync/mod.rs::tests`. |
| 53 | +- Popups (Branches/Submodules/etc.): `src/popups/<name>.rs`, registered in `src/popups/mod.rs` and |
| 54 | + the `setup_popups!` macro in `src/app.rs`; opened via an `InternalEvent` in `src/queue.rs`. |
| 55 | +- Components implement `Component` + `DrawableComponent` (`src/components/mod.rs`). Non-commit list |
| 56 | + views use `VerticalScroll` + `ui::scrolllist::draw_list` (see `src/popups/submodules.rs`). |
| 57 | +- Keybindings: `src/keys/key_list.rs` (`KeysList` struct + `Default`). Command/help strings: |
| 58 | + `src/strings.rs`. |
0 commit comments