reordered close

This commit is contained in:
2026-05-15 00:42:39 -05:00
parent 04d9f22d41
commit 8e4c2762cd
3 changed files with 48 additions and 34 deletions
+25 -25
View File
@@ -8,32 +8,32 @@ use crate::utils::*;
#[derive(Parser, Debug, PartialEq)]
pub struct CloseOperation {
pub drawer_file: PathBuf,
pub target_path: Option<PathBuf>,
pub target_path: PathBuf,
pub drawer_file: Option<PathBuf>,
#[arg(short = 'i')]
pub key: Option<PathBuf>,
}
impl Operation for CloseOperation {
fn validate(&self) -> Result<(), DrawerError> {
validate_drawer_extension(&self.drawer_file)?;
let drawer_file = self.drawer_file.as_ref().cloned()
.unwrap_or_else(|| self.target_path.with_extension("drawer"));
validate_drawer_extension(&drawer_file)?;
validate_ssh_key(&self.key)?;
let target = self.target_path.as_ref().cloned()
.unwrap_or_else(|| default_target(&self.drawer_file, None));
let meta = std::fs::metadata(&target)
.map_err(|_| DrawerError::TargetInvalid(target.clone()))?;
let meta = std::fs::metadata(&self.target_path)
.map_err(|_| DrawerError::TargetInvalid(self.target_path.clone()))?;
if !meta.is_dir() && !meta.is_file() {
return Err(DrawerError::TargetInvalid(target.clone()));
return Err(DrawerError::TargetInvalid(self.target_path.clone()));
}
if meta.is_dir() && std::fs::read_dir(&target).is_err() {
return Err(DrawerError::TargetInvalid(target.clone()));
if meta.is_dir() && std::fs::read_dir(&self.target_path).is_err() {
return Err(DrawerError::TargetInvalid(self.target_path.clone()));
}
let canon_target = target.canonicalize()
.unwrap_or_else(|_| target.clone());
let drawer_parent = parent_or_dot(&self.drawer_file);
let canon_target = self.target_path.canonicalize()
.unwrap_or_else(|_| self.target_path.clone());
let drawer_parent = parent_or_dot(&drawer_file);
let canon_drawer = drawer_parent.canonicalize()
.unwrap_or_else(|_| drawer_parent.to_path_buf())
.join(self.drawer_file.file_name().unwrap_or_default());
.join(drawer_file.file_name().unwrap_or_default());
if canon_drawer.starts_with(&canon_target) {
return Err(DrawerError::DrawerInsideTarget);
}
@@ -41,22 +41,22 @@ impl Operation for CloseOperation {
}
fn execute(&self) -> Result<(), DrawerError> {
let target = self.target_path.as_ref().cloned()
.unwrap_or_else(|| default_target(&self.drawer_file, None));
if self.target_path.is_none() {
println!("(assuming from {})", target.display());
let drawer_file = self.drawer_file.as_ref().cloned()
.unwrap_or_else(|| self.target_path.with_extension("drawer"));
if self.drawer_file.is_none() {
println!("(creating {})", drawer_file.display());
}
let mut buf: Vec<u8> = Vec::new();
{
let gz = GzEncoder::new(&mut buf, Compression::default());
let mut archive = tar::Builder::new(gz);
if target.is_dir() {
archive.append_dir_all(".", &target)
if self.target_path.is_dir() {
archive.append_dir_all(".", &self.target_path)
.map_err(|_| DrawerError::TarFailed)?;
} else {
let name = target.file_name().unwrap_or_default();
archive.append_path_with_name(&target, name)
let name = self.target_path.file_name().unwrap_or_default();
archive.append_path_with_name(&self.target_path, name)
.map_err(|_| DrawerError::TarFailed)?;
}
let gz = archive.into_inner()
@@ -65,8 +65,8 @@ impl Operation for CloseOperation {
.map_err(|_| DrawerError::TarFailed)?;
}
let encrypted = encrypt(&buf, &self.key, &self.drawer_file)?;
std::fs::write(&self.drawer_file, &encrypted)
.map_err(|_| DrawerError::WriteFailed(self.drawer_file.clone()))
let encrypted = encrypt(&buf, &self.key, &drawer_file)?;
std::fs::write(&drawer_file, &encrypted)
.map_err(|_| DrawerError::WriteFailed(drawer_file.clone()))
}
}
+3 -3
View File
@@ -32,12 +32,12 @@ mod tests {
#[test]
fn test_basic_close() {
let op = parse_args(vec!["drawer", "close", "blah.drawer", "-i", "foo.key", "blah"]);
let op = parse_args(vec!["drawer", "close", "blah", "-i", "foo.key", "blah.drawer"]);
assert_eq!(op, Ok(
Command::Close(CloseOperation{
drawer_file: "blah.drawer".into(),
drawer_file: Some("blah.drawer".into()),
key: Some(PathBuf::from("foo.key")),
target_path: Some("blah".into()),
target_path: "blah".into(),
})
))
}
+20 -6
View File
@@ -47,10 +47,10 @@ err "key: refuse missing parent" $DRAWER key "$WORK/nosuchdir/test.key"
DRAWER_FILE="$WORK/test.drawer"
ok "close: pack test dir" $DRAWER close -i "$KEY" "$DRAWER_FILE" "$TEST_DIR"
err "close: refuse without key" DRAWER_KEY="" $DRAWER close "$DRAWER_FILE" "$TEST_DIR"
err "close: refuse bad key" $DRAWER close -i "$WORK/notakey" "$DRAWER_FILE" "$TEST_DIR"
err "close: refuse bad extension" $DRAWER close -i "$KEY" "$WORK/test.notadrawer" "$TEST_DIR"
ok "close: pack test dir" $DRAWER close -i "$KEY" "$TEST_DIR" "$DRAWER_FILE"
err "close: refuse without key" DRAWER_KEY="" $DRAWER close "$TEST_DIR" "$DRAWER_FILE"
err "close: refuse bad key" $DRAWER close -i "$WORK/notakey" "$TEST_DIR" "$DRAWER_FILE"
err "close: refuse bad extension" $DRAWER close -i "$KEY" "$TEST_DIR" "$WORK/test.notadrawer"
# ── open ─────────────────────────────────────────────────────────────────────
@@ -76,11 +76,25 @@ err "open: refuse bad key" $DRAWER open -i "$WORK/notakey" "$DRAWER_FI
INFER_DRAWER="$WORK/inferred.drawer"
INFER_OUT="$WORK/inferred"
ok "close: inferred source" $DRAWER close -i "$KEY" "$INFER_DRAWER" "$TEST_DIR"
ok "close: inferred source" $DRAWER close -i "$KEY" "$TEST_DIR" "$INFER_DRAWER"
mkdir -p "$INFER_OUT"
ok "open: inferred target" $DRAWER open -i "$KEY" "$INFER_DRAWER" "$INFER_OUT"
ok "open: inferred file1.md" test -f "$INFER_OUT/file1.md"
# ── close: inferred drawer file ──────────────────────────────────────────────
INFER_CLOSE_SRC="$WORK/myproject"
INFER_CLOSE_DRAWER="$WORK/myproject.drawer"
cp -r "$TEST_DIR" "$INFER_CLOSE_SRC"
ok "close: inferred drawer file" $DRAWER close -i "$KEY" "$INFER_CLOSE_SRC"
ok "close: drawer file created" test -f "$INFER_CLOSE_DRAWER"
INFER_CLOSE_OUT="$WORK/myproject_out"
mkdir -p "$INFER_CLOSE_OUT"
ok "close: inferred round-trip open" $DRAWER open -i "$KEY" "$INFER_CLOSE_DRAWER" "$INFER_CLOSE_OUT"
ok "close: inferred round-trip file1" test -f "$INFER_CLOSE_OUT/file1.md"
# ── info ─────────────────────────────────────────────────────────────────────
$DRAWER info -i "$KEY" "$DRAWER_FILE" 2>/dev/null | grep -q "folder, 2 files" \
@@ -96,7 +110,7 @@ SINGLE_DRAWER="$WORK/file1.drawer"
SINGLE_OUT_DIR="$WORK/single_out"
mkdir -p "$SINGLE_OUT_DIR"
ok "close: single file" $DRAWER close -i "$KEY" "$SINGLE_DRAWER" "$SINGLE_SRC"
ok "close: single file" $DRAWER close -i "$KEY" "$SINGLE_SRC" "$SINGLE_DRAWER"
$DRAWER info -i "$KEY" "$SINGLE_DRAWER" 2>/dev/null | grep -q "file, " \
&& pass "info: reports single file" || fail "info: reports single file"
ok "open: single file" $DRAWER open -i "$KEY" "$SINGLE_DRAWER" "$SINGLE_OUT_DIR/file1.md"