Expand description
The scope vocabulary, derived from the repository rather than declared beside it.
§The table this replaces
The usual way to answer “what scope does this change belong to?” is a table: a list of path patterns and the scope each one maps to, written once, kept in a document a worker is told to read. It works on the day it is written. Then a directory is added, or renamed, or a subsystem is split in two, and the table says a scope that the history stopped using months ago — with nothing to notice, because a table has no way to be wrong.
The repository already knows the answer. Every commit in the history is a worked example
of which scope a set of paths belongs to, decided by whoever made the change and kept by
whoever reviewed it. derive reads those examples: the scopes the history uses, how
often, and which directories each one is written about. A scope is not configured. It is
observed, with the observation attached, so that the answer can be checked rather than
believed.
The consequence a person feels is that the vocabulary is never stale and never has to be maintained: a subsystem that gets its first commit today is in the vocabulary tomorrow, and one that nobody has touched for a year falls to the bottom of the list on its own.
§What it costs and where it is allowed to
Reading names out of the log is not free, and this is deliberately not on any hot path:
nothing about entering the repository, completing a word or answering --help reads it.
It is read when a commit is being planned or judged, which is a moment that already
involves a person waiting for git.
use majordomus_cli::commit::ScopeVocabulary;
// A vocabulary is normally learned with `derive`; stated directly it reads the same.
let mut v = ScopeVocabulary::default();
v.learn("commit", "apps/majordomus-cli/src/commit", 40);
v.learn("site", "site/content", 90);
let s = v.suggest(&["apps/majordomus-cli/src/commit/plan.rs".into()]).expect("an association");
assert_eq!(s.scope, "commit");
assert_eq!(s.commits, 40, "the association, not the vote weight");
assert!(!s.ambiguous);
// and a path nothing in the history scopes is answered with nothing, never with the
// repository's most popular scope
assert!(v.suggest(&["brand/new/thing.rs".into()]).is_none());Structs§
- Scope
Suggestion - Which scope a set of paths belongs to, and the evidence for it.
- Scope
Use - One scope the history uses, and how much.
- Scope
Vocabulary - The vocabulary as observed, with what was observed.
Constants§
- SAMPLE
- How many commits back the vocabulary is learned from.
Functions§
- derive
- Learn the vocabulary from the repository’s own history.