diff options
Diffstat (limited to '')
| -rw-r--r-- | crates/common/src/api.rs (renamed from crates/turtle/src/atuin_common/api.rs) | 16 | ||||
| -rw-r--r-- | crates/common/src/lib.rs (renamed from crates/turtle/src/atuin_common/mod.rs) | 13 | ||||
| -rw-r--r-- | crates/common/src/record.rs (renamed from crates/turtle/src/atuin_common/record.rs) | 84 | ||||
| -rw-r--r-- | crates/common/src/shell.rs (renamed from crates/turtle/src/atuin_common/shell.rs) | 10 | ||||
| -rw-r--r-- | crates/common/src/utils.rs (renamed from crates/turtle/src/atuin_common/utils.rs) | 69 |
5 files changed, 102 insertions, 90 deletions
diff --git a/crates/turtle/src/atuin_common/api.rs b/crates/common/src/api.rs index 0868943d..0e34171d 100644 --- a/crates/turtle/src/atuin_common/api.rs +++ b/crates/common/src/api.rs @@ -4,19 +4,19 @@ use std::borrow::Cow; use std::sync::LazyLock; // the usage of X- has been deprecated for quite along time, it turns out -pub(crate) static ATUIN_HEADER_VERSION: &str = "Atuin-Version"; -pub(crate) static ATUIN_CARGO_VERSION: &str = env!("CARGO_PKG_VERSION"); +pub static ATUIN_HEADER_VERSION: &str = "Atuin-Version"; +pub static ATUIN_CARGO_VERSION: &str = env!("CARGO_PKG_VERSION"); -pub(crate) static ATUIN_VERSION: LazyLock<Version> = +pub static ATUIN_VERSION: LazyLock<Version> = LazyLock::new(|| Version::parse(ATUIN_CARGO_VERSION).expect("failed to parse self semver")); #[derive(Debug, Serialize, Deserialize)] -pub(crate) struct ErrorResponse<'a> { - pub(crate) reason: Cow<'a, str>, +pub struct ErrorResponse<'a> { + pub reason: Cow<'a, str>, } #[derive(Debug, Serialize, Deserialize)] -pub(crate) struct IndexResponse { - pub(crate) homage: String, - pub(crate) version: String, +pub struct IndexResponse { + pub homage: String, + pub version: String, } diff --git a/crates/turtle/src/atuin_common/mod.rs b/crates/common/src/lib.rs index 635c9fc3..18e3189f 100644 --- a/crates/turtle/src/atuin_common/mod.rs +++ b/crates/common/src/lib.rs @@ -14,7 +14,7 @@ macro_rules! new_uuid { serde::Deserialize, )] #[serde(transparent)] - pub(crate) struct $name(pub(crate) Uuid); + pub struct $name(pub Uuid); impl<DB: sqlx::Database> sqlx::Type<DB> for $name where @@ -42,7 +42,7 @@ macro_rules! new_uuid { { fn encode_by_ref( &self, - buf: &mut DB::ArgumentBuffer<'q>, + buf: &mut DB::ArgumentBuffer, ) -> Result<sqlx::encode::IsNull, Box<dyn std::error::Error + Send + Sync + 'static>> { self.0.encode_by_ref(buf) @@ -51,8 +51,7 @@ macro_rules! new_uuid { }; } -pub(crate) mod api; -pub(crate) mod record; -pub(crate) mod shell; -pub(crate) mod tls; -pub(crate) mod utils; +pub mod api; +pub mod record; +pub mod shell; +pub mod utils; diff --git a/crates/turtle/src/atuin_common/record.rs b/crates/common/src/record.rs index f8f9f8a7..c5985cea 100644 --- a/crates/turtle/src/atuin_common/record.rs +++ b/crates/common/src/record.rs @@ -6,30 +6,30 @@ use typed_builder::TypedBuilder; use uuid::Uuid; #[derive(Clone, Debug, PartialEq)] -pub(crate) struct DecryptedData(pub(crate) Vec<u8>); +pub struct DecryptedData(pub Vec<u8>); #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub(crate) struct EncryptedData { - pub(crate) data: String, - pub(crate) content_encryption_key: String, +pub struct EncryptedData { + pub data: String, + pub content_encryption_key: String, } #[derive(Debug, PartialEq, PartialOrd, Ord, Eq)] -pub(crate) struct Diff { - pub(crate) host: HostId, - pub(crate) tag: String, - pub(crate) local: Option<RecordIdx>, - pub(crate) remote: Option<RecordIdx>, +pub struct Diff { + pub host: HostId, + pub tag: String, + pub local: Option<RecordIdx>, + pub remote: Option<RecordIdx>, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] -pub(crate) struct Host { - pub(crate) id: HostId, - pub(crate) name: String, +pub struct Host { + pub id: HostId, + pub name: String, } impl Host { - pub(crate) fn new(id: HostId) -> Self { + pub fn new(id: HostId) -> Self { Self { id, name: String::new(), @@ -40,55 +40,55 @@ impl Host { new_uuid!(RecordId); new_uuid!(HostId); -pub(crate) type RecordIdx = u64; +pub type RecordIdx = u64; /// A single record stored inside of our local database #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, TypedBuilder)] -pub(crate) struct Record<Data> { +pub struct Record<Data> { /// a unique ID - #[builder(default = RecordId(crate::atuin_common::utils::uuid_v7()))] - pub(crate) id: RecordId, + #[builder(default = RecordId(crate::utils::uuid_v7()))] + pub id: RecordId, /// The integer record ID. This is only unique per (host, tag). - pub(crate) idx: RecordIdx, + pub idx: RecordIdx, /// The unique ID of the host. // TODO(ellie): Optimize the storage here. We use a bunch of IDs, and currently store // as strings. I would rather avoid normalization, so store as UUID binary instead of // encoding to a string and wasting much more storage. - pub(crate) host: Host, + pub host: Host, /// The creation time in nanoseconds since unix epoch #[builder(default = time::OffsetDateTime::now_utc().unix_timestamp_nanos() as u64)] - pub(crate) timestamp: u64, + pub timestamp: u64, /// The version the data in the entry conforms to // However we want to track versions for this tag, eg v2 - pub(crate) version: String, + pub version: String, /// The type of data we are storing here. Eg, "history" - pub(crate) tag: String, + pub tag: String, /// Some data. This can be anything you wish to store. Use the tag field to know how to handle it. - pub(crate) data: Data, + pub data: Data, } /// Extra data from the record that should be encoded in the data #[derive(Debug, Copy, Clone)] -pub(crate) struct AdditionalData<'a> { - pub(crate) id: &'a RecordId, - pub(crate) idx: &'a u64, - pub(crate) version: &'a str, - pub(crate) tag: &'a str, - pub(crate) host: &'a HostId, +pub struct AdditionalData<'a> { + pub id: &'a RecordId, + pub idx: &'a u64, + pub version: &'a str, + pub tag: &'a str, + pub host: &'a HostId, } /// An index representing the current state of the record stores /// This can be both remote, or local, and compared in either direction #[derive(Debug, Serialize, Deserialize)] -pub(crate) struct RecordStatus { +pub struct RecordStatus { // A map of host -> tag -> max(idx) - pub(crate) hosts: HashMap<HostId, HashMap<String, RecordIdx>>, + pub hosts: HashMap<HostId, HashMap<String, RecordIdx>>, } impl Default for RecordStatus { @@ -106,18 +106,18 @@ impl Extend<(HostId, String, RecordIdx)> for RecordStatus { } impl RecordStatus { - pub(crate) fn new() -> Self { + pub fn new() -> Self { Self { hosts: HashMap::new(), } } /// Insert a new tail record into the store - pub(crate) fn set_raw(&mut self, host: HostId, tag: String, tail_id: RecordIdx) { + pub fn set_raw(&mut self, host: HostId, tag: String, tail_id: RecordIdx) { self.hosts.entry(host).or_default().insert(tag, tail_id); } - pub(crate) fn get(&self, host: HostId, tag: &str) -> Option<RecordIdx> { + pub fn get(&self, host: HostId, tag: &str) -> Option<RecordIdx> { self.hosts.get(&host).and_then(|v| v.get(tag)).copied() } @@ -128,7 +128,7 @@ impl RecordStatus { /// then we need to do some downloading. If it is smaller, then we need to do some uploading /// Note that we cannot upload if we are not the owner of the record store - hosts can only /// write to their own store. - pub(crate) fn diff(&self, other: &Self) -> Vec<Diff> { + pub fn diff(&self, other: &Self) -> Vec<Diff> { let mut ret = Vec::new(); // First, we check if other has everything that self has @@ -183,7 +183,7 @@ impl RecordStatus { } } -pub(crate) trait Encryption { +pub trait Encryption { fn re_encrypt( data: EncryptedData, ad: AdditionalData<'_>, @@ -202,7 +202,7 @@ pub(crate) trait Encryption { } impl Record<DecryptedData> { - pub(crate) fn encrypt<E: Encryption>(self, key: &[u8; 32]) -> Record<EncryptedData> { + pub fn encrypt<E: Encryption>(self, key: &[u8; 32]) -> Record<EncryptedData> { let ad = AdditionalData { id: &self.id, version: &self.version, @@ -223,7 +223,7 @@ impl Record<DecryptedData> { } impl Record<EncryptedData> { - pub(crate) fn decrypt<E: Encryption>(self, key: &[u8; 32]) -> Result<Record<DecryptedData>> { + pub fn decrypt<E: Encryption>(self, key: &[u8; 32]) -> Result<Record<DecryptedData>> { let ad = AdditionalData { id: &self.id, version: &self.version, @@ -242,7 +242,7 @@ impl Record<EncryptedData> { }) } - pub(crate) fn re_encrypt<E: Encryption>( + pub fn re_encrypt<E: Encryption>( self, old_key: &[u8; 32], new_key: &[u8; 32], @@ -268,15 +268,15 @@ impl Record<EncryptedData> { #[cfg(test)] mod tests { - use crate::atuin_common::record::{Host, HostId}; + use crate::record::{Host, HostId}; use super::{DecryptedData, Record}; fn test_record() -> Record<DecryptedData> { Record::builder() - .host(Host::new(HostId(crate::atuin_common::utils::uuid_v7()))) + .host(Host::new(HostId(crate::utils::uuid_v7()))) .version("v1".into()) - .tag(crate::atuin_common::utils::uuid_v7().simple().to_string()) + .tag(crate::utils::uuid_v7().simple().to_string()) .data(DecryptedData(vec![0, 1, 2, 3])) .idx(0) .build() diff --git a/crates/turtle/src/atuin_common/shell.rs b/crates/common/src/shell.rs index 880ff00f..a57250e2 100644 --- a/crates/turtle/src/atuin_common/shell.rs +++ b/crates/common/src/shell.rs @@ -1,5 +1,5 @@ -#[derive(PartialEq)] -pub(crate) enum Shell { +#[derive(PartialEq, Clone, Copy, Debug)] +pub enum Shell { Sh, Bash, Fish, @@ -30,13 +30,15 @@ impl std::fmt::Display for Shell { } impl Shell { - pub(crate) fn from_env() -> Self { + #[must_use] + pub fn from_env() -> Self { std::env::var("ATUIN_SHELL").map_or(Self::Unknown, |shell| { Self::from_string(shell.trim().to_lowercase().as_str()) }) } - pub(crate) fn from_string(name: &str) -> Self { + #[must_use] + pub fn from_string(name: &str) -> Self { match name { "bash" => Self::Bash, "fish" => Self::Fish, diff --git a/crates/turtle/src/atuin_common/utils.rs b/crates/common/src/utils.rs index dbe9dfbc..b50328a9 100644 --- a/crates/turtle/src/atuin_common/utils.rs +++ b/crates/common/src/utils.rs @@ -4,11 +4,29 @@ use std::path::{Path, PathBuf}; use uuid::Uuid; -pub(crate) fn uuid_v7() -> Uuid { +#[must_use] +pub fn get_hostname() -> String { + env::var("ATUIN_HOST_NAME") + .unwrap_or_else(|_| whoami::hostname().unwrap_or_else(|_| "unknown-host".to_string())) +} + +#[must_use] +pub fn get_username() -> String { + env::var("ATUIN_HOST_USER") + .unwrap_or_else(|_| whoami::username().unwrap_or_else(|_| "unknown-user".to_string())) +} + +/// Returns a pair of the hostname and username, separated by a colon. +#[must_use] +pub fn get_host_user() -> String { + format!("{}:{}", get_hostname(), get_username()) +} + +pub fn uuid_v7() -> Uuid { Uuid::now_v7() } -pub(crate) fn has_git_dir(path: &str) -> bool { +pub fn has_git_dir(path: &str) -> bool { let mut gitdir = PathBuf::from(path); gitdir.push(".git"); @@ -50,7 +68,7 @@ fn resolve_git_worktree(path: &Path) -> Option<PathBuf> { // detect if any parent dir has a git repo in it // I really don't want to bring in libgit for something simple like this // If we start to do anything more advanced, then perhaps -pub(crate) fn in_git_repo(path: &str) -> Option<PathBuf> { +pub fn in_git_repo(path: &str) -> Option<PathBuf> { let mut gitdir = PathBuf::from(path); while gitdir.parent().is_some() && !has_git_dir(gitdir.to_str().unwrap()) { @@ -73,41 +91,47 @@ pub(crate) fn in_git_repo(path: &str) -> Option<PathBuf> { // I don't want to use ProjectDirs, it puts config in awkward places on // mac. Data too. Seems to be more intended for GUI apps. -pub(crate) fn home_dir() -> PathBuf { +#[must_use] +pub fn home_dir() -> PathBuf { directories::BaseDirs::new() .map(|d| d.home_dir().to_path_buf()) .expect("could not determine home directory") } -pub(crate) fn config_dir() -> PathBuf { +#[must_use] +pub fn config_dir() -> PathBuf { let config_dir = env::var("XDG_CONFIG_HOME").map_or_else(|_| home_dir().join(".config"), PathBuf::from); - config_dir.join("atuin") + config_dir.join("turtle") } -pub(crate) fn data_dir() -> PathBuf { +#[must_use] +pub fn data_dir() -> PathBuf { let data_dir = env::var("XDG_DATA_HOME") .map_or_else(|_| home_dir().join(".local").join("share"), PathBuf::from); - data_dir.join("atuin") + data_dir.join("turtle") } -pub(crate) fn runtime_dir() -> PathBuf { - env::var("XDG_RUNTIME_DIR").map_or_else(|_| data_dir(), PathBuf::from) +#[must_use] +pub fn daemon_socket_path() -> PathBuf { + runtime_dir().join("turtle.sock") } -pub(crate) fn logs_dir() -> PathBuf { - home_dir().join(".atuin").join("logs") +#[must_use] +pub fn runtime_dir() -> PathBuf { + env::var("XDG_RUNTIME_DIR").map_or_else(|_| data_dir(), PathBuf::from) } -pub(crate) fn get_current_dir() -> String { +#[must_use] +pub fn get_current_dir() -> String { // Prefer PWD environment variable over cwd if available to better support symbolic links env::var("PWD").unwrap_or_else(|_| { env::current_dir().map_or_else(|_| String::new(), |dir| dir.display().to_string()) }) } -pub(crate) fn broken_symlink<P: Into<PathBuf>>(path: P) -> bool { +pub fn broken_symlink<P: Into<PathBuf>>(path: P) -> bool { let path = path.into(); path.is_symlink() && !path.exists() } @@ -118,7 +142,7 @@ pub(crate) fn broken_symlink<P: Into<PathBuf>>(path: P) -> bool { /// Intended to help prevent control characters being printed and interpreted by the terminal when /// printing history as well as to ensure the commands that appear in the interactive search /// reflect the actual command run rather than just the printable characters. -pub(crate) trait Escapable: AsRef<str> { +pub trait Escapable: AsRef<str> { fn escape_control(&self) -> Cow<'_, str> { if self.as_ref().contains(|c: char| c.is_ascii_control()) { let mut remaining = self.as_ref(); @@ -146,7 +170,7 @@ impl<T: AsRef<str>> Escapable for T {} #[cfg(test)] mod tests { - use super::{Cow, Escapable, Uuid, env, in_git_repo, uuid_v7}; + use super::{Cow, Uuid, env, in_git_repo, uuid_v7}; use std::collections::HashSet; @@ -241,17 +265,4 @@ mod tests { std::fs::remove_dir_all(&tmp).unwrap(); } - - #[test] - fn dumb_random_test() { - // Obviously not a test of randomness, but make sure we haven't made some - // catastrophic error - - assert_ne!(crypto_random_string::<1>(), crypto_random_string::<1>()); - assert_ne!(crypto_random_string::<2>(), crypto_random_string::<2>()); - assert_ne!(crypto_random_string::<4>(), crypto_random_string::<4>()); - assert_ne!(crypto_random_string::<8>(), crypto_random_string::<8>()); - assert_ne!(crypto_random_string::<16>(), crypto_random_string::<16>()); - assert_ne!(crypto_random_string::<32>(), crypto_random_string::<32>()); - } } |
