use std::path::Path;
use microvms_app::control::artifact::ProjectFiles;
use microvms_app::control::project::project_ecosystem;
use microvms_app::error::{Error, ErrorKind};
pub fn read_project_files(dir: impl AsRef<Path>) -> Result<ProjectFiles, Error> {
let dir = dir.as_ref();
let ecosystem = project_ecosystem(&dir.display().to_string(), |name| dir.join(name).is_file())?;
let read = |name: &str| {
let path = dir.join(name);
std::fs::read(&path).map_err(|error| {
Error::new(
ErrorKind::Precondition,
format!("could not read {}: {error}", path.display()),
)
.with_source(error)
})
};
Ok(ProjectFiles {
ecosystem,
manifest: read(ecosystem.manifest_name())?,
lockfile: read(ecosystem.lockfile_name())?,
})
}
#[cfg(test)]
mod tests {
use microvms_app::control::artifact::Ecosystem;
use super::*;
#[test]
fn a_project_dir_with_one_pair_reads_both_files() {
let dir = tempfile::tempdir().expect("a temp dir");
std::fs::write(dir.path().join("pyproject.toml"), b"[project]").expect("writes");
std::fs::write(dir.path().join("uv.lock"), b"version = 1").expect("writes");
std::fs::write(dir.path().join(".env"), b"SECRET=1").expect("writes");
let files = read_project_files(dir.path()).expect("one pair, one ecosystem");
assert_eq!(files.ecosystem, Ecosystem::Uv);
assert_eq!(files.manifest, b"[project]");
assert_eq!(files.lockfile, b"version = 1");
}
#[test]
fn a_project_dir_without_a_pair_is_refused_naming_it() {
let dir = tempfile::tempdir().expect("a temp dir");
std::fs::write(dir.path().join("pyproject.toml"), b"[project]").expect("writes");
let error = read_project_files(dir.path()).expect_err("no lockfile to key on");
assert_eq!(error.kind(), ErrorKind::Precondition);
let message = error.to_string();
assert!(message.contains("uv lock"), "{message}");
assert!(
message.contains(&dir.path().display().to_string()),
"{message}"
);
}
}