diff options
Diffstat (limited to 'src/project')
-rw-r--r-- | src/project/git.rs | 105 | ||||
-rw-r--r-- | src/project/path.rs | 57 |
2 files changed, 32 insertions, 130 deletions
diff --git a/src/project/git.rs b/src/project/git.rs index 4584a7a..e2067ec 100644 --- a/src/project/git.rs +++ b/src/project/git.rs @@ -1,102 +1,39 @@ use git2::{BranchType, Repository}; -use ignore::DirEntry; use std::{path::PathBuf, time::Duration}; -use tracing::{debug, warn}; -use crate::{Error, Result}; - -use super::{ProjectParser, Timestamp}; +use super::{Project, ProjectParser}; #[derive(Debug, Clone)] pub struct GitMatcher; impl ProjectParser for GitMatcher { #[tracing::instrument] - fn parse(&self, path_buf: PathBuf) -> Option<super::ProjectItem> { - match GitProject::new(path_buf) { - Ok(g) => Some(Box::new(g)), - Err(err) => { - debug!(%err, "Failed to create git project"); - None - } - } + fn parse(&self, path_buf: PathBuf) -> Result<Project, Box<dyn std::error::Error>> { + Repository::open(&path_buf)?.parse(path_buf) } } -#[derive(Debug, Clone)] -pub struct GitProject { - path_buf: PathBuf, - latest_commit: Duration, -} +impl ProjectParser for Repository { + fn parse(&self, path_buf: PathBuf) -> Result<Project, Box<dyn std::error::Error>> { + let mut branches = self.branches(Some(BranchType::Local))?; + let timestamp = branches + .try_fold(0, |latest, branch| -> std::result::Result<u64, _> { + let (branch, _) = branch?; -impl GitProject { - fn new(path_buf: PathBuf) -> Result<Self> { - let repo = Repository::open(&path_buf)?; - let latest_commit = Self::get_timestamp(&repo); - Ok(Self { - path_buf, - latest_commit, - }) - } - - fn get_timestamp(repo: &Repository) -> Duration { - match Self::latest_commit(repo) { - Ok(s) => Duration::from_secs(s), - Err(err) => { - warn!(%err, "Failed to get latest commit from repository"); - Duration::default() - } - } - } + let name = branch + .name()? + .ok_or_else(|| git2::Error::from_str("Failed to find branch"))?; - fn latest_commit(repository: &Repository) -> Result<u64> { - let mut branches = repository.branches(Some(BranchType::Local))?; - branches.try_fold(0, |latest, branch| { - let (branch, _) = branch?; + self.revparse_single(name)? + .peel_to_commit() + .map(|c| (c.time().seconds() as u64).max(latest)) + }) + .map(Duration::from_secs) + .unwrap_or_default(); - let name = branch - .name()? - .ok_or_else(|| git2::Error::from_str("Failed to find branch"))?; - - repository - .revparse_single(name)? - .peel_to_commit() - .map(|c| (c.time().seconds() as u64).max(latest)) - .map_err(Into::into) + Ok(Project { + worktree: path_buf, + timestamp, }) } } - -impl Timestamp for GitProject { - fn timestamp(&self) -> &Duration { - &self.latest_commit - } -} - -impl AsRef<PathBuf> for GitProject { - fn as_ref(&self) -> &PathBuf { - &self.path_buf - } -} - -impl TryFrom<PathBuf> for GitProject { - type Error = Error; - - fn try_from(value: PathBuf) -> Result<Self> { - Self::new(value) - } -} - -impl TryFrom<DirEntry> for GitProject { - type Error = Error; - - fn try_from(value: DirEntry) -> Result<Self> { - Self::new(value.into_path()) - } -} - -impl From<GitProject> for PathBuf { - fn from(value: GitProject) -> Self { - value.path_buf - } -} diff --git a/src/project/path.rs b/src/project/path.rs index 5954ff9..0e38990 100644 --- a/src/project/path.rs +++ b/src/project/path.rs @@ -1,57 +1,22 @@ -use std::path::{Path, PathBuf}; -use std::time::{Duration, SystemTime}; -use tracing::debug; +use std::{io::ErrorKind, path::PathBuf}; -use super::{ProjectItem, ProjectParser}; +use super::{Project, ProjectParser}; #[derive(Debug, Clone)] pub enum PathMatcher { - All(PathBuf), + All, Pattern(String), } impl ProjectParser for PathMatcher { #[tracing::instrument] - fn parse(&self, path_buf: PathBuf) -> Option<ProjectItem> { - match self { - PathMatcher::All(p) if &path_buf != p => Some(Box::new(PathProject::new(path_buf))), - PathMatcher::Pattern(p) if path_buf.join(p).exists() => { - Some(Box::new(PathProject::new(path_buf))) - } - _ => { - debug!("Failed to match pattern in directory"); - None - } - } - } -} - -#[derive(Debug, PartialEq, Eq, Clone, Default)] -pub struct PathProject(PathBuf, Duration); - -impl PathProject { - pub fn new(path_buf: PathBuf) -> Self { - let modified = Self::get_modified(&path_buf).unwrap_or_default(); - Self(path_buf, modified) - } - - fn get_modified(path_buf: &Path) -> Result<Duration, std::io::Error> { - path_buf - .metadata()? - .modified()? - .duration_since(SystemTime::UNIX_EPOCH) - .map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err.to_string())) - } -} - -impl AsRef<PathBuf> for PathProject { - fn as_ref(&self) -> &PathBuf { - &self.0 - } -} - -impl AsRef<Duration> for PathProject { - fn as_ref(&self) -> &Duration { - &self.1 + fn parse(&self, path_buf: PathBuf) -> Result<Project, Box<dyn std::error::Error>> { + let project = match self { + PathMatcher::All => path_buf.try_into()?, + PathMatcher::Pattern(p) if path_buf.join(p).exists() => path_buf.try_into()?, + _ => return Err(Box::new(std::io::Error::from(ErrorKind::NotFound))), + }; + + Ok(project) } } |