mod config;
mod detector;
mod ecosystem;
mod image;
mod process;
mod project;
mod types;
pub use config::detect_from_config;
pub use detector::StackDetector;
pub use image::detect_from_image;
pub use process::{detect_from_process, detect_from_process_names};
pub use project::{
MAX_WALK_DEPTH, find_project_root, home_dir, project_name, resolve_project_root,
};
pub use types::{ProjectInput, StackInput, StackKind, StackLabel};
#[doc = include_str!("../README.md")]
#[cfg(doctest)]
pub struct ReadmeDoctests;
#[cfg(test)]
mod tests {
use std::collections::HashMap;
use super::*;
fn all_builtin_labels() -> Vec<&'static StackLabel> {
static STANDALONE: [StackLabel; 1] = [image::DOTNET_NAMESPACE_LABEL];
process::PROCESS_MAP
.iter()
.map(|(_, label, _)| label)
.chain(image::EXACT_IMAGE_RULES.iter().map(|(_, label)| label))
.chain(image::PREFIX_IMAGE_RULES.iter().map(|(_, label)| label))
.chain(STANDALONE.iter())
.chain(config::all_labels())
.collect()
}
#[test]
fn every_label_text_has_exactly_one_kind_across_all_rules() {
let mut kinds: HashMap<&str, StackKind> = HashMap::new();
for label in all_builtin_labels() {
let previous = kinds.insert(label.as_str(), label.kind());
assert!(
previous.is_none_or(|kind| kind == label.kind()),
"label {label} has conflicting kinds {previous:?} and {:?}",
label.kind()
);
}
assert!(kinds.len() > 40, "expected the full rule set to be scanned");
}
#[test]
fn stack_label_text_traits_ignore_kind_but_equality_does_not() {
let runtime = StackLabel::from_static("Vite", StackKind::Runtime);
let tool = StackLabel::new(String::from("Vite"), StackKind::Tool);
assert_eq!(runtime, "Vite");
assert_eq!("Vite", tool);
assert_eq!(runtime.as_str(), tool.as_ref());
assert_eq!(runtime.to_string(), "Vite");
assert_ne!(runtime, tool);
assert_eq!(String::from(tool.clone()), "Vite");
assert_eq!(tool.into_cow(), "Vite");
}
#[test]
fn builtin_labels_borrow_static_text() {
for label in all_builtin_labels() {
assert!(
matches!(label.clone().into_cow(), std::borrow::Cow::Borrowed(_)),
"label {label} should not allocate"
);
}
}
}