parent
bdba88c11f
commit
fc1a48a4f2
5 changed files with 24 additions and 27 deletions
|
@ -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)
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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!(
|
||||||
|
|
|
@ -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(),
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in a new issue