Browse Source

Scan for nested files on-demand, not all the time

This does a similar thing that we did with the xattrs, except with the nested files: it removes the 'this' field on File, and replaces it with a method (to_dir) that has the same effect.

This means we get to remove a bunch of 'recurse' fields and parameters that really had no business being there! Now the table doesn't need to know whether it's going to need to list files recursively or not.
Ben S 10 năm trước cách đây
mục cha
commit
b5edee53bd
4 tập tin đã thay đổi với 17 bổ sung35 xóa
  1. 2 4
      src/dir.rs
  2. 7 19
      src/file.rs
  3. 3 6
      src/main.rs
  4. 5 6
      src/output/details.rs

+ 2 - 4
src/dir.rs

@@ -37,10 +37,9 @@ impl Dir {
     ///
     ///
     /// Passing in `recurse` means that any directories will be scanned for
     /// Passing in `recurse` means that any directories will be scanned for
     /// their contents, as well.
     /// their contents, as well.
-    pub fn files<'dir>(&'dir self, recurse: bool) -> Files<'dir> {
+    pub fn files<'dir>(&'dir self) -> Files<'dir> {
         Files {
         Files {
             inner: self.contents.iter(),
             inner: self.contents.iter(),
-            recurse: recurse,
             dir: &self,
             dir: &self,
         }
         }
     }
     }
@@ -73,7 +72,6 @@ impl Dir {
 
 
 pub struct Files<'dir> {
 pub struct Files<'dir> {
     inner: SliceIter<'dir, PathBuf>,
     inner: SliceIter<'dir, PathBuf>,
-    recurse: bool,
     dir: &'dir Dir,
     dir: &'dir Dir,
 }
 }
 
 
@@ -81,6 +79,6 @@ impl<'dir> Iterator for Files<'dir> {
     type Item = Result<File<'dir>, (PathBuf, io::Error)>;
     type Item = Result<File<'dir>, (PathBuf, io::Error)>;
 
 
     fn next(&mut self) -> Option<Self::Item> {
     fn next(&mut self) -> Option<Self::Item> {
-        self.inner.next().map(|path| File::from_path(path, Some(self.dir), self.recurse).map_err(|t| (path.clone(), t)))
+        self.inner.next().map(|path| File::from_path(path, Some(self.dir)).map_err(|t| (path.clone(), t)))
     }
     }
 }
 }

+ 7 - 19
src/file.rs

@@ -53,10 +53,6 @@ pub struct File<'dir> {
     /// contain a reference to it, which is used in certain operations (such
     /// contain a reference to it, which is used in certain operations (such
     /// as looking up a file's Git status).
     /// as looking up a file's Git status).
     pub dir: Option<&'dir Dir>,
     pub dir: Option<&'dir Dir>,
