mirror of
https://github.com/NotAShelf/stash.git
synced 2026-04-13 14:33:47 +00:00
commands: more consistent error propagation
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I6a6a69647a0eb8de028e4251465fbb94f0a14cef
This commit is contained in:
parent
ae98cc0b86
commit
c9a73b462d
4 changed files with 66 additions and 71 deletions
|
|
@ -24,26 +24,33 @@ impl DecodeCommand for SqliteClipboardDb {
|
|||
s
|
||||
} else {
|
||||
let mut buf = String::new();
|
||||
if let Err(e) = in_.read_to_string(&mut buf) {
|
||||
log::error!("Failed to read stdin for decode: {e}");
|
||||
}
|
||||
in_
|
||||
.read_to_string(&mut buf)
|
||||
.map_err(|e| StashError::DecodeRead(e.to_string()))?;
|
||||
buf
|
||||
};
|
||||
|
||||
// If input is empty or whitespace, treat as error and trigger fallback
|
||||
if input_str.trim().is_empty() {
|
||||
log::info!("No input provided to decode; relaying clipboard to stdout");
|
||||
log::debug!("No input provided to decode; relaying clipboard to stdout");
|
||||
if let Ok((mut reader, _mime)) =
|
||||
get_contents(ClipboardType::Regular, Seat::Unspecified, MimeType::Any)
|
||||
{
|
||||
let mut buf = Vec::new();
|
||||
if let Err(err) = reader.read_to_end(&mut buf) {
|
||||
log::error!("Failed to read clipboard for relay: {err}");
|
||||
reader.read_to_end(&mut buf).map_err(|e| {
|
||||
StashError::DecodeRead(format!(
|
||||
"Failed to read clipboard for relay: {e}"
|
||||
))
|
||||
})?;
|
||||
out.write_all(&buf).map_err(|e| {
|
||||
StashError::DecodeWrite(format!(
|
||||
"Failed to write clipboard relay: {e}"
|
||||
))
|
||||
})?;
|
||||
} else {
|
||||
let _ = out.write_all(&buf);
|
||||
}
|
||||
} else {
|
||||
log::error!("Failed to get clipboard contents for relay");
|
||||
return Err(StashError::DecodeGet(
|
||||
"Failed to get clipboard contents for relay".to_string(),
|
||||
));
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
|
@ -54,25 +61,28 @@ impl DecodeCommand for SqliteClipboardDb {
|
|||
&mut out,
|
||||
Some(input_str.clone()),
|
||||
) {
|
||||
Ok(()) => {
|
||||
log::info!("Entry decoded");
|
||||
},
|
||||
Ok(()) => Ok(()),
|
||||
Err(e) => {
|
||||
log::error!("Failed to decode entry: {e}");
|
||||
// On decode failure, relay clipboard as fallback
|
||||
if let Ok((mut reader, _mime)) =
|
||||
get_contents(ClipboardType::Regular, Seat::Unspecified, MimeType::Any)
|
||||
{
|
||||
let mut buf = Vec::new();
|
||||
if let Err(err) = reader.read_to_end(&mut buf) {
|
||||
log::error!("Failed to read clipboard for relay: {err}");
|
||||
reader.read_to_end(&mut buf).map_err(|err| {
|
||||
StashError::DecodeRead(format!(
|
||||
"Failed to read clipboard for relay: {err}"
|
||||
))
|
||||
})?;
|
||||
out.write_all(&buf).map_err(|err| {
|
||||
StashError::DecodeWrite(format!(
|
||||
"Failed to write clipboard relay: {err}"
|
||||
))
|
||||
})?;
|
||||
Ok(())
|
||||
} else {
|
||||
let _ = out.write_all(&buf);
|
||||
}
|
||||
} else {
|
||||
log::error!("Failed to get clipboard contents for relay");
|
||||
Err(e)
|
||||
}
|
||||
},
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,15 +8,8 @@ pub trait DeleteCommand {
|
|||
|
||||
impl DeleteCommand for SqliteClipboardDb {
|
||||
fn delete(&self, input: impl Read) -> Result<usize, StashError> {
|
||||
match self.delete_entries(input) {
|
||||
Ok(deleted) => {
|
||||
let deleted = self.delete_entries(input)?;
|
||||
log::info!("Deleted {deleted} entries");
|
||||
Ok(deleted)
|
||||
},
|
||||
Err(e) => {
|
||||
log::error!("Failed to delete entries: {e}");
|
||||
Err(e)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
self
|
||||
.conn
|
||||
.execute(
|
||||
"INSERT INTO clipboard (contents, mime) VALUES (?1, ?2)",
|
||||
rusqlite::params![entry.contents, entry.mime],
|
||||
) {
|
||||
Ok(_) => {
|
||||
)
|
||||
.map_err(|e| {
|
||||
StashError::Store(format!(
|
||||
"Failed to insert entry at line {lineno}: {e}"
|
||||
))
|
||||
})?;
|
||||
imported += 1;
|
||||
info!("Imported entry from TSV");
|
||||
},
|
||||
Err(e) => error!("Failed to insert entry: {e}"),
|
||||
}
|
||||
}
|
||||
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(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,14 +16,11 @@ impl ListCommand for SqliteClipboardDb {
|
|||
out: impl Write,
|
||||
preview_width: u32,
|
||||
) -> Result<(), StashError> {
|
||||
self.list_entries(out, preview_width)?;
|
||||
log::info!("Listed clipboard entries");
|
||||
Ok(())
|
||||
self.list_entries(out, preview_width).map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
impl SqliteClipboardDb {
|
||||
/// Public TUI listing function for use in main.rs
|
||||
#[allow(clippy::too_many_lines)]
|
||||
pub fn list_tui(&self, preview_width: u32) -> Result<(), StashError> {
|
||||
use std::io::stdout;
|
||||
|
|
@ -272,14 +269,14 @@ impl SqliteClipboardDb {
|
|||
Ok(())
|
||||
})();
|
||||
|
||||
disable_raw_mode().ok();
|
||||
execute!(
|
||||
// Ignore errors during terminal restore, as we can't recover here.
|
||||
let _ = disable_raw_mode();
|
||||
let _ = execute!(
|
||||
terminal.backend_mut(),
|
||||
LeaveAlternateScreen,
|
||||
DisableMouseCapture
|
||||
)
|
||||
.ok();
|
||||
terminal.show_cursor().ok();
|
||||
);
|
||||
let _ = terminal.show_cursor();
|
||||
|
||||
res
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue