From 92b45e6908cab9ad1d1ede535b12f44bf39130b2 Mon Sep 17 00:00:00 2001 From: Ben S Date: Fri, 20 Jun 2014 21:07:53 +0100 Subject: [PATCH] Handle errors instead of fail!()ing Dir::readdir and File::from path now both return IoResults, rather than just calling fail! and exiting. This allows the program to continue after an error. --- dir.rs | 28 +++++++++++++++++++--------- exa.rs | 15 ++++++++++++--- file.rs | 16 ++++++---------- 3 files changed, 37 insertions(+), 22 deletions(-) diff --git a/dir.rs b/dir.rs index 5b4770b..b4c7463 100644 --- a/dir.rs +++ b/dir.rs @@ -1,4 +1,4 @@ -use std::io::fs; +use std::io::{fs, IoResult}; use file::File; // The purpose of a Dir is to provide a cached list of the file paths @@ -12,17 +12,27 @@ pub struct Dir<'a> { } impl<'a> Dir<'a> { - pub fn readdir(path: Path) -> Dir<'a> { - match fs::readdir(&path) { - Ok(paths) => Dir { - contents: paths, - }, - Err(e) => fail!("readdir: {}", e), - } + pub fn readdir(path: Path) -> IoResult> { + fs::readdir(&path).map(|paths| Dir { + contents: paths, + }) } pub fn files(&'a self) -> Vec> { - self.contents.iter().map(|path| File::from_path(path, self)).collect() + let mut files = vec![]; + + for path in self.contents.iter() { + match File::from_path(path, self) { + Ok(file) => { + files.push(file); + } + Err(e) => { + println!("{}: {}", path.filename_str().unwrap(), e); + } + } + } + + files } pub fn contains(&self, path: &Path) -> bool { diff --git a/exa.rs b/exa.rs index 40fa2bd..0d053cf 100644 --- a/exa.rs +++ b/exa.rs @@ -35,14 +35,23 @@ fn main() { }; for dir in strs.move_iter() { - exa(&opts, Path::new(dir)) + exa(&opts, dir) } } }; } -fn exa(options: &Options, path: Path) { - let dir = Dir::readdir(path); +fn exa(options: &Options, string: String) { + let path = Path::new(string.clone()); + + let dir = match Dir::readdir(path) { + Ok(dir) => dir, + Err(e) => { + println!("{}: {}", string, e); + return; + } + }; + let unsorted_files = dir.files(); let files: Vec<&File> = options.transform_files(&unsorted_files); diff --git a/file.rs b/file.rs index 6ed3139..497f23e 100644 --- a/file.rs +++ b/file.rs @@ -1,5 +1,5 @@ -use colours::{Plain, Style, Black, Red, Green, Yellow, Blue, Purple, Cyan, Fixed}; -use std::io::fs; +use colours::{Plain, Style, Black, Red, Green, Yellow, Blue, Purple, Cyan}; +use std::io::{fs, IoResult}; use std::io; use column::{Column, Permissions, FileName, FileSize, User, Group}; @@ -26,7 +26,7 @@ pub struct File<'a> { } impl<'a> File<'a> { - pub fn from_path(path: &'a Path, parent: &'a Dir) -> File<'a> { + pub fn from_path(path: &'a Path, parent: &'a Dir) -> IoResult> { // Getting the string from a filename fails whenever it's not // UTF-8 representable - just assume it is for now. let filename: &str = path.filename_str().unwrap(); @@ -34,19 +34,15 @@ impl<'a> File<'a> { // Use lstat here instead of file.stat(), as it doesn't follow // symbolic links. Otherwise, the stat() call will fail if it // encounters a link that's target is non-existent. - let stat: io::FileStat = match fs::lstat(path) { - Ok(stat) => stat, - Err(e) => fail!("Couldn't stat {}: {}", filename, e), - }; - - return File { + + fs::lstat(path).map(|stat| File { path: path, dir: parent, stat: stat, name: filename, ext: File::ext(filename), parts: SortPart::split_into_parts(filename), - }; + }) } fn ext(name: &'a str) -> Option<&'a str> {