use std::fs;
use std::io;
use std::path::{Path, PathBuf};
pub fn should_embed(var: Option<&str>, profile: &str) -> Result<bool, String> {
match var {
None => Ok(profile == "release"),
Some("1") => Ok(true),
Some("0") => Ok(false),
Some(other) => Err(format!("NOVA_EMBED_RUNTIME must be 1 or 0, not {other:?}")),
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Route {
InPlace,
Copy,
}
pub fn route(runtime_dir: &Path) -> io::Result<Route> {
let manifest = fs::read_to_string(runtime_dir.join("Cargo.toml"))?;
let inherits = manifest.lines().any(|line| {
let line = line.trim_start();
!line.starts_with('#') && line.replace(' ', "").contains("workspace=true")
});
Ok(if inherits {
Route::InPlace
} else {
Route::Copy
})
}
pub fn copy_package(from: &Path, to: &Path) -> io::Result<()> {
if to.exists() {
fs::remove_dir_all(to)?;
}
fs::create_dir_all(to)?;
for entry in fs::read_dir(from)? {
let entry = entry?;
let name = entry.file_name();
if name == "Cargo.lock" || name == "target" {
continue;
}
copy_tree(&entry.path(), &to.join(&name))?;
}
let manifest = to.join("Cargo.toml");
let mut text = fs::read_to_string(&manifest)?;
if !text.ends_with('\n') {
text.push('\n');
}
text.push_str("\n[workspace]\n");
fs::write(&manifest, text)
}
fn copy_tree(from: &Path, to: &Path) -> io::Result<()> {
if fs::metadata(from)?.is_dir() {
fs::create_dir_all(to)?;
for entry in fs::read_dir(from)? {
let entry = entry?;
copy_tree(&entry.path(), &to.join(entry.file_name()))?;
}
Ok(())
} else {
fs::copy(from, to).map(|_| ())
}
}
pub fn dep_info_sources(dep_info: &str) -> Vec<PathBuf> {
let Some(rule) = dep_info.lines().find(|line| !line.trim().is_empty()) else {
return Vec::new();
};
let Some((_, sources)) = rule.split_once(": ") else {
return Vec::new();
};
sources
.replace("\\ ", "\u{0}")
.split_whitespace()
.map(|source| PathBuf::from(source.replace('\u{0}', " ")))
.filter(|source| source.is_absolute())
.collect()
}
pub fn workspace_lockfile(runtime_dir: &Path) -> Option<PathBuf> {
runtime_dir
.ancestors()
.map(|dir| dir.join("Cargo.lock"))
.find(|lock| lock.is_file())
}
pub fn staticlib_name(target_env: &str) -> &'static str {
if target_env == "msvc" {
"nova_runtime.lib"
} else {
"libnova_runtime.a"
}
}