cleanup having two AsyncStatus

This commit is contained in:
Stephan Dilly 2020-05-22 14:58:59 +02:00
parent e271defc63
commit 572be62b5f
5 changed files with 82 additions and 199 deletions

View file

@ -8,14 +8,12 @@ mod diff;
mod error;
mod revlog;
mod status;
mod status2;
pub mod sync;
pub use crate::{
diff::{AsyncDiff, DiffParams},
revlog::AsyncLog,
status::AsyncStatus,
status2::{AsyncStatus2, StatusParams},
status::{AsyncStatus, StatusParams},
sync::{
diff::{DiffLine, DiffLineType, FileDiff},
status::{StatusItem, StatusItemType},
@ -25,7 +23,6 @@ pub use crate::{
use std::{
collections::hash_map::DefaultHasher,
hash::{Hash, Hasher},
time::{SystemTime, UNIX_EPOCH},
};
/// this type is used to communicate events back through the channel
@ -48,11 +45,3 @@ pub fn hash<T: Hash + ?Sized>(v: &T) -> u64 {
v.hash(&mut hasher);
hasher.finish()
}
/// helper function to return the current tick since unix epoch
pub fn current_tick() -> u64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_millis() as u64
}

View file

@ -1,6 +1,5 @@
use crate::{
error::Result, hash, sync, sync::status::StatusType,
AsyncNotification, StatusItem, CWD,
error::Result, hash, sync, AsyncNotification, StatusItem, CWD,
};
use crossbeam_channel::Sender;
use log::trace;
@ -10,12 +9,42 @@ use std::{
atomic::{AtomicUsize, Ordering},
Arc, Mutex,
},
time::{SystemTime, UNIX_EPOCH},
};
use sync::status::StatusType;
fn current_tick() -> u64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_millis() as u64
}
#[derive(Default, Hash, Clone)]
pub struct Status {
pub work_dir: Vec<StatusItem>,
pub stage: Vec<StatusItem>,
pub items: Vec<StatusItem>,
}
///
#[derive(Default, Hash, Clone, PartialEq)]
pub struct StatusParams {
tick: u64,
status_type: StatusType,
include_untracked: bool,
}
impl StatusParams {
///
pub fn new(
status_type: StatusType,
include_untracked: bool,
) -> Self {
Self {
tick: current_tick(),
status_type,
include_untracked,
}
}
}
struct Request<R, A>(R, Option<A>);
@ -51,10 +80,13 @@ impl AsyncStatus {
}
///
pub fn fetch(&mut self, request: u64) -> Result<Option<Status>> {
let hash_request = hash(&request);
pub fn fetch(
&mut self,
params: StatusParams,
) -> Result<Option<Status>> {
let hash_request = hash(&params);
trace!("request: {} [hash: {}]", request, hash_request);
trace!("request: [hash: {}]", hash_request);
{
let mut current = self.current.lock()?;
@ -71,10 +103,14 @@ impl AsyncStatus {
let arc_last = Arc::clone(&self.last);
let sender = self.sender.clone();
let arc_pending = Arc::clone(&self.pending);
let status_type = params.status_type;
let include_untracked = params.include_untracked;
rayon_core::spawn(move || {
arc_pending.fetch_add(1, Ordering::Relaxed);
AsyncStatus::fetch_helper(
Self::fetch_helper(
status_type,
include_untracked,
hash_request,
arc_current,
arc_last,
@ -92,11 +128,13 @@ impl AsyncStatus {
}
fn fetch_helper(
status_type: StatusType,
include_untracked: bool,
hash_request: u64,
arc_current: Arc<Mutex<Request<u64, Status>>>,
arc_last: Arc<Mutex<Status>>,
) -> Result<()> {
let res = Self::get_status()?;
let res = Self::get_status(status_type, include_untracked)?;
trace!("status fetched: {}", hash(&res));
{
@ -114,11 +152,16 @@ impl AsyncStatus {
Ok(())
}
fn get_status() -> Result<Status> {
let work_dir =
sync::status::get_status(CWD, StatusType::WorkingDir)?;
let stage = sync::status::get_status(CWD, StatusType::Stage)?;
Ok(Status { stage, work_dir })
fn get_status(
status_type: StatusType,
include_untracked: bool,
) -> Result<Status> {
Ok(Status {
items: sync::status::get_status_new(
CWD,
status_type,
include_untracked,
)?,
})
}
}

View file

@ -1,160 +0,0 @@
use crate::{
current_tick, error::Result, hash, sync, AsyncNotification,
StatusItem, CWD,
};
use crossbeam_channel::Sender;
use log::trace;
use std::{
hash::Hash,
sync::{
atomic::{AtomicUsize, Ordering},
Arc, Mutex,
},
};
use sync::status::StatusType;
#[derive(Default, Hash, Clone)]
pub struct Status2 {
pub items: Vec<StatusItem>,
}
///
#[derive(Default, Hash, Clone, PartialEq)]
pub struct StatusParams {
tick: u64,
status_type: StatusType,
include_untracked: bool,
}
impl StatusParams {
///
pub fn new(
status_type: StatusType,
include_untracked: bool,
) -> Self {
Self {
tick: current_tick(),
status_type,
include_untracked,
}
}
}
struct Request<R, A>(R, Option<A>);
///TODO: merge functionality with AsyncStatus
pub struct AsyncStatus2 {
current: Arc<Mutex<Request<u64, Status2>>>,
last: Arc<Mutex<Status2>>,
sender: Sender<AsyncNotification>,
pending: Arc<AtomicUsize>,
}
impl AsyncStatus2 {
///
pub fn new(sender: Sender<AsyncNotification>) -> Self {
Self {
current: Arc::new(Mutex::new(Request(0, None))),
last: Arc::new(Mutex::new(Status2::default())),
sender,
pending: Arc::new(AtomicUsize::new(0)),
}
}
///
pub fn last(&mut self) -> Result<Status2> {
let last = self.last.lock()?;
Ok(last.clone())
}
///
pub fn is_pending(&self) -> bool {
self.pending.load(Ordering::Relaxed) > 0
}
///
pub fn fetch(
&mut self,
params: StatusParams,
) -> Result<Option<Status2>> {
let hash_request = hash(&params);
trace!("request: [hash: {}]", hash_request);
{
let mut current = self.current.lock()?;
if current.0 == hash_request {
return Ok(current.1.clone());
}
current.0 = hash_request;
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);
let status_type = params.status_type;
let include_untracked = params.include_untracked;
rayon_core::spawn(move || {
arc_pending.fetch_add(1, Ordering::Relaxed);
Self::fetch_helper(
status_type,
include_untracked,
hash_request,
arc_current,
arc_last,
)
.expect("failed to fetch status");
arc_pending.fetch_sub(1, Ordering::Relaxed);
sender
.send(AsyncNotification::Status)
.expect("error sending status");
});
Ok(None)
}
fn fetch_helper(
status_type: StatusType,
include_untracked: bool,
hash_request: u64,
arc_current: Arc<Mutex<Request<u64, Status2>>>,
arc_last: Arc<Mutex<Status2>>,
) -> Result<()> {
let res = Self::get_status(status_type, include_untracked)?;
trace!("status fetched: {}", hash(&res));
{
let mut current = arc_current.lock()?;
if current.0 == hash_request {
current.1 = Some(res.clone());
}
}
{
let mut last = arc_last.lock()?;
*last = res;
}
Ok(())
}
fn get_status(
status_type: StatusType,
include_untracked: bool,
) -> Result<Status2> {
Ok(Status2 {
items: sync::status::get_status_new(
CWD,
status_type,
include_untracked,
)?,
})
}
}

View file

@ -10,7 +10,7 @@ use crate::{
};
use asyncgit::{
sync::{self, status::StatusType},
AsyncNotification, AsyncStatus2, StatusParams, CWD,
AsyncNotification, AsyncStatus, StatusParams, CWD,
};
use crossbeam_channel::Sender;
use crossterm::event::Event;
@ -31,7 +31,7 @@ pub struct Stashing {
options: Options,
index: FileTreeComponent,
theme: Theme,
git_status: AsyncStatus2,
git_status: AsyncStatus,
queue: Queue,
}
@ -55,7 +55,7 @@ impl Stashing {
theme,
),
theme: *theme,
git_status: AsyncStatus2::new(sender.clone()),
git_status: AsyncStatus::new(sender.clone()),
queue: queue.clone(),
}
}

View file

@ -11,8 +11,8 @@ use crate::{
ui::style::Theme,
};
use asyncgit::{
current_tick, AsyncDiff, AsyncNotification, AsyncStatus,
DiffParams,
sync::status::StatusType, AsyncDiff, AsyncNotification,
AsyncStatus, DiffParams, StatusParams,
};
use crossbeam_channel::Sender;
use crossterm::event::Event;
@ -42,7 +42,8 @@ pub struct Status {
index_wd: ChangesComponent,
diff: DiffComponent,
git_diff: AsyncDiff,
git_status: AsyncStatus,
git_status_workdir: AsyncStatus,
git_status_stage: AsyncStatus,
}
impl DrawableComponent for Status {
@ -122,7 +123,8 @@ impl Status {
),
diff: DiffComponent::new(queue.clone(), theme),
git_diff: AsyncDiff::new(sender.clone()),
git_status: AsyncStatus::new(sender.clone()),
git_status_workdir: AsyncStatus::new(sender.clone()),
git_status_stage: AsyncStatus::new(sender.clone()),
}
}
@ -188,12 +190,19 @@ impl Status {
///
pub fn update(&mut self) {
self.git_diff.refresh().unwrap();
self.git_status.fetch(current_tick()).unwrap();
self.git_status_workdir
.fetch(StatusParams::new(StatusType::WorkingDir, true))
.unwrap();
self.git_status_stage
.fetch(StatusParams::new(StatusType::Stage, true))
.unwrap();
}
///
pub fn anything_pending(&self) -> bool {
self.git_diff.is_pending() || self.git_status.is_pending()
self.git_diff.is_pending()
|| self.git_status_stage.is_pending()
|| self.git_status_workdir.is_pending()
}
///
@ -206,9 +215,11 @@ impl Status {
}
fn update_status(&mut self) {
let status = self.git_status.last().unwrap();
self.index.update(&status.stage);
self.index_wd.update(&status.work_dir);
let status = self.git_status_stage.last().unwrap();
self.index.update(&status.items);
let status = self.git_status_workdir.last().unwrap();
self.index_wd.update(&status.items);
self.update_diff();
}