chore: migrate to rust 2024 (#2635)

* chore: upgrade to 2024 edition

* ugh unsafe

* format

* nixxxxxxxxxxx why
This commit is contained in:
Ellie Huxtable
2025-03-19 12:44:20 +00:00
committed by GitHub
parent 28d5ff83c2
commit 14ec768b45
93 changed files with 1035 additions and 777 deletions

1119
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
[package]
name = "atuin-client"
edition = "2021"
edition = "2024"
description = "client library for atuin"
rust-version = { workspace = true }

View File

@ -2,12 +2,16 @@ use std::collections::HashMap;
use std::env;
use std::time::Duration;
use eyre::{bail, Result};
use eyre::{Result, bail};
use reqwest::{
header::{HeaderMap, AUTHORIZATION, USER_AGENT},
Response, StatusCode, Url,
header::{AUTHORIZATION, HeaderMap, USER_AGENT},
};
use atuin_common::{
api::{ATUIN_CARGO_VERSION, ATUIN_HEADER_VERSION, ATUIN_VERSION},
record::{EncryptedData, HostId, Record, RecordIdx},
};
use atuin_common::{
api::{
AddHistoryRequest, ChangePasswordRequest, CountResponse, DeleteHistoryRequest,
@ -17,14 +21,10 @@ use atuin_common::{
},
record::RecordStatus,
};
use atuin_common::{
api::{ATUIN_CARGO_VERSION, ATUIN_HEADER_VERSION, ATUIN_VERSION},
record::{EncryptedData, HostId, Record, RecordIdx},
};
use semver::Version;
use time::format_description::well_known::Rfc3339;
use time::OffsetDateTime;
use time::format_description::well_known::Rfc3339;
use crate::{history::History, sync::hash_str, utils::get_host_user};
@ -126,7 +126,9 @@ pub fn ensure_version(response: &Response) -> Result<bool> {
// If the client is newer than the server
if version.major < ATUIN_VERSION.major {
println!("Atuin version mismatch! In order to successfully sync, the server needs to run a newer version of Atuin");
println!(
"Atuin version mismatch! In order to successfully sync, the server needs to run a newer version of Atuin"
);
println!("Client: {}", ATUIN_CARGO_VERSION);
println!("Server: {}", version);
@ -157,10 +159,14 @@ async fn handle_resp_error(resp: Response) -> Result<Response> {
bail!("Invalid request to the service: {status} - {reason}.")
}
bail!("There was an error with the atuin sync service, server error {status}: {reason}.\nIf the problem persists, contact the host")
bail!(
"There was an error with the atuin sync service, server error {status}: {reason}.\nIf the problem persists, contact the host"
)
}
bail!("There was an error with the atuin sync service: Status {status:?}.\nIf the problem persists, contact the host")
bail!(
"There was an error with the atuin sync service: Status {status:?}.\nIf the problem persists, contact the host"
)
}
Ok(resp)

View File

@ -10,14 +10,14 @@ use async_trait::async_trait;
use atuin_common::utils;
use fs_err as fs;
use itertools::Itertools;
use rand::{distributions::Alphanumeric, Rng};
use sql_builder::{bind::Bind, esc, quote, SqlBuilder, SqlName};
use rand::{Rng, distributions::Alphanumeric};
use sql_builder::{SqlBuilder, SqlName, bind::Bind, esc, quote};
use sqlx::{
Result, Row,
sqlite::{
SqliteConnectOptions, SqliteJournalMode, SqlitePool, SqlitePoolOptions, SqliteRow,
SqliteSynchronous,
},
Result, Row,
};
use time::OffsetDateTime;
@ -55,7 +55,9 @@ pub struct OptFilters {
pub fn current_context() -> Context {
let Ok(session) = env::var("ATUIN_SESSION") else {
eprintln!("ERROR: Failed to find $ATUIN_SESSION in the environment. Check that you have correctly set up your shell.");
eprintln!(
"ERROR: Failed to find $ATUIN_SESSION in the environment. Check that you have correctly set up your shell."
);
std::process::exit(1);
};
let hostname = get_host_user();
@ -131,7 +133,9 @@ impl Sqlite {
debug!("opening sqlite database at {:?}", path);
if utils::broken_symlink(path) {
eprintln!("Atuin: Sqlite db path ({path:?}) is a broken symlink. Unable to read or create replacement.");
eprintln!(
"Atuin: Sqlite db path ({path:?}) is a broken symlink. Unable to read or create replacement."
);
std::process::exit(1);
}

View File

@ -10,17 +10,17 @@
use std::{io::prelude::*, path::PathBuf};
use base64::prelude::{Engine, BASE64_STANDARD};
use base64::prelude::{BASE64_STANDARD, Engine};
pub use crypto_secretbox::Key;
use crypto_secretbox::{
aead::{Nonce, OsRng},
AeadCore, AeadInPlace, KeyInit, XSalsa20Poly1305,
aead::{Nonce, OsRng},
};
use eyre::{bail, ensure, eyre, Context, Result};
use eyre::{Context, Result, bail, ensure, eyre};
use fs_err as fs;
use rmp::{decode::Bytes, Marker};
use rmp::{Marker, decode::Bytes};
use serde::{Deserialize, Serialize};
use time::{format_description::well_known::Rfc3339, macros::format_description, OffsetDateTime};
use time::{OffsetDateTime, format_description::well_known::Rfc3339, macros::format_description};
use crate::{history::History, settings::Settings};
@ -265,9 +265,9 @@ fn error_report<E: std::fmt::Debug>(err: E) -> eyre::Report {
#[cfg(test)]
mod test {
use crypto_secretbox::{aead::OsRng, KeyInit, XSalsa20Poly1305};
use crypto_secretbox::{KeyInit, XSalsa20Poly1305, aead::OsRng};
use pretty_assertions::assert_eq;
use time::{macros::datetime, OffsetDateTime};
use time::{OffsetDateTime, macros::datetime};
use crate::history::History;
@ -392,7 +392,7 @@ mod test {
#[test]
fn key_encodings() {
use super::{decode_key, encode_key, Key};
use super::{Key, decode_key, encode_key};
// a history of our key encodings.
// v11.0.0 xCAbWypb0msJ2Kq+8j4GVEWUlDX7deKnrTRSIopuqXxc5Q==

View File

@ -1,13 +1,13 @@
use core::fmt::Formatter;
use rmp::decode::ValueReadError;
use rmp::{decode::Bytes, Marker};
use rmp::{Marker, decode::Bytes};
use std::env;
use std::fmt::Display;
use atuin_common::record::DecryptedData;
use atuin_common::utils::uuid_v7;
use eyre::{bail, eyre, Result};
use eyre::{Result, bail, eyre};
use crate::secrets::SECRET_PATTERNS_RE;
use crate::settings::Settings;

View File

@ -1,16 +1,16 @@
use std::{collections::HashSet, fmt::Write, time::Duration};
use eyre::{bail, eyre, Result};
use eyre::{Result, bail, eyre};
use indicatif::{ProgressBar, ProgressState, ProgressStyle};
use rmp::decode::Bytes;
use crate::{
database::{current_context, Database},
database::{Database, current_context},
record::{encryption::PASETO_V4, sqlite_store::SqliteStore, store::Store},
};
use atuin_common::record::{DecryptedData, Host, HostId, Record, RecordId, RecordIdx};
use super::{History, HistoryId, HISTORY_TAG, HISTORY_VERSION};
use super::{HISTORY_TAG, HISTORY_VERSION, History, HistoryId};
#[derive(Debug, Clone)]
pub struct HistoryStore {
@ -246,10 +246,11 @@ impl HistoryStore {
for id in ids {
let record = self.store.get(*id).await;
let record = if let Ok(record) = record {
record
} else {
let record = match record {
Ok(record) => record,
_ => {
continue;
}
};
if record.tag != HISTORY_TAG {
@ -342,7 +343,7 @@ mod tests {
use atuin_common::record::DecryptedData;
use time::macros::datetime;
use crate::history::{store::HistoryRecord, HISTORY_VERSION};
use crate::history::{HISTORY_VERSION, store::HistoryRecord};
use super::History;

View File

@ -2,11 +2,11 @@ use std::{path::PathBuf, str};
use async_trait::async_trait;
use directories::UserDirs;
use eyre::{eyre, Result};
use eyre::{Result, eyre};
use itertools::Itertools;
use time::{Duration, OffsetDateTime};
use super::{get_histpath, unix_byte_lines, Importer, Loader};
use super::{Importer, Loader, get_histpath, unix_byte_lines};
use crate::history::History;
use crate::import::read_to_end;
@ -73,7 +73,9 @@ impl Importer for Bash {
LineType::Empty => {} // do nothing
LineType::Timestamp(t) => {
if t < next_timestamp {
warn!("Time reversal detected in Bash history! Commands may be ordered incorrectly.");
warn!(
"Time reversal detected in Bash history! Commands may be ordered incorrectly."
);
}
next_timestamp = t;
}
@ -126,9 +128,9 @@ fn try_parse_line_as_timestamp(line: &str) -> Option<OffsetDateTime> {
mod test {
use std::cmp::Ordering;
use itertools::{assert_equal, Itertools};
use itertools::{Itertools, assert_equal};
use crate::import::{tests::TestLoader, Importer};
use crate::import::{Importer, tests::TestLoader};
use super::Bash;

View File

@ -5,10 +5,10 @@ use std::path::PathBuf;
use async_trait::async_trait;
use directories::BaseDirs;
use eyre::{eyre, Result};
use eyre::{Result, eyre};
use time::OffsetDateTime;
use super::{unix_byte_lines, Importer, Loader};
use super::{Importer, Loader, unix_byte_lines};
use crate::history::History;
use crate::import::read_to_end;
@ -110,7 +110,7 @@ impl Importer for Fish {
#[cfg(test)]
mod test {
use crate::import::{tests::TestLoader, Importer};
use crate::import::{Importer, tests::TestLoader};
use super::Fish;
@ -160,7 +160,7 @@ ERROR
// simple wrapper for fish history entry
macro_rules! fishtory {
($timestamp:expr, $command:expr) => {
($timestamp:expr_2021, $command:expr_2021) => {
let h = history.next().expect("missing entry in history");
assert_eq!(h.command.as_str(), $command);
assert_eq!(h.timestamp.unix_timestamp(), $timestamp);

View File

@ -3,7 +3,7 @@ use std::io::Read;
use std::path::PathBuf;
use async_trait::async_trait;
use eyre::{bail, Result};
use eyre::{Result, bail};
use memchr::Memchr;
use crate::history::History;

View File

@ -5,10 +5,10 @@ use std::path::PathBuf;
use async_trait::async_trait;
use directories::BaseDirs;
use eyre::{eyre, Result};
use eyre::{Result, eyre};
use time::OffsetDateTime;
use super::{unix_byte_lines, Importer, Loader};
use super::{Importer, Loader, unix_byte_lines};
use crate::history::History;
use crate::import::read_to_end;

View File

@ -5,8 +5,8 @@ use std::path::PathBuf;
use async_trait::async_trait;
use directories::BaseDirs;
use eyre::{eyre, Result};
use sqlx::{sqlite::SqlitePool, Pool};
use eyre::{Result, eyre};
use sqlx::{Pool, sqlite::SqlitePool};
use time::{Duration, OffsetDateTime};
use super::Importer;

View File

@ -2,10 +2,10 @@ use std::{path::PathBuf, str};
use async_trait::async_trait;
use directories::UserDirs;
use eyre::{eyre, Result};
use time::{macros::format_description, OffsetDateTime, PrimitiveDateTime};
use eyre::{Result, eyre};
use time::{OffsetDateTime, PrimitiveDateTime, macros::format_description};
use super::{get_histpath, unix_byte_lines, Importer, Loader};
use super::{Importer, Loader, get_histpath, unix_byte_lines};
use crate::history::History;
use crate::import::read_to_end;
@ -72,7 +72,7 @@ fn try_parse_line_as_timestamp(line: &str) -> Option<OffsetDateTime> {
#[cfg(test)]
mod test {
use crate::import::{tests::TestLoader, Importer};
use crate::import::{Importer, tests::TestLoader};
use super::Replxx;
@ -100,7 +100,7 @@ CREATE TABLE test( stamp DateTime('UTC'))ENGINE = MergeTreePARTITION BY toDat
// simple wrapper for replxx history entry
macro_rules! history {
($timestamp:expr, $command:expr) => {
($timestamp:expr_2021, $command:expr_2021) => {
let h = history.next().expect("missing entry in history");
assert_eq!(h.command.as_str(), $command);
assert_eq!(h.timestamp.unix_timestamp(), $timestamp);
@ -114,6 +114,9 @@ CREATE TABLE test( stamp DateTime('UTC'))ENGINE = MergeTreePARTITION BY toDat
history!(1707603396, "select * from numbers(10)");
history!(1707603401, "select * from system.numbers");
history!(1707603568, "select 1");
history!(1708600533, "CREATE TABLE test\n( stamp DateTime('UTC'))\nENGINE = MergeTree\nPARTITION BY toDate(stamp)\norder by tuple() as select toDateTime('2020-01-01')+number*60 from numbers(80000);");
history!(
1708600533,
"CREATE TABLE test\n( stamp DateTime('UTC'))\nENGINE = MergeTree\nPARTITION BY toDate(stamp)\norder by tuple() as select toDateTime('2020-01-01')+number*60 from numbers(80000);"
);
}
}

View File

@ -2,13 +2,13 @@ use std::path::PathBuf;
use async_trait::async_trait;
use directories::UserDirs;
use eyre::{eyre, Result};
use eyre::{Result, eyre};
use serde::Deserialize;
use atuin_common::utils::uuid_v7;
use time::OffsetDateTime;
use super::{get_histpath, unix_byte_lines, Importer, Loader};
use super::{Importer, Loader, get_histpath, unix_byte_lines};
use crate::history::History;
use crate::import::read_to_end;

View File

@ -4,13 +4,13 @@ use std::path::{Path, PathBuf};
use async_trait::async_trait;
use directories::BaseDirs;
use eyre::{eyre, Result};
use eyre::{Result, eyre};
use serde::Deserialize;
use time::OffsetDateTime;
use uuid::timestamp::{context::NoContext, Timestamp};
use uuid::Uuid;
use uuid::timestamp::{Timestamp, context::NoContext};
use super::{get_histpath, Importer, Loader};
use super::{Importer, Loader, get_histpath};
use crate::history::History;
use crate::utils::get_host_user;

View File

@ -3,14 +3,14 @@ use std::path::PathBuf;
use async_trait::async_trait;
use directories::BaseDirs;
use eyre::{eyre, Result};
use eyre::{Result, eyre};
use futures::TryStreamExt;
use sqlx::{sqlite::SqlitePool, FromRow, Row};
use sqlx::{FromRow, Row, sqlite::SqlitePool};
use time::OffsetDateTime;
use uuid::timestamp::{context::NoContext, Timestamp};
use uuid::Uuid;
use uuid::timestamp::{Timestamp, context::NoContext};
use super::{get_histpath, Importer, Loader};
use super::{Importer, Loader, get_histpath};
use crate::history::History;
use crate::utils::get_host_user;

View File

@ -6,10 +6,10 @@ use std::path::PathBuf;
use async_trait::async_trait;
use directories::UserDirs;
use eyre::{eyre, Result};
use eyre::{Result, eyre};
use time::OffsetDateTime;
use super::{get_histpath, unix_byte_lines, Importer, Loader};
use super::{Importer, Loader, get_histpath, unix_byte_lines};
use crate::history::History;
use crate::import::read_to_end;
@ -38,7 +38,7 @@ fn default_histpath() -> Result<PathBuf> {
None => {
break Err(eyre!(
"Could not find history file. Try setting and exporting $HISTFILE"
))
));
}
}
}

View File

@ -38,8 +38,8 @@ use std::path::{Path, PathBuf};
use async_trait::async_trait;
use atuin_common::utils::uuid_v7;
use directories::UserDirs;
use eyre::{eyre, Result};
use sqlx::{sqlite::SqlitePool, Pool};
use eyre::{Result, eyre};
use sqlx::{Pool, sqlite::SqlitePool};
use time::PrimitiveDateTime;
use super::Importer;
@ -178,10 +178,12 @@ mod test {
use sqlx::sqlite::SqlitePoolOptions;
use std::env;
#[tokio::test(flavor = "multi_thread")]
#[allow(unsafe_code)]
async fn test_env_vars() {
let test_env_db = "nonstd-zsh-history.db";
let key = "HISTDB_FILE";
env::set_var(key, test_env_db);
// TODO: Audit that the environment access only happens in single-threaded code.
unsafe { env::set_var(key, test_env_db) };
// test the env got set
assert_eq!(env::var(key).unwrap(), test_env_db.to_string());

View File

@ -1,7 +1,7 @@
use std::collections::BTreeMap;
use atuin_common::record::{DecryptedData, Host, HostId};
use eyre::{bail, ensure, eyre, Result};
use eyre::{Result, bail, ensure, eyre};
use serde::Deserialize;
use crate::record::encryption::PASETO_V4;
@ -200,7 +200,7 @@ mod tests {
use crate::record::sqlite_store::SqliteStore;
use crate::settings::test_local_timeout;
use super::{KvRecord, KvStore, KV_VERSION};
use super::{KV_VERSION, KvRecord, KvStore};
#[test]
fn encode_decode() {

View File

@ -1,4 +1,4 @@
#![forbid(unsafe_code)]
#![deny(unsafe_code)]
#[macro_use]
extern crate log;

View File

@ -1,13 +1,13 @@
use std::path::PathBuf;
use atuin_common::api::LoginRequest;
use eyre::{bail, Context, Result};
use eyre::{Context, Result, bail};
use tokio::fs::File;
use tokio::io::AsyncWriteExt;
use crate::{
api_client,
encryption::{decode_key, encode_key, load_key, Key},
encryption::{Key, decode_key, encode_key, load_key},
record::{sqlite_store::SqliteStore, store::Store},
settings::Settings,
};
@ -23,7 +23,8 @@ pub async fn login(
let key = match bip39::Mnemonic::from_phrase(&key, bip39::Language::English) {
Ok(mnemonic) => encode_key(Key::from_slice(mnemonic.entropy()))?,
Err(err) => {
if let Some(err) = err.downcast_ref::<bip39::ErrorKind>() {
match err.downcast_ref::<bip39::ErrorKind>() {
Some(err) => {
match err {
// assume they copied in the base64 key
bip39::ErrorKind::InvalidWord => key,
@ -36,11 +37,13 @@ pub async fn login(
bail!("key was not the correct length")
}
}
} else {
}
_ => {
// unknown error. assume they copied the base64 key
key
}
}
}
};
let key_path = settings.key_path.as_str();

View File

@ -1,8 +1,8 @@
use atuin_common::record::{
AdditionalData, DecryptedData, EncryptedData, Encryption, HostId, RecordId, RecordIdx,
};
use base64::{engine::general_purpose, Engine};
use eyre::{ensure, Context, Result};
use base64::{Engine, engine::general_purpose};
use eyre::{Context, Result, ensure};
use rusty_paserk::{Key, KeyId, Local, PieWrappedKey};
use rusty_paseto::core::{
ImplicitAssertion, Key as DataKey, Local as LocalPurpose, Paseto, PasetoNonce, Payload, V4,

View File

@ -6,12 +6,12 @@ use std::str::FromStr;
use std::{path::Path, time::Duration};
use async_trait::async_trait;
use eyre::{eyre, Result};
use eyre::{Result, eyre};
use fs_err as fs;
use sqlx::{
sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePool, SqlitePoolOptions, SqliteRow},
Row,
sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePool, SqlitePoolOptions, SqliteRow},
};
use atuin_common::record::{
@ -35,7 +35,9 @@ impl SqliteStore {
debug!("opening sqlite database at {:?}", path);
if utils::broken_symlink(path) {
eprintln!("Atuin: Sqlite db path ({path:?}) is a broken symlink. Unable to read or create replacement.");
eprintln!(
"Atuin: Sqlite db path ({path:?}) is a broken symlink. Unable to read or create replacement."
);
std::process::exit(1);
}

View File

@ -133,7 +133,7 @@ pub async fn operations(
msg: String::from(
"diff has nothing for local or remote - (host, tag) does not exist",
),
})
});
}
};

View File

@ -38,7 +38,9 @@ pub static SECRET_PATTERNS: &[(&str, &str, TestValue)] = &[
(
"Atuin login",
r"atuin\s+login",
TestValue::Single("atuin login -u mycoolusername -p mycoolpassword -k \"lots of random words\""),
TestValue::Single(
"atuin login -u mycoolusername -p mycoolpassword -k \"lots of random words\"",
),
),
(
"GitHub PAT (old)",
@ -51,7 +53,7 @@ pub static SECRET_PATTERNS: &[(&str, &str, TestValue)] = &[
TestValue::Multiple(&[
"gh1_1234567890abcdefghijk_1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklm",
"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", // also legit, also expired
])
]),
),
(
"GitHub OAuth Access Token",
@ -71,7 +73,9 @@ pub static SECRET_PATTERNS: &[(&str, &str, TestValue)] = &[
(
"GitHub Refresh Token",
"ghr_[A-Za-z0-9]{76}",
TestValue::Single("ghr_1234567890abcdefghijklmnopqrstuvwx1234567890abcdefghijklmnopqrstuvwx1234567890abcdefghijklmnopqrstuvwx"), // not a real token
TestValue::Single(
"ghr_1234567890abcdefghijklmnopqrstuvwx1234567890abcdefghijklmnopqrstuvwx1234567890abcdefghijklmnopqrstuvwx",
), // not a real token
),
(
"GitHub App Installation Access Token v1",
@ -96,10 +100,20 @@ pub static SECRET_PATTERNS: &[(&str, &str, TestValue)] = &[
(
"Slack webhook",
"T[a-zA-Z0-9_]{8}/B[a-zA-Z0-9_]{8}/[a-zA-Z0-9_]{24}",
TestValue::Single("https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX"),
TestValue::Single(
"https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX",
),
),
(
"Stripe test key",
"sk_test_[0-9a-zA-Z]{24}",
TestValue::Single("sk_test_1234567890abcdefghijklmnop"),
),
(
"Stripe live key",
"sk_live_[0-9a-zA-Z]{24}",
TestValue::Single("sk_live_1234567890abcdefghijklmnop"),
),
("Stripe test key", "sk_test_[0-9a-zA-Z]{24}", TestValue::Single("sk_test_1234567890abcdefghijklmnop")),
("Stripe live key", "sk_live_[0-9a-zA-Z]{24}", TestValue::Single("sk_live_1234567890abcdefghijklmnop")),
(
"Netlify authentication token",
"nf[pcoub]_[0-9a-zA-Z]{36}",
@ -127,7 +141,7 @@ pub static SECRET_PATTERNS_RE: LazyLock<RegexSet> = LazyLock::new(|| {
mod tests {
use regex::Regex;
use crate::secrets::{TestValue, SECRET_PATTERNS};
use crate::secrets::{SECRET_PATTERNS, TestValue};
#[test]
fn test_secrets() {

View File

@ -6,19 +6,19 @@ use atuin_common::record::HostId;
use atuin_common::utils;
use clap::ValueEnum;
use config::{
builder::DefaultState, Config, ConfigBuilder, Environment, File as ConfigFile, FileFormat,
Config, ConfigBuilder, Environment, File as ConfigFile, FileFormat, builder::DefaultState,
};
use eyre::{bail, eyre, Context, Error, Result};
use fs_err::{create_dir_all, File};
use eyre::{Context, Error, Result, bail, eyre};
use fs_err::{File, create_dir_all};
use humantime::parse_duration;
use regex::RegexSet;
use semver::Version;
use serde::{Deserialize, Serialize};
use serde_with::DeserializeFromStr;
use time::{
format_description::{well_known::Rfc3339, FormatItem},
macros::format_description,
OffsetDateTime, UtcOffset,
format_description::{FormatItem, well_known::Rfc3339},
macros::format_description,
};
use uuid::Uuid;
@ -141,8 +141,9 @@ impl fmt::Display for Timezone {
}
}
/// format: <+|-><hour>[:<minute>[:<second>]]
static OFFSET_FMT: &[FormatItem<'_>] =
format_description!("[offset_hour sign:mandatory padding:none][optional [:[offset_minute padding:none][optional [:[offset_second padding:none]]]]]");
static OFFSET_FMT: &[FormatItem<'_>] = format_description!(
"[offset_hour sign:mandatory padding:none][optional [:[offset_minute padding:none][optional [:[offset_second padding:none]]]]]"
);
impl FromStr for Timezone {
type Err = Error;

View File

@ -109,15 +109,18 @@ async fn sync_download(
for i in remote_status.deleted {
// we will update the stored history to have this data
// pretty much everything can be nullified
if let Some(h) = db.load(i.as_str()).await? {
match db.load(i.as_str()).await? {
Some(h) => {
db.delete(h).await?;
} else {
}
_ => {
info!(
"could not delete history with id {}, not found locally",
i.as_str()
);
}
}
}
Ok((local_count - initial_local, local_count))
}

View File

@ -416,7 +416,7 @@ impl ThemeManager {
"set theme debug on for more info".to_string()
}
),
)))
)));
}
};
let colors: HashMap<Meaning, String> = theme_config.colors;
@ -697,7 +697,8 @@ mod theme_tests {
testing_logger::validate(|captured_logs| {
assert_eq!(captured_logs.len(), 1);
assert_eq!(captured_logs[0].body,
assert_eq!(
captured_logs[0].body,
"Could not load theme nonsolarized: Empty theme directory override and could not find theme elsewhere"
);
assert_eq!(captured_logs[0].level, log::Level::Warn)

View File

@ -1,6 +1,6 @@
[package]
name = "atuin-common"
edition = "2021"
edition = "2024"
description = "common library for atuin"
rust-version = { workspace = true }

View File

@ -1,4 +1,4 @@
#![forbid(unsafe_code)]
#![deny(unsafe_code)]
/// Defines a new UUID type wrapper
macro_rules! new_uuid {

View File

@ -1,7 +1,7 @@
use std::{ffi::OsStr, path::Path, process::Command};
use serde::Serialize;
use sysinfo::{get_current_pid, Process, System};
use sysinfo::{Process, System, get_current_pid};
use thiserror::Error;
#[derive(PartialEq)]

View File

@ -2,9 +2,9 @@ use std::borrow::Cow;
use std::env;
use std::path::PathBuf;
use eyre::{eyre, Result};
use eyre::{Result, eyre};
use base64::prelude::{Engine, BASE64_URL_SAFE_NO_PAD};
use base64::prelude::{BASE64_URL_SAFE_NO_PAD, Engine};
use getrandom::getrandom;
use uuid::Uuid;
@ -194,6 +194,7 @@ pub fn unquote(s: &str) -> Result<String> {
impl<T: AsRef<str>> Escapable for T {}
#[allow(unsafe_code)]
#[cfg(test)]
mod tests {
use pretty_assertions::assert_ne;
@ -214,36 +215,48 @@ mod tests {
}
fn test_config_dir_xdg() {
env::remove_var("HOME");
env::set_var("XDG_CONFIG_HOME", "/home/user/custom_config");
// TODO: Audit that the environment access only happens in single-threaded code.
unsafe { env::remove_var("HOME") };
// TODO: Audit that the environment access only happens in single-threaded code.
unsafe { env::set_var("XDG_CONFIG_HOME", "/home/user/custom_config") };
assert_eq!(
config_dir(),
PathBuf::from("/home/user/custom_config/atuin")
);
env::remove_var("XDG_CONFIG_HOME");
// TODO: Audit that the environment access only happens in single-threaded code.
unsafe { env::remove_var("XDG_CONFIG_HOME") };
}
fn test_config_dir() {
env::set_var("HOME", "/home/user");
env::remove_var("XDG_CONFIG_HOME");
// TODO: Audit that the environment access only happens in single-threaded code.
unsafe { env::set_var("HOME", "/home/user") };
// TODO: Audit that the environment access only happens in single-threaded code.
unsafe { env::remove_var("XDG_CONFIG_HOME") };
assert_eq!(config_dir(), PathBuf::from("/home/user/.config/atuin"));
env::remove_var("HOME");
// TODO: Audit that the environment access only happens in single-threaded code.
unsafe { env::remove_var("HOME") };
}
fn test_data_dir_xdg() {
env::remove_var("HOME");
env::set_var("XDG_DATA_HOME", "/home/user/custom_data");
// TODO: Audit that the environment access only happens in single-threaded code.
unsafe { env::remove_var("HOME") };
// TODO: Audit that the environment access only happens in single-threaded code.
unsafe { env::set_var("XDG_DATA_HOME", "/home/user/custom_data") };
assert_eq!(data_dir(), PathBuf::from("/home/user/custom_data/atuin"));
env::remove_var("XDG_DATA_HOME");
// TODO: Audit that the environment access only happens in single-threaded code.
unsafe { env::remove_var("XDG_DATA_HOME") };
}
fn test_data_dir() {
env::set_var("HOME", "/home/user");
env::remove_var("XDG_DATA_HOME");
// TODO: Audit that the environment access only happens in single-threaded code.
unsafe { env::set_var("HOME", "/home/user") };
// TODO: Audit that the environment access only happens in single-threaded code.
unsafe { env::remove_var("XDG_DATA_HOME") };
assert_eq!(data_dir(), PathBuf::from("/home/user/.local/share/atuin"));
env::remove_var("HOME");
// TODO: Audit that the environment access only happens in single-threaded code.
unsafe { env::remove_var("HOME") };
}
#[test]

View File

@ -1,6 +1,6 @@
[package]
name = "atuin-daemon"
edition = "2021"
edition = "2024"
version = { workspace = true }
description = "The daemon crate for Atuin"

View File

@ -12,7 +12,7 @@ use tokio::net::UnixStream;
use atuin_client::history::History;
use crate::history::{
history_client::HistoryClient as HistoryServiceClient, EndHistoryRequest, StartHistoryRequest,
EndHistoryRequest, StartHistoryRequest, history_client::HistoryClient as HistoryServiceClient,
};
pub struct HistoryClient {

View File

@ -7,13 +7,13 @@ use atuin_client::settings::Settings;
use std::path::PathBuf;
use std::sync::Arc;
use time::OffsetDateTime;
use tracing::{instrument, Level};
use tracing::{Level, instrument};
use atuin_client::database::{Database, Sqlite as HistoryDatabase};
use atuin_client::history::{History, HistoryId};
use dashmap::DashMap;
use eyre::Result;
use tonic::{transport::Server, Request, Response, Status};
use tonic::{Request, Response, Status, transport::Server};
use crate::history::history_server::{History as HistorySvc, HistoryServer};
@ -194,7 +194,9 @@ async fn start_server(settings: Settings, history: HistoryService) -> Result<()>
}
}
Err(err) => {
tracing::warn!("could not detect systemd socket path, ensure that it's at the configured path: {socket_path:?}, error: {err:?}");
tracing::warn!(
"could not detect systemd socket path, ensure that it's at the configured path: {socket_path:?}, error: {err:?}"
);
}
}
(UnixListener::from_std(listener)?, false)

View File

@ -10,7 +10,7 @@ use atuin_client::{
settings::Settings,
};
use atuin_dotfiles::store::{var::VarStore, AliasStore};
use atuin_dotfiles::store::{AliasStore, var::VarStore};
pub async fn worker(
settings: Settings,

View File

@ -1,7 +1,7 @@
[package]
name = "atuin-dotfiles"
description = "The dotfiles crate for Atuin"
edition = "2021"
edition = "2024"
version = { workspace = true }
authors.workspace = true

View File

@ -1,4 +1,4 @@
use eyre::{ensure, eyre, Result};
use eyre::{Result, ensure, eyre};
use rmp::{decode, encode};
use serde::Serialize;
@ -158,7 +158,7 @@ pub async fn import_aliases(store: &AliasStore) -> Result<Vec<Alias>> {
#[cfg(test)]
mod tests {
use crate::shell::{parse_alias, Alias};
use crate::shell::{Alias, parse_alias};
#[test]
fn test_parse_simple_alias() {
@ -177,7 +177,10 @@ mod tests {
let git_alias = super::parse_alias("gwip='git add -A; git rm $(git ls-files --deleted) 2> /dev/null; git commit --no-verify --no-gpg-sign --message \"--wip-- [skip ci]\"'").expect("failed to parse alias");
assert_eq!(git_alias.name, "gwip");
assert_eq!(git_alias.value, "'git add -A; git rm $(git ls-files --deleted) 2> /dev/null; git commit --no-verify --no-gpg-sign --message \"--wip-- [skip ci]\"'");
assert_eq!(
git_alias.value,
"'git add -A; git rm $(git ls-files --deleted) 2> /dev/null; git commit --no-verify --no-gpg-sign --message \"--wip-- [skip ci]\"'"
);
}
#[test]

View File

@ -1,6 +1,6 @@
use std::path::PathBuf;
use crate::store::{var::VarStore, AliasStore};
use crate::store::{AliasStore, var::VarStore};
async fn cached_aliases(path: PathBuf, store: &AliasStore) -> String {
match tokio::fs::read_to_string(path).await {

View File

@ -1,7 +1,7 @@
// Configuration for fish
use std::path::PathBuf;
use crate::store::{var::VarStore, AliasStore};
use crate::store::{AliasStore, var::VarStore};
async fn cached_aliases(path: PathBuf, store: &AliasStore) -> String {
match tokio::fs::read_to_string(path).await {

View File

@ -1,6 +1,6 @@
use std::path::PathBuf;
use crate::store::{var::VarStore, AliasStore};
use crate::store::{AliasStore, var::VarStore};
async fn cached_aliases(path: PathBuf, store: &AliasStore) -> String {
match tokio::fs::read_to_string(path).await {

View File

@ -1,6 +1,6 @@
use std::path::PathBuf;
use crate::store::{var::VarStore, AliasStore};
use crate::store::{AliasStore, var::VarStore};
async fn cached_aliases(path: PathBuf, store: &AliasStore) -> String {
match tokio::fs::read_to_string(path).await {

View File

@ -7,7 +7,7 @@ use atuin_client::record::sqlite_store::SqliteStore;
// + stores, rather than one mega config store.
use atuin_common::record::{DecryptedData, Host, HostId};
use atuin_common::utils::unquote;
use eyre::{bail, ensure, eyre, Result};
use eyre::{Result, bail, ensure, eyre};
use atuin_client::record::encryption::PASETO_V4;
use atuin_client::record::store::Store;
@ -315,7 +315,7 @@ mod tests {
use crate::shell::Alias;
use super::{test_local_timeout, AliasRecord, AliasStore, CONFIG_SHELL_ALIAS_VERSION};
use super::{AliasRecord, AliasStore, CONFIG_SHELL_ALIAS_VERSION, test_local_timeout};
use crypto_secretbox::{KeyInit, XSalsa20Poly1305};
#[test]

View File

@ -6,7 +6,7 @@ use std::collections::BTreeMap;
use atuin_client::record::sqlite_store::SqliteStore;
use atuin_common::record::{DecryptedData, Host, HostId};
use eyre::{bail, ensure, eyre, Result};
use eyre::{Result, bail, ensure, eyre};
use atuin_client::record::encryption::PASETO_V4;
use atuin_client::record::store::Store;
@ -294,7 +294,7 @@ mod tests {
use crate::{shell::Var, store::test_local_timeout};
use super::{VarRecord, VarStore, DOTFILES_VAR_VERSION};
use super::{DOTFILES_VAR_VERSION, VarRecord, VarStore};
use crypto_secretbox::{KeyInit, XSalsa20Poly1305};
#[test]

View File

@ -1,7 +1,7 @@
[package]
name = "atuin-history"
description = "The history crate for Atuin"
edition = "2021"
edition = "2024"
version = { workspace = true }
authors.workspace = true

View File

@ -178,7 +178,9 @@ pub fn pretty_print(stats: Stats, ngram_size: usize, theme: &Theme) {
.collect::<Vec<_>>()
.join(" | ");
println!("{ResetColor}] {gray}{count:num_pad$}{ResetColor} {bold}{formatted_command}{ResetColor}");
println!(
"{ResetColor}] {gray}{count:num_pad$}{ResetColor} {bold}{formatted_command}{ResetColor}"
);
}
println!("Total commands: {}", stats.total_commands);
println!("Unique commands: {}", stats.unique_commands);

View File

@ -1,6 +1,6 @@
[package]
name = "atuin-server-database"
edition = "2021"
edition = "2024"
description = "server database library for atuin"
version = { workspace = true }

View File

@ -15,7 +15,7 @@ use self::{
};
use async_trait::async_trait;
use atuin_common::record::{EncryptedData, HostId, Record, RecordIdx, RecordStatus};
use serde::{de::DeserializeOwned, Serialize};
use serde::{Serialize, de::DeserializeOwned};
use time::{Date, Duration, Month, OffsetDateTime, Time, UtcOffset};
use tracing::instrument;

View File

@ -1,6 +1,6 @@
[package]
name = "atuin-server-postgres"
edition = "2021"
edition = "2024"
description = "server postgres database library for atuin"
version = { workspace = true }

View File

@ -10,8 +10,8 @@ use atuin_server_database::{Database, DbError, DbResult};
use futures_util::TryStreamExt;
use metrics::counter;
use serde::{Deserialize, Serialize};
use sqlx::postgres::PgPoolOptions;
use sqlx::Row;
use sqlx::postgres::PgPoolOptions;
use time::{OffsetDateTime, PrimitiveDateTime, UtcOffset};
use tracing::{instrument, trace};

View File

@ -1,7 +1,7 @@
use ::sqlx::{FromRow, Result};
use atuin_common::record::{EncryptedData, Host, Record};
use atuin_server_database::models::{History, Session, User};
use sqlx::{postgres::PgRow, Row};
use sqlx::{Row, postgres::PgRow};
use time::PrimitiveDateTime;
pub struct DbUser(pub User);

View File

@ -1,6 +1,6 @@
[package]
name = "atuin-server"
edition = "2021"
edition = "2024"
description = "server library for atuin"
rust-version = { workspace = true }

View File

@ -1,4 +1,4 @@
use axum::{http, response::IntoResponse, Json};
use axum::{Json, http, response::IntoResponse};
use serde::Serialize;

View File

@ -1,9 +1,9 @@
use std::{collections::HashMap, convert::TryFrom};
use axum::{
Json,
extract::{Path, Query, State},
http::{HeaderMap, StatusCode},
Json,
};
use metrics::counter;
use time::{Month, UtcOffset};
@ -15,9 +15,9 @@ use crate::{
utils::client_version_min,
};
use atuin_server_database::{
Database,
calendar::{TimePeriod, TimePeriodInfo},
models::NewHistory,
Database,
};
use atuin_common::api::*;
@ -223,7 +223,7 @@ pub async fn calendar<DB: Database>(
"day" => TimePeriod::Day { year, month },
_ => {
return Err(ErrorResponse::reply("invalid focus: use year/month/day")
.with_status(StatusCode::BAD_REQUEST))
.with_status(StatusCode::BAD_REQUEST));
}
};

View File

@ -1,6 +1,6 @@
use atuin_common::api::{ErrorResponse, IndexResponse};
use atuin_server_database::Database;
use axum::{extract::State, http, response::IntoResponse, Json};
use axum::{Json, extract::State, http, response::IntoResponse};
use crate::router::AppState;

View File

@ -1,4 +1,4 @@
use axum::{http::StatusCode, response::IntoResponse, Json};
use axum::{Json, http::StatusCode, response::IntoResponse};
use serde_json::json;
use tracing::instrument;

View File

@ -1,4 +1,4 @@
use axum::{extract::State, http::StatusCode, Json};
use axum::{Json, extract::State, http::StatusCode};
use tracing::instrument;
use super::{ErrorResponse, ErrorResponseStatus, RespExt};
@ -28,7 +28,7 @@ pub async fn status<DB: Database>(
Ok(count) => count,
Err(_) => {
return Err(ErrorResponse::reply("failed to query history count")
.with_status(StatusCode::INTERNAL_SERVER_ERROR))
.with_status(StatusCode::INTERNAL_SERVER_ERROR));
}
},
};

View File

@ -3,17 +3,17 @@ use std::collections::HashMap;
use std::time::Duration;
use argon2::{
password_hash::SaltString, Algorithm, Argon2, Params, PasswordHash, PasswordHasher,
PasswordVerifier, Version,
Algorithm, Argon2, Params, PasswordHash, PasswordHasher, PasswordVerifier, Version,
password_hash::SaltString,
};
use axum::{
Json,
extract::{Path, State},
http::StatusCode,
Json,
};
use metrics::counter;
use postmark::{reqwest::PostmarkClient, Query};
use postmark::{Query, reqwest::PostmarkClient};
use rand::rngs::OsRng;
use tracing::{debug, error, info, instrument};
@ -21,8 +21,8 @@ use tracing::{debug, error, info, instrument};
use super::{ErrorResponse, ErrorResponseStatus, RespExt};
use crate::router::{AppState, UserAuth};
use atuin_server_database::{
models::{NewSession, NewUser},
Database, DbError,
models::{NewSession, NewUser},
};
use reqwest::header::CONTENT_TYPE;
@ -104,7 +104,7 @@ pub async fn register<DB: Database>(
return Err(ErrorResponse::reply(
"Only alphanumeric and hyphens (-) are allowed in usernames",
)
.with_status(StatusCode::BAD_REQUEST))
.with_status(StatusCode::BAD_REQUEST));
}
}
}
@ -201,12 +201,13 @@ pub async fn send_verification<DB: Database>(
}
// TODO: if we ever add another mail provider, can match on them all here.
let postmark_token = if let Some(token) = settings.mail.postmark.token {
token
} else {
let postmark_token = match settings.mail.postmark.token {
Some(token) => token,
_ => {
error!("Failed to verify email: got None for postmark token");
return Err(ErrorResponse::reply("mail not configured")
.with_status(StatusCode::INTERNAL_SERVER_ERROR));
}
};
let db = &state.0.database;

View File

@ -1,4 +1,4 @@
use axum::{extract::Query, extract::State, http::StatusCode, Json};
use axum::{Json, extract::Query, extract::State, http::StatusCode};
use metrics::counter;
use serde::Deserialize;
use tracing::{error, instrument};

View File

@ -4,18 +4,18 @@ use std::future::Future;
use std::net::SocketAddr;
use atuin_server_database::Database;
use axum::{serve, Router};
use axum_server::tls_rustls::RustlsConfig;
use axum::{Router, serve};
use axum_server::Handle;
use eyre::{eyre, Context, Result};
use axum_server::tls_rustls::RustlsConfig;
use eyre::{Context, Result, eyre};
mod handlers;
mod metrics;
mod router;
mod utils;
pub use settings::example_config;
pub use settings::Settings;
pub use settings::example_config;
pub mod settings;

View File

@ -28,10 +28,9 @@ pub fn setup_metrics_recorder() -> PrometheusHandle {
pub async fn track_metrics(req: Request, next: Next) -> impl IntoResponse {
let start = Instant::now();
let path = if let Some(matched_path) = req.extensions().get::<MatchedPath>() {
matched_path.as_str().to_owned()
} else {
req.uri().path().to_owned()
let path = match req.extensions().get::<MatchedPath>() {
Some(matched_path) => matched_path.as_str().to_owned(),
_ => req.uri().path().to_owned(),
};
let method = req.method().clone();

View File

@ -1,12 +1,12 @@
use async_trait::async_trait;
use atuin_common::api::{ErrorResponse, ATUIN_CARGO_VERSION, ATUIN_HEADER_VERSION};
use atuin_common::api::{ATUIN_CARGO_VERSION, ATUIN_HEADER_VERSION, ErrorResponse};
use axum::{
Router,
extract::{FromRequestParts, Request},
http::{self, request::Parts},
middleware::Next,
response::{IntoResponse, Response},
routing::{delete, get, patch, post},
Router,
};
use eyre::Result;
use tower::ServiceBuilder;
@ -18,7 +18,7 @@ use crate::{
metrics,
settings::Settings,
};
use atuin_server_database::{models::User, Database, DbError};
use atuin_server_database::{Database, DbError, models::User};
pub struct UserAuth(pub User);

View File

@ -1,9 +1,9 @@
use std::{io::prelude::*, path::PathBuf};
use config::{Config, Environment, File as ConfigFile, FileFormat};
use eyre::{eyre, Result};
use fs_err::{create_dir_all, File};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use eyre::{Result, eyre};
use fs_err::{File, create_dir_all};
use serde::{Deserialize, Serialize, de::DeserializeOwned};
static EXAMPLE_CONFIG: &str = include_str!("../server.toml");

View File

@ -1,6 +1,6 @@
[package]
name = "atuin"
edition = "2021"
edition = "2024"
description = "atuin - magical shell history"
readme = "./README.md"

View File

@ -1,5 +1,5 @@
use clap::Parser;
use eyre::{bail, Result};
use eyre::{Result, bail};
use atuin_client::{api_client, settings::Settings};
use rpassword::prompt_password;

View File

@ -1,5 +1,5 @@
use atuin_client::{api_client, settings::Settings};
use eyre::{bail, Result};
use eyre::{Result, bail};
use std::fs::remove_file;
use std::path::PathBuf;

View File

@ -1,12 +1,12 @@
use std::{io, path::PathBuf};
use clap::Parser;
use eyre::{bail, Context, Result};
use eyre::{Context, Result, bail};
use tokio::{fs::File, io::AsyncWriteExt};
use atuin_client::{
api_client,
encryption::{decode_key, encode_key, load_key, Key},
encryption::{Key, decode_key, encode_key, load_key},
record::sqlite_store::SqliteStore,
record::store::Store,
settings::Settings,
@ -56,7 +56,9 @@ impl Cmd {
let key_path = PathBuf::from(key_path);
println!("IMPORTANT");
println!("If you are already logged in on another machine, you must ensure that the key you use here is the same as the key you used there.");
println!(
"If you are already logged in on another machine, you must ensure that the key you use here is the same as the key you used there."
);
println!("You can find your key by running 'atuin key' on the other machine");
println!("Do not share this key with anyone");
println!("\nRead more here: https://docs.atuin.sh/guide/sync/#login \n");
@ -75,7 +77,8 @@ impl Cmd {
match bip39::Mnemonic::from_phrase(&key, bip39::Language::English) {
Ok(mnemonic) => encode_key(Key::from_slice(mnemonic.entropy()))?,
Err(err) => {
if let Some(err) = err.downcast_ref::<bip39::ErrorKind>() {
match err.downcast_ref::<bip39::ErrorKind>() {
Some(err) => {
match err {
// assume they copied in the base64 key
bip39::ErrorKind::InvalidWord => key,
@ -88,12 +91,14 @@ impl Cmd {
bail!("key was not the correct length")
}
}
} else {
}
_ => {
// unknown error. assume they copied the base64 key
key
}
}
}
}
};
// I've simplified this a little, but it could really do with a refactor
@ -106,7 +111,9 @@ impl Cmd {
bail!("the key in existing key file was invalid");
}
} else {
panic!("No key provided. Please use 'atuin key' on your other machine, or recover your key from a backup.")
panic!(
"No key provided. Please use 'atuin key' on your other machine, or recover your key from a backup."
)
}
} else if !key_path.exists() {
if decode_key(key.clone()).is_err() {
@ -184,6 +191,9 @@ mod tests {
.into_phrase();
let mnemonic = bip39::Mnemonic::from_phrase(&phrase, bip39::Language::English).unwrap();
assert_eq!(mnemonic.entropy(), key.as_slice());
assert_eq!(phrase, "adapt amused able anxiety mother adapt beef gaze amount else seat alcohol cage lottery avoid scare alcohol cactus school avoid coral adjust catch pink");
assert_eq!(
phrase,
"adapt amused able anxiety mother adapt beef gaze amount else seat alcohol cage lottery avoid scare alcohol cactus school avoid coral adjust catch pink"
);
}
}

View File

@ -1,5 +1,5 @@
use clap::Parser;
use eyre::{bail, Result};
use eyre::{Result, bail};
use tokio::{fs::File, io::AsyncWriteExt};
use atuin_client::{api_client, settings::Settings};
@ -51,8 +51,12 @@ pub async fn run(
let _key = atuin_client::encryption::load_key(settings)?;
println!("Registration successful! Please make a note of your key (run 'atuin key') and keep it safe.");
println!("You will need it to log in on other devices, and we cannot help recover it if you lose it.");
println!(
"Registration successful! Please make a note of your key (run 'atuin key') and keep it safe."
);
println!(
"You will need it to log in on other devices, and we cannot help recover it if you lose it."
);
Ok(())
}

View File

@ -35,11 +35,15 @@ pub async fn run(settings: &Settings, token: Option<String>) -> Result<()> {
}
(false, false) => {
println!("Your Atuin server does not have mail setup. This is not required, though your account cannot be verified. Speak to your admin.");
println!(
"Your Atuin server does not have mail setup. This is not required, though your account cannot be verified. Speak to your admin."
);
}
_ => {
println!("Invalid email and verification status. This is a bug. Please open an issue: https://github.com/atuinsh/atuin");
println!(
"Invalid email and verification status. This is a bug. Please open an issue: https://github.com/atuinsh/atuin"
);
}
}

View File

@ -3,13 +3,13 @@ use std::{env, path::PathBuf, str::FromStr};
use atuin_client::database::Sqlite;
use atuin_client::settings::Settings;
use atuin_common::shell::{shell_name, Shell};
use atuin_common::shell::{Shell, shell_name};
use atuin_common::utils;
use colored::Colorize;
use eyre::Result;
use serde::Serialize;
use sysinfo::{get_current_pid, Disks, System};
use sysinfo::{Disks, System, get_current_pid};
#[derive(Debug, Serialize)]
struct ShellInfo {

View File

@ -1,5 +1,5 @@
use clap::Subcommand;
use eyre::{eyre, Context, Result};
use eyre::{Context, Result, eyre};
use atuin_client::{encryption, record::sqlite_store::SqliteStore, settings::Settings};
@ -92,7 +92,9 @@ impl Cmd {
pub async fn run(&self, settings: &Settings, store: SqliteStore) -> Result<()> {
if !settings.dotfiles.enabled {
eprintln!("Dotfiles are not enabled. Add\n\n[dotfiles]\nenabled = true\n\nto your configuration file to enable them.\n");
eprintln!(
"Dotfiles are not enabled. Add\n\n[dotfiles]\nenabled = true\n\nto your configuration file to enable them.\n"
);
eprintln!("The default configuration file is located at ~/.config/atuin/config.toml.");
return Ok(());
}

View File

@ -73,7 +73,9 @@ impl Cmd {
pub async fn run(&self, settings: &Settings, store: SqliteStore) -> Result<()> {
if !settings.dotfiles.enabled {
eprintln!("Dotfiles are not enabled. Add\n\n[dotfiles]\nenabled = true\n\nto your configuration file to enable them.\n");
eprintln!(
"Dotfiles are not enabled. Add\n\n[dotfiles]\nenabled = true\n\nto your configuration file to enable them.\n"
);
eprintln!("The default configuration file is located at ~/.config/atuin/config.toml.");
return Ok(());
}

View File

@ -11,9 +11,9 @@ use eyre::{Context, Result};
use runtime_format::{FormatKey, FormatKeyError, ParseSegment, ParsedFmt};
use atuin_client::{
database::{current_context, Database, Sqlite},
database::{Database, Sqlite, current_context},
encryption,
history::{store::HistoryStore, History},
history::{History, store::HistoryStore},
record::sqlite_store::SqliteStore,
settings::{
FilterMode::{Directory, Global, Session},
@ -25,7 +25,7 @@ use atuin_client::{
use atuin_client::{record, sync};
use log::{debug, warn};
use time::{macros::format_description, OffsetDateTime};
use time::{OffsetDateTime, macros::format_description};
use super::search::format_duration_into;
@ -285,7 +285,9 @@ fn parse_fmt(format: &str) -> ParsedFmt {
Ok(fmt) => fmt,
Err(err) => {
eprintln!("ERROR: History formatting failed with the following error: {err}");
println!("If your formatting string contains curly braces (eg: {{var}}) you need to escape them this way: {{{{var}}.");
println!(
"If your formatting string contains curly braces (eg: {{var}}) you need to escape them this way: {{{{var}}."
);
std::process::exit(1)
}
}
@ -550,11 +552,11 @@ impl Cmd {
if settings.daemon.enabled {
match self {
Self::Start { command } => {
return Self::handle_daemon_start(settings, &command).await
return Self::handle_daemon_start(settings, &command).await;
}
Self::End { id, exit, duration } => {
return Self::handle_daemon_end(settings, &id, exit, duration).await
return Self::handle_daemon_end(settings, &id, exit, duration).await;
}
_ => {}

View File

@ -9,8 +9,8 @@ use atuin_client::{
database::Database,
history::History,
import::{
bash::Bash, fish::Fish, nu::Nu, nu_histdb::NuHistDb, replxx::Replxx, resh::Resh,
xonsh::Xonsh, xonsh_sqlite::XonshSqlite, zsh::Zsh, zsh_histdb::ZshHistDb, Importer, Loader,
Importer, Loader, bash::Bash, fish::Fish, nu::Nu, nu_histdb::NuHistDb, replxx::Replxx,
resh::Resh, xonsh::Xonsh, xonsh_sqlite::XonshSqlite, zsh::Zsh, zsh_histdb::ZshHistDb,
},
};
@ -57,7 +57,9 @@ impl Cmd {
match self {
Self::Auto => {
if cfg!(windows) {
println!("This feature does not work on windows. Please run atuin import <SHELL>. To view a list of shells, run atuin import.");
println!(
"This feature does not work on windows. Please run atuin import <SHELL>. To view a list of shells, run atuin import."
);
return Ok(());
}

View File

@ -1,7 +1,7 @@
use std::path::PathBuf;
use atuin_client::{encryption, record::sqlite_store::SqliteStore, settings::Settings};
use atuin_dotfiles::store::{var::VarStore, AliasStore};
use atuin_dotfiles::store::{AliasStore, var::VarStore};
use clap::{Parser, ValueEnum};
use eyre::{Result, WrapErr};
@ -160,7 +160,9 @@ $env.config = (
pub async fn run(self, settings: &Settings) -> Result<()> {
if !settings.paths_ok() {
eprintln!("Atuin settings paths are broken. Disabling atuin shell hooks. Run `atuin doctor` to diagnose.");
eprintln!(
"Atuin settings paths are broken. Disabling atuin shell hooks. Run `atuin doctor` to diagnose."
);
return Ok(());
}

View File

@ -1,4 +1,4 @@
use atuin_dotfiles::store::{var::VarStore, AliasStore};
use atuin_dotfiles::store::{AliasStore, var::VarStore};
use eyre::Result;
pub fn init_static(disable_up_arrow: bool, disable_ctrl_r: bool) {

View File

@ -1,4 +1,4 @@
use atuin_dotfiles::store::{var::VarStore, AliasStore};
use atuin_dotfiles::store::{AliasStore, var::VarStore};
use eyre::Result;
pub fn init_static(disable_up_arrow: bool, disable_ctrl_r: bool) {

View File

@ -1,4 +1,4 @@
use atuin_dotfiles::store::{var::VarStore, AliasStore};
use atuin_dotfiles::store::{AliasStore, var::VarStore};
use eyre::Result;
pub fn init_static(disable_up_arrow: bool, disable_ctrl_r: bool) {

View File

@ -1,4 +1,4 @@
use atuin_dotfiles::store::{var::VarStore, AliasStore};
use atuin_dotfiles::store::{AliasStore, var::VarStore};
use eyre::Result;
pub fn init_static(disable_up_arrow: bool, disable_ctrl_r: bool) {

View File

@ -1,4 +1,4 @@
use std::io::{stderr, IsTerminal as _};
use std::io::{IsTerminal as _, stderr};
use atuin_common::utils::{self, Escapable as _};
use clap::Parser;
@ -6,9 +6,9 @@ use eyre::Result;
use atuin_client::{
database::Database,
database::{current_context, OptFilters},
database::{OptFilters, current_context},
encryption,
history::{store::HistoryStore, History},
history::{History, store::HistoryStore},
record::sqlite_store::SqliteStore,
settings::{FilterMode, KeymapMode, SearchMode, Settings, Timezone},
theme::Theme,
@ -165,7 +165,9 @@ impl Cmd {
}
if self.delete && query.is_empty() {
eprintln!("Please specify a query to match the items you wish to delete. If you wish to delete all history, pass --delete-it-all");
eprintln!(
"Please specify a query to match the items you wish to delete. If you wish to delete all history, pass --delete-it-all"
);
return Ok(());
}

View File

@ -184,11 +184,7 @@ impl Cursor {
}
pub fn back(&mut self) -> Option<char> {
if self.left() {
self.remove()
} else {
None
}
if self.left() { self.remove() } else { None }
}
pub fn clear(&mut self) {

View File

@ -3,7 +3,7 @@ use std::path::Path;
use async_trait::async_trait;
use atuin_client::{database::Database, history::History, settings::FilterMode};
use eyre::Result;
use fuzzy_matcher::{skim::SkimMatcherV2, FuzzyMatcher};
use fuzzy_matcher::{FuzzyMatcher, skim::SkimMatcherV2};
use itertools::Itertools;
use time::OffsetDateTime;
use tokio::task::yield_now;

View File

@ -6,12 +6,12 @@ use atuin_client::{
settings::Settings,
};
use ratatui::{
Frame,
crossterm::event::{KeyCode, KeyEvent, KeyModifiers},
layout::Rect,
prelude::{Constraint, Direction, Layout},
style::Style,
widgets::{Bar, BarChart, BarGroup, Block, Borders, Padding, Paragraph, Row, Table},
Frame,
};
use super::duration::format_duration;
@ -21,11 +21,7 @@ use super::interactive::{InputAction, State};
#[allow(clippy::cast_sign_loss)]
fn u64_or_zero(num: i64) -> u64 {
if num < 0 {
0
} else {
num as u64
}
if num < 0 { 0 } else { num as u64 }
}
pub fn draw_commands(

View File

@ -1,5 +1,5 @@
use std::{
io::{stdout, Write},
io::{Write, stdout},
time::Duration,
};
@ -11,8 +11,8 @@ use time::OffsetDateTime;
use unicode_width::UnicodeWidthStr;
use atuin_client::{
database::{current_context, Database},
history::{store::HistoryStore, History, HistoryStats},
database::{Database, current_context},
history::{History, HistoryStats, store::HistoryStore},
settings::{
CursorStyle, ExitMode, FilterMode, KeymapMode, PreviewStrategy, SearchMode, Settings,
},
@ -25,9 +25,10 @@ use super::{
};
use crate::command::client::theme::{Meaning, Theme};
use crate::{command::client::search::engines, VERSION};
use crate::{VERSION, command::client::search::engines};
use ratatui::{
Frame, Terminal, TerminalOptions, Viewport,
backend::CrosstermBackend,
crossterm::{
cursor::SetCursorStyle,
@ -42,8 +43,7 @@ use ratatui::{
prelude::*,
style::{Modifier, Style},
text::{Line, Span, Text},
widgets::{block::Title, Block, BorderType, Borders, Padding, Paragraph, Tabs},
Frame, Terminal, TerminalOptions, Viewport,
widgets::{Block, BorderType, Borders, Padding, Paragraph, Tabs, block::Title},
};
const TAB_TITLES: [&str; 2] = ["Search", "Inspect"];
@ -390,7 +390,7 @@ impl State {
KeyCode::Char(c @ '1'..='9') if modfr => {
return c.to_digit(10).map_or(InputAction::Continue, |c| {
InputAction::Accept(self.results_state.selected() + c as usize)
})
});
}
KeyCode::Left if ctrl => self
.search
@ -763,7 +763,9 @@ impl State {
// HACK: I'm following up with abstracting this into the UI container, with a
// sub-widget for search + for inspector
let feedback = Paragraph::new("The inspector is new - please give feedback (good, or bad) at https://forum.atuin.sh");
let feedback = Paragraph::new(
"The inspector is new - please give feedback (good, or bad) at https://forum.atuin.sh",
);
f.render_widget(feedback, input_chunk);
return;

View File

@ -4,7 +4,7 @@ use interim::parse_date_string;
use time::{Duration, OffsetDateTime, Time};
use atuin_client::{
database::{current_context, Database},
database::{Database, current_context},
settings::Settings,
theme::Theme,
};

View File

@ -1,6 +1,6 @@
use atuin_dotfiles::store::{var::VarStore, AliasStore};
use atuin_dotfiles::store::{AliasStore, var::VarStore};
use clap::Args;
use eyre::{bail, Result};
use eyre::{Result, bail};
use atuin_client::{
database::Database, encryption, history::store::HistoryStore,

View File

@ -1,9 +1,9 @@
use clap::Args;
use eyre::{bail, Result};
use eyre::{Result, bail};
use tokio::{fs::File, io::AsyncWriteExt};
use atuin_client::{
encryption::{decode_key, encode_key, generate_encoded_key, load_key, Key},
encryption::{Key, decode_key, encode_key, generate_encoded_key, load_key},
record::sqlite_store::SqliteStore,
record::store::Store,
settings::Settings,
@ -23,7 +23,8 @@ impl Rekey {
let key = match bip39::Mnemonic::from_phrase(&key, bip39::Language::English) {
Ok(mnemonic) => encode_key(Key::from_slice(mnemonic.entropy()))?,
Err(err) => {
if let Some(err) = err.downcast_ref::<bip39::ErrorKind>() {
match err.downcast_ref::<bip39::ErrorKind>() {
Some(err) => {
match err {
// assume they copied in the base64 key
bip39::ErrorKind::InvalidWord => key,
@ -36,11 +37,13 @@ impl Rekey {
bail!("key was not the correct length")
}
}
} else {
}
_ => {
// unknown error. assume they copied the base64 key
key
}
}
}
};
key

View File

@ -5,7 +5,7 @@ use time::{Date, Duration, Month, OffsetDateTime, Time};
use atuin_client::{database::Database, settings::Settings, theme::Theme};
use atuin_history::stats::{compute, Stats};
use atuin_history::stats::{Stats, compute};
#[derive(Debug)]
struct WrappedStats {
@ -293,7 +293,9 @@ pub async fn run(
let history = db.range(start, end).await?;
if history.is_empty() {
println!("Your history for {year} is empty!\nMaybe 'atuin import' could help you import your previous history 🪄");
println!(
"Your history for {year} is empty!\nMaybe 'atuin import' could help you import your previous history 🪄"
);
return Ok(());
}

View File

@ -1,5 +1,5 @@
use clap::{CommandFactory, Parser, ValueEnum};
use clap_complete::{generate, generate_to, Generator, Shell};
use clap_complete::{Generator, Shell, generate, generate_to};
use clap_complete_nushell::Nushell;
use eyre::Result;

View File

@ -1,12 +1,12 @@
use std::net::SocketAddr;
use atuin_server_postgres::Postgres;
use tracing_subscriber::{fmt, prelude::*, EnvFilter};
use tracing_subscriber::{EnvFilter, fmt, prelude::*};
use clap::Parser;
use eyre::{Context, Result};
use atuin_server::{example_config, launch, launch_metrics_server, Settings};
use atuin_server::{Settings, example_config, launch, launch_metrics_server};
#[derive(Parser, Debug)]
#[clap(infer_subcommands = true)]

View File

@ -1,4 +1,4 @@
use atuin_dotfiles::store::{var::VarStore, AliasStore};
use atuin_dotfiles::store::{AliasStore, var::VarStore};
use eyre::{Context, Result};
use atuin_client::{

View File

@ -2,12 +2,12 @@ use std::{env, time::Duration};
use atuin_client::api_client;
use atuin_common::utils::uuid_v7;
use atuin_server::{launch_with_tcp_listener, Settings as ServerSettings};
use atuin_server::{Settings as ServerSettings, launch_with_tcp_listener};
use atuin_server_postgres::{Postgres, PostgresSettings};
use futures_util::TryFutureExt;
use tokio::{net::TcpListener, sync::oneshot, task::JoinHandle};
use tracing::{dispatcher, Dispatch};
use tracing_subscriber::{layer::SubscriberExt, EnvFilter};
use tracing::{Dispatch, dispatcher};
use tracing_subscriber::{EnvFilter, layer::SubscriberExt};
pub async fn start_server(path: &str) -> (String, oneshot::Sender<()>, JoinHandle<()>) {
let formatting_layer = tracing_tree::HierarchicalLayer::default()

View File

@ -32,7 +32,7 @@
fenix.packages.${system}.fromToolchainFile
{
file = ./rust-toolchain.toml;
sha256 = "sha256-AJ6LX/Q/Er9kS15bn9iflkUwcgYqRQxiOIL2ToVAXaU=";
sha256 = "sha256-Hn2uaQzRLidAWpfmRwSRdImifGUCAb9HeAqTYFXWeQk=";
};
in
pkgs.makeRustPlatform {