mirror of
https://github.com/Llewellynvdm/exa.git
synced 2024-11-29 15:13:54 +00:00
Prevent infinite loop with -aaR
This happened because exa would recurse into `.` over and over again. There was nothing distinguishing the pseudo-entry for `.` that was being added by `--a` from a `.` passed in on the command-line, so it was looping forever. It gets fixed by having the File value keep track of whether it’s an --all --all entry, and not recursing into directories with this field set. Fixes #515
This commit is contained in:
parent
7dada93c3e
commit
e936d7e09f
@ -191,7 +191,7 @@ impl<'args, 'w, W: Write + 'w> Exa<'args, 'w, W> {
|
|||||||
if !recurse_opts.tree && !recurse_opts.is_too_deep(depth) {
|
if !recurse_opts.tree && !recurse_opts.is_too_deep(depth) {
|
||||||
|
|
||||||
let mut child_dirs = Vec::new();
|
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() {
|
match child_dir.to_dir() {
|
||||||
Ok(d) => child_dirs.push(d),
|
Ok(d) => child_dirs.push(d),
|
||||||
Err(e) => writeln!(stderr(), "{}: {}", child_dir.path.display(), e)?,
|
Err(e) => writeln!(stderr(), "{}: {}", child_dir.path.display(), e)?,
|
||||||
|
@ -140,12 +140,12 @@ impl<'dir, 'ig> Iterator for Files<'dir, 'ig> {
|
|||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
if let Dots::DotNext = self.dots {
|
if let Dots::DotNext = self.dots {
|
||||||
self.dots = Dots::DotDotNext;
|
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)))
|
.map_err(|e| (Path::new(".").to_path_buf(), e)))
|
||||||
}
|
}
|
||||||
else if let Dots::DotDotNext = self.dots {
|
else if let Dots::DotDotNext = self.dots {
|
||||||
self.dots = Dots::FilesNext;
|
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)))
|
.map_err(|e| (self.parent(), e)))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -55,6 +55,13 @@ 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 compiled files).
|
/// as looking up compiled files).
|
||||||
pub parent_dir: Option<&'dir Dir>,
|
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> {
|
impl<'dir> File<'dir> {
|
||||||
@ -68,8 +75,30 @@ impl<'dir> File<'dir> {
|
|||||||
|
|
||||||
debug!("Statting file {:?}", &path);
|
debug!("Statting file {:?}", &path);
|
||||||
let metadata = fs::symlink_metadata(&path)?;
|
let metadata = fs::symlink_metadata(&path)?;
|
||||||
|
let is_all_all = false;
|
||||||
|
|
||||||
Ok(File { path, parent_dir, metadata, ext, name })
|
Ok(File { path, parent_dir, metadata, ext, name, is_all_all })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_aa_current(parent_dir: &'dir Dir) -> IOResult<File<'dir>> {
|
||||||
|
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<File<'dir>> {
|
||||||
|
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 })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A file’s name is derived from its string. This needs to handle directories
|
/// A file’s name is derived from its string. This needs to handle directories
|
||||||
@ -219,7 +248,7 @@ impl<'dir> File<'dir> {
|
|||||||
Ok(metadata) => {
|
Ok(metadata) => {
|
||||||
let ext = File::ext(&path);
|
let ext = File::ext(&path);
|
||||||
let name = File::filename(&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) => {
|
Err(e) => {
|
||||||
error!("Error following link {:?}: {:#?}", &path, e);
|
error!("Error following link {:?}: {:#?}", &path, e);
|
||||||
|
Loading…
Reference in New Issue
Block a user