1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
//! `mmz` is a memoized command runner.
//!
//! Prefix any command with `mmz`. A `.mmz/config.yaml` manifest declares named input
//! scopes and command rules that reference them. When the invoked command
//! matches a rule and that rule's inputs are byte-for-byte unchanged since the
//! command last succeeded, `mmz` skips execution and exits 0; otherwise it runs
//! the command, streams its output, and records the new state on success. A
//! rule may also declare `outputs` — literal artifact paths whose absence voids
//! the record, however the inputs hash (see [`outputs`]) — and draw an input
//! from a named command's stdout rather than a file (see [`probe`]).
//!
//! The cache identity is the matched rule, so the operator controls
//! granularity through how specifically rules are written. State lives in a
//! gitignored cache directory (`.mmz/cache` by default) and is throwaway.
//!
//! # Use as a library
//!
//! The binary is a thin wrapper over this crate; the same entry points are
//! public. [`run`] memoizes one invocation against the nearest manifest,
//! returning the exit code to propagate:
//!
//! ```no_run
//! use std::path::Path;
//!
//! let argv = vec!["cargo".to_owned(), "test".to_owned()];
//! let exit_code: u8 = mmz::run(&argv, Path::new("."))?;
//! # let _ = exit_code;
//! # Ok::<(), mmz::Error>(())
//! ```
//!
//! [`status::report_json`] renders the freshness report, [`freshness::evaluate`]
//! gates a rule's freshness without running it, [`prune::prune`] sweeps orphaned
//! records, and [`Manifest`] loads and validates a `.mmz/config.yaml` for callers
//! that want the parsed model directly.
//!
//! Modules: the manifest ([`manifest`]), fragment import resolution and merge
//! ([`compose`]), `imports:` path resolution ([`import_paths`]), the source
//! of every scope, probe and command a merge produces ([`provenance`]),
//! pattern resolution ([`resolve`]), content hashing ([`hashing`]),
//! command-driven inputs ([`probe`]), in-process AST matching ([`ast`]),
//! declared artifact outputs
//! ([`outputs`]), rule matching ([`matcher`]), glob-fanned parametric rules
//! ([`parametric`]), the cache ([`cache`]), cache-hit notices ([`notice`]), the
//! process clock ([`clock`]), record expiry ([`ttl`]), and the orchestration
//! engine ([`engine`]). The
//! `mmz --…` actions live in [`init`], [`schema`], [`status`], [`freshness`],
//! [`prune`], [`import_records`], and [`dump`].
//!
//! # Reproducible output
//!
//! Anything mmz prints or stamps with a time reads one clock, resolved once per
//! invocation and threaded down. Set `MMZ_NOW` to a Unix epoch in seconds and a
//! record's `ran_at` and `mmz --status`'s ages become facts a build can capture;
//! leave it unset and mmz reads the system clock. A rule's `ttl` is aged against
//! the same clock, so the pin also decides which records have expired. See
//! [`clock`].
/// The in-process AST matcher a probe's `ast:` key selects with, and the
/// failure type [`probe::ProbeFailure::Ast`] carries. Public because a missing
/// grammar is answered by a build flag, and a library caller matching on
/// that case needs the variant rather than a rendered string.
/// Which grammars this build carries, and how `lang:` and a file extension
/// reach one. Internal: the set is a build-time fact mmz reports through
/// errors and `--dump-config`, never a type a caller holds.
/// How one matched node becomes the bytes an `ast:` probe hashes. Internal for
/// the same reason [`json`] is: bytes in, bytes out.
/// The in-process jq engine a probe's `json:` key selects with. Internal: it
/// takes bytes and a program and hands back bytes, so no jaq type reaches a
/// library caller's signature and the engine stays swappable.
/// Whether a chosen set of rules is something to gate or report on, and what
/// to say when it came out empty. Internal: it decides the wording of an
/// error and of one report line, neither of which a library caller composes.
pub use run;
pub use ;
pub use Manifest;