aboutsummaryrefslogtreecommitdiffstats
path: root/crates/atuin-client
diff options
context:
space:
mode:
authorJames Trew <66286082+jamestrew@users.noreply.github.com>2025-03-09 18:34:49 -0400
committerGitHub <noreply@github.com>2025-03-09 22:34:49 +0000
commitc05b8f6879bad7fa9a49094b15a39a45a0b458d6 (patch)
tree57dcac9d789ed010d774030b439198f35c7f1367 /crates/atuin-client
parentfeat: make new arrow key behavior configurable (#2606) (diff)
downloadatuin-c05b8f6879bad7fa9a49094b15a39a45a0b458d6.zip
fix: improve broken symlink error handling (#2589)
Check atuin setting paths (eg. `db_path`) for broken symlinks on initialization and disable all shell hooks + print error message. sqlite doesn't create db files even with `.create_if_missing` when the db files are a broken symlink. This would cause sqlite to error and atuin to panic on every single keypress. Also improves related error handling when calling atuin client commands directly.
Diffstat (limited to 'crates/atuin-client')
-rw-r--r--crates/atuin-client/src/database.rs9
-rw-r--r--crates/atuin-client/src/record/sqlite_store.rs9
-rw-r--r--crates/atuin-client/src/settings.rs32
3 files changed, 34 insertions, 16 deletions
diff --git a/crates/atuin-client/src/database.rs b/crates/atuin-client/src/database.rs
index 5bdbb75c..b64ff4ce 100644
--- a/crates/atuin-client/src/database.rs
+++ b/crates/atuin-client/src/database.rs
@@ -130,8 +130,12 @@ impl Sqlite {
let path = path.as_ref();
debug!("opening sqlite database at {:?}", path);
- let create = !path.exists();
- if create {
+ if utils::broken_symlink(path) {
+ eprintln!("Atuin: Sqlite db path ({path:?}) is a broken symlink. Unable to read or create replacement.");
+ std::process::exit(1);
+ }
+
+ if !path.exists() {
if let Some(dir) = path.parent() {
fs::create_dir_all(dir)?;
}
@@ -150,7 +154,6 @@ impl Sqlite {
.await?;
Self::setup_db(&pool).await?;
-
Ok(Self { pool })
}
diff --git a/crates/atuin-client/src/record/sqlite_store.rs b/crates/atuin-client/src/record/sqlite_store.rs
index 2937dbd7..c42476d4 100644
--- a/crates/atuin-client/src/record/sqlite_store.rs
+++ b/crates/atuin-client/src/record/sqlite_store.rs
@@ -17,6 +17,7 @@ use sqlx::{
use atuin_common::record::{
EncryptedData, Host, HostId, Record, RecordId, RecordIdx, RecordStatus,
};
+use atuin_common::utils;
use uuid::Uuid;
use super::encryption::PASETO_V4;
@@ -33,8 +34,12 @@ impl SqliteStore {
debug!("opening sqlite database at {:?}", path);
- let create = !path.exists();
- if create {
+ if utils::broken_symlink(path) {
+ eprintln!("Atuin: Sqlite db path ({path:?}) is a broken symlink. Unable to read or create replacement.");
+ std::process::exit(1);
+ }
+
+ if !path.exists() {
if let Some(dir) = path.parent() {
fs::create_dir_all(dir)?;
}
diff --git a/crates/atuin-client/src/settings.rs b/crates/atuin-client/src/settings.rs
index c01281c7..a1b0724f 100644
--- a/crates/atuin-client/src/settings.rs
+++ b/crates/atuin-client/src/settings.rs
@@ -3,6 +3,7 @@ use std::{
};
use atuin_common::record::HostId;
+use atuin_common::utils;
use clap::ValueEnum;
use config::{
builder::DefaultState, Config, ConfigBuilder, Environment, File as ConfigFile, FileFormat,
@@ -852,24 +853,33 @@ impl Settings {
.map_err(|e| eyre!("failed to deserialize: {}", e))?;
// all paths should be expanded
- let db_path = settings.db_path;
- let db_path = shellexpand::full(&db_path)?;
- settings.db_path = db_path.to_string();
-
- let key_path = settings.key_path;
- let key_path = shellexpand::full(&key_path)?;
- settings.key_path = key_path.to_string();
-
- let session_path = settings.session_path;
- let session_path = shellexpand::full(&session_path)?;
- settings.session_path = session_path.to_string();
+ settings.db_path = Self::expand_path(settings.db_path)?;
+ settings.record_store_path = Self::expand_path(settings.record_store_path)?;
+ settings.key_path = Self::expand_path(settings.key_path)?;
+ settings.session_path = Self::expand_path(settings.session_path)?;
Ok(settings)
}
+ fn expand_path(path: String) -> Result<String> {
+ shellexpand::full(&path)
+ .map(|p| p.to_string())
+ .map_err(|e| eyre!("failed to expand path: {}", e))
+ }
+
pub fn example_config() -> &'static str {
EXAMPLE_CONFIG
}
+
+ pub fn paths_ok(&self) -> bool {
+ let paths = [
+ &self.db_path,
+ &self.record_store_path,
+ &self.key_path,
+ &self.session_path,
+ ];
+ paths.iter().all(|p| !utils::broken_symlink(p))
+ }
}
impl Default for Settings {