commands: more consistent error propagation

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I6a6a69647a0eb8de028e4251465fbb94f0a14cef
This commit is contained in:
raf 2025-08-20 11:14:51 +03:00
commit c9a73b462d
Signed by: NotAShelf
GPG key ID: 29D95B64378DB4BF
4 changed files with 66 additions and 71 deletions

View file

@ -1,7 +1,5 @@
use std::io::{self, BufRead};
use log::{error, info};
use crate::db::{
ClipboardDb,
Entry,
@ -12,18 +10,6 @@ use crate::db::{
pub trait ImportCommand {
/// Import clipboard entries from TSV format.
///
/// # Arguments
///
/// * `input` - A readable stream containing TSV lines, each of the form
/// `<id>\t<contents>`.
/// * `max_items` - The maximum number of clipboard entries to keep after
/// import. If set to `u64::MAX`, no trimming occurs.
///
/// # Returns
///
/// * `Ok(())` if all entries are imported and trimming succeeds.
/// * `Err(StashError)` if any error occurs during import or trimming.
fn import_tsv(
&self,
input: impl io::Read,
@ -39,16 +25,21 @@ impl ImportCommand for SqliteClipboardDb {
) -> Result<(), StashError> {
let reader = io::BufReader::new(input);
let mut imported = 0;
for line in reader.lines().map_while(Result::ok) {
for (lineno, line) in reader.lines().enumerate() {
let line = line.map_err(|e| {
StashError::Store(format!("Failed to read line {lineno}: {e}"))
})?;
let mut parts = line.splitn(2, '\t');
let (Some(id_str), Some(val)) = (parts.next(), parts.next()) else {
error!("Malformed TSV line: {line:?}");
continue;
return Err(StashError::Store(format!(
"Malformed TSV line {lineno}: {line:?}"
)));
};
let Ok(_id) = id_str.parse::<u64>() else {
error!("Failed to parse id from line: {id_str}");
continue;
return Err(StashError::Store(format!(
"Failed to parse id from line {lineno}: {id_str}"
)));
};
let entry = Entry {
@ -56,22 +47,26 @@ impl ImportCommand for SqliteClipboardDb {
mime: detect_mime(val.as_bytes()),
};
match self.conn.execute(
"INSERT INTO clipboard (contents, mime) VALUES (?1, ?2)",
rusqlite::params![entry.contents, entry.mime],
) {
Ok(_) => {
imported += 1;
info!("Imported entry from TSV");
},
Err(e) => error!("Failed to insert entry: {e}"),
}
self
.conn
.execute(
"INSERT INTO clipboard (contents, mime) VALUES (?1, ?2)",
rusqlite::params![entry.contents, entry.mime],
)
.map_err(|e| {
StashError::Store(format!(
"Failed to insert entry at line {lineno}: {e}"
))
})?;
imported += 1;
}
info!("Imported {imported} records from TSV into SQLite database.");
log::info!("Imported {imported} records from TSV into SQLite database.");
// Trim database to max_items after import
self.trim_db(max_items)?;
info!("Trimmed clipboard database to max_items = {max_items}");
log::info!("Trimmed clipboard database to max_items = {max_items}");
Ok(())
}
}