-
-    /// If this `File` is also a directory, then this field is the same file
-    /// as a `Dir`.
-    pub this: Option<io::Result<Dir>>,
 }
 }
 
 
 impl<'dir> File<'dir> {
 impl<'dir> File<'dir> {
@@ -65,31 +61,20 @@ impl<'dir> File<'dir> {
     ///
     ///
     /// This uses `symlink_metadata` instead of `metadata`, which doesn't
     /// This uses `symlink_metadata` instead of `metadata`, which doesn't
     /// follow symbolic links.
     /// follow symbolic links.
-    pub fn from_path(path: &Path, parent: Option<&'dir Dir>, recurse: bool) -> io::Result<File<'dir>> {
-        fs::symlink_metadata(path).map(|metadata| File::with_metadata(metadata, path, parent, recurse))
+    pub fn from_path(path: &Path, parent: Option<&'dir Dir>) -> io::Result<File<'dir>> {
+        fs::symlink_metadata(path).map(|metadata| File::with_metadata(metadata, path, parent))
     }
     }
 
 
     /// Create a new File object from the given metadata result, and other data.
     /// Create a new File object from the given metadata result, and other data.
-    pub fn with_metadata(metadata: fs::Metadata, path: &Path, parent: Option<&'dir Dir>, recurse: bool) -> File<'dir> {
+    pub fn with_metadata(metadata: fs::Metadata, path: &Path, parent: Option<&'dir Dir>) -> File<'dir> {
         let filename = path_filename(path);
         let filename = path_filename(path);
 
 
-        // If we are recursing, then the `this` field contains a Dir object
-        // that represents the current File as a directory, if it is a
-        // directory. This is used for the --tree option.
-        let this = if recurse && metadata.is_dir() {
-            Some(Dir::readdir(path, false))
-        }
-        else {
-            None
-        };
-
         File {
         File {
             path:   path.to_path_buf(),
             path:   path.to_path_buf(),
             dir:    parent,
             dir:    parent,
             metadata:   metadata,
             metadata:   metadata,
             ext:    ext(&filename),
             ext:    ext(&filename),
             name:   filename.to_string(),
             name:   filename.to_string(),
-            this:   this,
         }
         }
     }
     }
 
 
@@ -98,6 +83,10 @@ impl<'dir> File<'dir> {
         self.metadata.is_dir()
         self.metadata.is_dir()
     }
     }
 
 
+    pub fn to_dir(&self) -> io::Result<Dir> {
+        Dir::readdir(&*self.path, false)
+    }
+
     /// Whether this file is a regular file on the filesystem - that is, not a
     /// Whether this file is a regular file on the filesystem - that is, not a
     /// directory, a link, or anything else treated specially.
     /// directory, a link, or anything else treated specially.
     pub fn is_file(&self) -> bool {
     pub fn is_file(&self) -> bool {
@@ -194,7 +183,6 @@ impl<'dir> File<'dir> {
                 metadata:   metadata,
                 metadata:   metadata,
                 ext:    ext(&filename),
                 ext:    ext(&filename),
                 name:   filename.to_string(),
                 name:   filename.to_string(),
-                this:   None,
             })
             })
         }
         }
         else {
         else {

+ 3 - 6
src/main.rs

@@ -90,11 +90,8 @@ impl<'dir> Exa<'dir> {
                 let path = Path::new(&*file);
                 let path = Path::new(&*file);
                 let _ = tx.send(match fs::metadata(&path) {
                 let _ = tx.send(match fs::metadata(&path) {
                     Ok(metadata) => {
                     Ok(metadata) => {
-                        if !metadata.is_dir() {
-                            StatResult::File(File::with_metadata(metadata, &path, None, false))
-                        }
-                        else if is_tree {
-                            StatResult::File(File::with_metadata(metadata, &path, None, true))
+                        if is_tree || !metadata.is_dir() {
+                            StatResult::File(File::with_metadata(metadata, &path, None))
                         }
                         }
                         else {
                         else {
                             StatResult::Dir(path.to_path_buf())
                             StatResult::Dir(path.to_path_buf())
@@ -149,7 +146,7 @@ impl<'dir> Exa<'dir> {
                 Ok(ref dir) => {
                 Ok(ref dir) => {
                     let mut files = Vec::new();
                     let mut files = Vec::new();
 
 
-                    for file in dir.files(true) {
+                    for file in dir.files() {
                         match file {
                         match file {
                             Ok(file) => files.push(file),
                             Ok(file) => files.push(file),
                             Err((path, e))   => println!("[{}: {}]", path.display(), e),
                             Err((path, e))   => println!("[{}: {}]", path.display(), e),

+ 5 - 6
src/output/details.rs

@@ -104,18 +104,18 @@ impl Details {
             // dealt with in the main module. So only actually recurse if we
             // dealt with in the main module. So only actually recurse if we
             // are in tree mode - the other case will be dealt with elsewhere.
             // are in tree mode - the other case will be dealt with elsewhere.
             if let Some((r, filter)) = self.recurse {
             if let Some((r, filter)) = self.recurse {
-                if r.tree == false || r.is_too_deep(depth) {
+                if !file.is_directory() || !r.tree || r.is_too_deep(depth) {
                     continue;
                     continue;
                 }
                 }
 
 
                 // Use the filter to remove unwanted files *before* expanding
                 // Use the filter to remove unwanted files *before* expanding
                 // them, so we don't examine any directories that wouldn't
                 // them, so we don't examine any directories that wouldn't
                 // have their contents listed anyway.
                 // have their contents listed anyway.
-                match file.this {
-                    Some(Ok(ref dir)) => {
+                match file.to_dir() {
+                    Ok(ref dir) => {
                         let mut files = Vec::new();
                         let mut files = Vec::new();
 
 
-                        let files_to_add = dir.files(true).collect::<Vec<_>>();
+                        let files_to_add = dir.files().collect::<Vec<_>>();
                         let child_count = files_to_add.len();
                         let child_count = files_to_add.len();
                         for (index, file_to_add) in files_to_add.into_iter().enumerate() {
                         for (index, file_to_add) in files_to_add.into_iter().enumerate() {
                             match file_to_add {
                             match file_to_add {
@@ -127,10 +127,9 @@ impl Details {
                         filter.transform_files(&mut files);
                         filter.transform_files(&mut files);
                         self.add_files_to_table(table, &files, depth + 1);
                         self.add_files_to_table(table, &files, depth + 1);
                     },
                     },
-                    Some(Err(ref e)) => {
+                    Err(ref e) => {
                         table.add_error(e, depth + 1, true, None);
                         table.add_error(e, depth + 1, true, None);
                     },
                     },
-                    None => {},
                 }
                 }
             }
             }
         }
         }