diff options
| author | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2026-07-20 23:00:06 +0200 |
|---|---|---|
| committer | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2026-07-20 23:00:06 +0200 |
| commit | 2f671f196e245ac1a791c001286e401a2fab9d3a (patch) | |
| tree | be90d8f16d5c8b65c6b77ebe1359d22e9738bbf6 /crates/daemon/src/aclient/database | |
| parent | chore: Commit (diff) | |
| download | atuin-2f671f196e245ac1a791c001286e401a2fab9d3a.zip | |
chore: Commit
Diffstat (limited to '')
| -rw-r--r-- | crates/daemon/src/aclient/database/mod.rs | 145 |
1 files changed, 62 insertions, 83 deletions
diff --git a/crates/daemon/src/aclient/database/mod.rs b/crates/daemon/src/aclient/database/mod.rs index cdf71065..9da943ca 100644 --- a/crates/daemon/src/aclient/database/mod.rs +++ b/crates/daemon/src/aclient/database/mod.rs @@ -12,8 +12,8 @@ use sqlx::{ }; use time::OffsetDateTime; use tracing::debug; -use turtle::history::{History, HistoryId, get_host_user}; -use turtle_common::utils; +use turtle::history::{History, HistoryId}; +use turtle_common::utils::{self, get_host_user}; use uuid::Uuid; use crate::aclient::{ @@ -25,46 +25,29 @@ use crate::aclient::{settings::Settings, utils::setup_db}; #[derive(Clone)] pub(crate) struct Context { - pub(crate) session: String, - pub(crate) cwd: String, - pub(crate) hostname: String, - pub(crate) host_id: String, - pub(crate) git_root: Option<PathBuf>, + session: String, + cwd: String, + hostname: String, + host_id: String, + git_root: Option<PathBuf>, } #[derive(Default, Clone)] -pub(crate) struct OptFilters { - pub(crate) exit: Option<i64>, - pub(crate) exclude_exit: Option<i64>, - pub(crate) cwd: Option<String>, - pub(crate) exclude_cwd: Option<String>, - pub(crate) before: Option<String>, - pub(crate) after: Option<String>, - pub(crate) limit: Option<i64>, - pub(crate) offset: Option<i64>, - pub(crate) reverse: bool, - pub(crate) include_duplicates: bool, -} - -pub(crate) async fn current_context(session: String) -> eyre::Result<Context> { - // TODO(@bpeetz): More of this needs to be moved to the client <2026-07-20> - - let hostname = get_host_user(); - let cwd = utils::get_current_dir(); - let host_id = Settings::host_id().await?; - let git_root = utils::in_git_repo(cwd.as_str()); - - Ok(Context { - session, - hostname, - cwd, - git_root, - host_id: host_id.0.as_simple().to_string(), - }) +struct OptFilters { + exit: Option<i64>, + exclude_exit: Option<i64>, + cwd: Option<String>, + exclude_cwd: Option<String>, + before: Option<String>, + after: Option<String>, + limit: Option<i64>, + offset: Option<i64>, + reverse: bool, + include_duplicates: bool, } impl Context { - pub(crate) fn from_history(entry: &History) -> Self { + fn from_history(entry: &History) -> Self { Self { session: entry.session.clone(), cwd: entry.cwd.clone(), @@ -88,12 +71,12 @@ fn get_session_start_time(session_id: &str) -> Option<i64> { // Intended for use on a developer machine and not a sync server. // TODO: implement IntoIterator #[derive(Debug, Clone)] -pub struct ClientSqlite { - pub(crate) pool: SqlitePool, +pub(crate) struct ClientSqlite { + pool: SqlitePool, } impl ClientSqlite { - pub async fn new(path: impl AsRef<Path>, timeout: f64) -> Result<Self> { + pub(crate) async fn new(path: impl AsRef<Path>, timeout: f64) -> Result<Self> { fn mk_opts(path: &str) -> Result<SqliteConnectOptions> { let opts = SqliteConnectOptions::from_str(path)? .journal_mode(SqliteJournalMode::Wal) @@ -220,7 +203,7 @@ impl ClientSqlite { Ok(()) } - pub(crate) async fn load(&self, id: &str) -> Result<Option<History>> { + async fn load(&self, id: &str) -> Result<Option<History>> { debug!("loading history item {}", id); let res = sqlx::query("select * from history where id = ?1") @@ -232,11 +215,10 @@ impl ClientSqlite { Ok(res) } - // make a unique list, that only shows the *newest* version of things + /// make a unique list, that only shows the *newest* version of things pub(crate) async fn list( &self, - filters: &[FilterMode], - context: &Context, + filters: Option<(&Context, &[FilterMode])>, max: Option<usize>, unique: bool, include_deleted: bool, @@ -249,28 +231,30 @@ impl ClientSqlite { query.and_where_is_null("deleted_at"); } - let git_root = context.git_root.clone().map_or_else( - || context.cwd.clone(), - |git_root| git_root.to_str().unwrap_or("/").to_string(), - ); + if let Some((context, filters)) = filters { + let git_root = context.git_root.clone().map_or_else( + || context.cwd.clone(), + |git_root| git_root.to_str().unwrap_or("/").to_string(), + ); - let session_start = get_session_start_time(&context.session); + let session_start = get_session_start_time(&context.session); - for filter in filters { - match filter { - FilterMode::Global => &mut query, - FilterMode::Host => query.and_where_eq("hostname", quote(&context.hostname)), - FilterMode::Session => query.and_where_eq("session", quote(&context.session)), - FilterMode::SessionPreload => { - query.and_where_eq("session", quote(&context.session)); - if let Some(session_start) = session_start { - query.or_where_lt("timestamp", session_start); + for filter in filters { + match filter { + FilterMode::Global => &mut query, + FilterMode::Host => query.and_where_eq("hostname", quote(&context.hostname)), + FilterMode::Session => query.and_where_eq("session", quote(&context.session)), + FilterMode::SessionPreload => { + query.and_where_eq("session", quote(&context.session)); + if let Some(session_start) = session_start { + query.or_where_lt("timestamp", session_start); + } + &mut query } - &mut query - } - FilterMode::Directory => query.and_where_eq("cwd", quote(&context.cwd)), - FilterMode::Workspace => query.and_where_like_left("cwd", &git_root), - }; + FilterMode::Directory => query.and_where_eq("cwd", quote(&context.cwd)), + FilterMode::Workspace => query.and_where_like_left("cwd", &git_root), + }; + } } if unique { @@ -310,7 +294,7 @@ impl ClientSqlite { Ok(res) } - pub(crate) async fn last(&self) -> Result<Option<History>> { + async fn last(&self) -> Result<Option<History>> { let res = sqlx::query( "select * from history where duration >= 0 order by timestamp desc limit 1", ) @@ -321,7 +305,7 @@ impl ClientSqlite { Ok(res) } - pub(crate) async fn history_count(&self, include_deleted: bool) -> Result<i64> { + async fn history_count(&self, include_deleted: bool) -> Result<i64> { let query = if include_deleted { "select count(1) from history" } else { @@ -336,7 +320,7 @@ impl ClientSqlite { // Could maybe break it down to a searchparams struct or smth but that feels a little... pointless. // Been debating maybe a DSL for search? eg "before:time limit:1 the query" #[expect(clippy::too_many_lines)] - pub(crate) async fn search( + async fn search( &self, search_mode: SearchMode, filter: FilterMode, @@ -492,7 +476,7 @@ impl ClientSqlite { Ok(ordering::reorder_fuzzy(search_mode, orig_query, res)) } - pub(crate) async fn query_history(&self, query: &str) -> Result<Vec<History>> { + async fn query_history(&self, query: &str) -> Result<Vec<History>> { let res = sqlx::query(query) .map(Self::query_history_inner) .fetch_all(&self.pool) @@ -501,7 +485,7 @@ impl ClientSqlite { Ok(res) } - pub(crate) async fn all_with_count(&self) -> Result<Vec<(History, i32)>> { + async fn all_with_count(&self) -> Result<Vec<(History, i32)>> { debug!("listing history"); let mut query = SqlBuilder::select_from(SqlName::new("history").alias("h").baquoted()); @@ -539,7 +523,7 @@ impl ClientSqlite { Ok(res) } - pub(crate) fn all_paged(&self, page_size: usize, include_deleted: bool, unique: bool) -> Paged { + fn all_paged(&self, page_size: usize, include_deleted: bool, unique: bool) -> Paged { Paged::new(self.clone(), page_size, include_deleted, unique) } @@ -555,7 +539,7 @@ impl ClientSqlite { Ok(()) } - pub(crate) async fn stats(&self, h: &History) -> Result<HistoryStats> { + async fn stats(&self, h: &History) -> Result<HistoryStats> { // We select the previous in the session by time let mut prev = SqlBuilder::select_from("history"); prev.field("*") @@ -672,7 +656,7 @@ impl ClientSqlite { }) } - pub(crate) async fn get_dups(&self, before: i64, dupkeep: u32) -> Result<Vec<History>> { + async fn get_dups(&self, before: i64, dupkeep: u32) -> Result<Vec<History>> { let res = sqlx::query( "SELECT * FROM ( SELECT *, ROW_NUMBER() @@ -693,7 +677,7 @@ impl ClientSqlite { } } -pub(crate) struct Paged { +struct Paged { database: ClientSqlite, page_size: usize, last_id: Option<String>, @@ -702,12 +686,7 @@ pub(crate) struct Paged { } impl Paged { - pub(crate) fn new( - database: ClientSqlite, - page_size: usize, - include_deleted: bool, - unique: bool, - ) -> Self { + fn new(database: ClientSqlite, page_size: usize, include_deleted: bool, unique: bool) -> Self { Self { database, page_size, @@ -717,7 +696,7 @@ impl Paged { } } - pub(crate) async fn next(&mut self) -> Result<Option<Vec<History>>> { + async fn next(&mut self) -> Result<Option<Vec<History>>> { let mut query = SqlBuilder::select_from(SqlName::new("history").alias("h").baquoted()); query.field("*").order_desc("id"); @@ -1220,12 +1199,12 @@ mod test { } } -pub(crate) struct QueryTokenizer<'a> { +struct QueryTokenizer<'a> { query: &'a str, last_pos: usize, } -pub(crate) enum QueryToken<'a> { +enum QueryToken<'a> { Match(&'a str, bool), MatchStart(&'a str, bool), MatchEnd(&'a str, bool), @@ -1235,7 +1214,7 @@ pub(crate) enum QueryToken<'a> { } impl QueryToken<'_> { - pub(crate) fn has_uppercase(&self) -> bool { + fn has_uppercase(&self) -> bool { match self { Self::Match(term, _) | Self::MatchStart(term, _) @@ -1245,7 +1224,7 @@ impl QueryToken<'_> { } } - pub(crate) fn is_inverse(&self) -> bool { + fn is_inverse(&self) -> bool { match self { Self::Match(_, inv) | Self::MatchStart(_, inv) @@ -1257,7 +1236,7 @@ impl QueryToken<'_> { } impl<'a> QueryTokenizer<'a> { - pub(crate) fn new(query: &'a str) -> Self { + fn new(query: &'a str) -> Self { Self { query, last_pos: 0 } } } |
