dir.rs 2.6 KB
Newer Older
1 2 3
use std::io;
use std::fs;
use std::path::{Path, PathBuf};
4
use std::slice::Iter as SliceIter;
5

B
Ben S 已提交
6 7 8 9
use feature::Git;
use file::{File, fields};


B
Ben S 已提交
10 11 12 13 14 15
/// A **Dir** provides a cached list of the file paths in a directory that's
/// being listed.
///
/// This object gets passed to the Files themselves, in order for them to
/// check the existence of surrounding files, then highlight themselves
/// accordingly. (See `File#get_source_files`)
B
Ben S 已提交
16
pub struct Dir {
17 18
    contents: Vec<PathBuf>,
    path: PathBuf,
B
Ben S 已提交
19
    git: Option<Git>,
B
Ben S 已提交
20 21
}

B
Ben S 已提交
22
impl Dir {
23

B
Ben S 已提交
24 25
    /// Create a new Dir object filled with all the files in the directory
    /// pointed to by the given path. Fails if the directory can't be read, or
26 27
    /// isn't actually a directory, or if there's an IO error that occurs
    /// while scanning.
28
    pub fn readdir(path: &Path, git: bool) -> io::Result<Dir> {
29 30 31 32 33
        let reader = try!(fs::read_dir(path));
        let contents = try!(reader.map(|e| e.map(|e| e.path())).collect());

        Ok(Dir {
            contents: contents,
34
            path: path.to_path_buf(),
35
            git: if git { Git::scan(path).ok() } else { None },
B
Ben S 已提交
36
        })
B
Ben S 已提交
37 38
    }

39 40
    /// Produce an iterator of IO results of trying to read all the files in
    /// this directory.
41
    pub fn files<'dir>(&'dir self) -> Files<'dir> {
42 43 44
        Files {
            inner: self.contents.iter(),
            dir: &self,
B
Ben S 已提交
45
        }
B
Ben S 已提交
46 47
    }

B
Ben S 已提交
48
    /// Whether this directory contains a file with the given path.
B
Ben S 已提交
49
    pub fn contains(&self, path: &Path) -> bool {
50
        self.contents.iter().any(|ref p| p.as_path() == path)
B
Ben S 已提交
51
    }
B
Ben S 已提交
52 53

    /// Append a path onto the path specified by this directory.
54
    pub fn join(&self, child: &Path) -> PathBuf {
B
Ben S 已提交
55 56
        self.path.join(child)
    }
B
Ben S 已提交
57 58 59 60 61 62 63

    /// Return whether there's a Git repository on or above this directory.
    pub fn has_git_repo(&self) -> bool {
        self.git.is_some()
    }

    /// Get a string describing the Git status of the given file.
B
Ben S 已提交
64
    pub fn git_status(&self, path: &Path, prefix_lookup: bool) -> fields::Git {
B
Ben S 已提交
65
        match (&self.git, prefix_lookup) {
B
Ben S 已提交
66 67
            (&Some(ref git), false)  => git.status(path),
            (&Some(ref git), true)   => git.dir_status(path),
B
Ben S 已提交
68
            (&None, _)               => fields::Git::empty()
B
Ben S 已提交
69 70
        }
    }
B
Ben S 已提交
71
}
72 73 74 75 76 77 78 79


pub struct Files<'dir> {
    inner: SliceIter<'dir, PathBuf>,
    dir: &'dir Dir,
}

impl<'dir> Iterator for Files<'dir> {
B
Ben S 已提交
80
    type Item = Result<File<'dir>, (PathBuf, io::Error)>;
81 82

    fn next(&mut self) -> Option<Self::Item> {
83
        self.inner.next().map(|path| File::from_path(path, Some(self.dir)).map_err(|t| (path.clone(), t)))
84 85
    }
}