mirror of https://github.com/bobwen-dev/hunter
further speed up creation of Files
This commit is contained in:
parent
5899ee9b65
commit
c8e6ea51bb
|
@ -476,22 +476,20 @@ impl FileBrowser {
|
|||
|
||||
self.prev_cwd = Some(self.cwd.clone());
|
||||
self.cwd = dir.clone();
|
||||
let file_source = FileSource::Path(self.cwd.clone());
|
||||
|
||||
let main_async_widget = self.main_async_widget_mut()?;
|
||||
main_async_widget.change_to(move |stale: &Stale, core| {
|
||||
let (selected_file, files) = cache.get_files(&dir, stale.clone())?;
|
||||
let files = files.run_sync()?;
|
||||
let main_async_widget = self.main_async_widget_mut()?;
|
||||
main_async_widget.change_to(move |stale: &Stale, core| {
|
||||
let view = ListView::builder(core, file_source)
|
||||
.meta_all()
|
||||
.prerender()
|
||||
.with_cache(cache)
|
||||
.with_stale(stale.clone())
|
||||
.build()?;
|
||||
|
||||
let mut list = ListView::new(&core, files);
|
||||
Ok(view)
|
||||
}).log();
|
||||
|
||||
list.content.meta_set_fresh().log();
|
||||
list.content.meta_all();
|
||||
|
||||
if let Some(file) = selected_file {
|
||||
list.select_file(&file);
|
||||
}
|
||||
Ok(list)
|
||||
}).log();
|
||||
|
||||
if let Ok(grand_parent) = self.cwd()?.parent_as_file() {
|
||||
self.left_widget_goto(&grand_parent).log();
|
||||
|
@ -505,27 +503,28 @@ impl FileBrowser {
|
|||
}
|
||||
|
||||
pub fn left_widget_goto(&mut self, dir: &File) -> HResult<()> {
|
||||
// Check if we're in the correct directory already and return
|
||||
// if we are
|
||||
let left_dir = &self.left_widget()?.content.directory;
|
||||
if self.left_widget().is_ok() && left_dir == dir {
|
||||
return Ok(());
|
||||
}
|
||||
// Check if we're in the correct directory already and return
|
||||
// if we are
|
||||
let left_dir = &self.left_widget()?.content.directory;
|
||||
if self.left_widget().is_ok() && left_dir == dir {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let cache = self.fs_cache.clone();
|
||||
let dir = dir.clone();
|
||||
let cache = self.fs_cache.clone();
|
||||
let file_source = FileSource::Path(dir.clone());
|
||||
let left_async_widget = self.left_async_widget_mut()?;
|
||||
left_async_widget.change_to(move |stale, core| {
|
||||
let view = ListView::builder(core, file_source)
|
||||
.meta_all()
|
||||
.prerender()
|
||||
.with_cache(cache)
|
||||
.with_stale(stale.clone())
|
||||
.build()?;
|
||||
|
||||
let left_async_widget = self.left_async_widget_mut()?;
|
||||
left_async_widget.change_to(move |stale, core| {
|
||||
let cached_files = cache.get_files(&dir, stale.clone())?;
|
||||
let (_, files) = cached_files;
|
||||
Ok(view)
|
||||
}).log();
|
||||
|
||||
let files = files.run_sync()?;
|
||||
|
||||
let list = ListView::new(&core, files);
|
||||
Ok(list)
|
||||
})?;
|
||||
Ok(())
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn go_back(&mut self) -> HResult<()> {
|
||||
|
|
217
src/files.rs
217
src/files.rs
|
@ -344,8 +344,7 @@ impl Files {
|
|||
None
|
||||
} else {
|
||||
let file = File::new_from_direntry(file,
|
||||
Some(dirty_meta.clone()),
|
||||
stale.clone());
|
||||
Some(dirty_meta.clone()));
|
||||
Some(file)
|
||||
}
|
||||
})
|
||||
|
@ -470,7 +469,7 @@ impl Files {
|
|||
}
|
||||
|
||||
match (a.meta(), b.meta()) {
|
||||
(Ok(a_meta), Ok(b_meta)) => {
|
||||
(Some(a_meta), Some(b_meta)) => {
|
||||
match a_meta.size() == b_meta.size() {
|
||||
true => compare_str(&b.name, &a.name),
|
||||
false => b_meta.size()
|
||||
|
@ -496,7 +495,7 @@ impl Files {
|
|||
}
|
||||
|
||||
match (a.meta(), b.meta()) {
|
||||
(Ok(a_meta), Ok(b_meta)) => {
|
||||
(Some(a_meta), Some(b_meta)) => {
|
||||
match a_meta.mtime() == b_meta.mtime() {
|
||||
true => compare_str(&b.name, &a.name),
|
||||
false => b_meta.mtime()
|
||||
|
@ -621,59 +620,22 @@ impl Files {
|
|||
}
|
||||
|
||||
pub fn meta_all_sync(&mut self) -> HResult<()> {
|
||||
let mut same = true;
|
||||
|
||||
for file in self.iter_files_mut() {
|
||||
if !file.meta_processed {
|
||||
file.meta_sync().log();
|
||||
}
|
||||
}
|
||||
self.set_dirty();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn meta_all(&mut self) {
|
||||
let len = self.len();
|
||||
self.meta_upto(len, None);
|
||||
self.dirty_meta.set_dirty();
|
||||
self.meta_set_fresh().log();
|
||||
}
|
||||
|
||||
pub fn meta_upto(&mut self, to: usize, sender: Option<Sender<Events>>) {
|
||||
let meta_files = if self.meta_upto > Some(to) {
|
||||
self.meta_upto.unwrap()
|
||||
} else {
|
||||
if to > self.len() {
|
||||
self.len()
|
||||
} else {
|
||||
to
|
||||
}
|
||||
};
|
||||
|
||||
if self.meta_upto >= Some(meta_files) && !self.dirty_meta.is_dirty() { return }
|
||||
|
||||
self.set_dirty();
|
||||
self.dirty_meta.set_clean();
|
||||
|
||||
let meta_pool = make_pool(sender.clone());
|
||||
|
||||
for file in self.iter_files_mut()
|
||||
.take(meta_files) {
|
||||
if !file.meta_processed {
|
||||
file.take_meta(&meta_pool).ok();
|
||||
}
|
||||
if file.is_dir() {
|
||||
file.take_dirsize(&meta_pool).ok();
|
||||
same = false;
|
||||
}
|
||||
}
|
||||
|
||||
self.meta_upto = Some(meta_files);
|
||||
}
|
||||
if !same {
|
||||
self.set_dirty();
|
||||
}
|
||||
|
||||
pub fn meta_set_fresh(&self) -> HResult<()> {
|
||||
self.iter_files().nth(0)?.meta.set_fresh()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
pub fn set_filter(&mut self, filter: Option<String>) {
|
||||
self.filter = filter;
|
||||
|
||||
|
@ -771,10 +733,10 @@ pub struct File {
|
|||
pub path: PathBuf,
|
||||
pub hidden: bool,
|
||||
pub kind: Kind,
|
||||
pub dirsize: Option<Async<usize>>,
|
||||
pub dirsize: Option<usize>,
|
||||
pub target: Option<PathBuf>,
|
||||
pub color: Option<lscolors::Color>,
|
||||
pub meta: Async<Metadata>,
|
||||
pub meta: Option<Metadata>,
|
||||
pub dirty_meta: Option<AsyncDirtyBit>,
|
||||
pub meta_processed: bool,
|
||||
pub selected: bool,
|
||||
|
@ -787,19 +749,15 @@ impl File {
|
|||
path: PathBuf,
|
||||
dirty_meta: Option<AsyncDirtyBit>) -> File {
|
||||
let hidden = name.starts_with(".");
|
||||
let meta = File::make_async_meta(&path, dirty_meta.clone(), None);
|
||||
let dirsize = if path.is_dir() {
|
||||
Some(File::make_async_dirsize(&path, dirty_meta.clone(), None))
|
||||
} else { None };
|
||||
|
||||
File {
|
||||
name: name.to_string(),
|
||||
hidden: hidden,
|
||||
kind: if path.is_dir() { Kind::Directory } else { Kind::File },
|
||||
path: path,
|
||||
dirsize: dirsize,
|
||||
dirsize: None,
|
||||
target: None,
|
||||
meta: meta,
|
||||
meta: None,
|
||||
meta_processed: false,
|
||||
dirty_meta: dirty_meta,
|
||||
color: None,
|
||||
|
@ -810,26 +768,17 @@ impl File {
|
|||
|
||||
pub fn new_with_stale(name: &str,
|
||||
path: PathBuf,
|
||||
dirty_meta: Option<AsyncDirtyBit>,
|
||||
stale: Stale) -> File {
|
||||
dirty_meta: Option<AsyncDirtyBit>) -> File {
|
||||
let hidden = name.starts_with(".");
|
||||
let meta = File::make_async_meta(&path,
|
||||
dirty_meta.clone(),
|
||||
Some(stale.clone()));
|
||||
let dirsize = if path.is_dir() {
|
||||
Some(File::make_async_dirsize(&path,
|
||||
dirty_meta.clone(),
|
||||
Some(stale)))
|
||||
} else { None };
|
||||
|
||||
File {
|
||||
name: name.to_string(),
|
||||
hidden: hidden,
|
||||
kind: if path.is_dir() { Kind::Directory } else { Kind::File },
|
||||
path: path,
|
||||
dirsize: dirsize,
|
||||
dirsize: None,
|
||||
target: None,
|
||||
meta: meta,
|
||||
meta: None,
|
||||
meta_processed: false,
|
||||
dirty_meta: dirty_meta,
|
||||
color: None,
|
||||
|
@ -839,8 +788,7 @@ impl File {
|
|||
}
|
||||
|
||||
pub fn new_from_direntry(direntry: std::fs::DirEntry,
|
||||
dirty_meta: Option<AsyncDirtyBit>,
|
||||
stale: Stale) -> File {
|
||||
dirty_meta: Option<AsyncDirtyBit>) -> File {
|
||||
let path = direntry.path();
|
||||
let name = direntry.file_name()
|
||||
.to_string_lossy()
|
||||
|
@ -855,25 +803,14 @@ impl File {
|
|||
_ => Kind::Placeholder
|
||||
};
|
||||
|
||||
let meta = File::make_async_meta(&path,
|
||||
dirty_meta.clone(),
|
||||
Some(stale.clone()));
|
||||
|
||||
let dirsize = match kind {
|
||||
Kind::Directory => Some(File::make_async_dirsize(&path,
|
||||
dirty_meta.clone(),
|
||||
Some(stale.clone()))),
|
||||
_ => None
|
||||
};
|
||||
|
||||
File {
|
||||
name: name,
|
||||
hidden: hidden,
|
||||
kind: kind,
|
||||
path: path,
|
||||
dirsize: dirsize,
|
||||
dirsize: None,
|
||||
target: None,
|
||||
meta: meta,
|
||||
meta: None,
|
||||
meta_processed: false,
|
||||
dirty_meta: dirty_meta,
|
||||
color: None,
|
||||
|
@ -907,104 +844,24 @@ impl File {
|
|||
}
|
||||
|
||||
pub fn meta_sync(&mut self) -> HResult<()> {
|
||||
let stale = self.meta.get_stale();
|
||||
let meta = std::fs::metadata(&self.path)?;
|
||||
self.meta = Async::new_with_value(meta);
|
||||
self.meta.put_stale(stale);
|
||||
let meta = std::fs::symlink_metadata(&self.path)?;
|
||||
self.meta = Some(meta);
|
||||
self.process_meta().log();
|
||||
|
||||
if self.is_dir() {
|
||||
let dirsize = self.dirsize
|
||||
.take()
|
||||
.map(|s| s.run_sync())??;
|
||||
self.dirsize = Some(Async::new_with_value(dirsize));
|
||||
let dirsize = std::fs::read_dir(&self.path)?.count();
|
||||
self.dirsize = Some(dirsize);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn make_async_meta(path: &PathBuf,
|
||||
dirty_meta: Option<AsyncDirtyBit>,
|
||||
stale_preview: Option<Stale>) -> Async<Metadata> {
|
||||
let path = path.clone();
|
||||
|
||||
let mut meta = Async::new(move |stale: &Stale| {
|
||||
if stale.is_stale()? { HError::stale()? }
|
||||
Ok(std::fs::symlink_metadata(&path)?)
|
||||
});
|
||||
|
||||
stale_preview.map(|s| meta.put_stale(s));
|
||||
|
||||
dirty_meta.map(|mut d|
|
||||
meta.on_ready(move |_,_| {
|
||||
d.set_dirty();
|
||||
|
||||
Ok(())
|
||||
}).log()
|
||||
);
|
||||
meta
|
||||
}
|
||||
|
||||
pub fn make_async_dirsize(path: &PathBuf,
|
||||
dirty_meta: Option<AsyncDirtyBit>,
|
||||
stale_preview: Option<Stale>) -> Async<usize> {
|
||||
let path = path.clone();
|
||||
|
||||
let mut dirsize = Async::new(move |stale: &Stale| {
|
||||
if stale.is_stale()? { HError::stale()? }
|
||||
Ok(std::fs::read_dir(&path)?.count())
|
||||
});
|
||||
|
||||
stale_preview.map(|s| dirsize.put_stale(s));
|
||||
|
||||
dirty_meta.map(|mut d|
|
||||
dirsize.on_ready(move |_,_| {
|
||||
d.set_dirty();
|
||||
|
||||
Ok(())
|
||||
}).log()
|
||||
);
|
||||
dirsize
|
||||
}
|
||||
|
||||
pub fn meta(&self) -> HResult<&Metadata> {
|
||||
Ok(self.meta.get()?)
|
||||
}
|
||||
|
||||
fn take_dirsize(&mut self,
|
||||
pool: &ThreadPool) -> HResult<()> {
|
||||
let dirsize = self.dirsize.as_mut()?;
|
||||
if let Ok(_) = dirsize.value { return Ok(()) }
|
||||
|
||||
if !dirsize.is_running() && !dirsize.is_ready() {
|
||||
dirsize.run_pooled(Some(&*pool))?;
|
||||
}
|
||||
|
||||
if dirsize.is_ready() {
|
||||
dirsize.pull_async()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn take_meta(&mut self,
|
||||
pool: &ThreadPool) -> HResult<()> {
|
||||
if self.meta_processed { return Ok(()) }
|
||||
|
||||
if !self.meta.is_running() && !self.meta.is_ready() {
|
||||
self.meta.run_pooled(Some(&*pool))?;
|
||||
}
|
||||
|
||||
if self.meta.is_ready() {
|
||||
self.meta.pull_async()?;
|
||||
self.process_meta()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
pub fn meta(&self) -> Option<&Metadata> {
|
||||
self.meta.as_ref()
|
||||
}
|
||||
|
||||
pub fn process_meta(&mut self) -> HResult<()> {
|
||||
if let Ok(meta) = self.meta.get() {
|
||||
if let Some(ref meta) = self.meta {
|
||||
let color = self.get_color(&meta);
|
||||
let target = if meta.file_type().is_symlink() {
|
||||
self.path.read_link().ok()
|
||||
|
@ -1019,18 +876,7 @@ impl File {
|
|||
|
||||
pub fn reload_meta(&mut self) -> HResult<()> {
|
||||
self.meta_processed = false;
|
||||
self.meta = File::make_async_meta(&self.path,
|
||||
self.dirty_meta.clone(),
|
||||
None);
|
||||
self.meta.run()?;
|
||||
|
||||
if self.dirsize.is_some() {
|
||||
self.dirsize = Some(File::make_async_dirsize(&self.path,
|
||||
self.dirty_meta.clone(),
|
||||
None));
|
||||
self.dirsize.as_mut()?.run()?;
|
||||
}
|
||||
Ok(())
|
||||
self.meta_sync()
|
||||
}
|
||||
|
||||
fn get_color(&self, meta: &std::fs::Metadata) -> Option<lscolors::Color> {
|
||||
|
@ -1042,7 +888,7 @@ impl File {
|
|||
|
||||
pub fn calculate_size(&self) -> HResult<(u32, &str)> {
|
||||
if let Some(ref dirsize) = self.dirsize {
|
||||
return Ok((*dirsize.value.as_ref().unwrap_or(&0) as u32, ""))
|
||||
return Ok((*dirsize as u32, ""))
|
||||
}
|
||||
|
||||
|
||||
|
@ -1073,7 +919,6 @@ impl File {
|
|||
// Fix crash in tree_magic when called on non-regular file
|
||||
// Also fix crash when a file doesn't exist any more
|
||||
self.meta()
|
||||
.ok()
|
||||
.and_then(|meta| {
|
||||
if meta.is_file() && self.path.exists() {
|
||||
let mime = tree_magic::from_filepath(&self.path);
|
||||
|
@ -1239,7 +1084,7 @@ impl File {
|
|||
}
|
||||
|
||||
pub fn pretty_user(&self) -> Option<String> {
|
||||
if self.meta().is_err() { return None }
|
||||
if self.meta().is_none() { return None }
|
||||
let uid = self.meta().unwrap().uid();
|
||||
let file_user = users::get_user_by_uid(uid)?;
|
||||
let cur_user = users::get_current_username()?;
|
||||
|
@ -1252,7 +1097,7 @@ impl File {
|
|||
}
|
||||
|
||||
pub fn pretty_group(&self) -> Option<String> {
|
||||
if self.meta().is_err() { return None }
|
||||
if self.meta().is_none() { return None }
|
||||
let gid = self.meta().unwrap().gid();
|
||||
let file_group = users::get_group_by_gid(gid)?;
|
||||
let cur_group = users::get_current_groupname()?;
|
||||
|
@ -1265,7 +1110,7 @@ impl File {
|
|||
}
|
||||
|
||||
pub fn pretty_mtime(&self) -> Option<String> {
|
||||
if self.meta().is_err() { return None }
|
||||
if self.meta().is_none() { return None }
|
||||
let time: chrono::DateTime<chrono::Local>
|
||||
= chrono::Local.timestamp(self.meta().unwrap().mtime(), 0);
|
||||
Some(time.format("%F %R").to_string())
|
||||
|
|
|
@ -108,7 +108,7 @@ impl Listable for ListView<Files> {
|
|||
.cloned()
|
||||
.unwrap_or_default();
|
||||
|
||||
if !file.meta.value.is_ok() {
|
||||
if file.meta.is_none() {
|
||||
file.meta_sync().log();
|
||||
}
|
||||
|
||||
|
@ -311,7 +311,7 @@ impl FileListBuilder {
|
|||
pub fn build(self) -> HResult<ListView<Files>> {
|
||||
let c = &self.cache;
|
||||
let s = self.stale.clone();
|
||||
let mut files = match self.source {
|
||||
let files = match self.source {
|
||||
FileSource::Files(f) => Ok(f),
|
||||
FileSource::Path(f) => {
|
||||
c.as_ref()
|
||||
|
|
Loading…
Reference in New Issue