From d6b816d2734e5a0bdefed286439d725710aaa3c6 Mon Sep 17 00:00:00 2001 From: Ross Andrews Date: Sat, 9 May 2026 18:07:24 -0500 Subject: [PATCH] phase 3 --- CLAUDE.md | 16 ++++++++++++++++ src/error.rs | 4 ++++ src/main.rs | 2 +- src/parsing.rs | 26 +++++++++++++++++++++++++- test/file1.md | 1 + test/file2.md | 1 + 6 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 test/file1.md create mode 100644 test/file2.md diff --git a/CLAUDE.md b/CLAUDE.md index 0df9e93..95c7bd6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -90,6 +90,22 @@ The `validate` method should take `&self` and return `Result<(), DrawerError>`. creating a `DrawerOperation` and not using it, also call `validate` and print out the error if there is one. This means we also need to `impl Display` on `DrawerError`. +### Phase 3 + +For phase 3 we want to start implementing the `close` command. We'll get the tar part working but not worry about encryption yet. + +- Make a new method `perform` on `DrawerOperation` which takes `&self` and returns `Result<(), DrawerError>`. +- `perform` should first call `validate` and return the error if there is one. +- After that, it should call either `open(&self)` or `close(&self)` depending on the operation type. For now, `open` will just be a `todo!()` +- The new `close` method should create a vec consisting of the contents of the target directory as a tarball (use the tar create we depend on) +- After creating the vec, it should write it out to the drawer file path. + +I'm going to add some test data to the project under `tests/` but it's just random data to test, ignore the contents of all those files. + +### Phase 3a + +As a minor improvement, make the `perform_close` method also gzip the contents of the tarball. + ## Commands ```bash diff --git a/src/error.rs b/src/error.rs index 186a5d6..fa14c36 100644 --- a/src/error.rs +++ b/src/error.rs @@ -11,6 +11,8 @@ pub enum DrawerError { KeyInvalid(PathBuf), TargetNotEmpty(PathBuf), DrawerInsideTarget, + TarFailed, + WriteFailed(PathBuf), } impl fmt::Display for DrawerError { @@ -24,6 +26,8 @@ impl fmt::Display for DrawerError { DrawerError::KeyInvalid(p) => write!(f, "key not found or not readable: {}", p.display()), DrawerError::TargetNotEmpty(p) => write!(f, "target is not empty: {} (use -f to force)", p.display()), DrawerError::DrawerInsideTarget => write!(f, "drawer file is inside the target directory"), + DrawerError::TarFailed => write!(f, "failed to create tarball"), + DrawerError::WriteFailed(p) => write!(f, "failed to write drawer file: {}", p.display()), } } } diff --git a/src/main.rs b/src/main.rs index 6796f70..63e622c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,7 @@ fn main() { match parse_args(std::env::args_os()) { Err(e) => eprintln!("{e}"), Ok(op) => { - if let Err(e) = op.validate() { + if let Err(e) = op.perform() { eprintln!("{e}"); } } diff --git a/src/parsing.rs b/src/parsing.rs index e27dcf5..837a8d3 100644 --- a/src/parsing.rs +++ b/src/parsing.rs @@ -1,5 +1,4 @@ use std::ffi::OsString; -use std::io; use std::path::{Path, PathBuf}; use clap::{Parser, Subcommand}; use crate::error::DrawerError; @@ -94,6 +93,31 @@ fn resolve_key(key: Option) -> KeyType { } impl DrawerOperation { + pub fn perform(&self) -> Result<(), DrawerError> { + self.validate()?; + match self.operation_type { + OperationType::Open => self.perform_open(), + OperationType::Close => self.perform_close(), + } + } + + fn perform_open(&self) -> Result<(), DrawerError> { + todo!() + } + + fn perform_close(&self) -> Result<(), DrawerError> { + let mut buf: Vec = Vec::new(); + { + let mut archive = tar::Builder::new(&mut buf); + archive.append_dir_all(".", &self.target_path) + .map_err(|_| DrawerError::TarFailed)?; + archive.finish() + .map_err(|_| DrawerError::TarFailed)?; + } + std::fs::write(&self.drawer_file, &buf) + .map_err(|_| DrawerError::WriteFailed(self.drawer_file.clone())) + } + pub fn validate(&self) -> Result<(), DrawerError> { if self.drawer_file.extension().and_then(|e| e.to_str()) != Some("drawer") { return Err(DrawerError::DrawerFileInvalidExtension(self.drawer_file.clone())); diff --git a/test/file1.md b/test/file1.md new file mode 100644 index 0000000..82aa8cb --- /dev/null +++ b/test/file1.md @@ -0,0 +1 @@ +Ignore this diff --git a/test/file2.md b/test/file2.md new file mode 100644 index 0000000..4180b70 --- /dev/null +++ b/test/file2.md @@ -0,0 +1 @@ +Ignore this too