diff --git a/crates/core/src/class.rs b/crates/core/src/class.rs index 7a486ba..c26de32 100644 --- a/crates/core/src/class.rs +++ b/crates/core/src/class.rs @@ -8,3 +8,28 @@ pub struct Class { pub path: PathBuf, pub checksum: String, } + +impl Class { + pub fn is_updated(&self) -> crate::Result { + // If the path is local and that file has not been updated. + Ok(self.checksum == sha256::try_digest(self.path.clone())?) + } + + pub fn update(&mut self) -> crate::Result<()> { + self.checksum = sha256::try_digest(self.path.clone())?; + Ok(()) + } +} + +// TODO: Make it clearer that this is for general files, +// not nests. +impl TryFrom for Class { + type Error = crate::Error; + + fn try_from(value: PathBuf) -> Result { + Ok(Self { + path: value.clone(), + checksum: sha256::try_digest(value)?, + }) + } +} diff --git a/crates/core/src/dependency.rs b/crates/core/src/dependency.rs index 190972a..a18223b 100644 --- a/crates/core/src/dependency.rs +++ b/crates/core/src/dependency.rs @@ -7,7 +7,8 @@ use crate::package::PackageHandler; #[derive(Debug, Clone, Deserialize, Serialize, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Dependency { name: String, - version: Version, + #[serde(skip_serializing_if = ">::is_none")] + version: Option, pub checksum: String, #[serde(skip_serializing_if = ">::is_none")] source: Option, // Path / URL @@ -24,13 +25,19 @@ impl Dependency { // TODO: Convert from reverse domain name to path. return self.name.clone(); } + + pub fn is_updated(&self) -> crate::Result { + // If the path is local and that file has not been updated. + Ok(self.source.as_ref().is_some_and(|path| is_url(path)) + && self.checksum == sha256::try_digest(self.source.as_ref().unwrap())?) + } } impl From for Dependency { fn from(value: PackageHandler) -> Self { Dependency { name: value.name(), - version: value.version(), + version: Some(value.version()), checksum: String::new(), source: None, } diff --git a/crates/core/src/package.rs b/crates/core/src/package.rs index 97506ff..6debff9 100644 --- a/crates/core/src/package.rs +++ b/crates/core/src/package.rs @@ -1,8 +1,10 @@ use std::hash::Hash; use std::path::{Path, PathBuf}; +use fs::expand_files; use serde::{Deserialize, Serialize}; +use crate::class::Class; use crate::prey::{F_PREY_LOCK, F_PREY_TOML, Prey, PreyLock}; /// Hashing is only based off the Prey. @@ -15,6 +17,8 @@ pub struct PackageHandler { } impl PackageHandler { + const DIR_JAVA: &str = "java/"; + pub fn new>(package_root: P, target_dir: P) -> crate::Result { let package_root = package_root.as_ref().to_path_buf(); @@ -26,8 +30,6 @@ impl PackageHandler { }) } - pub fn update_class_cache(&self) {} - pub fn entry_point(&self) -> PathBuf { self.prey.entry_point() } @@ -39,6 +41,34 @@ impl PackageHandler { pub fn version(&self) -> semver::Version { self.prey.version() } + + pub fn get_update_targets(&mut self) -> crate::Result> { + let mut targets = vec![]; + + if self.prey_lock.is_none() { + // Try to pass a reference to the class so that there's mutability of the object + // available at the workspace level instead of parsing all the way down the + // tree. How I do this, idk. My brain is friend from a few days of JS. + + self.prey_lock = Some(PreyLock::from(expand_files(Self::DIR_JAVA)?)); + return Ok(self + .prey_lock + .clone() + .unwrap() + .classes + .iter() + .map(|mut *class| &mut class) + .collect()); + } + + for mut tracked in self.prey_lock.unwrap().classes { + if !tracked.is_updated()? { + targets.push(&mut tracked); + } + } + + Ok(targets) + } } impl Hash for PackageHandler { diff --git a/crates/core/src/prey.rs b/crates/core/src/prey.rs index c11b71d..afc83be 100644 --- a/crates/core/src/prey.rs +++ b/crates/core/src/prey.rs @@ -1,13 +1,14 @@ use std::collections::HashSet; use std::fs::{File, OpenOptions}; use std::io::Read; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use serde::{Deserialize, Serialize}; use crate::class::Class; use crate::meta::Meta; use crate::package::Package; +use crate::prelude::Dependency; pub const F_PREY_TOML: &str = "Prey.toml"; pub const F_PREY_LOCK: &str = "Prey.lock"; @@ -53,11 +54,19 @@ impl TryFrom for Prey { } /// Data struct -#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)] +#[derive(Debug, Clone, Default, Deserialize, Serialize, PartialEq, Eq)] pub struct PreyLock { - classes: HashSet, + pub classes: HashSet, } +impl PreyLock { + pub fn with_class(&mut self, class: Class) -> &mut Self { + self.classes.insert(class); + self + } +} + +/// Load the PreyLock from Prey.lock file. impl TryFrom for PreyLock { type Error = crate::Error; @@ -76,3 +85,21 @@ impl TryFrom for PreyLock { Ok(toml::from_str(buf.as_str())?) } } + +impl From> for PreyLock { + fn from(value: Vec) -> Self { + let mut lock = Self::default(); + lock.classes = value + .iter() + .filter_map(|f| { + let dep = Class::try_from(f.to_owned()); + if dep.is_ok() { + Some(dep.unwrap()) + } else { + None + } + }) + .collect(); + lock + } +} diff --git a/crates/core/src/workspace.rs b/crates/core/src/workspace.rs index 7923841..6d34dd3 100644 --- a/crates/core/src/workspace.rs +++ b/crates/core/src/workspace.rs @@ -139,6 +139,24 @@ impl WorkspaceHandler { // This is the naive build pub fn build(&mut self) -> crate::Result<()> { + let mut targets = vec![]; + + for (_name, mut handler) in self.packages.clone() { + targets.append(&mut handler.get_update_targets()?); + } + + let compiler = java::compiler::CompilerBuilder::new() + .class_path(Self::DIR_TARGET) + .class_path(Self::DIR_TARGET) + .build(); + + for target in targets { + // Possibly come up with a source file handler for this? + if let Ok(_) = compiler.clone().compile(target) { + // No, this does not run O(1) + } + } + Ok(()) }