summaryrefslogtreecommitdiffstats
path: root/asyncgit/src/diff.rs
diff options
context:
space:
mode:
Diffstat (limited to 'asyncgit/src/diff.rs')
-rw-r--r--asyncgit/src/diff.rs334
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(&params);
-
- {
- 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, &params.path, true)?
- }
- DiffType::WorkDir => {
- sync::diff::get_diff(CWD, &params.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(&params);
+
+ {
+ 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, &params.path, true)?
+ }
+ DiffType::WorkDir => {
+ sync::diff::get_diff(CWD, &params.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(())
+ }
}