115 lines
3.1 KiB
Rust
115 lines
3.1 KiB
Rust
use std::hash::{self, Hash};
|
|
use std::path::{Path, PathBuf};
|
|
use std::sync::{Arc, Mutex};
|
|
|
|
use crate::{Error, Result};
|
|
|
|
use java::{JAVA_EXT_CLASS, JAVA_EXT_SOURCE};
|
|
use path::PathHandler;
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
pub struct Class {
|
|
#[serde(skip_deserializing, skip_serializing)]
|
|
ph: Option<Arc<Mutex<PathHandler>>>,
|
|
path: PathBuf,
|
|
checksum: String,
|
|
}
|
|
|
|
impl Class {
|
|
pub fn new<P: AsRef<Path>>(ph: Arc<Mutex<PathHandler>>, path: P, checksum: String) -> Self {
|
|
Self {
|
|
ph: Some(ph),
|
|
path: path.as_ref().to_path_buf(),
|
|
checksum,
|
|
}
|
|
}
|
|
|
|
pub fn from_file<P: AsRef<Path>>(ph: Arc<Mutex<PathHandler>>, path: P) -> Result<Self> {
|
|
let mut path = path.as_ref().to_path_buf();
|
|
if path.is_relative() {
|
|
path = path.canonicalize()?;
|
|
}
|
|
|
|
let dir_src = ph.try_lock()?.dir_src();
|
|
|
|
Ok(Self {
|
|
ph: Some(ph),
|
|
path: PathBuf::from(
|
|
pathsub::sub_paths(path.as_path(), dir_src.as_path()).ok_or(Error::PathSub)?,
|
|
)
|
|
.with_extension(""),
|
|
checksum: sha256::try_digest(&path)?,
|
|
})
|
|
}
|
|
|
|
pub fn path(&self) -> PathBuf {
|
|
self.path.clone()
|
|
}
|
|
|
|
pub fn checksum(&self) -> String {
|
|
self.checksum.clone()
|
|
}
|
|
|
|
/// Returns the path such that src/ and target/ don't matter.
|
|
/// E.g., `main/Main.java` as_subpath is `Main.java`
|
|
/// allowing it to match with `target/main/Main.class`
|
|
/// because Java diregards the top level subdir in `src/`
|
|
fn subpath(&self) -> PathBuf {
|
|
let mut p = self.path.components();
|
|
p.next(); // Remove the top level dir.
|
|
p.as_path().to_path_buf()
|
|
}
|
|
|
|
/// Returns true if the class needs updating.
|
|
/// This may also cautionarily return true if it cannot digest the file.
|
|
pub fn is_updated(&mut self) -> Result<bool> {
|
|
// Still doesn't handle inter-dependency checks.
|
|
// Hopefully then I'll clean this horror up.
|
|
let mut ph = self
|
|
.ph
|
|
.as_ref()
|
|
.ok_or(Error::MissingPathHandler)?
|
|
.try_lock()?;
|
|
|
|
Ok(ph
|
|
.dir_target()
|
|
.join(self.subpath())
|
|
.with_extension(JAVA_EXT_CLASS)
|
|
.exists()
|
|
&& sha256::try_digest(
|
|
ph.dir_src()
|
|
.join(self.path())
|
|
.with_extension(JAVA_EXT_SOURCE),
|
|
)
|
|
.is_ok_and(|hash| self.checksum == hash))
|
|
}
|
|
|
|
pub fn set_path_handler(&mut self, ph: Arc<Mutex<PathHandler>>) {
|
|
self.ph = Some(ph);
|
|
}
|
|
|
|
pub fn with_path_handler(&mut self, ph: Arc<Mutex<PathHandler>>) -> &mut Self {
|
|
self.ph = Some(ph);
|
|
self
|
|
}
|
|
}
|
|
|
|
impl Hash for Class {
|
|
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
|
self.path.hash(state);
|
|
}
|
|
}
|
|
|
|
impl PartialEq for Class {
|
|
fn eq(&self, other: &Self) -> bool {
|
|
self.path == other.path
|
|
}
|
|
|
|
fn ne(&self, other: &Self) -> bool {
|
|
self.path != other.path
|
|
}
|
|
}
|
|
|
|
impl Eq for Class {}
|