handle missing entries (fixes #1236) (#1253)

* fix #1236

* lints
This commit is contained in:
Conrad Ludgate 2023-09-26 14:52:45 +01:00 committed by GitHub
parent bdba88c11f
commit fc1a48a4f2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 24 additions and 27 deletions

View file

@ -73,7 +73,7 @@ pub trait Database: Send + Sync + 'static {
async fn save(&mut self, h: &History) -> Result<()>; async fn save(&mut self, h: &History) -> Result<()>;
async fn save_bulk(&mut self, h: &[History]) -> Result<()>; async fn save_bulk(&mut self, h: &[History]) -> Result<()>;
async fn load(&self, id: &str) -> Result<History>; async fn load(&self, id: &str) -> Result<Option<History>>;
async fn list( async fn list(
&self, &self,
filter: FilterMode, filter: FilterMode,
@ -86,8 +86,7 @@ pub trait Database: Send + Sync + 'static {
async fn update(&self, h: &History) -> Result<()>; async fn update(&self, h: &History) -> Result<()>;
async fn history_count(&self) -> Result<i64>; async fn history_count(&self) -> Result<i64>;
async fn first(&self) -> Result<History>; async fn last(&self) -> Result<Option<History>>;
async fn last(&self) -> Result<History>;
async fn before(&self, timestamp: OffsetDateTime, count: i64) -> Result<Vec<History>>; async fn before(&self, timestamp: OffsetDateTime, count: i64) -> Result<Vec<History>>;
async fn delete(&self, mut h: History) -> Result<()>; async fn delete(&self, mut h: History) -> Result<()>;
@ -216,13 +215,13 @@ impl Database for Sqlite {
Ok(()) Ok(())
} }
async fn load(&self, id: &str) -> Result<History> { async fn load(&self, id: &str) -> Result<Option<History>> {
debug!("loading history item {}", id); debug!("loading history item {}", id);
let res = sqlx::query("select * from history where id = ?1") let res = sqlx::query("select * from history where id = ?1")
.bind(id) .bind(id)
.map(Self::query_history) .map(Self::query_history)
.fetch_one(&self.pool) .fetch_optional(&self.pool)
.await?; .await?;
Ok(res) Ok(res)
@ -308,22 +307,12 @@ impl Database for Sqlite {
Ok(res) Ok(res)
} }
async fn first(&self) -> Result<History> { async fn last(&self) -> Result<Option<History>> {
let res =
sqlx::query("select * from history where duration >= 0 order by timestamp asc limit 1")
.map(Self::query_history)
.fetch_one(&self.pool)
.await?;
Ok(res)
}
async fn last(&self) -> Result<History> {
let res = sqlx::query( let res = sqlx::query(
"select * from history where duration >= 0 order by timestamp desc limit 1", "select * from history where duration >= 0 order by timestamp desc limit 1",
) )
.map(Self::query_history) .map(Self::query_history)
.fetch_one(&self.pool) .fetch_optional(&self.pool)
.await?; .await?;
Ok(res) Ok(res)

View file

@ -210,9 +210,11 @@ mod tests {
// Test that we don't save history where necessary // Test that we don't save history where necessary
#[test] #[test]
fn privacy_test() { fn privacy_test() {
let mut settings = Settings::default(); let settings = Settings {
settings.cwd_filter = RegexSet::new(["^/supasecret"]).unwrap(); cwd_filter: RegexSet::new(["^/supasecret"]).unwrap(),
settings.history_filter = RegexSet::new(["^psql"]).unwrap(); history_filter: RegexSet::new(["^psql"]).unwrap(),
..Settings::default()
};
let normal_command: History = History::capture() let normal_command: History = History::capture()
.timestamp(time::OffsetDateTime::now_utc()) .timestamp(time::OffsetDateTime::now_utc())
@ -258,8 +260,10 @@ mod tests {
#[test] #[test]
fn disable_secrets() { fn disable_secrets() {
let mut settings = Settings::default(); let settings = Settings {
settings.secrets_filter = false; secrets_filter: false,
..Settings::default()
};
let stripe_key: History = History::capture() let stripe_key: History = History::capture()
.timestamp(time::OffsetDateTime::now_utc()) .timestamp(time::OffsetDateTime::now_utc())

View file

@ -46,7 +46,7 @@ mod tests {
fn test_secrets() { fn test_secrets() {
for (name, regex, test) in SECRET_PATTERNS { for (name, regex, test) in SECRET_PATTERNS {
let re = let re =
Regex::new(regex).expect(format!("Failed to compile regex for {name}").as_str()); Regex::new(regex).unwrap_or_else(|_| panic!("Failed to compile regex for {name}"));
assert!(re.is_match(test), "{name} test failed!"); assert!(re.is_match(test), "{name} test failed!");
} }

View file

@ -109,7 +109,7 @@ async fn sync_download(
for i in remote_status.deleted { for i in remote_status.deleted {
// we will update the stored history to have this data // we will update the stored history to have this data
// pretty much everything can be nullified // pretty much everything can be nullified
if let Ok(h) = db.load(i.as_str()).await { if let Some(h) = db.load(i.as_str()).await? {
db.delete(h).await?; db.delete(h).await?;
} else { } else {
info!( info!(

View file

@ -18,7 +18,7 @@ use atuin_client::{
#[cfg(feature = "sync")] #[cfg(feature = "sync")]
use atuin_client::sync; use atuin_client::sync;
use log::debug; use log::{debug, warn};
use time::{macros::format_description, OffsetDateTime}; use time::{macros::format_description, OffsetDateTime};
use super::search::format_duration_into; use super::search::format_duration_into;
@ -233,7 +233,10 @@ impl Cmd {
return Ok(()); return Ok(());
} }
let mut h = db.load(id).await?; let Some(mut h) = db.load(id).await? else {
warn!("history entry is missing");
return Ok(());
};
if h.duration > 0 { if h.duration > 0 {
debug!("cannot end history - already has duration"); debug!("cannot end history - already has duration");
@ -329,8 +332,9 @@ impl Cmd {
format, format,
} => { } => {
let last = db.last().await?; let last = db.last().await?;
let last = last.as_ref().map(std::slice::from_ref).unwrap_or_default();
print_list( print_list(
&[last], last,
ListMode::from_flags(human, cmd_only), ListMode::from_flags(human, cmd_only),
format.as_deref(), format.as_deref(),
); );