From af6bfadff8fe090b032f713e41dd2df34fb6cb5d Mon Sep 17 00:00:00 2001 From: Markus Scully Date: Thu, 7 Aug 2025 16:27:39 +0300 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=E2=9C=A8=E2=99=BB=EF=B8=8F=20cli,?= =?UTF-8?q?=20vanth,=20vanth=20tests:=20Refactor=20store=20initialization?= =?UTF-8?q?=20and=20add=20trace=20logging?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fixed CLI commands to prevent creating databases unnecessarily by using `StoreParams` with `create_if_not_exists: false` for `get`, `get_all`, `delete`, and `delete_all` commands. - Refactored `Store::sqlite_from_path` to accept `StoreParams` and dynamically generate SQLite open flags. - Added trace logging for received JSON content in `handle_write` command. --- crates/cli/src/cli.rs | 46 +++++++++++++++++++++---- crates/vanth/src/store.rs | 24 +++++++++++-- crates/vanth/tests/integration/store.rs | 4 +-- 3 files changed, 63 insertions(+), 11 deletions(-) diff --git a/crates/cli/src/cli.rs b/crates/cli/src/cli.rs index 6af5562..c8cce52 100644 --- a/crates/cli/src/cli.rs +++ b/crates/cli/src/cli.rs @@ -1,9 +1,13 @@ use clap::{Args, Parser, Subcommand}; +use tracing::trace; use std::io::{self, Read}; use std::path::PathBuf; use std::process; -use vanth::{ContentHash, store::Store, Ty}; use vanth::hash as vanth_hash; +use vanth::{ + ContentHash, Ty, + store::{Store, StoreParams}, +}; #[derive(Parser, Debug)] #[command(name = "vanth")] @@ -104,7 +108,7 @@ fn parse_hash(s: &str) -> ContentHash { } fn handle_write(args: &WriteArgs) { - let mut store = Store::sqlite_from_path(args.db.clone()).unwrap_or_else(|e| { + let mut store = Store::sqlite_from_path(args.db.clone(), StoreParams::default()).unwrap_or_else(|e| { eprintln!("Error opening store: {:?}", e); process::exit(1); }); @@ -119,6 +123,8 @@ fn handle_write(args: &WriteArgs) { process::exit(1); }); } + + trace!("Received JSON content: {}", content); let value: serde_json::Value = serde_json::from_str(&content).unwrap_or_else(|e| { eprintln!("Invalid JSON: {}", e); @@ -134,7 +140,14 @@ fn handle_write(args: &WriteArgs) { } fn handle_get(args: &GetArgs) { - let mut store = Store::sqlite_from_path(args.db.clone()).unwrap_or_else(|e| { + let mut store = Store::sqlite_from_path( + args.db.clone(), + StoreParams { + create_if_not_exists: false, + ..Default::default() + }, + ) + .unwrap_or_else(|e| { eprintln!("Error opening store: {:?}", e); process::exit(1); }); @@ -160,7 +173,14 @@ fn handle_get(args: &GetArgs) { } fn handle_get_all(args: &GetAllArgs) { - let mut store = Store::sqlite_from_path(args.db.clone()).unwrap_or_else(|e| { + let mut store = Store::sqlite_from_path( + args.db.clone(), + StoreParams { + create_if_not_exists: false, + ..Default::default() + }, + ) + .unwrap_or_else(|e| { eprintln!("Error opening store: {:?}", e); process::exit(1); }); @@ -180,7 +200,14 @@ fn handle_get_all(args: &GetAllArgs) { } fn handle_delete(args: &DeleteArgs) { - let mut store = Store::sqlite_from_path(args.db.clone()).unwrap_or_else(|e| { + let mut store = Store::sqlite_from_path( + args.db.clone(), + StoreParams { + create_if_not_exists: false, + ..Default::default() + }, + ) + .unwrap_or_else(|e| { eprintln!("Error opening store: {:?}", e); process::exit(1); }); @@ -188,7 +215,14 @@ fn handle_delete(args: &DeleteArgs) { } fn handle_delete_all(args: &DeleteAllArgs) { - let mut store = Store::sqlite_from_path(args.db.clone()).unwrap_or_else(|e| { + let mut store = Store::sqlite_from_path( + args.db.clone(), + StoreParams { + create_if_not_exists: false, + ..Default::default() + }, + ) + .unwrap_or_else(|e| { eprintln!("Error opening store: {:?}", e); process::exit(1); }); diff --git a/crates/vanth/src/store.rs b/crates/vanth/src/store.rs index f925743..b60b8b8 100644 --- a/crates/vanth/src/store.rs +++ b/crates/vanth/src/store.rs @@ -58,10 +58,27 @@ impl Default for StoreParams { impl Store { /// Use an SQLite backend with a database file at the provided path. - // TODO: Params - pub fn sqlite_from_path(path: PathBuf) -> Result { + pub fn sqlite_from_path(path: PathBuf, params: StoreParams) -> Result { + use rusqlite::OpenFlags; + // Base flags for URI handling and disabling mutexes. + let mut flags = OpenFlags::SQLITE_OPEN_URI | OpenFlags::SQLITE_OPEN_NO_MUTEX; + + // Read‑only takes precedence over read‑write. + if params.read_only { + flags |= OpenFlags::SQLITE_OPEN_READ_ONLY; + } else { + flags |= OpenFlags::SQLITE_OPEN_READ_WRITE; + } + + // Create the file if allowed. + if params.create_if_not_exists { + flags |= OpenFlags::SQLITE_OPEN_CREATE; + } + + // Open the SQLite connection with the computed flags. + let connection = rusqlite::Connection::open_with_flags(path, flags)?; Ok(Self { - backend: Box::new(Sqlite::new(path)?), + backend: Box::new(Sqlite { connection }), }) } @@ -154,6 +171,7 @@ pub struct Sqlite { } impl Sqlite { + // TODO: Use this instead of directly constructing the connection in `Store`. pub fn new(path: PathBuf) -> Result { use rusqlite::OpenFlags; // Remove the `SQLITE_OPEN_CREATE` flag because we do not want to create databases if they don't exist. diff --git a/crates/vanth/tests/integration/store.rs b/crates/vanth/tests/integration/store.rs index ff57d89..331ba64 100644 --- a/crates/vanth/tests/integration/store.rs +++ b/crates/vanth/tests/integration/store.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use std::path::PathBuf; use tempfile::TempDir; -use vanth::{Vanth, hash, store::Store}; +use vanth::{Vanth, hash, store::{Store, StoreParams}}; #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Vanth)] struct Foo { @@ -17,7 +17,7 @@ struct Bar { fn test_sqlite_store() { let dir = TempDir::new().unwrap(); let path = dir.path().join("test.db"); - let mut store = Store::sqlite_from_path(path.clone()).unwrap(); + let mut store = Store::sqlite_from_path(path.clone(), StoreParams::default()).unwrap(); let foo_1 = Foo { inner: 1 }; let foo_2 = Foo { inner: 2 };