devlog/
file.rs

1//! Load and parse a devlog entry file.
2
3use crate::task::Task;
4use std::fs::File;
5use std::io::Error as IOError;
6use std::io::{BufRead, BufReader};
7use std::path::Path;
8
9/// Represents a devlog entry file.
10pub struct LogFile {
11    tasks: Vec<Task>,
12}
13
14impl LogFile {
15    /// Loads and parses the devlog entry file at `path`
16    pub fn load(path: &Path) -> Result<LogFile, IOError> {
17        let f = File::open(path)?;
18        let r = BufReader::new(f);
19        let mut tasks = Vec::new();
20        for line in r.lines() {
21            if let Some(task) = Task::from_string(&line?) {
22                tasks.push(task)
23            }
24        }
25        Ok(LogFile { tasks })
26    }
27
28    /// Returns the tasks contained in the devlog entry file.
29    pub fn tasks(&self) -> &[Task] {
30        &self.tasks
31    }
32}
33
34#[cfg(test)]
35mod tests {
36    use super::*;
37    use crate::task::{Task, TaskStatus};
38    use std::fs::OpenOptions;
39    use std::io::Write;
40    use tempfile::tempdir;
41
42    #[test]
43    fn test_load() {
44        let dir = tempdir().unwrap();
45        let p = dir.path().join("testlog");
46        let mut f = OpenOptions::new()
47            .write(true)
48            .create(true)
49            .open(&p)
50            .unwrap();
51        write!(f, "+ DONE\n").unwrap();
52        write!(f, "- BLOCKED\n").unwrap();
53        write!(f, "* INCOMPLETE\n").unwrap();
54        write!(f, "COMMENT\n").unwrap();
55
56        let lf = LogFile::load(&p).unwrap();
57        let expected = vec![
58            Task::new(TaskStatus::Done, "DONE"),
59            Task::new(TaskStatus::Blocked, "BLOCKED"),
60            Task::new(TaskStatus::ToDo, "INCOMPLETE"),
61        ];
62        assert_eq!(lf.tasks(), &expected[..]);
63    }
64}