From 4e56f5a41e5224b816e9eafed145a03cbf52fd93 Mon Sep 17 00:00:00 2001 From: Ellie Huxtable Date: Sat, 6 Jan 2024 17:19:31 +0000 Subject: refactor: String -> HistoryId (#1512) --- atuin-client/src/api_client.rs | 4 +++- atuin-client/src/database.rs | 4 ++-- atuin-client/src/encryption.rs | 10 +++++----- atuin-client/src/history.rs | 29 +++++++++++++++++++++++------ atuin-client/src/history/builder.rs | 2 +- atuin-client/src/history/store.rs | 16 ++++++++-------- atuin-client/src/sync.rs | 6 +++--- 7 files changed, 45 insertions(+), 26 deletions(-) (limited to 'atuin-client') diff --git a/atuin-client/src/api_client.rs b/atuin-client/src/api_client.rs index 9007b9abc..d428d6b8c 100644 --- a/atuin-client/src/api_client.rs +++ b/atuin-client/src/api_client.rs @@ -259,7 +259,9 @@ impl<'a> Client<'a> { self.client .delete(url) - .json(&DeleteHistoryRequest { client_id: h.id }) + .json(&DeleteHistoryRequest { + client_id: h.id.to_string(), + }) .send() .await?; diff --git a/atuin-client/src/database.rs b/atuin-client/src/database.rs index c4b45302b..6a6f59911 100644 --- a/atuin-client/src/database.rs +++ b/atuin-client/src/database.rs @@ -153,7 +153,7 @@ impl Sqlite { "insert or ignore into history(id, timestamp, duration, exit, command, cwd, session, hostname, deleted_at) values(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9)", ) - .bind(h.id.as_str()) + .bind(h.id.0.as_str()) .bind(h.timestamp.unix_timestamp_nanos() as i64) .bind(h.duration) .bind(h.exit) @@ -236,7 +236,7 @@ impl Database for Sqlite { set timestamp = ?2, duration = ?3, exit = ?4, command = ?5, cwd = ?6, session = ?7, hostname = ?8, deleted_at = ?9 where id = ?1", ) - .bind(h.id.as_str()) + .bind(h.id.0.as_str()) .bind(h.timestamp.unix_timestamp_nanos() as i64) .bind(h.duration) .bind(h.exit) diff --git a/atuin-client/src/encryption.rs b/atuin-client/src/encryption.rs index f9f8bcb32..3c9f3d068 100644 --- a/atuin-client/src/encryption.rs +++ b/atuin-client/src/encryption.rs @@ -166,7 +166,7 @@ fn encode(h: &History) -> Result> { // INFO: ensure this is updated when adding new fields encode::write_array_len(&mut output, 9)?; - encode::write_str(&mut output, &h.id)?; + encode::write_str(&mut output, &h.id.0)?; encode::write_str(&mut output, &(format_rfc3339(h.timestamp)?))?; encode::write_sint(&mut output, h.duration)?; encode::write_sint(&mut output, h.exit)?; @@ -234,7 +234,7 @@ fn decode(bytes: &[u8]) -> Result { } Ok(History { - id: id.to_owned(), + id: id.to_owned().into(), timestamp: OffsetDateTime::parse(timestamp, &Rfc3339)?, duration, exit, @@ -312,7 +312,7 @@ mod test { 108, 117, 100, 103, 97, 116, 101, 192, ]; let history = History { - id: "66d16cbee7cd47538e5c5b8b44e9006e".to_owned(), + id: "66d16cbee7cd47538e5c5b8b44e9006e".to_owned().into(), timestamp: datetime!(2023-05-28 18:35:40.633872 +00:00), duration: 49206000, exit: 0, @@ -333,7 +333,7 @@ mod test { #[test] fn test_decode_deleted() { let history = History { - id: "66d16cbee7cd47538e5c5b8b44e9006e".to_owned(), + id: "66d16cbee7cd47538e5c5b8b44e9006e".to_owned().into(), timestamp: datetime!(2023-05-28 18:35:40.633872 +00:00), duration: 49206000, exit: 0, @@ -364,7 +364,7 @@ mod test { 108, 117, 100, 103, 97, 116, 101, ]; let history = History { - id: "66d16cbee7cd47538e5c5b8b44e9006e".to_owned(), + id: "66d16cbee7cd47538e5c5b8b44e9006e".to_owned().into(), timestamp: datetime!(2023-05-28 18:35:40.633872 +00:00), duration: 49206000, exit: 0, diff --git a/atuin-client/src/history.rs b/atuin-client/src/history.rs index 2b2c41eed..8c312dc21 100644 --- a/atuin-client/src/history.rs +++ b/atuin-client/src/history.rs @@ -1,6 +1,8 @@ +use core::fmt::Formatter; use rmp::decode::ValueReadError; use rmp::{decode::Bytes, Marker}; use std::env; +use std::fmt::Display; use atuin_common::record::DecryptedData; use atuin_common::utils::uuid_v7; @@ -17,6 +19,21 @@ pub mod store; const HISTORY_VERSION: &str = "v0"; const HISTORY_TAG: &str = "history"; +#[derive(Clone, Debug, Eq, PartialEq, Hash)] +pub struct HistoryId(pub String); + +impl Display for HistoryId { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +impl From for HistoryId { + fn from(s: String) -> Self { + Self(s) + } +} + /// Client-side history entry. /// /// Client stores data unencrypted, and only encrypts it before sending to the server. @@ -35,7 +52,7 @@ pub struct History { /// A client-generated ID, used to identify the entry when syncing. /// /// Stored as `client_id` in the database. - pub id: String, + pub id: HistoryId, /// When the command was run. pub timestamp: OffsetDateTime, /// How long the command took to run. @@ -78,7 +95,7 @@ impl History { }); Self { - id: uuid_v7().as_simple().to_string(), + id: uuid_v7().as_simple().to_string().into(), timestamp, command, cwd, @@ -103,7 +120,7 @@ impl History { // INFO: ensure this is updated when adding new fields encode::write_array_len(&mut output, 9)?; - encode::write_str(&mut output, &self.id)?; + encode::write_str(&mut output, &self.id.0)?; encode::write_u64(&mut output, self.timestamp.unix_timestamp_nanos() as u64)?; encode::write_sint(&mut output, self.duration)?; encode::write_sint(&mut output, self.exit)?; @@ -170,7 +187,7 @@ impl History { } Ok(History { - id: id.to_owned(), + id: id.to_owned().into(), timestamp: OffsetDateTime::from_unix_timestamp_nanos(timestamp as i128)?, duration, exit, @@ -402,7 +419,7 @@ mod tests { ]; let history = History { - id: "66d16cbee7cd47538e5c5b8b44e9006e".to_owned(), + id: "66d16cbee7cd47538e5c5b8b44e9006e".to_owned().into(), timestamp: datetime!(2023-05-28 18:35:40.633872 +00:00), duration: 49206000, exit: 0, @@ -429,7 +446,7 @@ mod tests { #[test] fn test_serialize_deserialize_deleted() { let history = History { - id: "66d16cbee7cd47538e5c5b8b44e9006e".to_owned(), + id: "66d16cbee7cd47538e5c5b8b44e9006e".to_owned().into(), timestamp: datetime!(2023-05-28 18:35:40.633872 +00:00), duration: 49206000, exit: 0, diff --git a/atuin-client/src/history/builder.rs b/atuin-client/src/history/builder.rs index 27531c95d..4e69cf664 100644 --- a/atuin-client/src/history/builder.rs +++ b/atuin-client/src/history/builder.rs @@ -85,7 +85,7 @@ pub struct HistoryFromDb { impl From for History { fn from(from_db: HistoryFromDb) -> Self { History { - id: from_db.id, + id: from_db.id.into(), timestamp: from_db.timestamp, exit: from_db.exit, command: from_db.command, diff --git a/atuin-client/src/history/store.rs b/atuin-client/src/history/store.rs index bf74a0a83..f4aa9d93c 100644 --- a/atuin-client/src/history/store.rs +++ b/atuin-client/src/history/store.rs @@ -4,7 +4,7 @@ use rmp::decode::Bytes; use crate::record::{encryption::PASETO_V4, sqlite_store::SqliteStore, store::Store}; use atuin_common::record::{DecryptedData, Host, HostId, Record, RecordIdx}; -use super::{History, HISTORY_TAG, HISTORY_VERSION}; +use super::{History, HistoryId, HISTORY_TAG, HISTORY_VERSION}; #[derive(Debug)] pub struct HistoryStore { @@ -15,8 +15,8 @@ pub struct HistoryStore { #[derive(Debug, Eq, PartialEq, Clone)] pub enum HistoryRecord { - Create(History), // Create a history record - Delete(String), // Delete a history record, identified by ID + Create(History), // Create a history record + Delete(HistoryId), // Delete a history record, identified by ID } impl HistoryRecord { @@ -51,7 +51,7 @@ impl HistoryRecord { HistoryRecord::Delete(id) => { // 1 -> a history delete encode::write_u8(&mut output, 1)?; - encode::write_str(&mut output, id)?; + encode::write_str(&mut output, id.0.as_str())?; } }; @@ -92,7 +92,7 @@ impl HistoryRecord { ); } - Ok(HistoryRecord::Delete(id.to_string())) + Ok(HistoryRecord::Delete(id.to_string().into())) } n => { @@ -134,7 +134,7 @@ impl HistoryStore { Ok(idx) } - pub async fn delete(&self, id: String) -> Result { + pub async fn delete(&self, id: HistoryId) -> Result { let record = HistoryRecord::Delete(id); self.push_record(record).await @@ -171,7 +171,7 @@ mod tests { ]; let history = History { - id: "018cd4fe81757cd2aee65cd7861f9c81".to_owned(), + id: "018cd4fe81757cd2aee65cd7861f9c81".to_owned().into(), timestamp: datetime!(2024-01-04 00:00:00.000000 +00:00), duration: 100, exit: 0, @@ -203,7 +203,7 @@ mod tests { 204, 1, 217, 32, 48, 49, 56, 99, 100, 52, 102, 101, 56, 49, 55, 53, 55, 99, 100, 50, 97, 101, 101, 54, 53, 99, 100, 55, 56, 54, 49, 102, 57, 99, 56, 49, ]; - let record = HistoryRecord::Delete("018cd4fe81757cd2aee65cd7861f9c81".to_string()); + let record = HistoryRecord::Delete("018cd4fe81757cd2aee65cd7861f9c81".to_string().into()); let serialized = record.serialize().expect("failed to serialize history"); assert_eq!(serialized.0, bytes); diff --git a/atuin-client/src/sync.rs b/atuin-client/src/sync.rs index 5f612c715..99b423c2c 100644 --- a/atuin-client/src/sync.rs +++ b/atuin-client/src/sync.rs @@ -73,7 +73,7 @@ async fn sync_download( .map(|h| serde_json::from_str(h).expect("invalid base64")) .map(|h| decrypt(h, key).expect("failed to decrypt history! check your key")) .map(|mut h| { - if remote_deleted.contains(h.id.as_str()) { + if remote_deleted.contains(h.id.0.as_str()) { h.deleted_at = Some(time::OffsetDateTime::now_utc()); h.command = String::from(""); } @@ -157,7 +157,7 @@ async fn sync_upload( let data = serde_json::to_string(&data)?; let add_hist = AddHistoryRequest { - id: i.id, + id: i.id.to_string(), timestamp: i.timestamp, data, hostname: hash_str(&i.hostname), @@ -177,7 +177,7 @@ async fn sync_upload( let deleted = db.deleted().await?; for i in deleted { - if remote_deleted.contains(&i.id) { + if remote_deleted.contains(&i.id.to_string()) { continue; } -- cgit v1.2.3