use std::collections::HashSet; use std::fs::{File, OpenOptions}; use std::io::Read; use std::path::PathBuf; use std::sync::{Arc, Mutex}; use crate::Error; use crate::dependency::Dependency; use crate::meta::Meta; use crate::package::Package; use crate::workspace::Workspace; use path::{PathHandled, PathHandler}; use pom::Pom; use serde::{Deserialize, Serialize}; #[derive(Debug, Default, Deserialize, Serialize)] pub struct Nest { pub workspace: Workspace, pub meta: Meta, #[serde(default, skip_serializing_if = "HashSet::is_empty")] pub dependencies: HashSet, #[serde(default, skip_serializing_if = "Pom::is_empty")] pub pom: Pom, } impl Nest { pub fn new(name: S) -> Self { Nest { meta: Meta::new(name), ..Default::default() } } } impl TryFrom for Nest { type Error = Error; fn try_from(value: File) -> Result { let mut value = value; let mut buf = String::new(); value.read_to_string(&mut buf)?; Ok(toml::from_str(buf.as_str())?) } } impl TryFrom for Nest { type Error = Error; fn try_from(value: PathBuf) -> Result { Nest::try_from(OpenOptions::new().read(true).open(value)?) } } // TODO: See if NestLock and PreyLock can be combined into one parent struct, // but with different generics, and merely call upon a is_updated method set // by the generics implementing a common IsUpdated trait. // // Not happening any time soon. An enum could get around the issue of being unable to // implement Deserialize on a generic. #[derive(Debug, Default, Deserialize, Serialize)] pub struct NestLock { #[serde(skip_serializing, skip_deserializing)] ph: Option>>, pub packages: HashSet, } impl NestLock { /// Update, retaining all packages that still exist. /// /// Presently only supports packages under src/ pub fn update(&mut self) -> crate::Result<()> { let dir_src = self .ph .as_ref() .ok_or(Error::MissingPathHandler)? .try_lock()? .dir_src(); self.packages = self .packages .clone() .into_iter() .filter_map(|package| { let path = dir_src.join(package.name()); if path.exists() && path.is_dir() { return Some(package); } None }) .collect(); Ok(()) } } impl TryFrom for NestLock { type Error = Error; fn try_from(value: File) -> Result { let mut value = value; let mut buf = String::new(); value.read_to_string(&mut buf)?; Ok(toml::from_str(buf.as_str())?) } } impl TryFrom for NestLock { type Error = Error; fn try_from(value: PathBuf) -> Result { NestLock::try_from(OpenOptions::new().read(true).open(&value)?) } } impl PathHandled for NestLock { fn set_path_handler(&mut self, ph: Arc>) { self.ph = Some(ph); } fn with_path_handler(&mut self, ph: Arc>) -> &mut Self { self.ph = Some(ph); self } }