diff options
Diffstat (limited to 'asyncgit/src/diff.rs')
-rw-r--r-- | asyncgit/src/diff.rs | 334 |
1 files changed, 167 insertions, 167 deletions
diff --git a/asyncgit/src/diff.rs b/asyncgit/src/diff.rs index 9214c50b..06c5e38f 100644 --- a/asyncgit/src/diff.rs +++ b/asyncgit/src/diff.rs @@ -1,195 +1,195 @@ use crate::{ - error::Result, - hash, - sync::{self, CommitId}, - AsyncGitNotification, FileDiff, CWD, + error::Result, + hash, + sync::{self, CommitId}, + AsyncGitNotification, FileDiff, CWD, }; use crossbeam_channel::Sender; use std::{ - hash::Hash, - sync::{ - atomic::{AtomicUsize, Ordering}, - Arc, Mutex, - }, + hash::Hash, + sync::{ + atomic::{AtomicUsize, Ordering}, + Arc, Mutex, + }, }; /// #[derive(Hash, Clone, PartialEq)] pub enum DiffType { - /// diff in a given commit - Commit(CommitId), - /// diff against staged file - Stage, - /// diff against file in workdir - WorkDir, + /// diff in a given commit + Commit(CommitId), + /// diff against staged file + Stage, + /// diff against file in workdir + WorkDir, } /// #[derive(Hash, Clone, PartialEq)] pub struct DiffParams { - /// path to the file to diff - pub path: String, - /// what kind of diff - pub diff_type: DiffType, + /// path to the file to diff + pub path: String, + /// what kind of diff + pub diff_type: DiffType, } struct Request<R, A>(R, Option<A>); #[derive(Default, Clone)] struct LastResult<P, R> { - params: P, - hash: u64, - result: R, + params: P, + hash: u64, + result: R, } /// pub struct AsyncDiff { - current: Arc<Mutex<Request<u64, FileDiff>>>, - last: Arc<Mutex<Option<LastResult<DiffParams, FileDiff>>>>, - sender: Sender<AsyncGitNotification>, - pending: Arc<AtomicUsize>, + current: Arc<Mutex<Request<u64, FileDiff>>>, + last: Arc<Mutex<Option<LastResult<DiffParams, FileDiff>>>>, + sender: Sender<AsyncGitNotification>, + pending: Arc<AtomicUsize>, } impl AsyncDiff { - /// - pub fn new(sender: &Sender<AsyncGitNotification>) -> Self { - Self { - current: Arc::new(Mutex::new(Request(0, None))), - last: Arc::new(Mutex::new(None)), - sender: sender.clone(), - pending: Arc::new(AtomicUsize::new(0)), - } - } - - /// - pub fn last(&mut self) -> Result<Option<(DiffParams, FileDiff)>> { - let last = self.last.lock()?; - - Ok(last.clone().map(|res| (res.params, res.result))) - } - - /// - pub fn refresh(&mut self) -> Result<()> { - if let Ok(Some(param)) = self.get_last_param() { - self.clear_current()?; - self.request(param)?; - } - Ok(()) - } - - /// - pub fn is_pending(&self) -> bool { - self.pending.load(Ordering::Relaxed) > 0 - } - - /// - pub fn request( - &mut self, - params: DiffParams, - ) -> Result<Option<FileDiff>> { - log::trace!("request"); - - let hash = hash(¶ms); - - { - let mut current = self.current.lock()?; - - if current.0 == hash { - return Ok(current.1.clone()); - } - - current.0 = hash; - current.1 = None; - } - - let arc_current = Arc::clone(&self.current); - let arc_last = Arc::clone(&self.last); - let sender = self.sender.clone(); - let arc_pending = Arc::clone(&self.pending); - - self.pending.fetch_add(1, Ordering::Relaxed); - - rayon_core::spawn(move || { - let notify = Self::get_diff_helper( - params, - &arc_last, - &arc_current, - hash, - ); - - let notify = match notify { - Err(err) => { - log::error!("get_diff_helper error: {}", err); - true - } - Ok(notify) => notify, - }; - - arc_pending.fetch_sub(1, Ordering::Relaxed); - - sender - .send(if notify { - AsyncGitNotification::Diff - } else { - AsyncGitNotification::FinishUnchanged - }) - .expect("error sending diff"); - }); - - Ok(None) - } - - fn get_diff_helper( - params: DiffParams, - arc_last: &Arc< - Mutex<Option<LastResult<DiffParams, FileDiff>>>, - >, - arc_current: &Arc<Mutex<Request<u64, FileDiff>>>, - hash: u64, - ) -> Result<bool> { - let res = match params.diff_type { - DiffType::Stage => { - sync::diff::get_diff(CWD, ¶ms.path, true)? - } - DiffType::WorkDir => { - sync::diff::get_diff(CWD, ¶ms.path, false)? - } - DiffType::Commit(id) => sync::diff::get_diff_commit( - CWD, - id, - params.path.clone(), - )?, - }; - - let mut notify = false; - { - let mut current = arc_current.lock()?; - if current.0 == hash { - current.1 = Some(res.clone()); - notify = true; - } - } - - { - let mut last = arc_last.lock()?; - *last = Some(LastResult { - result: res, - hash, - params, - }); - } - - Ok(notify) - } - - fn get_last_param(&self) -> Result<Option<DiffParams>> { - Ok(self.last.lock()?.clone().map(|e| e.params)) - } - - fn clear_current(&mut self) -> Result<()> { - let mut current = self.current.lock()?; - current.0 = 0; - current.1 = None; - Ok(()) - } + /// + pub fn new(sender: &Sender<AsyncGitNotification>) -> Self { + Self { + current: Arc::new(Mutex::new(Request(0, None))), + last: Arc::new(Mutex::new(None)), + sender: sender.clone(), + pending: Arc::new(AtomicUsize::new(0)), + } + } + + /// + pub fn last(&mut self) -> Result<Option<(DiffParams, FileDiff)>> { + let last = self.last.lock()?; + + Ok(last.clone().map(|res| (res.params, res.result))) + } + + /// + pub fn refresh(&mut self) -> Result<()> { + if let Ok(Some(param)) = self.get_last_param() { + self.clear_current()?; + self.request(param)?; + } + Ok(()) + } + + /// + pub fn is_pending(&self) -> bool { + self.pending.load(Ordering::Relaxed) > 0 + } + + /// + pub fn request( + &mut self, + params: DiffParams, + ) -> Result<Option<FileDiff>> { + log::trace!("request"); + + let hash = hash(¶ms); + + { + let mut current = self.current.lock()?; + + if current.0 == hash { + return Ok(current.1.clone()); + } + + current.0 = hash; + current.1 = None; + } + + let arc_current = Arc::clone(&self.current); + let arc_last = Arc::clone(&self.last); + let sender = self.sender.clone(); + let arc_pending = Arc::clone(&self.pending); + + self.pending.fetch_add(1, Ordering::Relaxed); + + rayon_core::spawn(move || { + let notify = Self::get_diff_helper( + params, + &arc_last, + &arc_current, + hash, + ); + + let notify = match notify { + Err(err) => { + log::error!("get_diff_helper error: {}", err); + true + } + Ok(notify) => notify, + }; + + arc_pending.fetch_sub(1, Ordering::Relaxed); + + sender + .send(if notify { + AsyncGitNotification::Diff + } else { + AsyncGitNotification::FinishUnchanged + }) + .expect("error sending diff"); + }); + + Ok(None) + } + + fn get_diff_helper( + params: DiffParams, + arc_last: &Arc< + Mutex<Option<LastResult<DiffParams, FileDiff>>>, + >, + arc_current: &Arc<Mutex<Request<u64, FileDiff>>>, + hash: u64, + ) -> Result<bool> { + let res = match params.diff_type { + DiffType::Stage => { + sync::diff::get_diff(CWD, ¶ms.path, true)? + } + DiffType::WorkDir => { + sync::diff::get_diff(CWD, ¶ms.path, false)? + } + DiffType::Commit(id) => sync::diff::get_diff_commit( + CWD, + id, + params.path.clone(), + )?, + }; + + let mut notify = false; + { + let mut current = arc_current.lock()?; + if current.0 == hash { + current.1 = Some(res.clone()); + notify = true; + } + } + + { + let mut last = arc_last.lock()?; + *last = Some(LastResult { + result: res, + hash, + params, + }); + } + + Ok(notify) + } + + fn get_last_param(&self) -> Result<Option<DiffParams>> { + Ok(self.last.lock()?.clone().map(|e| e.params)) + } + + fn clear_current(&mut self) -> Result<()> { + let mut current = self.current.lock()?; + current.0 = 0; + current.1 = None; + Ok(()) + } } |