Make pedantic clippy happy

This commit is contained in:
Ellie Huxtable 2021-02-14 15:15:26 +00:00
parent d128297e67
commit 660edfefed
9 changed files with 144 additions and 151 deletions

View file

@ -3,11 +3,11 @@ use std::env;
use eyre::Result; use eyre::Result;
use structopt::StructOpt; use structopt::StructOpt;
use crate::local::database::{Database, SqliteDatabase}; use crate::local::database::{Database, Sqlite};
use crate::local::history::History; use crate::local::history::History;
#[derive(StructOpt)] #[derive(StructOpt)]
pub enum HistoryCmd { pub enum Cmd {
#[structopt( #[structopt(
about="begins a new command in the history", about="begins a new command in the history",
aliases=&["s", "st", "sta", "star"], aliases=&["s", "st", "sta", "star"],
@ -34,10 +34,10 @@ pub enum HistoryCmd {
}, },
} }
impl HistoryCmd { impl Cmd {
pub fn run(&self, db: &mut SqliteDatabase) -> Result<()> { pub fn run(&self, db: &mut Sqlite) -> Result<()> {
match self { match self {
HistoryCmd::Start { command: words } => { Self::Start { command: words } => {
let command = words.join(" "); let command = words.join(" ");
let cwd = env::current_dir()?.display().to_string(); let cwd = env::current_dir()?.display().to_string();
@ -58,7 +58,7 @@ impl HistoryCmd {
Ok(()) Ok(())
} }
HistoryCmd::End { id, exit } => { Self::End { id, exit } => {
let mut h = db.load(id)?; let mut h = db.load(id)?;
h.exit = *exit; h.exit = *exit;
h.duration = chrono::Utc::now().timestamp_nanos() - h.timestamp; h.duration = chrono::Utc::now().timestamp_nanos() - h.timestamp;
@ -68,7 +68,7 @@ impl HistoryCmd {
Ok(()) Ok(())
} }
HistoryCmd::List { distinct } => db.list(*distinct), Self::List { distinct } => db.list(*distinct),
} }
} }
} }

View file

@ -5,13 +5,13 @@ use eyre::{eyre, Result};
use home::home_dir; use home::home_dir;
use structopt::StructOpt; use structopt::StructOpt;
use crate::local::database::{Database, SqliteDatabase}; use crate::local::database::{Database, Sqlite};
use crate::local::history::History; use crate::local::history::History;
use crate::local::import::ImportZsh; use crate::local::import::Zsh;
use indicatif::ProgressBar; use indicatif::ProgressBar;
#[derive(StructOpt)] #[derive(StructOpt)]
pub enum ImportCmd { pub enum Cmd {
#[structopt( #[structopt(
about="import history for the current shell", about="import history for the current shell",
aliases=&["a", "au", "aut"], aliases=&["a", "au", "aut"],
@ -25,22 +25,48 @@ pub enum ImportCmd {
Zsh, Zsh,
} }
impl ImportCmd { impl Cmd {
fn import_zsh(&self, db: &mut SqliteDatabase) -> Result<()> { pub fn run(&self, db: &mut Sqlite) -> Result<()> {
println!(" A'Tuin ");
println!("=====================");
println!(" \u{1f30d} ");
println!(" \u{1f418}\u{1f418}\u{1f418}\u{1f418} ");
println!(" \u{1f422} ");
println!("=====================");
println!("Importing history...");
match self {
Self::Auto => {
let shell = env::var("SHELL").unwrap_or_else(|_| String::from("NO_SHELL"));
if shell.as_str() == "/bin/zsh" {
println!("Detected ZSH");
import_zsh(db)
} else {
println!("cannot import {} history", shell);
Ok(())
}
}
Self::Zsh => import_zsh(db),
}
}
}
fn import_zsh(db: &mut Sqlite) -> Result<()> {
// oh-my-zsh sets HISTFILE=~/.zhistory // oh-my-zsh sets HISTFILE=~/.zhistory
// zsh has no default value for this var, but uses ~/.zhistory. // zsh has no default value for this var, but uses ~/.zhistory.
// we could maybe be smarter about this in the future :) // we could maybe be smarter about this in the future :)
let histpath = env::var("HISTFILE"); let histpath = env::var("HISTFILE");
let histpath = match histpath { let histpath = if let Ok(p) = histpath {
Ok(p) => PathBuf::from(p), PathBuf::from(p)
Err(_) => { } else {
let mut home = home_dir().unwrap(); let mut home = home_dir().unwrap();
home.push(".zhistory"); home.push(".zhistory");
home home
}
}; };
if !histpath.exists() { if !histpath.exists() {
@ -50,7 +76,7 @@ impl ImportCmd {
)); ));
} }
let zsh = ImportZsh::new(histpath.to_str().unwrap())?; let zsh = Zsh::new(histpath.to_str().unwrap())?;
let progress = ProgressBar::new(zsh.loc); let progress = ProgressBar::new(zsh.loc);
@ -76,7 +102,7 @@ impl ImportCmd {
} }
} }
if buf.len() > 0 { if !buf.is_empty() {
db.save_bulk(&buf)?; db.save_bulk(&buf)?;
progress.inc(buf.len() as u64); progress.inc(buf.len() as u64);
} }
@ -84,35 +110,4 @@ impl ImportCmd {
progress.finish_with_message("Imported history!"); progress.finish_with_message("Imported history!");
Ok(()) Ok(())
}
pub fn run(&self, db: &mut SqliteDatabase) -> Result<()> {
println!(" A'Tuin ");
println!("=====================");
println!(" 🌍 ");
println!(" 🐘🐘🐘🐘 ");
println!(" 🐢 ");
println!("=====================");
println!("Importing history...");
match self {
ImportCmd::Auto => {
let shell = env::var("SHELL").unwrap_or(String::from("NO_SHELL"));
match shell.as_str() {
"/bin/zsh" => {
println!("Detected ZSH");
self.import_zsh(db)
}
_ => {
println!("cannot import {} history", shell);
Ok(())
}
}
}
ImportCmd::Zsh => self.import_zsh(db),
}
}
} }

