mirror of
https://github.com/atuinsh/atuin.git
synced 2025-06-20 09:58:00 +02:00
fix(import/zsh-histdb): missing or wrong fields (#1740)
* fix(import/zsh-histdb): import exit_status and session * fix(import/zsh-histdb): avoid session id conflict * fix(import/zsh-histdb): follow the format conventions of session and hostname * fix(import/zsh-histdb): duration unit is nanosecond
This commit is contained in:
parent
3c375cad07
commit
21fee97a62
@ -20,8 +20,8 @@
|
|||||||
// places.dir,
|
// places.dir,
|
||||||
// commands.argv
|
// commands.argv
|
||||||
// from history
|
// from history
|
||||||
// left join commands on history.command_id = commands.rowid
|
// left join commands on history.command_id = commands.id
|
||||||
// left join places on history.place_id = places.rowid ;
|
// left join places on history.place_id = places.id ;
|
||||||
//
|
//
|
||||||
// CREATE TABLE history (id integer primary key autoincrement,
|
// CREATE TABLE history (id integer primary key autoincrement,
|
||||||
// session int,
|
// session int,
|
||||||
@ -32,9 +32,12 @@
|
|||||||
// duration int);
|
// duration int);
|
||||||
//
|
//
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::env;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
use atuin_common::utils::uuid_v7;
|
||||||
use directories::UserDirs;
|
use directories::UserDirs;
|
||||||
use eyre::{eyre, Result};
|
use eyre::{eyre, Result};
|
||||||
use sqlx::{sqlite::SqlitePool, Pool};
|
use sqlx::{sqlite::SqlitePool, Pool};
|
||||||
@ -57,39 +60,22 @@ pub struct HistDbEntry {
|
|||||||
pub dir: Vec<u8>,
|
pub dir: Vec<u8>,
|
||||||
pub argv: Vec<u8>,
|
pub argv: Vec<u8>,
|
||||||
pub duration: i64,
|
pub duration: i64,
|
||||||
|
pub exit_status: i64,
|
||||||
|
pub session: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<HistDbEntry> for History {
|
fn get_hostname() -> String {
|
||||||
fn from(histdb_item: HistDbEntry) -> Self {
|
env::var("ATUIN_HOST_NAME").unwrap_or_else(|_| whoami::hostname())
|
||||||
let imported = History::import()
|
|
||||||
.timestamp(histdb_item.start_time.assume_utc())
|
|
||||||
.command(
|
|
||||||
String::from_utf8(histdb_item.argv)
|
|
||||||
.unwrap_or_else(|_e| String::from(""))
|
|
||||||
.trim_end()
|
|
||||||
.to_string(),
|
|
||||||
)
|
|
||||||
.cwd(
|
|
||||||
String::from_utf8(histdb_item.dir)
|
|
||||||
.unwrap_or_else(|_e| String::from(""))
|
|
||||||
.trim_end()
|
|
||||||
.to_string(),
|
|
||||||
)
|
|
||||||
.duration(histdb_item.duration)
|
|
||||||
.hostname(
|
|
||||||
String::from_utf8(histdb_item.host)
|
|
||||||
.unwrap_or_else(|_e| String::from(""))
|
|
||||||
.trim_end()
|
|
||||||
.to_string(),
|
|
||||||
);
|
|
||||||
|
|
||||||
imported.build().into()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_username() -> String {
|
||||||
|
env::var("ATUIN_HOST_USER").unwrap_or_else(|_| whoami::username())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ZshHistDb {
|
pub struct ZshHistDb {
|
||||||
histdb: Vec<HistDbEntry>,
|
histdb: Vec<HistDbEntry>,
|
||||||
|
username: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read db at given file, return vector of entries.
|
/// Read db at given file, return vector of entries.
|
||||||
@ -99,7 +85,15 @@ async fn hist_from_db(dbpath: PathBuf) -> Result<Vec<HistDbEntry>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn hist_from_db_conn(pool: Pool<sqlx::Sqlite>) -> Result<Vec<HistDbEntry>> {
|
async fn hist_from_db_conn(pool: Pool<sqlx::Sqlite>) -> Result<Vec<HistDbEntry>> {
|
||||||
let query = "select history.id,history.start_time,history.duration,places.host,places.dir,commands.argv from history left join commands on history.command_id = commands.rowid left join places on history.place_id = places.rowid order by history.start_time";
|
let query = r#"
|
||||||
|
SELECT
|
||||||
|
history.id, history.start_time, history.duration, places.host, places.dir,
|
||||||
|
commands.argv, history.exit_status, history.session
|
||||||
|
FROM history
|
||||||
|
LEFT JOIN commands ON history.command_id = commands.id
|
||||||
|
LEFT JOIN places ON history.place_id = places.id
|
||||||
|
ORDER BY history.start_time
|
||||||
|
"#;
|
||||||
let histdb_vec: Vec<HistDbEntry> = sqlx::query_as::<_, HistDbEntry>(query)
|
let histdb_vec: Vec<HistDbEntry> = sqlx::query_as::<_, HistDbEntry>(query)
|
||||||
.fetch_all(&pool)
|
.fetch_all(&pool)
|
||||||
.await?;
|
.await?;
|
||||||
@ -144,14 +138,42 @@ impl Importer for ZshHistDb {
|
|||||||
let histdb_entry_vec = hist_from_db(dbpath).await?;
|
let histdb_entry_vec = hist_from_db(dbpath).await?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
histdb: histdb_entry_vec,
|
histdb: histdb_entry_vec,
|
||||||
|
username: get_username(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn entries(&mut self) -> Result<usize> {
|
async fn entries(&mut self) -> Result<usize> {
|
||||||
Ok(self.histdb.len())
|
Ok(self.histdb.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn load(self, h: &mut impl Loader) -> Result<()> {
|
async fn load(self, h: &mut impl Loader) -> Result<()> {
|
||||||
for i in self.histdb {
|
let mut session_map = HashMap::new();
|
||||||
h.push(i.into()).await?;
|
for entry in self.histdb {
|
||||||
|
let command = match std::str::from_utf8(&entry.argv) {
|
||||||
|
Ok(s) => s.trim_end(),
|
||||||
|
Err(_) => continue, // we can skip past things like invalid utf8
|
||||||
|
};
|
||||||
|
let cwd = match std::str::from_utf8(&entry.dir) {
|
||||||
|
Ok(s) => s.trim_end(),
|
||||||
|
Err(_) => continue, // we can skip past things like invalid utf8
|
||||||
|
};
|
||||||
|
let hostname = format!(
|
||||||
|
"{}:{}",
|
||||||
|
String::from_utf8(entry.host).unwrap_or_else(|_e| get_hostname()),
|
||||||
|
self.username
|
||||||
|
);
|
||||||
|
let session = session_map.entry(entry.session).or_insert_with(uuid_v7);
|
||||||
|
|
||||||
|
let imported = History::import()
|
||||||
|
.timestamp(entry.start_time.assume_utc())
|
||||||
|
.command(command)
|
||||||
|
.cwd(cwd)
|
||||||
|
.duration(entry.duration * 1_000_000_000)
|
||||||
|
.exit(entry.exit_status)
|
||||||
|
.session(session.as_simple().to_string())
|
||||||
|
.hostname(hostname)
|
||||||
|
.build();
|
||||||
|
h.push(imported.into()).await?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -219,7 +241,10 @@ mod test {
|
|||||||
|
|
||||||
// test histdb iterator
|
// test histdb iterator
|
||||||
let histdb_vec = hist_from_db_conn(pool).await.unwrap();
|
let histdb_vec = hist_from_db_conn(pool).await.unwrap();
|
||||||
let histdb = ZshHistDb { histdb: histdb_vec };
|
let histdb = ZshHistDb {
|
||||||
|
histdb: histdb_vec,
|
||||||
|
username: get_username(),
|
||||||
|
};
|
||||||
|
|
||||||
println!("h: {:#?}", histdb.histdb);
|
println!("h: {:#?}", histdb.histdb);
|
||||||
println!("counter: {:?}", histdb.histdb.len());
|
println!("counter: {:?}", histdb.histdb.len());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user