summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorConrad Ludgate <conradludgate@gmail.com>2022-04-25 07:13:30 +0100
committerGitHub <noreply@github.com>2022-04-25 07:13:30 +0100
commit7f5310a1aa87cb32499e7f50c864fdaa9a82bd53 (patch)
treea1c499f3876d92687f71e72076c3a715d9f16798
parent2fd9651dea01d301584644caa495a7f9a661600f (diff)
history list (#340)
-rw-r--r--Cargo.lock101
-rw-r--r--Cargo.toml1
-rw-r--r--atuin-client/Cargo.toml6
-rw-r--r--atuin-client/src/api_client.rs2
-rw-r--r--atuin-client/src/history.rs4
-rw-r--r--atuin-client/src/sync.rs9
-rw-r--r--atuin-common/Cargo.toml1
-rw-r--r--atuin-common/src/utils.rs9
-rw-r--r--atuin-server/Cargo.toml1
-rw-r--r--src/command/client/history.rs98
-rw-r--r--src/command/client/search.rs182
11 files changed, 175 insertions, 239 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 009a922b..df2c1bfb 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -93,7 +93,6 @@ dependencies = [
"pretty_env_logger",
"serde",
"serde_json",
- "tabwriter",
"termion",
"tokio",
"tracing-subscriber",
@@ -115,6 +114,7 @@ dependencies = [
"directories",
"eyre",
"fs-err",
+ "hex",
"itertools",
"lazy_static",
"log",
@@ -123,9 +123,9 @@ dependencies = [
"regex",
"reqwest",
"rmp-serde",
- "rust-crypto",
"serde",
"serde_json",
+ "sha2",
"shellexpand",
"sodiumoxide",
"sql-builder",
@@ -141,7 +141,6 @@ name = "atuin-common"
version = "0.9.1"
dependencies = [
"chrono",
- "rust-crypto",
"serde",
"uuid",
]
@@ -160,8 +159,7 @@ dependencies = [
"eyre",
"fs-err",
"http",
- "rand 0.8.5",
- "rust-crypto",
+ "rand",
"serde",
"serde_json",
"sodiumoxide",
@@ -725,12 +723,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bd79fa345a495d3ae89fb7165fec01c0e72f41821d642dda363a1e97975652e"
[[package]]
-name = "fuchsia-cprng"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
-
-[[package]]
name = "futures-channel"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -795,12 +787,6 @@ dependencies = [
]
[[package]]
-name = "gcc"
-version = "0.3.55"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
-
-[[package]]
name = "generic-array"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1618,36 +1604,13 @@ dependencies = [
[[package]]
name = "rand"
-version = "0.3.23"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c"
-dependencies = [
- "libc",
- "rand 0.4.6",
-]
-
-[[package]]
-name = "rand"
-version = "0.4.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
-dependencies = [
- "fuchsia-cprng",
- "libc",
- "rand_core 0.3.1",
- "rdrand",
- "winapi",
-]
-
-[[package]]
-name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
- "rand_core 0.6.3",
+ "rand_core",
]
[[package]]
@@ -1657,26 +1620,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
- "rand_core 0.6.3",
+ "rand_core",
]
[[package]]
name = "rand_core"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
-dependencies = [
- "rand_core 0.4.2",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
-
-[[package]]
-name = "rand_core"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
@@ -1685,15 +1633,6 @@ dependencies = [
]
[[package]]
-name = "rdrand"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
-dependencies = [
- "rand_core 0.3.1",
-]
-
-[[package]]
name = "redox_syscall"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1835,19 +1774,6 @@ dependencies = [
]
[[package]]
-name = "rust-crypto"
-version = "0.2.36"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a"
-dependencies = [
- "gcc",
- "libc",
- "rand 0.3.23",
- "rustc-serialize",
- "time",
-]
-
-[[package]]
name = "rust-ini"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1858,12 +1784,6 @@ dependencies = [
]
[[package]]
-name = "rustc-serialize"
-version = "0.3.24"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
-
-[[package]]
name = "rustls"
version = "0.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2172,7 +2092,7 @@ dependencies = [
"once_cell",
"paste",
"percent-encoding",
- "rand 0.8.5",
+ "rand",
"rustls 0.19.1",
"serde",
"serde_json",
@@ -2260,15 +2180,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8"
[[package]]
-name = "tabwriter"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36205cfc997faadcc4b0b87aaef3fbedafe20d38d4959a7ca6ff803564051111"
-dependencies = [
- "unicode-width",
-]
-
-[[package]]
name = "termcolor"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index e6dd5da3..2b77a8c7 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -60,7 +60,6 @@ chrono-english = "0.1.4"
cli-table = "0.4"
base64 = "0.13.0"
humantime = "2.1.0"
-tabwriter = "1.2.1"
crossbeam-channel = "0.5.1"
clap = { version = "3.1.11", features = ["derive"] }
clap_complete = "3.1.2"
diff --git a/atuin-client/Cargo.toml b/atuin-client/Cargo.toml
index 8b816d0c..01918706 100644
--- a/atuin-client/Cargo.toml
+++ b/atuin-client/Cargo.toml
@@ -16,7 +16,8 @@ sync = [
"urlencoding",
"sodiumoxide",
"reqwest",
- "rust-crypto",
+ "sha2",
+ "hex",
"rmp-serde",
"base64",
]
@@ -56,7 +57,8 @@ reqwest = { version = "0.11", features = [
"json",
"rustls-tls",
], default-features = false, optional = true }
-rust-crypto = { version = "^0.2", optional = true }
+hex = { version = "0.4", optional = true }
+sha2 = { version = "0.10", optional = true }
rmp-serde = { version = "1.0.0", optional = true }
base64 = { version = "0.13.0", optional = true }
diff --git a/atuin-client/src/api_client.rs b/atuin-client/src/api_client.rs
index d907265b..528d1611 100644
--- a/atuin-client/src/api_client.rs
+++ b/atuin-client/src/api_client.rs
@@ -10,10 +10,10 @@ use atuin_common::api::{
AddHistoryRequest, CountResponse, LoginRequest, LoginResponse, RegisterResponse,
SyncHistoryResponse,
};
-use atuin_common::utils::hash_str;
use crate::encryption::{decode_key, decrypt};
use crate::history::History;
+use crate::sync::hash_str;
static APP_USER_AGENT: &str = concat!("atuin/", env!("CARGO_PKG_VERSION"),);
diff --git a/atuin-client/src/history.rs b/atuin-client/src/history.rs
index 6610b988..c7bf6111 100644
--- a/atuin-client/src/history.rs
+++ b/atuin-client/src/history.rs
@@ -45,4 +45,8 @@ impl History {
hostname,
}
}
+
+ pub fn success(&self) -> bool {
+ self.exit == 0 || self.duration == -1
+ }
}
diff --git a/atuin-client/src/sync.rs b/atuin-client/src/sync.rs
index 9e749614..23f552e5 100644
--- a/atuin-client/src/sync.rs
+++ b/atuin-client/src/sync.rs
@@ -3,13 +3,20 @@ use std::convert::TryInto;
use chrono::prelude::*;
use eyre::Result;
-use atuin_common::{api::AddHistoryRequest, utils::hash_str};
+use atuin_common::api::AddHistoryRequest;
use crate::api_client;
use crate::database::Database;
use crate::encryption::{encrypt, load_encoded_key, load_key};
use crate::settings::{Settings, HISTORY_PAGE_SIZE};
+pub fn hash_str(string: &str) -> String {
+ use sha2::{Digest, Sha256};
+ let mut hasher = Sha256::new();
+ hasher.update(string.as_bytes());
+ hex::encode(hasher.finalize())
+}
+
// Currently sync is kinda naive, and basically just pages backwards through
// history. This means newly added stuff shows up properly! We also just use
// the total count in each database to indicate whether a sync is needed.
diff --git a/atuin-common/Cargo.toml b/atuin-common/Cargo.toml
index 67e78f39..66408779 100644
--- a/atuin-common/Cargo.toml
+++ b/atuin-common/Cargo.toml
@@ -11,7 +11,6 @@ repository = "https://github.com/ellie/atuin"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-rust-crypto = "^0.2"
chrono = { version = "0.4", features = ["serde"] }
serde = { version = "1.0.126", features = ["derive"] }
uuid = { version = "1.0", features = ["v4"] }
diff --git a/atuin-common/src/utils.rs b/atuin-common/src/utils.rs
index 3e3e645b..59545a26 100644
--- a/atuin-common/src/utils.rs
+++ b/atuin-common/src/utils.rs
@@ -3,15 +3,6 @@ use std::path::PathBuf;
use chrono::NaiveDate;
use uuid::Uuid;
-pub fn hash_str(string: &str) -> String {
- use crypto::digest::Digest;
- use crypto::sha2::Sha256;
- let mut hasher = Sha256::new();
- hasher.input_str(string);
-
- hasher.result_str()
-}
-
pub fn uuid_v4() -> String {
Uuid::new_v4().as_simple().to_string()
}
diff --git a/atuin-server/Cargo.toml b/atuin-server/Cargo.toml
index 8e5dbb45..c3e7f66a 100644
--- a/atuin-server/Cargo.toml
+++ b/atuin-server/Cargo.toml
@@ -22,7 +22,6 @@ serde_json = "1.0.75"
sodiumoxide = "0.2.6"
base64 = "0.13.0"
rand = "0.8.4"
-rust-crypto = "^0.2"
tokio = { version = "1", features = ["full"] }
sqlx = { version = "0.5", features = [ "runtime-tokio-rustls", "chrono", "postgres" ] }
async-trait = "0.1.49"
diff --git a/src/command/client/history.rs b/src/command/client/history.rs
index 4f96c444..6e265e30 100644
--- a/src/command/client/history.rs
+++ b/src/command/client/history.rs
@@ -1,10 +1,9 @@
use std::env;
-use std::io::Write;
+use std::io::{StdoutLock, Write};
use std::time::Duration;
use clap::Subcommand;
use eyre::Result;
-use tabwriter::TabWriter;
use atuin_client::database::{current_context, Database};
use atuin_client::history::History;
@@ -53,44 +52,75 @@ pub enum Cmd {
},
}
-#[allow(clippy::cast_sign_loss)]
-pub fn print_list(h: &[History], human: bool, cmd_only: bool) {
- let mut writer = TabWriter::new(std::io::stdout()).padding(2);
+#[derive(Clone, Copy, Debug)]
+pub enum ListMode {
+ Human,
+ CmdOnly,
+ Regular,
+}
- let lines = h.iter().rev().map(|h| {
+impl ListMode {
+ pub const fn from_flags(human: bool, cmd_only: bool) -> Self {
if human {
- let duration = humantime::format_duration(Duration::from_nanos(std::cmp::max(
- h.duration, 0,
- ) as u64))
- .to_string();
- let duration: Vec<&str> = duration.split(' ').collect();
- let duration = duration[0];
-
- format!(
- "{}\t{}\t{}\n",
- h.timestamp.format("%Y-%m-%d %H:%M:%S"),
- h.command.trim(),
- duration,
- )
+ ListMode::Human
} else if cmd_only {
- format!("{}\n", h.command.trim())
+ ListMode::CmdOnly
} else {
- format!(
- "{}\t{}\t{}\n",
- h.timestamp.timestamp_nanos(),
- h.command.trim(),
- h.duration
- )
+ ListMode::Regular
}
- });
+ }
+}
+
+#[allow(clippy::cast_sign_loss)]
+pub fn print_list(h: &[History], list_mode: ListMode) {
+ let w = std::io::stdout();
+ let mut w = w.lock();
+
+ match list_mode {
+ ListMode::Human => print_human_list(&mut w, h),
+ ListMode::CmdOnly => print_cmd_only(&mut w, h),
+ ListMode::Regular => print_regular(&mut w, h),
+ }
+
+ w.flush().expect("failed to flush history");
+}
+
+#[allow(clippy::cast_sign_loss)]
+pub fn print_human_list(w: &mut StdoutLock, h: &[History]) {
+ for h in h.iter().rev() {
+ let duration =
+ humantime::format_duration(Duration::from_nanos(std::cmp::max(h.duration, 0) as u64))
+ .to_string();
+ let duration: Vec<&str> = duration.split(' ').collect();
+ let duration = duration[0];
+
+ let time = h.timestamp.format("%Y-%m-%d %H:%M:%S");
+ let cmd = h.command.trim();
+
+ writeln!(w, "{time} ยท {duration}\t{cmd}").expect("failed to write history");
+ }
+}
- for i in lines {
- writer
- .write_all(i.as_bytes())
- .expect("failed to write to tab writer");
+#[allow(clippy::cast_sign_loss)]
+pub fn print_regular(w: &mut StdoutLock, h: &[History]) {
+ for h in h.iter().rev() {
+ let duration =
+ humantime::format_duration(Duration::from_nanos(std::cmp::max(h.duration, 0) as u64))
+ .to_string();
+ let duration: Vec<&str> = duration.split(' ').collect();
+ let duration = duration[0];
+
+ let time = h.timestamp.format("%Y-%m-%d %H:%M:%S");
+ let cmd = h.command.trim();
+
+ writeln!(w, "{time}\t{cmd}\t{duration}").expect("failed to write history");
}
+}
- writer.flush().expect("failed to flush tab writer");
+pub fn print_cmd_only(w: &mut StdoutLock, h: &[History]) {
+ for h in h.iter().rev() {
+ writeln!(w, "{}", h.command.trim()).expect("failed to write history");
+ }
}
impl Cmd {
@@ -195,14 +225,14 @@ impl Cmd {
}
};
- print_list(&history, *human, *cmd_only);
+ print_list(&history, ListMode::from_flags(*human, *cmd_only));
Ok(())
}
Self::Last { human, cmd_only } => {
let last = db.last().await?;
- print_list(&[last], *human, *cmd_only);
+ print_list(&[last], ListMode::from_flags(*human, *cmd_only));
Ok(())
}
diff --git a/src/command/client/search.rs b/src/command/client/search.rs
index a913e161..45b1f978 100644
--- a/src/command/client/search.rs
+++ b/src/command/client/search.rs
@@ -23,6 +23,7 @@ use atuin_client::{
};
use super::event::{Event, Events};
+use super::history::ListMode;
const VERSION: &str = env!("CARGO_PKG_VERSION");
@@ -73,21 +74,33 @@ impl Cmd {
db: &mut (impl Database + Send + Sync),
settings: &Settings,
) -> Result<()> {
- run(
- settings,
- self.cwd,
- self.exit,
- self.interactive,
- self.human,
- self.exclude_exit,
- self.exclude_cwd,
- self.before,
- self.after,
- self.cmd_only,
- &self.query,
- db,
- )
- .await
+ if self.interactive {
+ let item = select_history(
+ &self.query,
+ settings.search_mode,
+ settings.filter_mode,
+ settings.style,
+ db,
+ )
+ .await?;
+ eprintln!("{}", item);
+ } else {
+ let list_mode = ListMode::from_flags(self.human, self.cmd_only);
+ run_non_interactive(
+ settings,
+ list_mode,
+ self.cwd,
+ self.exit,
+ self.exclude_exit,
+ self.exclude_cwd,
+ self.before,
+ self.after,
+ &self.query,
+ db,
+ )
+ .await?;
+ };
+ Ok(())
}
}
@@ -196,7 +209,7 @@ impl State {
let duration = Span::styled(
duration,
- Style::default().fg(if m.exit == 0 || m.duration == -1 {
+ Style::default().fg(if m.success() {
Color::Green
} else {
Color::Red
@@ -565,117 +578,98 @@ async fn select_history(
// This is supposed to more-or-less mirror the command line version, so ofc
// it is going to have a lot of args
#[allow(clippy::too_many_arguments)]
-pub async fn run(
+async fn run_non_interactive(
settings: &Settings,
+ list_mode: ListMode,
cwd: Option<String>,
exit: Option<i64>,
- interactive: bool,
- human: bool,
exclude_exit: Option<i64>,
exclude_cwd: Option<String>,
before: Option<String>,
after: Option<String>,
- cmd_only: bool,
query: &[String],
db: &mut (impl Database + Send + Sync),
) -> Result<()> {
- let dir = if let Some(cwd) = cwd {
- if cwd == "." {
- let current = std::env::current_dir()?;
- let current = current.as_os_str();
- let current = current.to_str().unwrap();
+ let dir = if cwd.as_deref() == Some(".") {
+ let current = std::env::current_dir()?;
+ let current = current.as_os_str();
+ let current = current.to_str().unwrap();
- Some(current.to_owned())
- } else {
- Some(cwd)
- }
+ Some(current.to_owned())
} else {
- None
+ cwd
};
- if interactive {
- let item = select_history(
- query,
+ let context = current_context();
+
+ let results = db
+ .search(
+ None,
settings.search_mode,
settings.filter_mode,
- settings.style,
- db,
+ &context,
+ query.join(" ").as_str(),
)
.await?;
- eprintln!("{}", item);
- } else {
- let context = current_context();
-
- let results = db
- .search(
- None,
- settings.search_mode,
- settings.filter_mode,
- &context,
- query.join(" ").as_str(),
- )
- .await?;
- // TODO: This filtering would be better done in the SQL query, I just
- // need a nice way of building queries.
- let results: Vec<History> = results
- .iter()
- .filter(|h| {
- if let Some(exit) = exit {
- if h.exit != exit {
- return false;
- }
+ // TODO: This filtering would be better done in the SQL query, I just
+ // need a nice way of building queries.
+ let results: Vec<History> = results
+ .iter()
+ .filter(|h| {
+ if let Some(exit) = exit {
+ if h.exit != exit {
+ return false;
}
+ }
- if let Some(exit) = exclude_exit {
- if h.exit == exit {
- return false;
- }
+ if let Some(exit) = exclude_exit {
+ if h.exit == exit {
+ return false;
}
+ }
- if let Some(cwd) = &exclude_cwd {
- if h.cwd.as_str() == cwd.as_str() {
- return false;
- }
+ if let Some(cwd) = &exclude_cwd {
+ if h.cwd.as_str() == cwd.as_str() {
+ return false;
}
+ }
- if let Some(cwd) = &dir {
- if h.cwd.as_str() != cwd.as_str() {
- return false;
- }
+ if let Some(cwd) = &dir {
+ if h.cwd.as_str() != cwd.as_str() {
+ return false;
}
+ }
- if let Some(before) = &before {
- let before = chrono_english::parse_date_string(
- before.as_str(),
- Utc::now(),
- chrono_english::Dialect::Uk,
- );
+ if let Some(before) = &before {
+ let before = chrono_english::parse_date_string(
+ before.as_str(),
+ Utc::now(),
+ chrono_english::Dialect::Uk,
+ );
- if before.is_err() || h.timestamp.gt(&before.unwrap()) {
- return false;
- }
+ if before.is_err() || h.timestamp.gt(&before.unwrap()) {
+ return false;
}
+ }
- if let Some(after) = &after {
- let after = chrono_english::parse_date_string(
- after.as_str(),
- Utc::now(),
- chrono_english::Dialect::Uk,
- );
+ if let Some(after) = &after {
+ let after = chrono_english::parse_date_string(
+ after.as_str(),
+ Utc::now(),
+ chrono_english::Dialect::Uk,
+ );
- if after.is_err() || h.timestamp.lt(&after.unwrap()) {
- return false;
- }
+ if after.is_err() || h.timestamp.lt(&after.unwrap()) {
+ return false;
}
+ }
- true
- })
- .map(std::borrow::ToOwned::to_owned)
- .collect();
-
- super::history::print_list(&results, human, cmd_only);
- }
+ true
+ })
+ .map(std::borrow::ToOwned::to_owned)
+ .collect();
+ super::history::print_list(&results, list_mode);
Ok(())
}