use std::path::{Path, PathBuf};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ReferenceTree {
Base,
Modules,
Pvxs,
}
impl ReferenceTree {
pub fn env_var(self) -> &'static str {
match self {
ReferenceTree::Base => "EPICS_BASE",
ReferenceTree::Modules => "EPICS_MODULES",
ReferenceTree::Pvxs => "PVXS_HOME",
}
}
fn candidates(self) -> &'static [&'static str] {
match self {
ReferenceTree::Base => &["epics-base", "work/epics-base"],
ReferenceTree::Modules => &["epics-modules", "work/epics-modules"],
ReferenceTree::Pvxs => &[
"epics-modules/pvxs",
"work/epics-modules/pvxs",
"pvxs",
"work/pvxs",
],
}
}
fn sentinel(self) -> &'static str {
match self {
ReferenceTree::Base => "modules/database/src/ioc/db/dbAccess.c",
ReferenceTree::Modules => "std/stdApp/src/epidRecord.c",
ReferenceTree::Pvxs => "src/clientreq.cpp",
}
}
}
pub fn reference_root(tree: ReferenceTree) -> PathBuf {
if let Some(root) = try_reference_root(tree) {
return root;
}
panic!(
"{:?} reference tree not found. This test compares the port against \
the upstream sources and cannot run without them — it fails rather \
than skipping, because a skip reports as a pass and verifies \
nothing.\n Set {} to the checkout, or place it next to this \
repository as one of: {}.\n Searched upward from {}.",
tree,
tree.env_var(),
tree.candidates().join(", "),
env!("CARGO_MANIFEST_DIR"),
);
}
pub fn try_reference_root(tree: ReferenceTree) -> Option<PathBuf> {
if let Ok(explicit) = std::env::var(tree.env_var()) {
let root = PathBuf::from(explicit);
if root.join(tree.sentinel()).is_file() {
return Some(root);
}
panic!(
"{} is set to {:?}, but that is not a {:?} checkout — {} is \
missing. Point it at the real tree or unset it.",
tree.env_var(),
root,
tree,
tree.sentinel(),
);
}
for ancestor in Path::new(env!("CARGO_MANIFEST_DIR")).ancestors() {
for candidate in tree.candidates() {
let root = ancestor.join(candidate);
if root.join(tree.sentinel()).is_file() {
return Some(root);
}
}
}
None
}
pub fn reference_path(tree: ReferenceTree, relative: &str) -> PathBuf {
let path = reference_root(tree).join(relative);
assert!(
path.exists(),
"{relative} is missing from the {tree:?} checkout at {:?}. Upstream \
may have moved it; this test cannot verify anything without it.",
reference_root(tree),
);
path
}