Rework Worktree::scan_complete to use a watch

This commit is contained in:
Antonio Scandurra 2021-04-20 11:24:46 +02:00
parent a4c1fe5a0b
commit d11d5483b6

View file

@ -6,20 +6,21 @@ use crate::{
sum_tree::{self, Edit, SumTree}, sum_tree::{self, Edit, SumTree},
}; };
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use futures_core::future::BoxFuture;
pub use fuzzy::match_paths;
use fuzzy::PathEntry; use fuzzy::PathEntry;
pub use fuzzy::{match_paths, PathMatch};
use gpui::{scoped_pool, AppContext, Entity, ModelContext, ModelHandle, Task}; use gpui::{scoped_pool, AppContext, Entity, ModelContext, ModelHandle, Task};
use ignore::dir::{Ignore, IgnoreBuilder}; use ignore::dir::{Ignore, IgnoreBuilder};
use parking_lot::Mutex; use parking_lot::Mutex;
use postage::{oneshot, prelude::Stream, sink::Sink}; use postage::{
prelude::{Sink, Stream},
watch,
};
use smol::{channel::Sender, Timer}; use smol::{channel::Sender, Timer};
use std::{ use std::{
ffi::OsStr, ffi::OsStr,
fmt, fs, fmt, fs,
future::Future, future::Future,
io::{self, Read, Write}, io::{self, Read, Write},
mem,
ops::{AddAssign, Deref}, ops::{AddAssign, Deref},
os::unix::fs::MetadataExt, os::unix::fs::MetadataExt,
path::{Path, PathBuf}, path::{Path, PathBuf},
@ -27,20 +28,17 @@ use std::{
time::Duration, time::Duration,
}; };
pub use fuzzy::PathMatch; #[derive(Clone, Debug)]
#[derive(Debug)]
enum ScanState { enum ScanState {
Idle, Idle,
Scanning, Scanning,
Err(io::Error), Err(Arc<io::Error>),
} }
pub struct Worktree { pub struct Worktree {
snapshot: Snapshot, snapshot: Snapshot,
scanner: Arc<BackgroundScanner>, scanner: Arc<BackgroundScanner>,
scan_listeners: Mutex<Vec<postage::oneshot::Sender<()>>>, scan_state: (watch::Sender<ScanState>, watch::Receiver<ScanState>),
scan_state: ScanState,
poll_scheduled: bool, poll_scheduled: bool,
} }
@ -63,8 +61,7 @@ impl Worktree {
let tree = Self { let tree = Self {
snapshot, snapshot,
scanner, scanner,
scan_listeners: Default::default(), scan_state: watch::channel_with(ScanState::Scanning),
scan_state: ScanState::Scanning,
poll_scheduled: false, poll_scheduled: false,
}; };
@ -77,20 +74,18 @@ impl Worktree {
tree tree
} }
pub fn scan_complete(&self) -> BoxFuture<'static, ()> { pub fn scan_complete(&self) -> impl Future<Output = ()> {
if self.is_scanning() { let mut scan_state_rx = self.scan_state.1.clone();
let (tx, mut rx) = oneshot::channel::<()>(); async move {
self.scan_listeners.lock().push(tx); let mut next_scan_state = Some(scan_state_rx.borrow().clone());
Box::pin(async move { while let Some(ScanState::Scanning) = next_scan_state {
rx.recv().await; next_scan_state = scan_state_rx.recv().await;
}) }
} else {
Box::pin(async {})
} }
} }
fn observe_scan_state(&mut self, scan_state: ScanState, ctx: &mut ModelContext<Self>) { fn observe_scan_state(&mut self, scan_state: ScanState, ctx: &mut ModelContext<Self>) {
self.scan_state = scan_state; let _ = self.scan_state.0.blocking_send(scan_state);
self.poll_entries(ctx); self.poll_entries(ctx);
} }
@ -105,23 +100,11 @@ impl Worktree {
}) })
.detach(); .detach();
self.poll_scheduled = true; self.poll_scheduled = true;
} else {
let mut listeners = Vec::new();
mem::swap(self.scan_listeners.lock().as_mut(), &mut listeners);
ctx.spawn(
async move {
for mut tx in listeners {
tx.send(()).await.ok();
}
},
|_, _, _| {},
)
.detach();
} }
} }
fn is_scanning(&self) -> bool { fn is_scanning(&self) -> bool {
if let ScanState::Scanning = self.scan_state { if let ScanState::Scanning = *self.scan_state.1.borrow() {
true true
} else { } else {
false false
@ -554,7 +537,7 @@ impl BackgroundScanner {
} }
if let Err(err) = self.scan_dirs() { if let Err(err) = self.scan_dirs() {
if smol::block_on(self.notify.send(ScanState::Err(err))).is_err() { if smol::block_on(self.notify.send(ScanState::Err(Arc::new(err)))).is_err() {
return; return;
} }
} }