فهرست منبع

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.
Ben S 11 سال پیش
والد
کامیت
92b45e6908
3فایلهای تغییر یافته به همراه37 افزوده شده و 22 حذف شده
  1. 19 9
      dir.rs
  2. 12 3
      exa.rs
  3. 6 10
      file.rs

+ 19 - 9
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<Dir<'a>> {
+        fs::readdir(&path).map(|paths| Dir {
+            contents: paths,
+        })
     }
 
     pub fn files(&'a self) -> Vec<File<'a>> {
-        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 {

+ 12 - 3
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);
 

+ 6 - 10
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<File<'a>> {
         // 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> {