Address review comments

This commit is contained in:
James Falcon 2022-09-22 19:05:49 -05:00
parent 635a97e812
commit 98c6512e95
6 changed files with 42 additions and 25 deletions

11
Cargo.lock generated
View File

@ -254,6 +254,16 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "453440c271cf5577fd2a40e4942540cb7d0d2f85e27c8d07dd0023c925a67541" checksum = "453440c271cf5577fd2a40e4942540cb7d0d2f85e27c8d07dd0023c925a67541"
[[package]]
name = "edit"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c562aa71f7bc691fde4c6bf5f93ae5a5298b617c2eb44c76c87832299a17fbb4"
dependencies = [
"tempfile",
"which",
]
[[package]] [[package]]
name = "either" name = "either"
version = "1.7.0" version = "1.7.0"
@ -881,6 +891,7 @@ dependencies = [
"dialoguer", "dialoguer",
"dirs", "dirs",
"dunce", "dunce",
"edit",
"fastrand", "fastrand",
"glob", "glob",
"nix", "nix",

View File

@ -26,10 +26,10 @@ clap = { version = "3.1.0", features = ["derive"] }
dialoguer = "0.10.2" dialoguer = "0.10.2"
dirs = "4.0.0" dirs = "4.0.0"
dunce = "1.0.1" dunce = "1.0.1"
edit = "0.1.4"
fastrand = "1.7.0" fastrand = "1.7.0"
glob = "0.3.0" glob = "0.3.0"
serde = { version = "1.0.116", features = ["derive"] } serde = { version = "1.0.116", features = ["derive"] }
tempfile = "3.1.0"
[target.'cfg(unix)'.dependencies] [target.'cfg(unix)'.dependencies]
nix = { version = "0.24.1", default-features = false, features = [ nix = { version = "0.24.1", default-features = false, features = [
@ -49,6 +49,8 @@ clap_complete_fig = "3.1.0"
assert_cmd = "2.0.0" assert_cmd = "2.0.0"
rstest = { version = "0.15.0", default-features = false } rstest = { version = "0.15.0", default-features = false }
rstest_reuse = "0.4.0" rstest_reuse = "0.4.0"
tempfile = "3.1.0"
[features] [features]
default = [] default = []

View File

@ -31,7 +31,7 @@ impl Run for Add {
if !Path::new(path).is_dir() { if !Path::new(path).is_dir() {
bail!("not a directory: {path}"); bail!("not a directory: {path}");
} }
db.add(path, now); db.add(path, now, 1.0);
} }
if db.modified { if db.modified {

View File

@ -1,14 +1,13 @@
use crate::cmd::{Edit, Run}; use crate::cmd::{Edit, Run};
use crate::db::{db_path, Database, DatabaseFile, Epoch, Rank}; use crate::db::{Database, DatabaseFile, Epoch, Rank};
use crate::util::{rename, resolve_path}; use crate::util::resolve_path;
use crate::{config, util}; use crate::{config, util};
use anyhow::Result; use anyhow::Result;
use std::fmt::Write as FmtWrite; use std::fmt::Write as FmtWrite;
use std::path::PathBuf; use std::path::PathBuf;
use core::mem; use dialoguer::Input;
use dialoguer::{Editor, Input}; use edit::edit;
use tempfile::tempdir;
const HEADER: &str = "\ const HEADER: &str = "\
# Blank lines and lines prepended with '#' are ignored; Line order is insignificant # Blank lines and lines prepended with '#' are ignored; Line order is insignificant
@ -23,18 +22,16 @@ enum ValidationResult {
impl Run for Edit { impl Run for Edit {
fn run(&self) -> Result<()> { fn run(&self) -> Result<()> {
let temp_dir = tempdir()?;
let temp_dir_path = temp_dir.path();
while let Some(db_edits) = get_db_edits()? { while let Some(db_edits) = get_db_edits()? {
let mut db_file = DatabaseFile::new(temp_dir_path); let data_dir = config::data_dir()?;
let mut db_file = DatabaseFile::new(data_dir);
let mut db = db_file.open()?; let mut db = db_file.open()?;
let result = validate_db(&mut db, db_edits); db.clear();
let problems = get_problems(&mut db, db_edits);
let result = handle_problems(problems);
match result { match result {
ValidationResult::Success => { ValidationResult::Success => {
db.save()?; db.save()?;
mem::drop(db);
mem::drop(db_file);
rename(db_path(temp_dir_path), db_path(config::data_dir()?))?;
return Ok(()); return Ok(());
} }
ValidationResult::Exit => break, ValidationResult::Exit => break,
@ -55,7 +52,13 @@ fn get_db_edits() -> Result<Option<String>> {
while let Some(dir) = stream.next() { while let Some(dir) = stream.next() {
writeln!(&mut to_edit, "{},{},{}", dir.last_accessed, dir.rank, dir.path)?; writeln!(&mut to_edit, "{},{},{}", dir.last_accessed, dir.rank, dir.path)?;
} }
Ok(Editor::new().edit(&to_edit)?) let edit_result = edit(&to_edit)?;
if edit_result == to_edit {
// The file was not changed at all so we don't want to attempt to overwrite the original
Ok(None)
} else {
Ok(Some(edit_result))
}
} }
fn validate_db(db: &mut Database, db_edits: String) -> ValidationResult { fn validate_db(db: &mut Database, db_edits: String) -> ValidationResult {
@ -133,7 +136,7 @@ fn validate_db(db: &mut Database, db_edits: String) -> ValidationResult {
}; };
if let (Some(path), Some(last_accessed), Some(rank)) = (path, last_accessed, rank) { if let (Some(path), Some(last_accessed), Some(rank)) = (path, last_accessed, rank) {
db.add_raw(&path, last_accessed, rank); db.add(&path, last_accessed, rank);
} }
} }
let has_warnings = !warnings.is_empty(); let has_warnings = !warnings.is_empty();

View File

@ -31,11 +31,7 @@ impl<'file> Database<'file> {
} }
/// Adds a new directory or increments its rank. Also updates its last accessed time. /// Adds a new directory or increments its rank. Also updates its last accessed time.
pub fn add<S: AsRef<str>>(&mut self, path: S, now: Epoch) { pub fn add<S: AsRef<str>>(&mut self, path: S, last_accessed: Epoch, rank: Rank) {
self.add_raw(path, now, 1.0)
}
pub fn add_raw<S: AsRef<str>>(&mut self, path: S, last_accessed: Epoch, rank: Rank) {
let path = path.as_ref(); let path = path.as_ref();
match self.dirs.iter_mut().find(|dir| dir.path == path) { match self.dirs.iter_mut().find(|dir| dir.path == path) {
@ -95,6 +91,11 @@ impl<'file> Database<'file> {
false false
} }
/// Removes all entries from the store.
pub fn clear(&mut self) {
self.dirs = DirList::new();
}
pub fn age(&mut self, max_age: Rank) { pub fn age(&mut self, max_age: Rank) {
let sum_age = self.dirs.iter().map(|dir| dir.rank).sum::<Rank>(); let sum_age = self.dirs.iter().map(|dir| dir.rank).sum::<Rank>();
if sum_age > max_age { if sum_age > max_age {
@ -162,8 +163,8 @@ mod tests {
{ {
let mut db = DatabaseFile::new(data_dir.path()); let mut db = DatabaseFile::new(data_dir.path());
let mut db = db.open().unwrap(); let mut db = db.open().unwrap();
db.add(path, now); db.add(path, now, 1.0);
db.add(path, now); db.add(path, now, 1.0);
db.save().unwrap(); db.save().unwrap();
} }
{ {
@ -186,7 +187,7 @@ mod tests {
{ {
let mut db = DatabaseFile::new(data_dir.path()); let mut db = DatabaseFile::new(data_dir.path());
let mut db = db.open().unwrap(); let mut db = db.open().unwrap();
db.add(path, now); db.add(path, now, 1.0);
db.save().unwrap(); db.save().unwrap();
} }
{ {

View File

@ -160,7 +160,7 @@ fn tmpfile<P: AsRef<Path>>(dir: P) -> Result<(File, PathBuf)> {
} }
/// Similar to [`fs::rename`], but retries on Windows. /// Similar to [`fs::rename`], but retries on Windows.
pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> Result<()> { fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> Result<()> {
const MAX_ATTEMPTS: usize = 5; const MAX_ATTEMPTS: usize = 5;
let from = from.as_ref(); let from = from.as_ref();
let to = to.as_ref(); let to = to.as_ref();