use std::path::{Path, PathBuf};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct JobId(pub String);
impl JobId {
pub fn generate(archive_path: &Path, identity_hash: &str) -> Self {
let stem = archive_path
.file_stem()
.and_then(|s| s.to_str())
.unwrap_or("job")
.chars()
.filter(|c| c.is_alphanumeric() || *c == '-' || *c == '_')
.collect::<String>();
let short_id = if identity_hash.len() >= 8 {
&identity_hash[..8]
} else {
"00000000"
};
JobId(format!("{}_{}", stem, short_id))
}
pub fn as_str(&self) -> &str {
&self.0
}
}
pub fn global_jobs_dir() -> Option<PathBuf> {
std::env::var_os("HOME")
.map(PathBuf::from)
.map(|home| home.join(".unpackr").join("jobs"))
}
use crate::state::manifest::ExtractionManifest;
pub fn find_manifest_file(job_id_or_path: &str) -> Option<PathBuf> {
let direct_path = PathBuf::from(job_id_or_path);
if direct_path.is_file() {
return Some(direct_path);
}
if direct_path.is_dir() {
let m1 = direct_path.join(".unpackr").join("manifest.json");
if m1.is_file() {
return Some(m1);
}
let m2 = direct_path.join("manifest.json");
if m2.is_file() {
return Some(m2);
}
}
if let Some(global_dir) = global_jobs_dir() {
let is_safe_slug = !job_id_or_path.is_empty()
&& job_id_or_path
.chars()
.all(|c| c.is_alphanumeric() || c == '-' || c == '_');
if is_safe_slug {
let global_manifest = global_dir.join(job_id_or_path).join("manifest.json");
if global_manifest.is_file() {
if let Ok(manifest) = ExtractionManifest::load(&global_manifest) {
let dest_manifest = manifest.destination.join(".unpackr").join("manifest.json");
if dest_manifest.is_file() {
return Some(dest_manifest);
}
}
return Some(global_manifest);
}
}
}
None
}
pub fn find_manifest_for_job(target: &str, destination: Option<&Path>) -> Option<PathBuf> {
if let Some(dest) = destination {
let m1 = dest.join(".unpackr").join("manifest.json");
if m1.is_file() {
return Some(m1);
}
let m2 = dest.join("manifest.json");
if m2.is_file() {
return Some(m2);
}
}
if let Some(path) = find_manifest_file(target) {
return Some(path);
}
None
}