use std::env;
use std::fmt;
use std::fs;
use std::path;
use std::process;
use std::sync;
static mut VERSIONS: Option<Vec<(semver::Version, Format, path::PathBuf)>> = None;
static INIT: sync::Once = sync::Once::new();
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Format {
Html,
}
impl Format {
pub fn all() -> &'static [Format] {
FORMATS
}
}
static FORMATS: &[Format] = &[Format::Html];
impl fmt::Display for Format {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
Format::Html => "html",
})
}
}
fn get_versions() -> &'static [(semver::Version, Format, path::PathBuf)] {
INIT.call_once(|| {
let mut versions = Vec::new();
for format in Format::all() {
versions.append(&mut find_rust_versions(*format));
if env::var("RUSTY_MAN_GENERATE").is_ok() {
if let Some(docs) = generate_docs(*format) {
versions.push(docs);
}
}
}
unsafe {
VERSIONS = Some(versions);
}
});
unsafe { VERSIONS.as_ref().unwrap() }
}
fn find_rust_versions(format: Format) -> Vec<(semver::Version, Format, path::PathBuf)> {
let mut path = path::PathBuf::from("tests");
path.push(format.to_string());
if !path.is_dir() {
return Vec::new();
}
fs::read_dir(&path)
.unwrap()
.map(Result::unwrap)
.filter(|e| e.file_type().unwrap().is_dir())
.map(|e| {
(
semver::Version::parse(&e.file_name().into_string().unwrap()).unwrap(),
format,
e.path(),
)
})
.collect()
}
fn generate_docs(format: Format) -> Option<(semver::Version, Format, path::PathBuf)> {
if format != Format::Html {
return None;
}
let version = rustc_version::version().unwrap();
let mut path = tempfile::tempdir().unwrap().into_path();
process::Command::new(env::var_os("CARGO").unwrap())
.arg("doc")
.args(&["--package", "anyhow"])
.args(&["--package", "kuchiki"])
.args(&["--package", "log"])
.args(&["--package", "rand_core"])
.arg("--target-dir")
.arg(&path)
.arg("--no-deps")
.output()
.unwrap();
path.push("doc");
Some((version, format, path))
}
pub fn with_rustdoc<F>(version: &str, formats: &[Format], f: F)
where
F: Fn(&semver::Version, Format, &path::Path),
{
let version_req = semver::VersionReq::parse(version).unwrap();
let versions = get_versions();
for (version, format, path) in versions {
if version_req.matches(&version) && formats.contains(format) {
log::warn!(
"Executing test case for version {} at {} (format {})",
version,
path.display(),
format
);
f(version, *format, &path);
}
}
}