diff --git a/Cargo.lock b/Cargo.lock index dd1fa0a..d93203c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -564,7 +564,7 @@ dependencies = [ [[package]] name = "comline-codegen" version = "0.1.0" -source = "git+https://github.com/ComlineProject/generation?rev=9b8336e4acd0a1f10b75aa851c36571f4e1d0d47#9b8336e4acd0a1f10b75aa851c36571f4e1d0d47" +source = "git+https://github.com/ComlineProject/generation?rev=ac4425c32f88f98a2a3bfb971a209c173c6559a8#ac4425c32f88f98a2a3bfb971a209c173c6559a8" dependencies = [ "comline-core", "eyre", @@ -578,7 +578,7 @@ dependencies = [ [[package]] name = "comline-codegen-rust" version = "0.1.0" -source = "git+https://github.com/ComlineProject/comline-rust?rev=89530a72f37180517e1c70f88437b1bedf1e703a#89530a72f37180517e1c70f88437b1bedf1e703a" +source = "git+https://github.com/ComlineProject/comline-rust?rev=8d0d659d100d41d64d203a7890a6b15471cde802#8d0d659d100d41d64d203a7890a6b15471cde802" dependencies = [ "comline-codegen", "comline-core", @@ -588,7 +588,7 @@ dependencies = [ [[package]] name = "comline-codegen-typescript" version = "0.1.0" -source = "git+https://github.com/ComlineProject/comline-typescript?rev=82447d54a8616a1ed37e4a7886df25deb2af7baf#82447d54a8616a1ed37e4a7886df25deb2af7baf" +source = "git+https://github.com/ComlineProject/comline-typescript?rev=37cd70f96260325f37a39be6a15cb858d2e069dc#37cd70f96260325f37a39be6a15cb858d2e069dc" dependencies = [ "comline-codegen", "comline-core", @@ -598,7 +598,7 @@ dependencies = [ [[package]] name = "comline-core" version = "0.1.0" -source = "git+https://github.com/ComlineProject/core?rev=2be483f5adc303bd39c76e11f930ec2340eee57a#2be483f5adc303bd39c76e11f930ec2340eee57a" +source = "git+https://github.com/ComlineProject/core?rev=525939352b79538ce5e9b41ae6713ee6bd26a25e#525939352b79538ce5e9b41ae6713ee6bd26a25e" dependencies = [ "ariadne", "blake3", @@ -627,12 +627,12 @@ dependencies = [ [[package]] name = "comline-core-stdlib" version = "0.1.0" -source = "git+https://github.com/ComlineProject/core?rev=2be483f5adc303bd39c76e11f930ec2340eee57a#2be483f5adc303bd39c76e11f930ec2340eee57a" +source = "git+https://github.com/ComlineProject/core?rev=525939352b79538ce5e9b41ae6713ee6bd26a25e#525939352b79538ce5e9b41ae6713ee6bd26a25e" [[package]] name = "comline-doc-html" version = "0.1.0" -source = "git+https://github.com/ComlineProject/generation?rev=9b8336e4acd0a1f10b75aa851c36571f4e1d0d47#9b8336e4acd0a1f10b75aa851c36571f4e1d0d47" +source = "git+https://github.com/ComlineProject/generation?rev=ac4425c32f88f98a2a3bfb971a209c173c6559a8#ac4425c32f88f98a2a3bfb971a209c173c6559a8" dependencies = [ "comline-codegen", "eyre", @@ -643,7 +643,7 @@ dependencies = [ [[package]] name = "comline-doc-markdown" version = "0.1.0" -source = "git+https://github.com/ComlineProject/generation?rev=9b8336e4acd0a1f10b75aa851c36571f4e1d0d47#9b8336e4acd0a1f10b75aa851c36571f4e1d0d47" +source = "git+https://github.com/ComlineProject/generation?rev=ac4425c32f88f98a2a3bfb971a209c173c6559a8#ac4425c32f88f98a2a3bfb971a209c173c6559a8" dependencies = [ "comline-codegen", "eyre", diff --git a/Cargo.toml b/Cargo.toml index 65c57c0..1bc7615 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,20 +32,20 @@ eyre = "0.6.8" # needs real I/O (git fetch, filesystem), so it's off by default for # `comline-core`'s wasm32 consumers (the playground editor, the language # server); the CLI is the one consumer that actually runs `comline build`. -comline-core = { git = "https://github.com/ComlineProject/core", rev = "2be483f5adc303bd39c76e11f930ec2340eee57a", features = ["deps"] } +comline-core = { git = "https://github.com/ComlineProject/core", rev = "525939352b79538ce5e9b41ae6713ee6bd26a25e", features = ["deps"] } # All three pinned to revs that agree on one `comline-codegen`, and bumped # together: comline-rust and comline-typescript's codegen crates consume # `comline-codegen`'s types, so the rev below must be byte-identical to the # one *they* pin - Cargo only unifies a git dependency across identical rev # strings, and two copies of `GenRequest` are two incompatible types. -comline-codegen = { git = "https://github.com/ComlineProject/generation", rev = "9b8336e4acd0a1f10b75aa851c36571f4e1d0d47" } +comline-codegen = { git = "https://github.com/ComlineProject/generation", rev = "ac4425c32f88f98a2a3bfb971a209c173c6559a8" } # The official Markdown and HTML documentation renderers (`comline doc`), # linked in like the official generators. Same generation rev as # `comline-codegen`. -comline-doc-markdown = { git = "https://github.com/ComlineProject/generation", rev = "9b8336e4acd0a1f10b75aa851c36571f4e1d0d47" } -comline-doc-html = { git = "https://github.com/ComlineProject/generation", rev = "9b8336e4acd0a1f10b75aa851c36571f4e1d0d47" } -comline-codegen-rust = { git = "https://github.com/ComlineProject/comline-rust", rev = "89530a72f37180517e1c70f88437b1bedf1e703a", optional = true } -comline-codegen-typescript = { git = "https://github.com/ComlineProject/comline-typescript", rev = "82447d54a8616a1ed37e4a7886df25deb2af7baf", optional = true } +comline-doc-markdown = { git = "https://github.com/ComlineProject/generation", rev = "ac4425c32f88f98a2a3bfb971a209c173c6559a8" } +comline-doc-html = { git = "https://github.com/ComlineProject/generation", rev = "ac4425c32f88f98a2a3bfb971a209c173c6559a8" } +comline-codegen-rust = { git = "https://github.com/ComlineProject/comline-rust", rev = "8d0d659d100d41d64d203a7890a6b15471cde802", optional = true } +comline-codegen-typescript = { git = "https://github.com/ComlineProject/comline-typescript", rev = "37cd70f96260325f37a39be6a15cb858d2e069dc", optional = true } # `comline conformance`: the conformance runner (corpus loading, judging, # profile proofs) and its case format, a public spec. Pinned by git rev. comline-runtime-conformance = { git = "https://github.com/ComlineProject/runtime", rev = "4378c91b74ee1ef1debc800a3daf75c874198e70" } diff --git a/src/changes.rs b/src/changes.rs index b9286f3..e46a309 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -79,6 +79,11 @@ fn config_line(change: &ConfigChange) -> String { "~", format!("Changed `wire.framing`: {old} {arrow} {new}"), ), + ConfigChange::PackageIdChanged { old, new } => mark( + "🔄", + "~", + format!("Changed the package `id` (a different package): {old} {arrow} {new}"), + ), } } diff --git a/src/commands/build.rs b/src/commands/build.rs index c42cfcf..9fbdc1e 100644 --- a/src/commands/build.rs +++ b/src/commands/build.rs @@ -29,6 +29,16 @@ pub fn run(work_dir: &Path, watching: bool) -> Result<()> { fn build_once(work_dir: &Path) -> Result<()> { ui::step(format!("Building project{}", ui::at_path(work_dir))); + // Every package has an id (its identity for `comline@2`); one without + // gets it here, as one line in config.idp. + match comline_core::package::id::ensure_in_config(work_dir) { + Ok(Some(id)) => ui::note(format!( + "config.idp had no `id`: added `id = \"{id}\"`. Keep it when renaming the \ + package, and change it in a copy" + )), + Ok(None) => {} + Err(e) => return Err(core_err("couldn't add an id to config.idp", e)), + } let spinner = ui::spinner("compiling schemas"); let registry = generator_registry(); let mut target_warnings = Vec::new(); diff --git a/src/commands/inspect.rs b/src/commands/inspect.rs index c2ee2eb..a856fd4 100644 --- a/src/commands/inspect.rs +++ b/src/commands/inspect.rs @@ -10,6 +10,7 @@ use std::io::Write as _; use std::path::Path; use anstyle::{AnsiColor, Color, Style}; +use comline_core::compat::{self, PackageFacts}; use comline_core::inspect::{self, Acceptance, Choice, ProtocolSummary, Source}; use miette::{IntoDiagnostic, Result}; @@ -30,9 +31,12 @@ pub fn run(work_dir: &Path, json: bool) -> Result<()> { let context = outcome.map_err(|e| core_err("validation failed", e))?; let protocols = inspect::protocols(&context); + // What the latest build records for `comline@2`: each protocol's line, + // shape hash and functions' "since". None before the first build. + let facts = latest_facts(work_dir); let mut out = anstream::stdout().lock(); if json { - let report = serde_json::json!({ "protocols": protocols }); + let report = serde_json::json!({ "protocols": protocols, "facts": facts }); writeln!( out, "{}", @@ -48,13 +52,61 @@ pub fn run(work_dir: &Path, json: bool) -> Result<()> { } let text = protocols .iter() - .map(|p| render(p, ui::plain())) + .map(|p| { + let mut text = render(p, ui::plain()); + if !p.dependency { + if let Some(facts) = &facts { + text += &render_facts( + facts, + &compat::protocol_path(&p.schema, &p.name), + ui::plain(), + ); + } + } + text + }) .collect::>() .join("\n"); write!(out, "{text}").into_diagnostic()?; Ok(()) } +/// The latest build's facts, if the package was built. Read-only: the +/// store is never created here. +fn latest_facts(work_dir: &Path) -> Option { + use comline_core::package::build::cas::{main_ref, ref_exists}; + if !ref_exists(work_dir, main_ref()) { + return None; + } + compat::facts(work_dir, None).ok() +} + +/// A protocol's line, shape hash and functions' "since", as the latest +/// build records them. `path` is its `namespace::Protocol`: facts are kept +/// per qualified path, so two protocols of one name stay apart. +pub fn render_facts(facts: &PackageFacts, path: &str, plain: bool) -> String { + let Some(p) = facts.protocols.iter().find(|p| p.path == path) else { + return String::new(); + }; + let dim = |text: &str| { + if plain { + text.to_string() + } else { + format!("{DIM}{text}{DIM:#}") + } + }; + let mut out = format!( + "\n {}\n", + dim(&format!("{} as of build {}", p.path, facts.version)) + ); + out += &format!(" {:<10} {}\n", "line", p.line); + out += &format!(" {:<10} {}\n", "shape", p.shape_hash); + for f in &p.functions { + out += &format!(" {:<10} {:<24} {}\n", "since", f.name, f.since); + } + out +} + /// One protocol: a header of choices, then a row per guarantee. Fits 80 /// columns: anything long goes on its own indented line. pub fn render(p: &ProtocolSummary, plain: bool) -> String { diff --git a/src/commands/new.rs b/src/commands/new.rs index 6279c71..141bec5 100644 --- a/src/commands/new.rs +++ b/src/commands/new.rs @@ -129,9 +129,12 @@ fn scaffold_language() -> String { fn config_idp(name: &str) -> String { let language = scaffold_language(); + // The package's identity: kept by a rename, changed by a copy. + let id = comline_core::package::id::config_line(&comline_core::package::id::generate()); format!( "\ congregation {name} +{id} specification_version = 1 code_generation = {{ diff --git a/tests/cli/build.rs b/tests/cli/build.rs index 4bb4186..9e419c7 100644 --- a/tests/cli/build.rs +++ b/tests/cli/build.rs @@ -23,6 +23,38 @@ fn freezes_an_initial_version() { assert!(project.join(".comline").is_dir()); } +#[test] +fn adds_a_missing_id_with_a_note_and_keeps_one_there_is() { + let temp = tempfile::tempdir().unwrap(); + let project = fixture_project(temp.path()); + let before = std::fs::read_to_string(project.join("config.idp")).unwrap(); + assert!(!before.contains("\nid = "), "{before}"); + + build(&project) + .success() + .stderr(predicate::str::contains("config.idp had no `id`: added")); + let after = std::fs::read_to_string(project.join("config.idp")).unwrap(); + // One line added after `congregation`, nothing else touched. + let added: Vec<&str> = after + .lines() + .filter(|l| !before.lines().any(|b| b == *l)) + .collect(); + assert_eq!(added.len(), 1, "{after}"); + assert!( + added[0].starts_with("id = \"") && added[0].len() == "id = \"\"".len() + 32, + "{after}" + ); + assert_eq!(after.replace(&format!("{}\n", added[0]), ""), before); + + build(&project) + .success() + .stderr(predicate::str::contains("had no `id`").not()); + assert_eq!( + std::fs::read_to_string(project.join("config.idp")).unwrap(), + after + ); +} + /// `fixture_project`, declaring `languages` (and anything after) instead. fn declaring(temp: &std::path::Path, languages: &str, rest: &str) -> std::path::PathBuf { let project = fixture_project(temp); diff --git a/tests/cli/new.rs b/tests/cli/new.rs index 769e0fb..789c00e 100644 --- a/tests/cli/new.rs +++ b/tests/cli/new.rs @@ -37,6 +37,12 @@ fn scaffolds_a_buildable_project() { let config = fs::read_to_string(root.join("config.idp")).unwrap(); assert!(config.contains("congregation my_api")); + // The package's identity, random, on the line after its name. + let id = config.lines().nth(1).unwrap(); + assert!( + id.starts_with("id = \"") && id.len() == "id = \"\"".len() + 32, + "{config}" + ); assert!(config.contains("code_generation")); // The widest promise: the Rust generator's floor. assert!(config.contains("rust#1.85.0 = {}"), "{config}"); diff --git a/tests/fixtures/generators/Cargo.lock b/tests/fixtures/generators/Cargo.lock index bca0cc8..1b6772f 100644 --- a/tests/fixtures/generators/Cargo.lock +++ b/tests/fixtures/generators/Cargo.lock @@ -79,7 +79,7 @@ dependencies = [ [[package]] name = "comline-codegen" version = "0.1.0" -source = "git+https://github.com/ComlineProject/generation?rev=9b8336e4acd0a1f10b75aa851c36571f4e1d0d47#9b8336e4acd0a1f10b75aa851c36571f4e1d0d47" +source = "git+https://github.com/ComlineProject/generation?rev=ac4425c32f88f98a2a3bfb971a209c173c6559a8#ac4425c32f88f98a2a3bfb971a209c173c6559a8" dependencies = [ "comline-core", "eyre", @@ -93,7 +93,7 @@ dependencies = [ [[package]] name = "comline-codegen-rust" version = "0.1.0" -source = "git+https://github.com/ComlineProject/comline-rust?rev=89530a72f37180517e1c70f88437b1bedf1e703a#89530a72f37180517e1c70f88437b1bedf1e703a" +source = "git+https://github.com/ComlineProject/comline-rust?rev=8d0d659d100d41d64d203a7890a6b15471cde802#8d0d659d100d41d64d203a7890a6b15471cde802" dependencies = [ "comline-codegen", "comline-core", @@ -103,7 +103,7 @@ dependencies = [ [[package]] name = "comline-core" version = "0.1.0" -source = "git+https://github.com/ComlineProject/core?rev=2be483f5adc303bd39c76e11f930ec2340eee57a#2be483f5adc303bd39c76e11f930ec2340eee57a" +source = "git+https://github.com/ComlineProject/core?rev=525939352b79538ce5e9b41ae6713ee6bd26a25e#525939352b79538ce5e9b41ae6713ee6bd26a25e" dependencies = [ "blake3", "ciborium", @@ -120,12 +120,12 @@ dependencies = [ [[package]] name = "comline-core-stdlib" version = "0.1.0" -source = "git+https://github.com/ComlineProject/core?rev=2be483f5adc303bd39c76e11f930ec2340eee57a#2be483f5adc303bd39c76e11f930ec2340eee57a" +source = "git+https://github.com/ComlineProject/core?rev=525939352b79538ce5e9b41ae6713ee6bd26a25e#525939352b79538ce5e9b41ae6713ee6bd26a25e" [[package]] name = "comline-doc-html" version = "0.1.0" -source = "git+https://github.com/ComlineProject/generation?rev=9b8336e4acd0a1f10b75aa851c36571f4e1d0d47#9b8336e4acd0a1f10b75aa851c36571f4e1d0d47" +source = "git+https://github.com/ComlineProject/generation?rev=ac4425c32f88f98a2a3bfb971a209c173c6559a8#ac4425c32f88f98a2a3bfb971a209c173c6559a8" dependencies = [ "comline-codegen", "eyre", @@ -136,7 +136,7 @@ dependencies = [ [[package]] name = "comline-doc-markdown" version = "0.1.0" -source = "git+https://github.com/ComlineProject/generation?rev=9b8336e4acd0a1f10b75aa851c36571f4e1d0d47#9b8336e4acd0a1f10b75aa851c36571f4e1d0d47" +source = "git+https://github.com/ComlineProject/generation?rev=ac4425c32f88f98a2a3bfb971a209c173c6559a8#ac4425c32f88f98a2a3bfb971a209c173c6559a8" dependencies = [ "comline-codegen", "eyre", diff --git a/tests/fixtures/generators/Cargo.toml b/tests/fixtures/generators/Cargo.toml index 8d8442a..1385786 100644 --- a/tests/fixtures/generators/Cargo.toml +++ b/tests/fixtures/generators/Cargo.toml @@ -12,7 +12,7 @@ publish = false [dependencies] # The same revs the CLI pins, so the real generator's output is comparable # byte for byte with the CLI's built-in one. -comline-codegen = { git = "https://github.com/ComlineProject/generation", rev = "9b8336e4acd0a1f10b75aa851c36571f4e1d0d47" } -comline-doc-markdown = { git = "https://github.com/ComlineProject/generation", rev = "9b8336e4acd0a1f10b75aa851c36571f4e1d0d47" } -comline-doc-html = { git = "https://github.com/ComlineProject/generation", rev = "9b8336e4acd0a1f10b75aa851c36571f4e1d0d47" } -comline-codegen-rust = { git = "https://github.com/ComlineProject/comline-rust", rev = "89530a72f37180517e1c70f88437b1bedf1e703a" } +comline-codegen = { git = "https://github.com/ComlineProject/generation", rev = "ac4425c32f88f98a2a3bfb971a209c173c6559a8" } +comline-doc-markdown = { git = "https://github.com/ComlineProject/generation", rev = "ac4425c32f88f98a2a3bfb971a209c173c6559a8" } +comline-doc-html = { git = "https://github.com/ComlineProject/generation", rev = "ac4425c32f88f98a2a3bfb971a209c173c6559a8" } +comline-codegen-rust = { git = "https://github.com/ComlineProject/comline-rust", rev = "8d0d659d100d41d64d203a7890a6b15471cde802" }