summaryrefslogtreecommitdiffstats
path: root/src/project.rs
diff options
context:
space:
mode:
authorToby Vincent <tobyv13@gmail.com>2023-04-28 17:32:24 -0500
committerToby Vincent <tobyv13@gmail.com>2023-04-28 17:32:24 -0500
commit589cd987217755e1da7acbc304c373a75a9f7db5 (patch)
tree2730a697e4f7b2f779fcd96b0452719cc67f36e3 /src/project.rs
parenta98b50667bc6a11e4b8be464969adc14601e9e78 (diff)
refactor: simplify logic and clean up dep.
Diffstat (limited to 'src/project.rs')
-rw-r--r--src/project.rs82
1 files changed, 57 insertions, 25 deletions
diff --git a/src/project.rs b/src/project.rs
index 26f0a8b..2b3e028 100644
--- a/src/project.rs
+++ b/src/project.rs
@@ -1,47 +1,79 @@
-use std::{path::PathBuf, time::Duration};
+use std::{
+ ops::{Deref, DerefMut},
+ path::PathBuf,
+ time::{Duration, SystemTime},
+};
+
+use tracing::warn;
pub mod path;
#[cfg(feature = "git")]
pub mod git;
-pub type ProjectParserGroup = Vec<Box<dyn ProjectParser>>;
-
pub trait ProjectParser {
- fn parse(&self, path_buf: PathBuf) -> Option<ProjectItem>;
+ fn parse(&self, path_buf: PathBuf) -> Result<Project, Box<dyn std::error::Error>>;
}
-impl ProjectParser for ProjectParserGroup {
- fn parse(&self, path_buf: std::path::PathBuf) -> Option<ProjectItem> {
- self.iter().find_map(|p| p.parse(path_buf.to_owned()))
+#[derive(Default)]
+pub struct ProjectParserGroup {
+ pub parsers: Vec<Box<dyn ProjectParser>>,
+}
+
+impl ProjectParserGroup {
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ pub fn parse(&self, path_buf: std::path::PathBuf) -> Option<Project> {
+ if self.parsers.is_empty() {
+ return path_buf.try_into().ok();
+ }
+
+ self.iter()
+ .map(|p| p.parse(path_buf.to_owned()))
+ .inspect(|res| {
+ if let Err(err) = res {
+ warn!(%err, "Parser failed to match");
+ }
+ })
+ .flatten()
+ .reduce(|max, p| p.max(max))
}
}
-pub type ProjectItem = Box<dyn Project>;
+impl Deref for ProjectParserGroup {
+ type Target = Vec<Box<dyn ProjectParser>>;
-pub trait Project: Timestamp {
- fn to_path_buf(&self) -> &PathBuf;
+ fn deref(&self) -> &Self::Target {
+ &self.parsers
+ }
}
-impl<T> Project for T
-where
- T: Timestamp,
- T: AsRef<PathBuf>,
-{
- fn to_path_buf(&self) -> &PathBuf {
- self.as_ref()
+impl DerefMut for ProjectParserGroup {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.parsers
}
}
-pub trait Timestamp {
- fn timestamp(&self) -> &Duration;
+#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
+pub struct Project {
+ pub timestamp: Duration,
+ pub worktree: PathBuf,
}
-impl<T> Timestamp for T
-where
- T: AsRef<Duration>,
-{
- fn timestamp(&self) -> &Duration {
- self.as_ref()
+impl TryFrom<PathBuf> for Project {
+ type Error = std::io::Error;
+
+ fn try_from(value: PathBuf) -> Result<Self, Self::Error> {
+ let timestamp = value
+ .metadata()?
+ .modified()?
+ .duration_since(SystemTime::UNIX_EPOCH)
+ .map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err.to_string()))?;
+ Ok(Self {
+ worktree: value,
+ timestamp,
+ })
}
}