diff options
| author | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2026-06-11 00:54:30 +0200 |
|---|---|---|
| committer | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2026-06-11 00:54:30 +0200 |
| commit | 5c39e7cf284a1f6e9a1657f2deb44e359fc47eb8 (patch) | |
| tree | c64baa8d5866c8e339eaf660dd3f94f30a3f7d8a /crates/atuin/src/command/client/store | |
| parent | chore: Somewhat simplify sync code (diff) | |
| download | atuin-5c39e7cf284a1f6e9a1657f2deb44e359fc47eb8.zip | |
chore: Move everything into one big crate
That helps remove duplicated code and rustc/cargo will now also show
dead code correctly.
Diffstat (limited to 'crates/atuin/src/command/client/store')
| -rw-r--r-- | crates/atuin/src/command/client/store/pull.rs | 94 | ||||
| -rw-r--r-- | crates/atuin/src/command/client/store/purge.rs | 26 | ||||
| -rw-r--r-- | crates/atuin/src/command/client/store/push.rs | 112 | ||||
| -rw-r--r-- | crates/atuin/src/command/client/store/rebuild.rs | 58 | ||||
| -rw-r--r-- | crates/atuin/src/command/client/store/rekey.rs | 41 | ||||
| -rw-r--r-- | crates/atuin/src/command/client/store/verify.rs | 26 |
6 files changed, 0 insertions, 357 deletions
diff --git a/crates/atuin/src/command/client/store/pull.rs b/crates/atuin/src/command/client/store/pull.rs deleted file mode 100644 index 25b925c7..00000000 --- a/crates/atuin/src/command/client/store/pull.rs +++ /dev/null @@ -1,94 +0,0 @@ -use clap::Args; -use eyre::Result; - -use atuin_client::{ - database::Database, - encryption::load_key, - record::store::Store, - record::sync::Operation, - record::{sqlite_store::SqliteStore, sync}, - settings::Settings, -}; - -#[derive(Args, Debug)] -pub struct Pull { - /// The tag to push (eg, 'history'). Defaults to all tags - #[arg(long, short)] - pub tag: Option<String>, - - /// Force push records - /// This will first wipe the local store, and then download all records from the remote - #[arg(long, default_value = "false")] - pub force: bool, - - /// Page Size - /// How many records to download at once. Defaults to 100 - #[arg(long, default_value = "100")] - pub page: u64, -} - -impl Pull { - pub async fn run( - &self, - settings: &Settings, - store: SqliteStore, - db: &dyn Database, - ) -> Result<()> { - if self.force { - println!("Forcing local overwrite!"); - println!("Clearing local store"); - - store.delete_all().await?; - } - - // We can actually just use the existing diff/etc to push - // 1. Diff - // 2. Get operations - // 3. Filter operations by - // a) are they a download op? - // b) are they for the host/tag we are pushing here? - let client = sync::build_client(settings).await?; - let (diff, remote_index) = sync::diff(&client, &store).await?; - - // Skip on --force: local was already wiped above, mismatch is the user's call. - if !self.force { - let key: [u8; 32] = load_key(settings)?.into(); - sync::check_encryption_key(&client, &remote_index, &key) - .await - .map_err(crate::print_error::format_sync_error)?; - } - - let operations = sync::operations(diff, &store).await?; - - let operations = operations - .into_iter() - .filter(|op| match op { - // No noops or downloads thx - Operation::Noop { .. } | Operation::Upload { .. } => false, - - // pull, so yes plz to downloads! - Operation::Download { tag, .. } => { - if self.force { - return true; - } - - if let Some(t) = self.tag.clone() - && t != *tag - { - return false; - } - - true - } - }) - .collect(); - - let (_, downloaded) = sync::sync_remote(&client, operations, &store, self.page).await?; - - println!("Downloaded {} records", downloaded.len()); - - crate::sync::build(settings, &store, db, Some(&downloaded)).await?; - - Ok(()) - } -} diff --git a/crates/atuin/src/command/client/store/purge.rs b/crates/atuin/src/command/client/store/purge.rs deleted file mode 100644 index ad2369ce..00000000 --- a/crates/atuin/src/command/client/store/purge.rs +++ /dev/null @@ -1,26 +0,0 @@ -use clap::Args; -use eyre::Result; - -use atuin_client::{ - encryption::load_key, - record::{sqlite_store::SqliteStore, store::Store}, - settings::Settings, -}; - -#[derive(Args, Debug)] -pub struct Purge {} - -impl Purge { - pub async fn run(&self, settings: &Settings, store: SqliteStore) -> Result<()> { - println!("Purging local records that cannot be decrypted"); - - let key = load_key(settings)?; - - match store.purge(&key.into()).await { - Ok(()) => println!("Local store purge completed OK"), - Err(e) => println!("Failed to purge local store: {e:?}"), - } - - Ok(()) - } -} diff --git a/crates/atuin/src/command/client/store/push.rs b/crates/atuin/src/command/client/store/push.rs deleted file mode 100644 index d8569e1e..00000000 --- a/crates/atuin/src/command/client/store/push.rs +++ /dev/null @@ -1,112 +0,0 @@ -use atuin_common::record::HostId; -use clap::Args; -use eyre::Result; -use uuid::Uuid; - -use atuin_client::{ - api_client::Client, - encryption::load_key, - record::sync::Operation, - record::{sqlite_store::SqliteStore, sync}, - settings::Settings, -}; - -#[derive(Args, Debug)] -pub struct Push { - /// The tag to push (eg, 'history'). Defaults to all tags - #[arg(long, short)] - pub tag: Option<String>, - - /// The host to push, in the form of a UUID host ID. Defaults to the current host. - #[arg(long)] - pub host: Option<Uuid>, - - /// Force push records - /// This will override both host and tag, to be all hosts and all tags. First clear the remote store, then upload all of the - /// local store - #[arg(long, default_value = "false")] - pub force: bool, - - /// Page Size - /// How many records to upload at once. Defaults to 100 - #[arg(long, default_value = "100")] - pub page: u64, -} - -impl Push { - pub async fn run(&self, settings: &Settings, store: SqliteStore) -> Result<()> { - let host_id = Settings::host_id().await?; - - if self.force { - println!("Forcing remote store overwrite!"); - println!("Clearing remote store"); - - let client = Client::new( - &settings.sync_address, - settings.sync_auth_token().await?, - settings.network_connect_timeout, - settings.network_timeout * 10, // we may be deleting a lot of data... so up the - // timeout - ) - .expect("failed to create client"); - - client.delete_store().await?; - } - - // We can actually just use the existing diff/etc to push - // 1. Diff - // 2. Get operations - // 3. Filter operations by - // a) are they an upload op? - // b) are they for the host/tag we are pushing here? - let client = sync::build_client(settings).await?; - let (diff, remote_index) = sync::diff(&client, &store).await?; - - // Skip on --force: that path intentionally replaces remote with local. - if !self.force { - let key: [u8; 32] = load_key(settings)?.into(); - sync::check_encryption_key(&client, &remote_index, &key) - .await - .map_err(crate::print_error::format_sync_error)?; - } - - let operations = sync::operations(diff, &store).await?; - - let operations = operations - .into_iter() - .filter(|op| match op { - // No noops or downloads thx - Operation::Noop { .. } | Operation::Download { .. } => false, - - // push, so yes plz to uploads! - Operation::Upload { host, tag, .. } => { - if self.force { - return true; - } - - if let Some(h) = self.host { - if HostId(h) != *host { - return false; - } - } else if *host != host_id { - return false; - } - - if let Some(t) = self.tag.clone() - && t != *tag - { - return false; - } - - true - } - }) - .collect(); - - let (uploaded, _) = sync::sync_remote(&client, operations, &store, self.page).await?; - - println!("Uploaded {uploaded} records"); - - Ok(()) - } -} diff --git a/crates/atuin/src/command/client/store/rebuild.rs b/crates/atuin/src/command/client/store/rebuild.rs deleted file mode 100644 index b9f2837b..00000000 --- a/crates/atuin/src/command/client/store/rebuild.rs +++ /dev/null @@ -1,58 +0,0 @@ -use clap::Args; -use eyre::{Result, bail}; - -#[cfg(feature = "daemon")] -use crate::command::client::daemon as daemon_cmd; - -use atuin_client::{ - database::Database, encryption, history::store::HistoryStore, - record::sqlite_store::SqliteStore, settings::Settings, -}; - -#[derive(Args, Debug)] -pub struct Rebuild { - pub tag: String, -} - -impl Rebuild { - pub async fn run( - &self, - settings: &Settings, - store: SqliteStore, - database: &dyn Database, - ) -> Result<()> { - // keep it as a string and not an enum atm - // would be super cool to build this dynamically in the future - // eg register handles for rebuilding various tags without having to make this part of the - // binary big - match self.tag.as_str() { - "history" => { - self.rebuild_history(settings, store.clone(), database) - .await?; - } - - tag => bail!("unknown tag: {tag}"), - } - - Ok(()) - } - - async fn rebuild_history( - &self, - settings: &Settings, - store: SqliteStore, - database: &dyn Database, - ) -> Result<()> { - let encryption_key: [u8; 32] = encryption::load_key(settings)?.into(); - - let host_id = Settings::host_id().await?; - let history_store = HistoryStore::new(store, host_id, encryption_key); - - history_store.build(database).await?; - - #[cfg(feature = "daemon")] - daemon_cmd::emit_event(settings, atuin_daemon::DaemonEvent::HistoryRebuilt).await; - - Ok(()) - } -} diff --git a/crates/atuin/src/command/client/store/rekey.rs b/crates/atuin/src/command/client/store/rekey.rs deleted file mode 100644 index c92d2555..00000000 --- a/crates/atuin/src/command/client/store/rekey.rs +++ /dev/null @@ -1,41 +0,0 @@ -use clap::Args; -use eyre::Result; -use tokio::{fs::File, io::AsyncWriteExt}; - -use atuin_client::{ - encryption::{decode_key, generate_encoded_key, load_key}, - record::sqlite_store::SqliteStore, - record::store::Store, - settings::Settings, -}; - -#[derive(Args, Debug)] -pub struct Rekey { - /// The new key to use for encryption. Omit for a randomly-generated key - key: Option<String>, -} - -impl Rekey { - pub async fn run(&self, settings: &Settings, store: SqliteStore) -> Result<()> { - let key = if let Some(key) = self.key.clone() { - println!("Re-encrypting store with specified key"); - - key - } else { - println!("Re-encrypting store with freshly-generated key"); - let (_, encoded) = generate_encoded_key()?; - encoded - }; - - let current_key: [u8; 32] = load_key(settings)?.into(); - let new_key: [u8; 32] = decode_key(key.clone())?.into(); - - store.re_encrypt(¤t_key, &new_key).await?; - - println!("Store rewritten. Saving new key"); - let mut file = File::create(settings.key_path.clone()).await?; - file.write_all(key.as_bytes()).await?; - - Ok(()) - } -} diff --git a/crates/atuin/src/command/client/store/verify.rs b/crates/atuin/src/command/client/store/verify.rs deleted file mode 100644 index 84bec96a..00000000 --- a/crates/atuin/src/command/client/store/verify.rs +++ /dev/null @@ -1,26 +0,0 @@ -use clap::Args; -use eyre::Result; - -use atuin_client::{ - encryption::load_key, - record::{sqlite_store::SqliteStore, store::Store}, - settings::Settings, -}; - -#[derive(Args, Debug)] -pub struct Verify {} - -impl Verify { - pub async fn run(&self, settings: &Settings, store: SqliteStore) -> Result<()> { - println!("Verifying local store can be decrypted with the current key"); - - let key = load_key(settings)?; - - match store.verify(&key.into()).await { - Ok(()) => println!("Local store encryption verified OK"), - Err(e) => println!("Failed to verify local store encryption: {e:?}"), - } - - Ok(()) - } -} |
