76 lines
2.3 KiB
Rust
76 lines
2.3 KiB
Rust
pub(crate) use crate::import::atuin::Atuin;
|
|
pub(crate) use crate::import::autojump::Autojump;
|
|
pub(crate) use crate::import::fasd::Fasd;
|
|
pub(crate) use crate::import::z::Z;
|
|
pub(crate) use crate::import::z_lua::ZLua;
|
|
pub(crate) use crate::import::zsh_z::ZshZ;
|
|
|
|
mod atuin;
|
|
mod autojump;
|
|
mod fasd;
|
|
mod z;
|
|
mod z_lua;
|
|
mod zsh_z;
|
|
|
|
use std::io::{self, Write};
|
|
use std::path::PathBuf;
|
|
|
|
use anyhow::Result;
|
|
|
|
use crate::config;
|
|
use crate::db::{Database, Dir};
|
|
|
|
pub(crate) trait Importer {
|
|
/// Yields directory entries to be imported.
|
|
///
|
|
/// The outer `Result` reports failure to fetch the input (e.g. missing
|
|
/// file, subprocess errored). The per-item `Result` reports a malformed
|
|
/// row, which doesn't necessarily abort the whole import.
|
|
fn dirs(&self) -> Result<impl Iterator<Item = Result<Dir<'static>, ImportError>>>;
|
|
}
|
|
|
|
/// A single record that failed to import.
|
|
#[derive(Debug)]
|
|
pub(crate) struct ImportError {
|
|
/// Path of the source file containing the offending record. `None` if the
|
|
/// importer is not file-based (e.g. atuin streams from a subprocess).
|
|
pub path: Option<PathBuf>,
|
|
|
|
/// 1-indexed line number of the offending input.
|
|
pub line_num: usize,
|
|
|
|
/// Underlying reason the record could not be imported.
|
|
pub source: anyhow::Error,
|
|
}
|
|
|
|
/// Drives a single importer end-to-end: writes each `Ok` dir into the
|
|
/// database and prints each `Err` to stderr in `<path>:<line>: <reason>`
|
|
/// format. Doesn't abort on per-record errors — bad rows are skipped, the
|
|
/// rest of the import continues. After the iteration completes successfully,
|
|
/// the database is deduplicated and aged.
|
|
pub(crate) fn run(importer: &impl Importer, db: &mut Database) -> Result<()> {
|
|
let stderr = io::stderr();
|
|
let mut stderr = stderr.lock();
|
|
|
|
for entry in importer.dirs()? {
|
|
match entry {
|
|
Ok(dir) => db.add_unchecked(dir.path, dir.rank, dir.last_accessed),
|
|
Err(e) => {
|
|
let location = match &e.path {
|
|
Some(path) => format!("{}:{}", path.display(), e.line_num),
|
|
None => format!("line {}", e.line_num),
|
|
};
|
|
_ = writeln!(stderr, "{location}: {:#}", e.source);
|
|
}
|
|
}
|
|
}
|
|
|
|
if db.dirty() {
|
|
db.dedup();
|
|
let max_age = config::maxage()?;
|
|
db.age(max_age);
|
|
}
|
|
|
|
Ok(())
|
|
}
|