diff --git a/src/exa.rs b/src/exa.rs index 851e521c..03e22fe1 100644 --- a/src/exa.rs +++ b/src/exa.rs @@ -191,7 +191,7 @@ impl<'args, 'w, W: Write + 'w> Exa<'args, 'w, W> { if !recurse_opts.tree && !recurse_opts.is_too_deep(depth) { let mut child_dirs = Vec::new(); - for child_dir in children.iter().filter(|f| f.is_directory()) { + for child_dir in children.iter().filter(|f| f.is_directory() && !f.is_all_all) { match child_dir.to_dir() { Ok(d) => child_dirs.push(d), Err(e) => writeln!(stderr(), "{}: {}", child_dir.path.display(), e)?, diff --git a/src/fs/dir.rs b/src/fs/dir.rs index 74480c5a..c9c6e2cd 100644 --- a/src/fs/dir.rs +++ b/src/fs/dir.rs @@ -140,12 +140,12 @@ impl<'dir, 'ig> Iterator for Files<'dir, 'ig> { fn next(&mut self) -> Option { if let Dots::DotNext = self.dots { self.dots = Dots::DotDotNext; - Some(File::new(self.dir.path.to_path_buf(), self.dir, String::from(".")) + Some(File::new_aa_current(self.dir) .map_err(|e| (Path::new(".").to_path_buf(), e))) } else if let Dots::DotDotNext = self.dots { self.dots = Dots::FilesNext; - Some(File::new(self.parent(), self.dir, String::from("..")) + Some(File::new_aa_parent(self.parent(), self.dir) .map_err(|e| (self.parent(), e))) } else { diff --git a/src/fs/file.rs b/src/fs/file.rs index 4196419a..7580a71e 100644 --- a/src/fs/file.rs +++ b/src/fs/file.rs @@ -55,6 +55,13 @@ pub struct File<'dir> { /// contain a reference to it, which is used in certain operations (such /// as looking up compiled files). pub parent_dir: Option<&'dir Dir>, + + /// Whether this is one of the two `--all all` directories, `.` and `..`. + /// + /// Unlike all other entries, these are not returned as part of the + /// directory's children, and are in fact added specifically by exa; this + /// means that they should be skipped when recursing. + pub is_all_all: bool, } impl<'dir> File<'dir> { @@ -68,8 +75,30 @@ impl<'dir> File<'dir> { debug!("Statting file {:?}", &path); let metadata = fs::symlink_metadata(&path)?; + let is_all_all = false; + + Ok(File { path, parent_dir, metadata, ext, name, is_all_all }) + } + + pub fn new_aa_current(parent_dir: &'dir Dir) -> IOResult> { + let path = parent_dir.path.to_path_buf(); + let ext = File::ext(&path); + + debug!("Statting file {:?}", &path); + let metadata = fs::symlink_metadata(&path)?; + let is_all_all = true; + + Ok(File { path, parent_dir: Some(parent_dir), metadata, ext, name: ".".to_string(), is_all_all }) + } + + pub fn new_aa_parent(path: PathBuf, parent_dir: &'dir Dir) -> IOResult> { + let ext = File::ext(&path); + + debug!("Statting file {:?}", &path); + let metadata = fs::symlink_metadata(&path)?; + let is_all_all = true; - Ok(File { path, parent_dir, metadata, ext, name }) + Ok(File { path, parent_dir: Some(parent_dir), metadata, ext, name: "..".to_string(), is_all_all }) } /// A file’s name is derived from its string. This needs to handle directories @@ -219,7 +248,7 @@ impl<'dir> File<'dir> { Ok(metadata) => { let ext = File::ext(&path); let name = File::filename(&path); - FileTarget::Ok(Box::new(File { parent_dir: None, path, ext, metadata, name })) + FileTarget::Ok(Box::new(File { parent_dir: None, path, ext, metadata, name, is_all_all: false })) } Err(e) => { error!("Error following link {:?}: {:#?}", &path, e);