aboutsummaryrefslogtreecommitdiffstats
path: root/crates/turtle/src/command/client/store.rs
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2026-06-11 00:54:30 +0200
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2026-06-11 00:54:30 +0200
commit5c39e7cf284a1f6e9a1657f2deb44e359fc47eb8 (patch)
treec64baa8d5866c8e339eaf660dd3f94f30a3f7d8a /crates/turtle/src/command/client/store.rs
parentchore: Somewhat simplify sync code (diff)
downloadatuin-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/turtle/src/command/client/store.rs')
-rw-r--r--crates/turtle/src/command/client/store.rs120
1 files changed, 120 insertions, 0 deletions
diff --git a/crates/turtle/src/command/client/store.rs b/crates/turtle/src/command/client/store.rs
new file mode 100644
index 00000000..dfa3b66c
--- /dev/null
+++ b/crates/turtle/src/command/client/store.rs
@@ -0,0 +1,120 @@
+use clap::Subcommand;
+use eyre::Result;
+
+use crate::atuin_client::{
+ database::Database,
+ record::{sqlite_store::SqliteStore, store::Store},
+ settings::Settings,
+};
+use itertools::Itertools;
+use time::{OffsetDateTime, UtcOffset};
+
+#[cfg(feature = "sync")]
+mod push;
+
+#[cfg(feature = "sync")]
+mod pull;
+
+mod purge;
+mod rebuild;
+mod rekey;
+mod verify;
+
+#[derive(Subcommand, Debug)]
+#[command(infer_subcommands = true)]
+pub enum Cmd {
+ /// Print the current status of the record store
+ Status,
+
+ /// Rebuild a store (eg atuin store rebuild history)
+ Rebuild(rebuild::Rebuild),
+
+ /// Re-encrypt the store with a new key (potential for data loss!)
+ Rekey(rekey::Rekey),
+
+ /// Delete all records in the store that cannot be decrypted with the current key
+ Purge(purge::Purge),
+
+ /// Verify that all records in the store can be decrypted with the current key
+ Verify(verify::Verify),
+
+ /// Push all records to the remote sync server (one way sync)
+ #[cfg(feature = "sync")]
+ Push(push::Push),
+
+ /// Pull records from the remote sync server (one way sync)
+ #[cfg(feature = "sync")]
+ Pull(pull::Pull),
+}
+
+impl Cmd {
+ pub async fn run(
+ &self,
+ settings: &Settings,
+ database: &dyn Database,
+ store: SqliteStore,
+ ) -> Result<()> {
+ match self {
+ Self::Status => self.status(store).await,
+ Self::Rebuild(rebuild) => rebuild.run(settings, store, database).await,
+ Self::Rekey(rekey) => rekey.run(settings, store).await,
+ Self::Verify(verify) => verify.run(settings, store).await,
+ Self::Purge(purge) => purge.run(settings, store).await,
+
+ #[cfg(feature = "sync")]
+ Self::Push(push) => push.run(settings, store).await,
+
+ #[cfg(feature = "sync")]
+ Self::Pull(pull) => pull.run(settings, store, database).await,
+ }
+ }
+
+ pub async fn status(&self, store: SqliteStore) -> Result<()> {
+ let host_id = Settings::host_id().await?;
+ let offset = UtcOffset::current_local_offset().unwrap_or(UtcOffset::UTC);
+
+ let status = store.status().await?;
+
+ // TODO: should probs build some data structure and then pretty-print it or smth
+ for (host, st) in status.hosts.iter().sorted_by_key(|(h, _)| *h) {
+ let host_string = if host == &host_id {
+ format!("host: {} <- CURRENT HOST", host.0.as_hyphenated())
+ } else {
+ format!("host: {}", host.0.as_hyphenated())
+ };
+
+ println!("{host_string}");
+
+ for (tag, idx) in st.iter().sorted_by_key(|(tag, _)| *tag) {
+ println!("\tstore: {tag}");
+
+ let first = store.first(*host, tag).await?;
+ let last = store.last(*host, tag).await?;
+
+ println!("\t\tidx: {idx}");
+
+ if let Some(first) = first {
+ println!("\t\tfirst: {}", first.id.0.as_hyphenated());
+
+ let time =
+ OffsetDateTime::from_unix_timestamp_nanos(i128::from(first.timestamp))?
+ .to_offset(offset);
+ println!("\t\t\tcreated: {time}");
+ }
+
+ if let Some(last) = last {
+ println!("\t\tlast: {}", last.id.0.as_hyphenated());
+
+ let time =
+ OffsetDateTime::from_unix_timestamp_nanos(i128::from(last.timestamp))?
+ .to_offset(offset);
+ println!("\t\t\tcreated: {time}");
+ }
+ }
+
+ println!();
+ }
+
+ Ok(())
+ }
+}