Просмотр исходного кода

Fix bug where files were Git-ignored too often

This was an unintended consequence of #653. The Files iterator stopped using IgnoreCache and started using GitCache, which would always populated when the `--git` option was passed, without checking whether files were meant to be ignored. This meant that passing `--git` started ignoring files even without `--git-ignore`.

The solution for now is to explicitly pass the flag around, which probably should be a better type than bool but isn't. This makes the git-ignoring-related extended tests pass.
Benjamin Sago 5 лет назад
Родитель
Сommit
e44858eb41
4 измененных файлов с 25 добавлено и 9 удалено
  1. 7 3
      src/exa.rs
  2. 9 5
      src/fs/dir.rs
  3. 4 1
      src/output/details.rs
  4. 5 0
      src/output/grid_details.rs

+ 7 - 3
src/exa.rs

@@ -11,6 +11,7 @@ use ansi_term::{ANSIStrings, Style};
 use log::debug;
 
 use crate::fs::{Dir, File};
+use crate::fs::filter::GitIgnore;
 use crate::fs::feature::git::GitCache;
 use crate::options::{Options, Vars};
 pub use crate::options::vars;
@@ -142,7 +143,8 @@ impl<'args, 'w, W: Write + 'w> Exa<'args, 'w, W> {
             }
 
             let mut children = Vec::new();
-            for file in dir.files(self.options.filter.dot_filter, self.git.as_ref()) {
+            let git_ignore = self.options.filter.git_ignore == GitIgnore::CheckAndIgnore;
+            for file in dir.files(self.options.filter.dot_filter, self.git.as_ref(), git_ignore) {
                 match file {
                     Ok(file)       => children.push(file),
                     Err((path, e)) => writeln!(stderr(), "[{}: {}]", path.display(), e)?,
@@ -201,7 +203,8 @@ impl<'args, 'w, W: Write + 'w> Exa<'args, 'w, W> {
                     let filter = &self.options.filter;
                     let recurse = self.options.dir_action.recurse_options();
 
-                    let r = details::Render { dir, files, colours, style, opts, filter, recurse };
+                    let git_ignoring = self.options.filter.git_ignore == GitIgnore::CheckAndIgnore;
+                    let r = details::Render { dir, files, colours, style, opts, filter, recurse, git_ignoring };
                     r.render(self.git.as_ref(), self.writer)
                 }
 
@@ -211,7 +214,8 @@ impl<'args, 'w, W: Write + 'w> Exa<'args, 'w, W> {
                     let details = &opts.details;
                     let row_threshold = opts.row_threshold;
 
-                    let r = grid_details::Render { dir, files, colours, style, grid, details, filter, row_threshold };
+                    let git_ignoring = self.options.filter.git_ignore == GitIgnore::CheckAndIgnore;
+                    let r = grid_details::Render { dir, files, colours, style, grid, details, filter, row_threshold, git_ignoring };
                     r.render(self.git.as_ref(), self.writer)
                 }
             }

+ 9 - 5
src/fs/dir.rs

@@ -47,13 +47,13 @@ impl Dir {
 
     /// Produce an iterator of IO results of trying to read all the files in
     /// this directory.
-    pub fn files<'dir, 'ig>(&'dir self, dots: DotFilter, git: Option<&'ig GitCache>) -> Files<'dir, 'ig> {
+    pub fn files<'dir, 'ig>(&'dir self, dots: DotFilter, git: Option<&'ig GitCache>, git_ignoring: bool) -> Files<'dir, 'ig> {
         Files {
             inner:     self.contents.iter(),
             dir:       self,
             dotfiles:  dots.shows_dotfiles(),
             dots:      dots.dots(),
-            git,
+            git, git_ignoring,
         }
     }
 
@@ -86,6 +86,8 @@ pub struct Files<'dir, 'ig> {
     dots: DotsNext,
 
     git: Option<&'ig GitCache>,
+
+    git_ignoring: bool,
 }
 
 impl<'dir, 'ig> Files<'dir, 'ig> {
@@ -106,9 +108,11 @@ impl<'dir, 'ig> Files<'dir, 'ig> {
                 let filename = File::filename(path);
                 if !self.dotfiles && filename.starts_with('.') { continue }
 
-                let git_status = self.git.map(|g| g.get(path, false)).unwrap_or_default();
-                if git_status.unstaged == GitStatus::Ignored {
-                     continue;
+                if self.git_ignoring {
+                    let git_status = self.git.map(|g| g.get(path, false)).unwrap_or_default();
+                    if git_status.unstaged == GitStatus::Ignored {
+                         continue;
+                    }
                 }
 
                 return Some(File::from_args(path.clone(), self.dir, filename)

+ 4 - 1
src/output/details.rs

@@ -128,6 +128,9 @@ pub struct Render<'a> {
 
     /// How to sort and filter the files after getting their details.
     pub filter: &'a FileFilter,
+
+    /// Whether we are skipping Git-ignored files.
+    pub git_ignoring: bool,
 }
 
 
@@ -303,7 +306,7 @@ impl<'a> Render<'a> {
             rows.push(row);
 
             if let Some(ref dir) = egg.dir {
-                for file_to_add in dir.files(self.filter.dot_filter, git) {
+                for file_to_add in dir.files(self.filter.dot_filter, git, self.git_ignoring) {
                     match file_to_add {
                         Ok(f)          => files.push(f),
                         Err((path, e)) => errors.push((e, Some(path)))

+ 5 - 0
src/output/grid_details.rs

@@ -76,6 +76,9 @@ pub struct Render<'a> {
     /// The minimum number of rows that there need to be before grid-details
     /// mode is activated.
     pub row_threshold: RowThreshold,
+
+    /// Whether we are skipping Git-ignored files.
+    pub git_ignoring: bool,
 }
 
 impl<'a> Render<'a> {
@@ -95,6 +98,7 @@ impl<'a> Render<'a> {
             opts: self.details,
             recurse: None,
             filter: self.filter,
+            git_ignoring: self.git_ignoring,
         }
     }
 
@@ -109,6 +113,7 @@ impl<'a> Render<'a> {
             opts: self.details,
             recurse: None,
             filter: &self.filter,
+            git_ignoring: self.git_ignoring,
         }
     }