View file

@ -1,14 +1,15 @@
use eyre::Result; use eyre::Result;
use structopt::StructOpt; use structopt::StructOpt;
use crate::server::server; use crate::remote::server;
#[derive(StructOpt)] #[derive(StructOpt)]
pub enum ServerCmd { pub enum Cmd {
Start { command: Vec<String> }, Start { host: Vec<String> },
} }
impl ServerCmd { #[allow(clippy::unused_self)] // I'll use it later
impl Cmd {
pub fn run(&self) -> Result<()> { pub fn run(&self) -> Result<()> {
server::launch(); server::launch();
Ok(()) Ok(())

View file

@ -9,7 +9,7 @@ use crate::History;
pub trait Database { pub trait Database {
fn save(&mut self, h: History) -> Result<()>; fn save(&mut self, h: History) -> Result<()>;
fn save_bulk(&mut self, h: &Vec<History>) -> Result<()>; fn save_bulk(&mut self, h: &[History]) -> Result<()>;
fn load(&self, id: &str) -> Result<History>; fn load(&self, id: &str) -> Result<History>;
fn list(&self, distinct: bool) -> Result<()>; fn list(&self, distinct: bool) -> Result<()>;
fn update(&self, h: History) -> Result<()>; fn update(&self, h: History) -> Result<()>;
@ -17,12 +17,12 @@ pub trait Database {
// Intended for use on a developer machine and not a sync server. // Intended for use on a developer machine and not a sync server.
// TODO: implement IntoIterator // TODO: implement IntoIterator
pub struct SqliteDatabase { pub struct Sqlite {
conn: Connection, conn: Connection,
} }
impl SqliteDatabase { impl Sqlite {
pub fn new(path: impl AsRef<Path>) -> Result<SqliteDatabase> { pub fn new(path: impl AsRef<Path>) -> Result<Self> {
let path = path.as_ref(); let path = path.as_ref();
debug!("opening sqlite database at {:?}", path); debug!("opening sqlite database at {:?}", path);
@ -39,7 +39,7 @@ impl SqliteDatabase {
Self::setup_db(&conn)?; Self::setup_db(&conn)?;
} }
Ok(SqliteDatabase { conn }) Ok(Self { conn })
} }
fn setup_db(conn: &Connection) -> Result<()> { fn setup_db(conn: &Connection) -> Result<()> {
@ -65,7 +65,7 @@ impl SqliteDatabase {
} }
} }
impl Database for SqliteDatabase { impl Database for Sqlite {
fn save(&mut self, h: History) -> Result<()> { fn save(&mut self, h: History) -> Result<()> {
debug!("saving history to sqlite"); debug!("saving history to sqlite");
let v = vec![h]; let v = vec![h];
@ -73,7 +73,7 @@ impl Database for SqliteDatabase {
self.save_bulk(&v) self.save_bulk(&v)
} }
fn save_bulk(&mut self, h: &Vec<History>) -> Result<()> { fn save_bulk(&mut self, h: &[History]) -> Result<()> {
debug!("saving history to sqlite"); debug!("saving history to sqlite");
let tx = self.conn.transaction()?; let tx = self.conn.transaction()?;
@ -116,7 +116,7 @@ impl Database for SqliteDatabase {
where id = ?1", where id = ?1",
)?; )?;
let iter = stmt.query_map(params![id], |row| { let mut iter = stmt.query_map(params![id], |row| {
Ok(History { Ok(History {
id: String::from(id), id: String::from(id),
timestamp: row.get(1)?, timestamp: row.get(1)?,
@ -129,11 +129,12 @@ impl Database for SqliteDatabase {
}) })
})?; })?;
for i in iter { let history = iter.next().unwrap();
return Ok(i.unwrap());
}
return Err(eyre!("Failed to fetch history: {}", id)); match history {
Ok(i) => Ok(i),
Err(e) => Err(eyre!("could not find item: {}", e)),
}
} }
fn update(&self, h: History) -> Result<()> { fn update(&self, h: History) -> Result<()> {
@ -152,14 +153,12 @@ impl Database for SqliteDatabase {
fn list(&self, distinct: bool) -> Result<()> { fn list(&self, distinct: bool) -> Result<()> {
debug!("listing history"); debug!("listing history");
let mut stmt = match distinct { let mut stmt = if distinct {
false => self self.conn
.conn .prepare("SELECT command FROM history order by timestamp asc")?
.prepare("SELECT command FROM history order by timestamp asc")?, } else {
self.conn
true => self .prepare("SELECT distinct command FROM history order by timestamp asc")?
.conn
.prepare("SELECT distinct command FROM history order by timestamp asc")?,
}; };
let history_iter = stmt.query_map(params![], |row| { let history_iter = stmt.query_map(params![], |row| {

View file

@ -23,10 +23,10 @@ impl History {
duration: i64, duration: i64,
session: Option<String>, session: Option<String>,
hostname: Option<String>, hostname: Option<String>,
) -> History { ) -> Self {
// get the current session or just generate a random string // get the current session or just generate a random string
let env_session = let env_session =
env::var("ATUIN_SESSION").unwrap_or(Uuid::new_v4().to_simple().to_string()); env::var("ATUIN_SESSION").unwrap_or_else(|_| Uuid::new_v4().to_simple().to_string());
// best attempt at getting the current hostname, or just unknown // best attempt at getting the current hostname, or just unknown
let os_hostname = hostname::get().unwrap(); let os_hostname = hostname::get().unwrap();
@ -36,7 +36,7 @@ impl History {
let session = session.unwrap_or(env_session); let session = session.unwrap_or(env_session);
let hostname = hostname.unwrap_or(os_hostname); let hostname = hostname.unwrap_or(os_hostname);
History { Self {
id: Uuid::new_v4().to_simple().to_string(), id: Uuid::new_v4().to_simple().to_string(),
timestamp, timestamp,
command, command,

View file

@ -9,7 +9,7 @@ use eyre::{eyre, Result};
use crate::local::history::History; use crate::local::history::History;
#[derive(Debug)] #[derive(Debug)]
pub struct ImportZsh { pub struct Zsh {
file: BufReader<File>, file: BufReader<File>,
pub loc: u64, pub loc: u64,
@ -23,14 +23,14 @@ fn count_lines(path: &str) -> Result<usize> {
Ok(buf.lines().count()) Ok(buf.lines().count())
} }
impl ImportZsh { impl Zsh {
pub fn new(path: &str) -> Result<ImportZsh> { pub fn new(path: &str) -> Result<Self> {
let loc = count_lines(path)?; let loc = count_lines(path)?;
let file = File::open(path)?; let file = File::open(path)?;
let buf = BufReader::new(file); let buf = BufReader::new(file);
Ok(ImportZsh { Ok(Self {
file: buf, file: buf,
loc: loc as u64, loc: loc as u64,
}) })
@ -50,17 +50,17 @@ fn trim_newline(s: &str) -> String {
s s
} }
fn parse_extended(line: String) -> History { fn parse_extended(line: &str) -> History {
let line = line.replacen(": ", "", 2); let line = line.replacen(": ", "", 2);
let mut split = line.splitn(2, ":"); let mut split = line.splitn(2, ':');
let time = split.next().unwrap_or("-1"); let time = split.next().unwrap_or("-1");
let time = time let time = time
.parse::<i64>() .parse::<i64>()
.unwrap_or(chrono::Utc::now().timestamp_nanos()); .unwrap_or_else(|_| chrono::Utc::now().timestamp_nanos());
let duration = split.next().unwrap(); // might be 0;the command let duration_command = split.next().unwrap(); // might be 0;the command
let mut split = duration.split(";"); let mut split = duration_command.split(';');
let duration = split.next().unwrap_or("-1"); // should just be the 0 let duration = split.next().unwrap_or("-1"); // should just be the 0
let duration = duration.parse::<i64>().unwrap_or(-1); let duration = duration.parse::<i64>().unwrap_or(-1);
@ -79,7 +79,7 @@ fn parse_extended(line: String) -> History {
) )
} }
impl Iterator for ImportZsh { impl Iterator for Zsh {
type Item = Result<History>; type Item = Result<History>;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
@ -94,10 +94,10 @@ impl Iterator for ImportZsh {
Err(e) => Some(Err(eyre!("failed to parse line: {}", e))), Err(e) => Some(Err(eyre!("failed to parse line: {}", e))),
Ok(_) => { Ok(_) => {
let extended = line.starts_with(":"); let extended = line.starts_with(':');
if extended { if extended {
Some(Ok(parse_extended(line))) Some(Ok(parse_extended(line.as_str())))
} else { } else {
Some(Ok(History::new( Some(Ok(History::new(
chrono::Utc::now().timestamp_nanos(), // what else? :/ chrono::Utc::now().timestamp_nanos(), // what else? :/

View file

@ -1,6 +1,6 @@
#![feature(proc_macro_hygiene)] #![feature(proc_macro_hygiene)]
#![feature(decl_macro)] #![feature(decl_macro)]
#![warn(clippy::pedantic)] #![warn(clippy::pedantic, clippy::nursery)]
use std::path::PathBuf; use std::path::PathBuf;
@ -15,13 +15,13 @@ extern crate log;
#[macro_use] #[macro_use]
extern crate rocket; extern crate rocket;
use command::{history::HistoryCmd, import::ImportCmd, server::ServerCmd}; use command::{history, import, server};
use local::database::SqliteDatabase; use local::database::Sqlite;
use local::history::History; use local::history::History;
mod command; mod command;
mod local; mod local;
mod server; mod remote;
#[derive(StructOpt)] #[derive(StructOpt)]
#[structopt( #[structopt(
@ -43,13 +43,13 @@ enum AtuinCmd {
about="manipulate shell history", about="manipulate shell history",
aliases=&["h", "hi", "his", "hist", "histo", "histor"], aliases=&["h", "hi", "his", "hist", "histo", "histor"],
)] )]
History(HistoryCmd), History(history::Cmd),
#[structopt(about = "import shell history from file")] #[structopt(about = "import shell history from file")]
Import(ImportCmd), Import(import::Cmd),
#[structopt(about = "start an atuin server")] #[structopt(about = "start an atuin server")]
Server(ServerCmd), Server(server::Cmd),
#[structopt(about = "generates a UUID")] #[structopt(about = "generates a UUID")]
Uuid, Uuid,
@ -57,24 +57,22 @@ enum AtuinCmd {
impl Atuin { impl Atuin {
fn run(self) -> Result<()> { fn run(self) -> Result<()> {
let db_path = match self.db { let db_path = if let Some(db_path) = self.db {
Some(db_path) => {
let path = db_path let path = db_path
.to_str() .to_str()
.ok_or(eyre!("path {:?} was not valid UTF-8", db_path))?; .ok_or_else(|| eyre!("path {:?} was not valid UTF-8", db_path))?;
let path = shellexpand::full(path)?; let path = shellexpand::full(path)?;
PathBuf::from(path.as_ref()) PathBuf::from(path.as_ref())
} } else {
None => { let project_dirs =
let project_dirs = ProjectDirs::from("com", "elliehuxtable", "atuin").ok_or( ProjectDirs::from("com", "elliehuxtable", "atuin").ok_or_else(|| {
eyre!("could not determine db file location\nspecify one using the --db flag"), eyre!("could not determine db file location\nspecify one using the --db flag")
)?; })?;
let root = project_dirs.data_dir(); let root = project_dirs.data_dir();
root.join("history.db") root.join("history.db")
}
}; };
let mut db = SqliteDatabase::new(db_path)?; let mut db = Sqlite::new(db_path)?;
match self.atuin { match self.atuin {
AtuinCmd::History(history) => history.run(&mut db), AtuinCmd::History(history) => history.run(&mut db),

View file

@ -1,5 +1,5 @@
#[get("/")] #[get("/")]
fn index() -> &'static str { const fn index() -> &'static str {
"Hello, world!" "Hello, world!"
} }