summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Batischev <eual.jp@gmail.com>2021-04-25 18:29:19 +0300
committerAlexander Batischev <eual.jp@gmail.com>2021-04-26 15:00:05 +0300
commit36c89315fad651b3b8ce1f8e25310db3ea668fae (patch)
tree64f15f87468b7eecf41b59b0fbf2f74369ce640b
parent80aaff3f70f790141fbc8caa8a2f4830cd5e3fee (diff)
downloadobnam2-36c89315fad651b3b8ce1f8e25310db3ea668fae.tar.gz
Expose fallibility of individual SQL results
`LocalGeneration::sql::files()` runs an SQL query, iterates over the results and collects the rows into a `Vec`. This can fail at any step: the query might fail to run, or one of the rows might fail to be fetched or processed. Right now, we lump all those failures into a `Result` that wraps the whole return value. This is only possible because we process each row before returning. Once `Vec` is replaced by an iterator, we won't have that luxury anymore, so we now wrap each individual element into its own `Result` (as well as wrapping the whole vector into a `Result` of its own).
-rw-r--r--src/cmd/list_files.rs1
-rw-r--r--src/cmd/restore.rs2
-rw-r--r--src/cmd/show_gen.rs17
-rw-r--r--src/generation.rs20
4 files changed, 27 insertions, 13 deletions
diff --git a/src/cmd/list_files.rs b/src/cmd/list_files.rs
index 22b102e..7f0cfed 100644
--- a/src/cmd/list_files.rs
+++ b/src/cmd/list_files.rs
@@ -23,6 +23,7 @@ impl ListFiles {
let gen = client.fetch_generation(&gen_id, temp.path())?;
for file in gen.files()? {
+ let file = file?;
println!("{}", format_entry(&file.entry(), file.reason()));
}
diff --git a/src/cmd/restore.rs b/src/cmd/restore.rs
index a321e80..f8bbaf4 100644
--- a/src/cmd/restore.rs
+++ b/src/cmd/restore.rs
@@ -41,6 +41,7 @@ impl Restore {
info!("restoring {} files", gen.file_count()?);
let progress = create_progress_bar(gen.file_count()?, true);
for file in gen.files()? {
+ let file = file?;
match file.reason() {
Reason::FileError => (),
_ => restore_generation(
@@ -54,6 +55,7 @@ impl Restore {
}
}
for file in gen.files()? {
+ let file = file?;
if file.entry().is_dir() {
restore_directory_metadata(file.entry(), &self.to)?;
}
diff --git a/src/cmd/show_gen.rs b/src/cmd/show_gen.rs
index ba39809..7dc52cf 100644
--- a/src/cmd/show_gen.rs
+++ b/src/cmd/show_gen.rs
@@ -23,14 +23,17 @@ impl ShowGeneration {
let gen = client.fetch_generation(&gen_id, temp.path())?;
let files = gen.files()?;
- let total_bytes = files.iter().fold(0, |acc, file| {
- let e = file.entry();
- if e.kind() == FilesystemKind::Regular {
- acc + file.entry().len()
- } else {
- acc
- }
+ let total_bytes = files.into_iter().try_fold(0, |acc, file| {
+ file.map(|file| {
+ let e = file.entry();
+ if e.kind() == FilesystemKind::Regular {
+ acc + e.len()
+ } else {
+ acc
+ }
+ })
});
+ let total_bytes = total_bytes?;
println!("generation-id: {}", gen_id);
println!("file-count: {}", gen.file_count()?);
diff --git a/src/generation.rs b/src/generation.rs
index 1d0ee52..a780203 100644
--- a/src/generation.rs
+++ b/src/generation.rs
@@ -196,7 +196,7 @@ impl LocalGeneration {
sql::file_count(&self.conn)
}
- pub fn files(&self) -> LocalGenerationResult<Vec<BackedUpFile>> {
+ pub fn files(&self) -> LocalGenerationResult<Vec<LocalGenerationResult<BackedUpFile>>> {
sql::files(&self.conn)
}
@@ -289,14 +289,22 @@ mod sql {
Ok(count)
}
- pub fn files(conn: &Connection) -> LocalGenerationResult<Vec<BackedUpFile>> {
+ pub fn files(
+ conn: &Connection,
+ ) -> LocalGenerationResult<Vec<LocalGenerationResult<BackedUpFile>>> {
let mut stmt = conn.prepare("SELECT * FROM files")?;
let iter = stmt.query_map(params![], |row| row_to_entry(row))?;
- let mut files = vec![];
+ let mut files: Vec<LocalGenerationResult<BackedUpFile>> = vec![];
for x in iter {
- let (fileno, json, reason) = x?;
- let entry = serde_json::from_str(&json)?;
- files.push(BackedUpFile::new(fileno, entry, &reason));
+ match x {
+ Ok((fileno, json, reason)) => {
+ let result = serde_json::from_str(&json)
+ .map(|entry| BackedUpFile::new(fileno, entry, &reason))
+ .map_err(|e| e.into());
+ files.push(result)
+ }
+ Err(e) => files.push(Err(e.into())),
+ }
}
Ok(files)
}