use std::path::{Path, PathBuf};
use std::process::Command;
fn repository_root() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR"))
.join("..")
.join("..")
.canonicalize()
.expect("the repository root is two directories above this crate")
}
fn is_registry_qualified(identifier: &str) -> bool {
let Some((registry, name)) = identifier.split_once(':') else {
return false;
};
!registry.is_empty()
&& registry.chars().all(|character| {
character.is_ascii_lowercase() || character.is_ascii_digit() || character == '-'
})
&& !name.is_empty()
&& !name.contains(':')
&& !name.chars().any(char::is_whitespace)
}
fn declared_target_ids(root: &Path) -> Vec<String> {
let declaration = root.join("release-targets.toml");
let text = std::fs::read_to_string(&declaration)
.unwrap_or_else(|error| panic!("could not read {}: {error}", declaration.display()));
let mut ids = Vec::new();
let mut in_target = false;
let mut targets = 0usize;
for line in text.lines() {
let line = line.trim();
if line.starts_with('#') {
continue;
}
if line.starts_with('[') {
assert_eq!(
ids.len(),
targets,
"{} has a [[target]] with no id in it",
declaration.display()
);
in_target = line.starts_with("[[target]]");
if in_target {
targets += 1;
}
continue;
}
if !in_target {
continue;
}
let Some((key, value)) = line.split_once('=') else {
continue;
};
if key.trim() != "id" {
continue;
}
let value = value.trim();
let quoted = value
.strip_prefix('"')
.and_then(|value| value.strip_suffix('"'))
.filter(|value| !value.is_empty() && !value.contains('"'));
let Some(identifier) = quoted.filter(|value| is_registry_qualified(value)) else {
panic!(
"{} gives a [[target]] the id {value}, which is not a quoted <registry>:<name>",
declaration.display()
)
};
assert_eq!(
ids.len() + 1,
targets,
"{} gives one [[target]] two ids, the second being {identifier}",
declaration.display()
);
ids.push(identifier.to_string());
}
assert_eq!(
ids.len(),
targets,
"{} has a [[target]] with no id in it",
declaration.display()
);
assert!(
!ids.is_empty(),
"{} declares no target, so there is nothing to ask a registry about",
declaration.display()
);
ids
}
#[test]
#[ignore = "reaches the public registries; run it with `just test-live`"]
fn every_declared_target_answers_from_its_real_registry() {
let root = repository_root();
let probe = root.join("scripts").join("release-probe.sh");
let mut failures = Vec::new();
for identifier in declared_target_ids(&root) {
let answer = Command::new("bash")
.arg(&probe)
.arg(&identifier)
.current_dir(&root)
.output()
.unwrap_or_else(|error| panic!("could not run {}: {error}", probe.display()));
let stdout = String::from_utf8_lossy(&answer.stdout).trim().to_string();
let stderr = String::from_utf8_lossy(&answer.stderr).trim().to_string();
if !answer.status.success() {
failures.push(format!(
"{identifier}: not answered ({}). The probe said: {stderr}",
answer.status
));
continue;
}
if stdout.is_empty() {
failures.push(format!(
"{identifier}: its registry answered that it serves nothing. Every declared \
target here has been released, so this is the lookup reaching the wrong \
place — re-observe that registry's interface and bring \
config/registry-interfaces.toml and scripts/release-probe.sh to it. A target \
declared before its own first release is the one other way to land here."
));
continue;
}
}
assert!(
failures.is_empty(),
"the public registries did not answer for every declared target:\n {}",
failures.join("\n ")
);
}