Expand description
The plan: what is in the working tree, how it divides into commits, and the fingerprint that says the plan is still about this tree.
§Why a plan is a value with a fingerprint on it
A plan is derived from a working tree at a moment. In a repository worked by one person at a time that is a detail; in this one it is the correctness question. Several workers share a checkout, more share a repository, and a plan computed at one HEAD and executed at another commits files somebody else staged, under a message about work that is no longer what changed.
PlanFingerprint is what makes that detectable rather than merely unlikely: the
repository, the worktree, HEAD, and the exact set of paths and states the plan was
derived from. A plan carries it, and anything that acts on a plan compares it with the
tree in front of it first. The comparison is cheap, it is not a lock, and it does not
prevent the race — it refuses to be the one that loses it silently.
§What grouping is and is not
Grouping is a recommendation with its reasoning attached, never an automatic split. The evidence is what the repository can see: which directories changed, which scope the history gives them, and which files are derived from which. Where that evidence supports one commit it says one; where it supports several it says several and says why; where it supports nothing it says so, which is the honest answer for a tree of unrelated edits that only a person can divide.
use majordomus_cli::commit::{ChangeStage, PlanFingerprint, WorkingTreeState};
use majordomus_cli::commit::plan::PathChange;
let change = |path: &str, stage| PathChange {
path: path.into(), stage, status: "M.".into(), partial: false,
};
let tree = WorkingTreeState {
head: Some("a1b2c3d4e5f60718293a4b5c6d7e8f9012345678".into()),
changes: vec![change("src/a.rs", ChangeStage::Staged)],
..WorkingTreeState::default()
};
// The same tree fingerprints the same way every time.
let made = PlanFingerprint::of("/repo/.git", "/repo", &tree);
assert!(made.differs_from(&PlanFingerprint::of("/repo/.git", "/repo", &tree)).is_none());
// Another worktree of the same repository is a different subject, and is named as one.
let elsewhere = PlanFingerprint::of("/repo/.git", "/repo-wt/feature/x", &tree);
let why = made.differs_from(&elsewhere).expect("another worktree");
assert!(why.contains("another worktree"), "{why}");Structs§
- Commit
Group - One commit a plan proposes. One commit a plan proposes: its message, its paths, and why those paths are one commit.
- Commit
Plan - A plan over a working tree.
- Path
Change - One path, and where it stands.
- Plan
Fingerprint - What a plan was derived from.
- Working
Tree State - What git says about the working tree right now.
Enums§
- Change
Stage - Where one path stands between the index and the working tree.
Functions§
- derived_
among - Which of
pathsthis repository declares derived, asked of git rather than parsed. - group
- Group a set of paths into the commits the evidence supports.
- kind_of
- The kind a set of paths suggests, from what the paths are.
- messages_
in - Every commit in
range, as a subject and a body, newest first. - working_
tree - Read
git status --porcelain=v2 --branch, which reports the branch, the upstream and the divergence in the same call as the paths.