GitBaby/AGENTS.md
zhenyi 680411c4fb chore: initialize gitbaby repository
gitbaby is an asynchronous Rust library wrapping git operations, built on
gix + tokio + async-trait.

Module layout:
- archive, blame, blob, branch, cleanup, commit, compare, config,
  conflict, diff, merge, refs, remote, setup, share, submodule, tags,
  tree (feature modules)
- command: command scheduler (cmd/env/pipe/context/error)
- repo: RepositoryFacade trait (consumers implement, exposing a
  gix::Repository)

Features:
- async API on tokio 1.53
- order-preserving Env (Vec<(String, String)>)
- hand-written BabyError / CmdError, not using thiserror derive
- integration tests covering cmd_run / context / env / pipe (env keys
  prefixed for isolation)

CI: none, standard cargo build / test / clippy / fmt only
2026-08-14 18:10:04 +08:00

3.2 KiB

AGENTS.md — gitbaby

What this is

  • Single-crate Rust library (no binary, no workspace). Edition 2024.
  • Public entrypoint: GitBaby::new(facade: Arc<dyn RepositoryFacade>, pipe: Pipe) in src/lib.rs.
  • Consumers must implement RepositoryFacade (src/repo.rs) — three async fns returning a path/paths and a gix::Repository. There is no default impl.

Build / test / verify

  • Standard cargo only. No CI, no pre-commit, no scripts, no rust-toolchain pin.
  • Edition 2024 requires a recent stable toolchain (rustc ≥ 1.85). Local env verified at rustc 1.97.1.
  • Useful commands (no order dependency beyond what's standard):
    • cargo build / cargo check / cargo build --release
    • cargo test (sync + #[tokio::test] integration tests in tests/)
    • cargo test --test <file> to run a single integration test file
    • cargo test <name> to filter by test name substring
    • cargo clippy --all-targets -- -D warnings if strict
    • cargo fmt --check / cargo fmt (default rustfmt; no rustfmt.toml)

Architecture notes

  • Error pattern is hand-written. BabyError (src/error.rs, ~50 variants) and CmdError (src/command/error.rs) implement Display + std::error::Error by hand. thiserror is in Cargo.toml but not used via #[derive(thiserror::Error)]. Do not "modernize" by adding the derive — keep the hand-written impls consistent.
  • Env in src/command/env.rs is order-preserving (Vec<(String, String)>), not a HashMap. with appends, set replaces in place. This matters for env-var ordering in spawned processes.
  • Cmd::Display = prog + config_args + args (config_args are prepended to args at runtime).
  • Pipe is Clone; cancel_pipe() sets cancelled=true and sends start_kill() to every running child but does not remove them from cmds.

Module layout convention

  • Most feature modules follow src/<feature>/{mod.rs, types.rs, helper.rs, usecase.rs}; mod.rs re-exports the public types from types.rs.
  • src/share/ is the outlier: it uses {cmd.rs, env.rs, error.rs, path.rs} instead. Don't "normalize" it.
  • src/command/ uses {cmd.rs, context.rs, env.rs, error.rs, pipe.rs} and has its own error.rs separate from src/error.rs.

Test quirks (tests/)

  • tests/cmd_run.rs defines a local unwrap_or_recover_or_panic!-style macro for asserting command output — reuse it, don't reinvent.
  • tests/env.rs mutates process env. It guards tests with static ENV_LOCK: Mutex<()> and uses keys prefixed GITBABY_TEST_ENV_<suffix> for isolation. std::env::set_var / remove_var are wrapped in local unsafe fns; follow that pattern when adding env-mutating tests.
  • tests/pipe.rs async cancel tests call tokio::time::sleep(Duration::from_millis(200)) after cancel_pipe() to let Child::try_wait observe exit — keep that delay when adding new cancel tests.

Gotchas

  • No README. No docs beyond the code. Treat Cargo.toml + source as the only source of truth.
  • gix = "0.86", tokio = 1.53 (full features), time = 0.3 — all recent; do not bump them speculatively.
  • Public API surfaces async (async_trait); sync callers must use a runtime (tests use #[tokio::test]).