diff --git a/Cargo.lock b/Cargo.lock index efc7e3b..f4c6612 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -55,6 +55,17 @@ dependencies = [ "hybrid-array", ] +[[package]] +name = "bstr" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb31b46c14244e20ee9984b11bf5c992b91fb6939fea616e3512c8baecdbe5f" +dependencies = [ + "memchr", + "regex-automata", + "serde_core", +] + [[package]] name = "bumpalo" version = "3.20.3" @@ -264,6 +275,7 @@ dependencies = [ "postgres-native-tls", "ratatui", "rusqlite", + "shellexpand", "tempfile", ] @@ -307,6 +319,27 @@ dependencies = [ "ctutils", ] +[[package]] +name = "dirs" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys", +] + [[package]] name = "document-features" version = "0.2.12" @@ -766,6 +799,21 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "os_str_bytes" +version = "6.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" +dependencies = [ + "memchr", +] + [[package]] name = "palette" version = "0.7.7" @@ -1042,6 +1090,22 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_users" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60dc65c0ff1a7ae1294b0c67b9f14baf70b644404010370171787bfac1038fc0" +dependencies = [ + "libredox", + "thiserror", +] + +[[package]] +name = "regex-automata" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" + [[package]] name = "rusqlite" version = "0.40.2" @@ -1174,6 +1238,17 @@ dependencies = [ "digest", ] +[[package]] +name = "shellexpand" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32824fab5e16e6c4d86dc1ba84489390419a39f97699852b66480bb87d297ed8" +dependencies = [ + "bstr", + "dirs", + "os_str_bytes", +] + [[package]] name = "shlex" version = "2.0.1" diff --git a/Cargo.toml b/Cargo.toml index 0168156..4cc47f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ postgres = "0.19" postgres-native-tls = "0.5" native-tls = "0.2" rusqlite = { version = "0.40", default-features = false, features = ["bundled"] } +shellexpand = { version = "3.1", features = ["path"] } [dev-dependencies] tempfile = "3" diff --git a/src/db/sqlite.rs b/src/db/sqlite.rs index 8b94ac0..ea26eea 100644 --- a/src/db/sqlite.rs +++ b/src/db/sqlite.rs @@ -7,7 +7,7 @@ use crate::Result; pub(super) fn open(path: &Path) -> Result { // An absolute existing path also prevents SQLite's special :memory: filename from creating a database. - let path = path.canonicalize()?; + let path = shellexpand::path::full(path)?.canonicalize()?; let connection = Connection::open_with_flags( path, OpenFlags::SQLITE_OPEN_READ_ONLY | OpenFlags::SQLITE_OPEN_NO_MUTEX, diff --git a/src/main.rs b/src/main.rs index 4c3726b..df27f74 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,6 +20,8 @@ Use the in-app password field to keep credentials out of process arguments. Open an existing SQLite database file (read-only; missing files are not created): cargo run -- --sqlite ./database.sqlite SQLite paths can be relative or absolute; quote paths containing spaces. +SQLite paths expand leading ~, $VAR, and ${VAR}; undefined variables are errors. +Expansion never runs shell commands. Quote CLI paths to let dbdash expand them. PostgreSQL URLs and libpq-style key=value strings are accepted. Use sslmode=require for mandatory TLS; certificates and hostnames are verified.