|
|
@@ -427,30 +427,74 @@ impl<'dir> File<'dir> {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // To display icons for empty folders.
|
|
|
- // The naive approach, as one would think that this info may have been cached.
|
|
|
- // but as mentioned in the size function comment above, different filesystems
|
|
|
- // make it difficult to get any info about a dir by it's size, so this may be it.
|
|
|
+ /// Returns the size of the file or indicates no size if it's a directory.
|
|
|
+ ///
|
|
|
+ /// For Windows platforms, the size of directories is not computed and will
|
|
|
+ /// return `Size::None`.
|
|
|
+ #[cfg(windows)]
|
|
|
+ pub fn size(&self) -> f::Size {
|
|
|
+ if self.is_directory() {
|
|
|
+ f::Size::None
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ f::Size::Some(self.metadata.len())
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Determines if the directory is empty or not.
|
|
|
+ ///
|
|
|
+ /// For Unix platforms, this function first checks the link count to quickly
|
|
|
+ /// determine non-empty directories. On most UNIX filesystems the link count
|
|
|
+ /// is two plus the number of subdirectories. If the link count is less than
|
|
|
+ /// or equal to 2, it then checks the directory contents to determine if
|
|
|
+ /// it's truly empty. The naive approach used here checks the contents
|
|
|
+ /// directly, as certain filesystems make it difficult to infer emptiness
|
|
|
+ /// based on directory size alone.
|
|
|
#[cfg(unix)]
|
|
|
pub fn is_empty_dir(&self) -> bool {
|
|
|
if self.is_directory() {
|
|
|
- match Dir::read_dir(self.path.clone()) {
|
|
|
- // . & .. are skipped, if the returned iterator has .next(), it's not empty
|
|
|
- Ok(has_files) => has_files.files(super::DotFilter::Dotfiles, None, false, false).next().is_none(),
|
|
|
- Err(_) => false,
|
|
|
+ if self.metadata.nlink() > 2 {
|
|
|
+ // Directories will have a link count of two if they do not have any subdirectories.
|
|
|
+ // The '.' entry is a link to itself and the '..' is a link to the parent directory.
|
|
|
+ // A subdirectory will have a link to its parent directory increasing the link count
|
|
|
+ // above two. This will avoid the expensive read_dir call below when a directory
|
|
|
+ // has subdirectories.
|
|
|
+ false
|
|
|
+ } else {
|
|
|
+ self.is_empty_directory()
|
|
|
}
|
|
|
} else {
|
|
|
false
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /// Determines if the directory is empty or not.
|
|
|
+ ///
|
|
|
+ /// For Windows platforms, this function checks the directory contents directly
|
|
|
+ /// to determine if it's empty. Since certain filesystems on Windows make it
|
|
|
+ /// challenging to infer emptiness based on directory size, this approach is used.
|
|
|
#[cfg(windows)]
|
|
|
- pub fn size(&self) -> f::Size {
|
|
|
+ pub fn is_empty_dir(&self) -> bool {
|
|
|
if self.is_directory() {
|
|
|
- f::Size::None
|
|
|
+ self.is_empty_directory()
|
|
|
+ } else {
|
|
|
+ false
|
|
|
}
|
|
|
- else {
|
|
|
- f::Size::Some(self.metadata.len())
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Checks the contents of the directory to determine if it's empty.
|
|
|
+ ///
|
|
|
+ /// This function avoids counting '.' and '..' when determining if the directory is
|
|
|
+ /// empty. If any other entries are found, it returns `false`.
|
|
|
+ ///
|
|
|
+ /// The naive approach, as one would think that this info may have been cached.
|
|
|
+ /// but as mentioned in the size function comment above, different filesystems
|
|
|
+ /// make it difficult to get any info about a dir by it's size, so this may be it.
|
|
|
+ fn is_empty_directory(&self) -> bool {
|
|
|
+ match Dir::read_dir(self.path.clone()) {
|
|
|
+ // . & .. are skipped, if the returned iterator has .next(), it's not empty
|
|
|
+ Ok(has_files) => has_files.files(super::DotFilter::Dotfiles, None, false, false).next().is_none(),
|
|
|
+ Err(_) => false,
|
|
|
}
|
|
|
}
|
|
|
|