Skip to main content

Module scopes

Module scopes 

Source
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§

ScopeSuggestion
Which scope a set of paths belongs to, and the evidence for it.
ScopeUse
One scope the history uses, and how much.
ScopeVocabulary
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.