diff --git a/pttodoer/src/main.rs b/pttodoer/src/main.rs index 7b63e9d..d00235d 100644 --- a/pttodoer/src/main.rs +++ b/pttodoer/src/main.rs @@ -40,6 +40,86 @@ impl Flags { } } +#[derive(Debug)] +pub struct DB(Vec); + +impl DB { + pub fn new(path: String) -> Result { + let metadata = match std::fs::metadata(path.clone()) { + Ok(v) => Ok(v), + Err(msg) => Err(format!("failed to load {}: {}", path, msg)), + }?; + let mut files = vec![]; + if metadata.is_file() { + files.push(path.clone()); + } else if metadata.is_dir() { + match std::fs::read_dir(path.clone()) { + Ok(paths) => { + files.extend(paths + .filter(|x| x.is_ok()) + .map(|x| x.unwrap()) + .filter(|x| x.metadata().unwrap().is_file()) + .map(|x| x.path().display().to_string()) + ); + Ok(()) + }, + Err(msg) => Err(format!("failed to read {}: {}", path.clone(), msg)), + }?; + } + + let mut result = vec![]; + for file in files { + let item = TasksAndMetadata::new(file)?; + result.push(item); + } + Ok(DB(result)) + } +} + +#[cfg(test)] +mod test_taskss { + use super::*; + + #[test] + fn read_dir_files() { + _ = DB::new("./src/testdata/taskss.d/files.d".to_string()).expect("failed to construct from dir of files"); + } + + #[test] + fn read_dir_file() { + _ = DB::new("./src/testdata/taskss.d/file.d".to_string()).expect("failed to construct from dir of a single file"); + } + + #[test] + fn read_single_file() { + _ = DB::new("./src/testdata/taskss.d/single_file.yaml".to_string()).expect("failed to construct from single file"); + } +} + +#[derive(Debug)] +pub struct TasksAndMetadata { + tasks: Tasks, + file: String, + version: TS, +} + +impl TasksAndMetadata { + pub fn new(file: String) -> Result { + let version = match std::fs::metadata(file.clone()) { + Ok(m) => Ok(TS::from_system_time(m.modified().unwrap())), + Err(msg) => Err(format!("couldnt get version from {}: {}", file, msg)), + }?; + match Tasks::from_file(file.clone()) { + Ok(tasks) => Ok(TasksAndMetadata{ + tasks: tasks, + file: file, + version: version, + }), + Err(msg) => Err(msg), + } + } +} + #[derive(Debug, serde::Serialize, serde::Deserialize)] pub struct Tasks(Vec); @@ -48,6 +128,14 @@ impl Tasks { Tasks(vec![]) } + pub fn from_file(path: String) -> Result { + let r = match std::fs::File::open(path.clone()) { + Ok(f) => Ok(f), + Err(msg) => Err(format!("could not open {}: {}", path, msg)), + }?; + Tasks::from_reader(r) + } + pub fn from_reader(r: impl std::io::Read) -> Result { let result = Tasks::_from_reader(r)?; if !result.is_legacy() { @@ -135,9 +223,7 @@ mod test_tasks { #[test] fn due() { - let tasks = Tasks::from_reader( - std::fs::File::open("./src/testdata/tasks_due_scheduled_done.yaml").expect("failed to open file") - ).expect("failed to read file"); + let tasks = Tasks::from_file("./src/testdata/tasks_due_scheduled_done.yaml".to_string()).expect("failed to open file"); eprintln!("{:?}", tasks); assert_eq!(2, tasks.due().len()); } @@ -600,6 +686,10 @@ impl TS { Self::from_unix(Local::now().timestamp() as u64) } + fn from_system_time(st: std::time::SystemTime) -> TS { + TS::from_unix(st.duration_since(std::time::SystemTime::UNIX_EPOCH).unwrap().as_secs()) + } + fn from_unix(src: u64) -> TS { TS{0: src} } diff --git a/pttodoer/src/testdata/taskss.d/file.d/file.yaml b/pttodoer/src/testdata/taskss.d/file.d/file.yaml new file mode 100644 index 0000000..d4c7c05 --- /dev/null +++ b/pttodoer/src/testdata/taskss.d/file.d/file.yaml @@ -0,0 +1 @@ +- file diff --git a/pttodoer/src/testdata/taskss.d/files.d/a.yaml b/pttodoer/src/testdata/taskss.d/files.d/a.yaml new file mode 100644 index 0000000..46ae6f5 --- /dev/null +++ b/pttodoer/src/testdata/taskss.d/files.d/a.yaml @@ -0,0 +1 @@ +- a diff --git a/pttodoer/src/testdata/taskss.d/files.d/b.yaml b/pttodoer/src/testdata/taskss.d/files.d/b.yaml new file mode 100644 index 0000000..7880ae6 --- /dev/null +++ b/pttodoer/src/testdata/taskss.d/files.d/b.yaml @@ -0,0 +1 @@ +- b diff --git a/pttodoer/src/testdata/taskss.d/single_file.yaml b/pttodoer/src/testdata/taskss.d/single_file.yaml new file mode 100644 index 0000000..47b487a --- /dev/null +++ b/pttodoer/src/testdata/taskss.d/single_file.yaml @@ -0,0 +1,4 @@ +- todo +- do: scheduled + schedule: 2099-01-01 +- _done: any