src/mimir_lens/room_feed/fixture/vectors.rs
//! The fixture of the per-function vectors: real source text on disk, and a
//! scripted dump whose spans point at it — so a chunk is cut exactly as in
//! production (the room's span, the checkout's lines).
//!
//! ```text
//! repo `mono` — crates alpha@0.1.0 and beta@0.1.0
//! alpha/src/lib.rs Reader::new · Reader::total · <Reader as Default>::default
//! parse_header · checksum · width (written by `make_getter!`)
//! beta/src/lib.rs Writer::new · <Writer as Default>::default
//! http::parse_header ← alpha's, byte for byte, one level deeper
//! shared/util.rs clamp — ONE file compiled into both crates: two nodes, the same lines
//! repo `other` — crate gamma@0.3.0
//! src/lib.rs parse_header (a third copy) · digest
//! (target dir) proto::decode — build-script output, outside the checkout
//! ring: kit@1.0.0 pad · trim (their source in a registry directory)
//! ```
//!
//! [`Vx::second_commit`]: `mono` seq 2 — a comment line on top of alpha's file
//! (every span below moves, no text changes), `total` and `checksum` get
//! another body, `fresh` is new; the ring gains kit@2.0.0.
use std::collections::BTreeSet;
use std::path::{Path, PathBuf};
use std::sync::Mutex;
use mimir_ingest::{CommitDump, Consumer, CrateDump, RepoSpec};
use mimir_schema::{EdgeKind, EdgeRow, Level, NodeRow, Origin, SpanRow, moniker};
use super::{N, Scripted, Workspace, e, n, span, unit};
use crate::code_room::CodeRoom;
use crate::vector::store::{Embedder, ModelProfile};
use crate::warehouse::iceberg::IcebergWarehouse;
pub const MONO: &str = "mono";
pub const OTHER: &str = "other";
pub fn alpha(d: &str) -> String {
moniker::moniker("alpha", "0.1.0", d)
}
pub fn beta(d: &str) -> String {
moniker::moniker("beta", "0.1.0", d)
}
pub fn gamma(d: &str) -> String {
moniker::moniker("gamma", "0.3.0", d)
}
pub fn kit(version: &str, d: &str) -> String {
moniker::moniker("kit", version, d)
}
/// A deterministic embedder: a bag of the text's identifier-like tokens,
/// hashed into 64 buckets. Identical text → identical vector; it records every
/// text it was asked for, so a test can count what was embedded.
#[derive(Default)]
pub struct Bag {
pub asked: Mutex<Vec<String>>,
}
impl Bag {
pub fn count(&self) -> usize {
self.asked.lock().unwrap().len()
}
}
impl Embedder for Bag {
fn profile(&self) -> ModelProfile {
ModelProfile { model_name: "test-bag".into(), weights_sha: "w".into(), tokenizer_sha: "t".into(), pooling: "sum".into(), normalize: true, dim: 64, dtype: "f32".into() }
}
fn embed(&self, texts: &[&str]) -> anyhow::Result<Vec<Vec<f32>>> {
self.asked.lock().unwrap().extend(texts.iter().map(|t| t.to_string()));
Ok(texts
.iter()
.map(|t| {
let mut v = vec![0f32; 64];
for tok in t.split(|c: char| !(c.is_alphanumeric() || c == '_')).filter(|s| !s.is_empty()) {
let h = tok.bytes().fold(0xcbf2_9ce4_8422_2325u64, |h, b| (h ^ b as u64).wrapping_mul(0x0100_0000_01b3));
v[(h % 64) as usize] += 1.0;
}
let norm = v.iter().map(|x| x * x).sum::<f32>().sqrt().max(f32::MIN_POSITIVE);
v.iter().map(|x| x / norm).collect()
})
.collect())
}
}
/// A source file being written: plain lines, and items whose extent is recorded.
#[derive(Default)]
pub(super) struct Source {
lines: Vec<String>,
/// `(node id, start, end)`.
at: Vec<(String, u32, u32)>,
}
impl Source {
pub(super) fn plain(&mut self, text: &str) -> &mut Self {
self.lines.extend(text.lines().map(str::to_string));
self
}
/// An item's own text; `indent` spaces are put in front of every line.
pub(super) fn item(&mut self, id: &str, indent: usize, text: &str) -> &mut Self {
let start = self.lines.len() as u32 + 1;
self.lines.extend(text.lines().map(|l| if l.is_empty() { String::new() } else { format!("{}{l}", " ".repeat(indent)) }));
self.at.push((id.to_string(), start, self.lines.len() as u32));
self.lines.push(String::new());
self
}
pub(super) fn write(&self, root: &Path, file: &str) -> Vec<SpanRow> {
let path = root.join(file);
std::fs::create_dir_all(path.parent().unwrap()).unwrap();
std::fs::write(&path, self.lines.join("\n") + "\n").unwrap();
self.at.iter().map(|(id, s, e)| span(id, file, *s, *e)).collect()
}
}
pub const PARSE_HEADER: &str = "pub fn parse_header(line: &str) -> Option<(String, String)> {
let (key, value) = line.split_once(':')?;
let key = key.trim().to_ascii_lowercase();
let value = value.trim().to_string();
if key.is_empty() {
return None;
}
Some((key, value))
}";
const DEFAULT: &str = "fn default() -> Self {
Self::new()
}";
const CLAMP: &str = "pub fn clamp(x: i64, lo: i64, hi: i64) -> i64 {
if x < lo {
return lo;
}
if x > hi { hi } else { x }
}";
const TOTAL_1: &str = "pub fn total(&self, xs: &[u32]) -> u32 {
let mut sum = 0;
for x in xs {
sum += *x;
}
sum + self.at as u32
}";
const TOTAL_2: &str = "pub fn total(&self, xs: &[u32]) -> u32 {
xs.iter().copied().fold(self.at as u32, u32::wrapping_add)
}";
const CHECKSUM_1: &str = "pub fn checksum(bytes: &[u8]) -> u32 {
let mut acc = 17u32;
for b in bytes {
acc = acc.rotate_left(5) ^ u32::from(*b);
}
acc
}";
const CHECKSUM_2: &str = "pub fn checksum(bytes: &[u8]) -> u32 {
let mut acc = 0x811c_9dc5u32;
for b in bytes {
acc = (acc ^ u32::from(*b)).wrapping_mul(0x0100_0193);
}
acc
}";
const FRESH: &str = "pub fn fresh(now: u64, then: u64) -> bool {
now.saturating_sub(then) < 60
}";
fn method(id: String, name: &str, parent: &str) -> N {
n(id, "method", Level::Part, name, Some(parent.to_string()))
}
pub(super) fn param(of: &str, name: &str, ty: &str) -> (N, EdgeRow) {
let id = format!("{of}({name})");
(n(id.clone(), "param", Level::Part, name, Some(of.to_string())).ty(ty), e(of, &id, EdgeKind::Contains, 1))
}
/// A callable with its params and the stubs it calls, appended to a unit.
#[allow(clippy::too_many_arguments)]
pub(super) fn callable(nodes: &mut Vec<N>, edges: &mut Vec<EdgeRow>, stubs: &mut BTreeSet<String>, node: N, parent: &str, params: &[(&str, &str)], calls: &[&str]) {
let id = node.0.id.clone();
nodes.push(node);
edges.push(e(parent, &id, EdgeKind::Contains, 1));
for (p, ty) in params {
let (pn, pe) = param(&id, p, ty);
nodes.push(pn);
edges.push(pe);
}
for c in calls {
let to = moniker::moniker("core", "1.0.0", &format!("{c}()."));
stubs.insert(to.clone());
edges.push(e(&id, &to, EdgeKind::Calls, 1));
}
}
pub(super) fn stubs_into(nodes: &mut Vec<N>, stubs: &BTreeSet<String>) {
for s in stubs {
let name = s.rsplit('/').next().unwrap_or(s).rsplit(' ').next().unwrap_or(s).trim_end_matches("().").to_string();
nodes.push(n(s.clone(), "fn", Level::Item, &name, None).stub(Origin::Library));
}
}
const HEADER_PARAMS: [(&str, &str); 1] = [("line", "&str")];
const HEADER_CALLS: [&str; 4] = ["split_once", "trim", "to_ascii_lowercase", "is_empty"];
/// `mono` at its first (`second = false`) or second commit, files written under `root`.
fn mono_commit(root: &Path, second: bool) -> CommitDump {
// ── alpha ──
let krate = alpha("crate/");
let imp = alpha("impl#[Reader]");
let imp_default = alpha("impl#[Reader][Default]");
let mac = alpha("make_getter!");
let util = alpha("util/");
let mut src = Source::default();
if second {
src.plain("// every span below moved by one line");
}
src.plain("//! alpha\n\npub struct Reader {\n at: usize,\n}\n\nimpl Reader {");
src.item(&alpha("impl#[Reader]new()."), 4, "pub fn new() -> Self {\n Reader { at: 0 }\n}");
src.item(&alpha("impl#[Reader]total()."), 4, if second { TOTAL_2 } else { TOTAL_1 });
src.plain("}\n\nimpl Default for Reader {");
src.item(&alpha("impl#[Reader][Default]default()."), 4, DEFAULT);
src.plain("}\n");
src.item(&alpha("parse_header()."), 0, PARSE_HEADER);
src.item(&alpha("checksum()."), 0, if second { CHECKSUM_2 } else { CHECKSUM_1 });
if second {
src.item(&alpha("fresh()."), 0, FRESH);
}
// the macro's product is positioned at the invocation
src.item(&alpha("width()."), 0, "make_getter!(width);");
let mut spans = src.write(root, "alpha/src/lib.rs");
let mut shared = Source::default();
shared.plain("//! compiled into alpha AND beta (`#[path]`)\n");
shared.item(&alpha("util/clamp()."), 0, CLAMP);
spans.extend(shared.write(root, "shared/util.rs"));
let mut nodes = vec![
n(krate.clone(), "crate", Level::Crate, "alpha", None),
n(imp.clone(), "impl", Level::Item, "Reader", Some(krate.clone())),
n(imp_default.clone(), "impl", Level::Item, "Reader", Some(krate.clone())),
n(mac.clone(), "macro", Level::Item, "make_getter", Some(krate.clone())),
n(util.clone(), "mod", Level::Module, "util", Some(krate.clone())),
];
let default_trait = moniker::moniker("core", "1.0.0", "default/Default#");
nodes.push(n(default_trait.clone(), "trait", Level::Item, "Default", None).stub(Origin::Library));
let mut edges = vec![
e(&krate, &imp, EdgeKind::Contains, 1),
e(&krate, &imp_default, EdgeKind::Contains, 1),
e(&krate, &mac, EdgeKind::Contains, 1),
e(&krate, &util, EdgeKind::Contains, 1),
e(&imp_default, &default_trait, EdgeKind::Implements, 1),
e(&alpha("width()."), &mac, EdgeKind::Expands, 1),
// the lockfile: kit 1.0.0, bumped to 2.0.0 by the second commit
e(&krate, &kit(if second { "2.0.0" } else { "1.0.0" }, "crate/"), EdgeKind::DependsOn, 1),
];
let mut stubs = BTreeSet::new();
callable(&mut nodes, &mut edges, &mut stubs, method(alpha("impl#[Reader]new()."), "new", &imp), &imp, &[], &[]);
callable(&mut nodes, &mut edges, &mut stubs, method(alpha("impl#[Reader]total()."), "total", &imp), &imp, &[("self", "&Reader"), ("xs", "&[u32]")], if second { &["fold", "copied"] } else { &[] });
callable(&mut nodes, &mut edges, &mut stubs, method(alpha("impl#[Reader][Default]default()."), "default", &imp_default), &imp_default, &[], &["new"]);
callable(&mut nodes, &mut edges, &mut stubs, n(alpha("parse_header()."), "fn", Level::Item, "parse_header", Some(krate.clone())), &krate, &HEADER_PARAMS, &HEADER_CALLS);
callable(&mut nodes, &mut edges, &mut stubs, n(alpha("checksum()."), "fn", Level::Item, "checksum", Some(krate.clone())), &krate, &[("bytes", "&[u8]")], &["rotate_left"]);
if second {
callable(&mut nodes, &mut edges, &mut stubs, n(alpha("fresh()."), "fn", Level::Item, "fresh", Some(krate.clone())), &krate, &[("now", "u64"), ("then", "u64")], &["saturating_sub"]);
}
callable(&mut nodes, &mut edges, &mut stubs, n(alpha("width()."), "fn", Level::Item, "width", Some(krate.clone())), &krate, &[("self", "&Reader")], &[]);
callable(&mut nodes, &mut edges, &mut stubs, n(alpha("util/clamp()."), "fn", Level::Item, "clamp", Some(util.clone())), &util, &[("x", "i64"), ("lo", "i64"), ("hi", "i64")], &[]);
stubs_into(&mut nodes, &stubs);
let alpha_unit = unit("alpha@0.1.0:lib", nodes, edges, spans);
// ── beta ──
let krate = beta("crate/");
let imp = beta("impl#[Writer]");
let imp_default = beta("impl#[Writer][Default]");
let http = beta("http/");
let util = beta("util/");
let mut src = Source::default();
src.plain("//! beta\n\npub struct Writer {\n n: usize,\n}\n\nimpl Writer {");
src.item(&beta("impl#[Writer]new()."), 4, "pub fn new() -> Self {\n Writer { n: 0 }\n}");
src.plain("}\n\nimpl Default for Writer {");
src.item(&beta("impl#[Writer][Default]default()."), 4, DEFAULT);
src.plain("}\n\npub mod http {");
// alpha's function, byte for byte, one level deeper
src.item(&beta("http/parse_header()."), 4, PARSE_HEADER);
src.plain("}");
let mut spans = src.write(root, "beta/src/lib.rs");
// the SAME lines of the shared file, as beta's node
spans.push(span(&beta("util/clamp()."), "shared/util.rs", shared.at[0].1, shared.at[0].2));
let mut nodes = vec![
n(krate.clone(), "crate", Level::Crate, "beta", None),
n(imp.clone(), "impl", Level::Item, "Writer", Some(krate.clone())),
n(imp_default.clone(), "impl", Level::Item, "Writer", Some(krate.clone())),
n(http.clone(), "mod", Level::Module, "http", Some(krate.clone())),
n(util.clone(), "mod", Level::Module, "util", Some(krate.clone())),
n(default_trait.clone(), "trait", Level::Item, "Default", None).stub(Origin::Library),
];
let mut edges = vec![
e(&krate, &imp, EdgeKind::Contains, 1),
e(&krate, &imp_default, EdgeKind::Contains, 1),
e(&krate, &http, EdgeKind::Contains, 1),
e(&krate, &util, EdgeKind::Contains, 1),
e(&imp_default, &default_trait, EdgeKind::Implements, 1),
];
let mut stubs = BTreeSet::new();
callable(&mut nodes, &mut edges, &mut stubs, method(beta("impl#[Writer]new()."), "new", &imp), &imp, &[], &[]);
callable(&mut nodes, &mut edges, &mut stubs, method(beta("impl#[Writer][Default]default()."), "default", &imp_default), &imp_default, &[], &["new"]);
callable(&mut nodes, &mut edges, &mut stubs, n(beta("http/parse_header()."), "fn", Level::Item, "parse_header", Some(http.clone())), &http, &HEADER_PARAMS, &HEADER_CALLS);
callable(&mut nodes, &mut edges, &mut stubs, n(beta("util/clamp()."), "fn", Level::Item, "clamp", Some(util.clone())), &util, &[("x", "i64"), ("lo", "i64"), ("hi", "i64")], &[]);
stubs_into(&mut nodes, &stubs);
let beta_unit = unit("beta@0.1.0:lib", nodes, edges, spans);
let mut crates = vec![alpha_unit, beta_unit, ring_unit("1.0.0")];
if second {
crates.push(ring_unit("2.0.0"));
}
CommitDump {
toolchain: "nightly-fixture".into(),
workspace_crates: ["alpha@0.1.0:lib".to_string(), "beta@0.1.0:lib".to_string()].into(),
workspace_targets: ["alpha:lib".to_string(), "beta:lib".to_string()].into(),
failed_units: BTreeSet::new(),
owner_disambiguations: 0,
crates,
binary: false,
binaries: vec![],
}
}
/// The lines of kit's `src/lib.rs` at `version`: `(text, [(descriptor, start, end)])`.
fn kit_source(version: &str) -> (String, Vec<(&'static str, u32, u32)>) {
let pad = "pub fn pad(s: &str, width: usize) -> String {\n format!(\"{s:>width$}\")\n}";
let trim = if version == "1.0.0" { "pub fn trim(s: &str) -> &str {\n s.trim()\n}" } else { "pub fn trim(s: &str) -> &str {\n s.trim_matches(' ')\n}" };
let text = format!("//! kit {version}\n\n{pad}\n\n{trim}\n");
(text, vec![("pad().", 3, 5), ("trim().", 7, 9)])
}
/// One ring crate (`kit@<version>`): defined library nodes with spans relative
/// to its own manifest directory.
fn ring_unit(version: &str) -> CrateDump {
let krate = kit(version, "crate/");
let mut rows: Vec<NodeRow> = vec![NodeRow::new(krate.clone(), "crate", Level::Crate, "kit", "kit", version, Origin::Library)];
let mut edges = Vec::new();
let mut spans = Vec::new();
for (d, start, end) in kit_source(version).1 {
let id = kit(version, d);
let mut row = NodeRow::new(id.clone(), "fn", Level::Item, d.trim_end_matches("()."), "kit", version, Origin::Library);
row.parent = Some(krate.clone());
rows.push(row);
edges.push(e(&krate, &id, EdgeKind::Contains, 1));
spans.push(span(&id, "src/lib.rs", start, end));
}
CrateDump {
krate: format!("kit@{version}:lib"),
universe: true,
nodes: vec![mimir_schema::nodes_batch(&rows).unwrap()],
edges: vec![mimir_schema::edges_batch(&edges).unwrap()],
spans: vec![mimir_schema::spans_batch(&spans).unwrap()],
}
}
/// [`Vx::digest_commit`]: gamma's `digest` becomes a fourth copy of
/// `parse_header` — the SAME bytes (so the feed re-links one function and
/// embeds nothing new), the same params and callees. Nothing above it moves.
fn other_commit(root: &Path, second: bool, uses: &[String]) -> CommitDump {
let krate = gamma("crate/");
// the manifest says the same as the lockfile edges: gamma depends on them
if !uses.is_empty() {
let deps: Vec<String> = uses.iter().filter_map(|m| moniker::parse(m)).map(|(p, v, _)| format!("{p} = {{ version = \"{v}\", path = \"../{p}\" }}")).collect();
std::fs::create_dir_all(root).unwrap();
std::fs::write(root.join("Cargo.toml"), format!("[package]\nname = \"gamma\"\nversion = \"0.3.0\"\n\n[dependencies]\n{}\n", deps.join("\n"))).unwrap();
}
let mut src = Source::default();
src.plain("//! gamma\n");
src.item(&gamma("parse_header()."), 0, PARSE_HEADER);
src.item(&gamma("digest()."), 0, if second { PARSE_HEADER } else { "pub fn digest(data: &[u8]) -> u64 {\n data.iter().fold(0u64, |h, b| h.wrapping_mul(31).wrapping_add(u64::from(*b)))\n}" });
let mut spans = src.write(root, "src/lib.rs");
// prost / bindgen output: positioned in the build's target directory, not in the repo
spans.push(span(&gamma("proto/decode()."), "/nonexistent/target/debug/build/gamma-1/out/proto.rs", 10, 40));
let mut nodes = vec![n(krate.clone(), "crate", Level::Crate, "gamma", None)];
// the lockfile: the crates gamma depends on ([`build_using`])
let mut edges: Vec<EdgeRow> = uses.iter().map(|to| e(&krate, to, EdgeKind::DependsOn, 1)).collect();
let mut stubs = BTreeSet::new();
callable(&mut nodes, &mut edges, &mut stubs, n(gamma("proto/decode()."), "fn", Level::Item, "decode", Some(krate.clone())), &krate, &[("buf", "&[u8]")], &[]);
callable(&mut nodes, &mut edges, &mut stubs, n(gamma("parse_header()."), "fn", Level::Item, "parse_header", Some(krate.clone())), &krate, &HEADER_PARAMS, &HEADER_CALLS);
let (digest_params, digest_calls): (&[(&str, &str)], &[&str]) = if second { (&HEADER_PARAMS, &HEADER_CALLS) } else { (&[("data", "&[u8]")], &["fold"]) };
callable(&mut nodes, &mut edges, &mut stubs, n(gamma("digest()."), "fn", Level::Item, "digest", Some(krate.clone())), &krate, digest_params, digest_calls);
stubs_into(&mut nodes, &stubs);
CommitDump {
toolchain: "nightly-fixture".into(),
workspace_crates: ["gamma@0.3.0:lib".to_string()].into(),
workspace_targets: ["gamma:lib".to_string()].into(),
failed_units: BTreeSet::new(),
owner_disambiguations: 0,
crates: vec![unit("gamma@0.3.0:lib", nodes, edges, spans)],
binary: false,
binaries: vec![],
}
}
/// The workspace, its two checkouts and the ring's registry directory.
pub struct Vx {
pub ws: Workspace,
root: PathBuf,
}
impl Vx {
/// The checkout of `repo` (the tree a feed run reads).
pub fn checkout(&self, repo: &str) -> PathBuf {
self.root.join(format!("src-{repo}"))
}
/// `(seq, sha)` the code room holds `repo` at.
pub fn at(&self, repo: &str) -> (i64, String) {
let log = self.ws.room.log().unwrap();
let o = log.block_on(log.offsets()).unwrap().remove(repo).unwrap_or_else(|| panic!("{repo} is not consumed"));
(o.seq, o.sha)
}
/// The function half of the feed for `repo`, as the consumer runs it.
pub fn embed(&self, repo: &str, bag: &Bag) -> crate::vector::fnvec::Run {
let (seq, sha) = self.at(repo);
let log = self.ws.room.log().unwrap();
let mut embedding = crate::vector::fnvec::Loaded { embedder: bag, backend: "test bag (cpu)" };
crate::vector::fnvec::room::embed_member_with(&self.ws.warehouse, &log, repo, &self.checkout(repo), seq, &sha, &mut embedding).unwrap()
}
/// The function shapes (`clone_shapes`' first half) of `repo` at its
/// current commit, as the consumer writes them.
pub fn shapes(&self, repo: &str) -> crate::clone_signals::feed::ShapeRun {
let (seq, sha) = self.at(repo);
let log = self.ws.room.log().unwrap();
crate::clone_signals::feed::shapes_member(&self.ws.warehouse, &log, repo, &self.checkout(repo), seq, &sha).unwrap()
}
/// Consume `mono`'s second commit.
pub fn second_commit(&self) {
let dir = self.checkout(MONO);
let dump = mono_commit(&dir, true);
self.registry("2.0.0");
nornir_git::gitio::commit_all(&dir, "second").unwrap();
consume_next(&self.ws.room, &dir, MONO, dump);
}
/// Consume `other`'s second commit: ONE function changes — `digest`
/// becomes a fourth copy of `parse_header` (same bytes, same callees);
/// every other span of the workspace stays where it was.
pub fn digest_commit(&self) {
let dir = self.checkout(OTHER);
let dump = other_commit(&dir, true, &[]);
nornir_git::gitio::commit_all(&dir, "digest is a copy now").unwrap();
consume_next(&self.ws.room, &dir, OTHER, dump);
}
/// The directory kit@`version`'s manifest is in, with its source written.
fn registry(&self, version: &str) -> PathBuf {
let dir = self.root.join("registry").join(format!("kit-{version}"));
std::fs::create_dir_all(dir.join("src")).unwrap();
std::fs::write(dir.join("Cargo.toml"), format!("[package]\nname = \"kit\"\nversion = \"{version}\"\n")).unwrap();
std::fs::write(dir.join("src/lib.rs"), kit_source(version).0).unwrap();
dir
}
/// Where kit's source is, per version — what `cargo metadata` tells the ring job.
pub fn ring_dirs(&self, versions: &[&str]) -> std::collections::BTreeMap<String, PathBuf> {
let packages: Vec<serde_json::Value> = versions.iter().map(|v| serde_json::json!({ "name": "kit", "version": v, "manifest_path": self.registry(v).join("Cargo.toml") })).collect();
crate::vector::fnvec::ring::dirs_from_metadata(&serde_json::json!({ "packages": packages }))
}
}
/// Consume the next commit of the repo at `dir` with `dump`.
pub(super) fn consume_next(room: &CodeRoom, dir: &Path, name: &str, dump: CommitDump) {
let spec = RepoSpec { name: name.into(), source: dir.to_string_lossy().into_owned(), branch: "main".into(), worktree: room.layout().clone_of(name), initial_offset: None };
let log = room.log().expect("the lake opens");
let reports = log.block_on(async {
let mut c = Consumer::boot(log.clone(), Scripted(vec![dump])).await.unwrap();
c.run(&spec).await.unwrap()
});
assert!(reports.len() == 1 && reports[0].status == "ok", "{reports:?}");
}
/// Both repos consumed at their first commit; nothing embedded yet.
pub fn build() -> Vx {
build_using(&[])
}
/// [`build`], gamma (repo `other`) depending on the crates `uses` names
/// (crate monikers, e.g. `alpha("crate/")`): its `parse_header` is then a copy
/// of a function of a crate it imports.
pub fn build_using(uses: &[String]) -> Vx {
let tmp = tempfile::tempdir().unwrap();
let root = tmp.path().to_path_buf();
let builds = root.join("builds");
std::fs::create_dir_all(&builds).unwrap();
let warehouse = IcebergWarehouse::open(&builds).unwrap();
let room = CodeRoom::new("vectors", &builds);
for name in [MONO, OTHER] {
let dir = root.join(format!("src-{name}"));
nornir_git::gitio::init(&dir).unwrap();
let dump = if name == MONO { mono_commit(&dir, false) } else { other_commit(&dir, false, uses) };
nornir_git::gitio::commit_all(&dir, "first").unwrap();
consume_next(&room, &dir, name, dump);
}
let vx = Vx { ws: Workspace { room, warehouse, builds, _tmp: tmp }, root };
vx.registry("1.0.0");
vx
}