mirror of
https://github.com/extrawurst/gitui.git
synced 2024-11-23 03:32:30 +03:00
update diff if changed externally
This commit is contained in:
parent
7e78a182b2
commit
d52308ea0a
@ -55,7 +55,6 @@ GITUI_LOGGING=true gitui
|
||||
|
||||
# todo for 0.1 (first release)
|
||||
|
||||
* [ ] fix: diff is not updated when changed
|
||||
* [ ] better help command
|
||||
* [ ] -> fix: dont show scroll option when any popup open
|
||||
* [ ] confirm destructive commands (revert/reset)
|
||||
|
@ -6,14 +6,23 @@ use std::{
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
#[derive(Default, Hash)]
|
||||
struct DiffRequest(String, bool);
|
||||
///
|
||||
#[derive(Default, Hash, Clone)]
|
||||
pub struct DiffParams(pub String, pub bool);
|
||||
|
||||
struct Request<R, A>(R, Option<A>);
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
struct LastResult<P, R> {
|
||||
params: P,
|
||||
hash: u64,
|
||||
result: R,
|
||||
}
|
||||
|
||||
///
|
||||
pub struct AsyncDiff {
|
||||
current: Arc<Mutex<Request<u64, Diff>>>,
|
||||
last: Arc<Mutex<Option<LastResult<DiffParams, Diff>>>>,
|
||||
sender: Sender<AsyncNotification>,
|
||||
}
|
||||
|
||||
@ -22,21 +31,34 @@ impl AsyncDiff {
|
||||
pub fn new(sender: Sender<AsyncNotification>) -> Self {
|
||||
Self {
|
||||
current: Arc::new(Mutex::new(Request(0, None))),
|
||||
last: Arc::new(Mutex::new(None)),
|
||||
sender,
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
pub fn request(
|
||||
&mut self,
|
||||
file_path: String,
|
||||
stage: bool,
|
||||
) -> Option<Diff> {
|
||||
pub fn last(&mut self) -> Option<Diff> {
|
||||
let last = self.last.lock().unwrap();
|
||||
if let Some(res) = last.clone() {
|
||||
Some(res.result.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
pub fn refresh(&mut self) {
|
||||
if let Some(param) = self.get_last_param() {
|
||||
self.clear_current();
|
||||
self.request(param);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
pub fn request(&mut self, params: DiffParams) -> Option<Diff> {
|
||||
trace!("request");
|
||||
|
||||
let request = DiffRequest(file_path.clone(), stage);
|
||||
|
||||
let hash = hash(&request);
|
||||
let hash = hash(¶ms);
|
||||
|
||||
{
|
||||
let mut current = self.current.lock().unwrap();
|
||||
@ -49,19 +71,30 @@ impl AsyncDiff {
|
||||
current.1 = None;
|
||||
}
|
||||
|
||||
let arc_clone = Arc::clone(&self.current);
|
||||
let arc_current = Arc::clone(&self.current);
|
||||
let arc_last = Arc::clone(&self.last);
|
||||
let sender = self.sender.clone();
|
||||
rayon_core::spawn(move || {
|
||||
let res = sync::diff::get_diff(file_path.clone(), stage);
|
||||
let res =
|
||||
sync::diff::get_diff(params.0.clone(), params.1);
|
||||
let mut notify = false;
|
||||
{
|
||||
let mut current = arc_clone.lock().unwrap();
|
||||
let mut current = arc_current.lock().unwrap();
|
||||
if current.0 == hash {
|
||||
current.1 = Some(res);
|
||||
current.1 = Some(res.clone());
|
||||
notify = true;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let mut last = arc_last.lock().unwrap();
|
||||
*last = Some(LastResult {
|
||||
result: res,
|
||||
hash: hash,
|
||||
params: params,
|
||||
});
|
||||
}
|
||||
|
||||
if notify {
|
||||
sender.send(AsyncNotification::Diff).unwrap();
|
||||
}
|
||||
@ -69,4 +102,18 @@ impl AsyncDiff {
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn get_last_param(&self) -> Option<DiffParams> {
|
||||
self.last
|
||||
.lock()
|
||||
.unwrap()
|
||||
.clone()
|
||||
.map_or(None, |e| Some(e.params))
|
||||
}
|
||||
|
||||
fn clear_current(&mut self) {
|
||||
let mut current = self.current.lock().unwrap();
|
||||
current.0 = 0;
|
||||
current.1 = None;
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ mod status;
|
||||
pub mod sync;
|
||||
|
||||
pub use crate::{
|
||||
diff::AsyncDiff,
|
||||
diff::{AsyncDiff, DiffParams},
|
||||
status::AsyncStatus,
|
||||
sync::{
|
||||
diff::{Diff, DiffLine, DiffLineType},
|
||||
|
34
src/app.rs
34
src/app.rs
@ -7,6 +7,7 @@ use crate::{
|
||||
};
|
||||
use asyncgit::{
|
||||
current_tick, sync, AsyncDiff, AsyncNotification, AsyncStatus,
|
||||
DiffParams,
|
||||
};
|
||||
use crossbeam_channel::Sender;
|
||||
use crossterm::event::Event;
|
||||
@ -201,8 +202,7 @@ impl App {
|
||||
pub fn update(&mut self) {
|
||||
trace!("update");
|
||||
|
||||
self.update_diff();
|
||||
|
||||
self.git_diff.refresh();
|
||||
self.git_status.fetch(current_tick());
|
||||
}
|
||||
|
||||
@ -215,15 +215,6 @@ impl App {
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
pub fn update_status(&mut self) {
|
||||
let status = self.git_status.last();
|
||||
self.index.update(&status.stage);
|
||||
self.index_wd.update(&status.work_dir);
|
||||
self.update_diff();
|
||||
self.help.set_cmds(self.commands());
|
||||
}
|
||||
|
||||
///
|
||||
pub fn is_quit(&self) -> bool {
|
||||
self.do_quit
|
||||
@ -240,21 +231,38 @@ impl App {
|
||||
|
||||
if let Some(i) = idx.selection() {
|
||||
let path = i.path;
|
||||
let diff_params = DiffParams(path.clone(), is_stage);
|
||||
|
||||
if self.diff.current() != (path.clone(), is_stage) {
|
||||
if let Some(diff) =
|
||||
self.git_diff.request(path.clone(), is_stage)
|
||||
// we dont show the right diff right now, so we need to request
|
||||
if let Some(diff) = self.git_diff.request(diff_params)
|
||||
{
|
||||
self.diff.update(path.clone(), is_stage, diff);
|
||||
} else {
|
||||
self.diff.clear();
|
||||
}
|
||||
} else {
|
||||
// we are already showing a diff of the right file
|
||||
// maybe the diff changed (outside file change)
|
||||
if let Some(last) = self.git_diff.last() {
|
||||
self.diff.update(path.clone(), is_stage, last);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.diff.clear();
|
||||
}
|
||||
}
|
||||
|
||||
fn update_status(&mut self) {
|
||||
let status = self.git_status.last();
|
||||
self.index.update(&status.stage);
|
||||
self.index_wd.update(&status.work_dir);
|
||||
|
||||
self.update_diff();
|
||||
|
||||
self.help.set_cmds(self.commands());
|
||||
}
|
||||
|
||||
fn commands(&self) -> Vec<CommandInfo> {
|
||||
let mut res = self.commit.commands();
|
||||
res.extend(self.help.commands());
|
||||
|
@ -2,7 +2,7 @@ use crate::{
|
||||
components::{CommandInfo, Component},
|
||||
strings,
|
||||
};
|
||||
use asyncgit::{Diff, DiffLine, DiffLineType};
|
||||
use asyncgit::{hash, Diff, DiffLine, DiffLineType};
|
||||
use crossterm::event::{Event, KeyCode};
|
||||
use tui::{
|
||||
backend::Backend,
|
||||
@ -19,6 +19,7 @@ pub struct DiffComponent {
|
||||
scroll: u16,
|
||||
focused: bool,
|
||||
current: (String, bool),
|
||||
current_hash: u64,
|
||||
}
|
||||
|
||||
impl DiffComponent {
|
||||
@ -28,7 +29,7 @@ impl DiffComponent {
|
||||
}
|
||||
///
|
||||
pub fn current(&self) -> (String, bool) {
|
||||
self.current.clone()
|
||||
(self.current.0.clone(), self.current.1)
|
||||
}
|
||||
///
|
||||
pub fn clear(&mut self) {
|
||||
@ -36,10 +37,17 @@ impl DiffComponent {
|
||||
self.diff = Diff::default();
|
||||
}
|
||||
///
|
||||
pub fn update(&mut self, path: String, stage: bool, diff: Diff) {
|
||||
self.current = (path, stage);
|
||||
pub fn update(
|
||||
&mut self,
|
||||
path: String,
|
||||
is_stage: bool,
|
||||
diff: Diff,
|
||||
) {
|
||||
let hash = hash(&diff);
|
||||
|
||||
if diff != self.diff {
|
||||
if self.current_hash != hash {
|
||||
self.current = (path, is_stage);
|
||||
self.current_hash = hash;
|
||||
self.diff = diff;
|
||||
self.scroll = 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user