diff options
| author | WriterV2 <primary-v2@protonmail.com> | 2023-06-03 12:56:11 +0200 |
|---|---|---|
| committer | WriterV2 <primary-v2@protonmail.com> | 2023-06-03 12:56:11 +0200 |
| commit | 683ca3627f38461cbbdee321a15821b46e72ae6a (patch) | |
| tree | b24297b68f591d343055fea6226dba7b69905e18 | |
| parent | 8072e6194d7b77d54ff75f245a5101ea72e5e8a1 (diff) | |
Fix error handling context
| -rw-r--r-- | src/main.rs | 28 | ||||
| -rw-r--r-- | src/works/mod.rs | 33 | ||||
| -rw-r--r-- | src/works/stories.rs | 60 |
3 files changed, 65 insertions, 56 deletions
diff --git a/src/main.rs b/src/main.rs index 26c3794..4dc6e5e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ -use anyhow::Result; -use tera::{Context, Tera}; +use anyhow::{Context, Ok, Result}; +use tera::Tera; use crate::works::Works; @@ -7,19 +7,25 @@ mod works; fn main() -> Result<()> { // new tera instance - let tera = Tera::new("templates/**/*.html")?; + let tera = Tera::new("templates/**/*.html").context("Failed to create new Tera instance")?; // render index.html file - let context = Context::new(); - let output = tera.render("index.html", &context)?; - std::fs::write("docs/index.html", output)?; + let context = tera::Context::new(); + let output = tera + .render("index.html", &context) + .context("Failed to render index.html")?; + std::fs::write("docs/index.html", output).context("Failed to write index.html")?; // render stories.html file let stories = std::rc::Rc::new(works::stories::Stories::new_from_file( - &std::fs::File::open(std::path::PathBuf::from("stories.json"))?, + &std::fs::File::open(std::path::PathBuf::from("stories.json")) + .context("Failed to open stories.json")?, )?); - std::rc::Rc::clone(&stories).render_overview_page(&tera, "stories")?; - std::rc::Rc::clone(&stories).render_single_pages(&tera, "story")?; - - anyhow::Ok(()) + std::rc::Rc::clone(&stories) + .render_overview_page(&tera, "stories") + .context("Failed to render overview page for stories")?; + std::rc::Rc::clone(&stories) + .render_single_pages(&tera, "story") + .context("Failed to render single pages for stories")?; + Ok(()) } diff --git a/src/works/mod.rs b/src/works/mod.rs index cb82168..77dd35d 100644 --- a/src/works/mod.rs +++ b/src/works/mod.rs @@ -1,4 +1,4 @@ -use anyhow::{Context, Result}; +use anyhow::{Context, Ok, Result}; use serde::{Deserialize, Serialize}; pub mod stories; @@ -8,17 +8,17 @@ pub trait Works: for<'a> Deserialize<'a> + Serialize { // create works from the corresponding JSON file, // e.g. stories from stories.json fn new_from_file(file: &std::fs::File) -> Result<Self> { - serde_json::from_reader(std::io::BufReader::new(file)) - // add error context - .with_context(|| format!("Failed to create works from {:?}", &file)) + let file = serde_json::from_reader(std::io::BufReader::new(file)) + .with_context(|| format!("Failed to create works from {:#?}", &file))?; + Ok(file) } // crate tera context from the group of work // tera context can be accessed in HTML tera templating - fn create_tera_context(&self) -> Result<tera::Context> { + fn create_tera_context(&self) -> tera::Context { let mut context = tera::Context::new(); context.insert("works", &self); - anyhow::Ok(context).with_context(|| "Failed to create works") + context } // render page for every work @@ -33,17 +33,24 @@ pub trait Works: for<'a> Deserialize<'a> + Serialize { ) -> Result<()> { std::fs::write( format!("docs/{}.html", filename_without_extension).as_str(), - tera_instance.render( - format!("{}.html", filename_without_extension).as_str(), - &self.create_tera_context()?, - )?, + tera_instance + .render( + format!("{}.html", filename_without_extension).as_str(), + &self.create_tera_context(), + ) + .with_context(|| { + format!( + "Failed rendering overview page for {}", + filename_without_extension + ) + })?, ) - // add error context .with_context(|| { format!( - "Failed to render overview page for {:?}", + "Failed to write overview page for {}", filename_without_extension ) - }) + })?; + Ok(()) } } diff --git a/src/works/stories.rs b/src/works/stories.rs index 80ab8de..f86d24a 100644 --- a/src/works/stories.rs +++ b/src/works/stories.rs @@ -1,6 +1,4 @@ -use std::format; - -use anyhow::Context; +use anyhow::{Result, Ok, Context}; use chrono::NaiveDate; use serde::{Deserialize, Serialize}; @@ -29,50 +27,48 @@ impl super::Works for Stories { &self, tera_instance: &tera::Tera, template_name: &str, - ) -> anyhow::Result<()> { + ) -> Result<()> { let mut result = Vec::new(); for story in self.0.iter() { - if story.update_available()? { + if story.update_available().with_context(|| format!("Failed to check for update for {}", story.title))? { let mut context = tera::Context::new(); context.insert("story", story); - context.insert("text", &story.get_text()?); + context.insert("text", &story.get_text().with_context(|| format!("Failed to get text from {}", story.title))?); result.push(std::fs::write( story.get_html_path().as_str(), - tera_instance.render(format!("{}.html", template_name).as_str(), &context)?, + tera_instance.render(format!("{}.html", template_name).as_str(), &context).with_context(|| format!("Failed to render single story page for {}", story.title))?, )); } } - anyhow::Ok(()).with_context(|| "Failed to render single story pages") + Ok(()) } // create stories from stories.json and add last modification date - fn new_from_file(file: &std::fs::File) -> anyhow::Result<Self> { - let mut stories: Stories = serde_json::from_reader(std::io::BufReader::new(file))?; + fn new_from_file(file: &std::fs::File) -> Result<Self> { + let mut stories: Stories = serde_json::from_reader(std::io::BufReader::new(file)).with_context(|| format!("Failed to read JSON from {:#?}", file))?; for story in stories.0.iter_mut() { - story.get_last_modified()?; - story.get_pages_num()?; + story.get_last_modified().with_context(|| format!("Failed to get last modified date for {}", story.title))?; + story.get_pages_num().with_context(|| format!("Failed to get number of pages from {}'s PDF", story.title))?; } - // add error context - anyhow::Ok(stories).with_context(|| format!("Failed to create new story {:?}", file)) + Ok(stories) } } impl Story { // check if it's necessary to re-compile the html single page - fn update_available(&self) -> anyhow::Result<bool> { - anyhow::Ok( + fn update_available(&self) -> Result<bool> { + Ok( // HTML file doesn't exist yet !std::path::Path::new(&self.get_html_path()).exists() // pdf document changes - || std::fs::metadata(self.get_pdf_path())?.modified()? - > std::fs::metadata(self.get_html_path())?.modified()? + || std::fs::metadata(self.get_pdf_path()).with_context(|| format!("Failed to get PDF metadata for {}", self.title))?.modified().with_context(|| format!("Failed to get last modified date for {}'s PDF", self.title))? + > std::fs::metadata(self.get_html_path()).with_context(|| format!("Failed to get HTML metadata for {}", self.title))?.modified().with_context(|| format!("Failed to get last modified date for {}'s HTML", self.title))? // base template changes - || std::fs::metadata("templates/base.html")?.modified()? - > std::fs::metadata(self.get_html_path())?.modified()? + || std::fs::metadata("templates/base.html").context("Failed to get metadata for base HTML template")?.modified().context("Failed to get last modified date for base HTML template")? + > std::fs::metadata(self.get_html_path()).with_context(|| format!("Failed to get HTML metadata for {}", self.title))?.modified().with_context(|| format!("Failed to get last modified date for {}'s HTML", self.title))? // story template changes - ||std::fs::metadata("templates/story.html")?.modified()? > std::fs::metadata(self.get_html_path())?.modified()?, // add error context + ||std::fs::metadata("templates/story.html").context("Failed to get metadata for story HTML template")?.modified().context("Failed to get last modified date for story HTML template")? > std::fs::metadata(self.get_html_path()).with_context(|| format!("Failed to get HTML metadata for {}", self.title))?.modified().with_context(|| format!("Failed to get last modified date for {}'s HTML", self.title))?, // add error context ) - .with_context(|| format!("Failed to check for update for {}", self.title)) } // use story document name for the single page @@ -98,31 +94,31 @@ impl Story { } // extract text from pdf document - fn get_text(&self) -> anyhow::Result<String> { - let text = std::fs::read_to_string(self.get_content_html_path())?; - anyhow::Ok(text).with_context(|| format!("Failed to extract text for {}", self.title)) + fn get_text(&self) -> Result<String> { + let text = std::fs::read_to_string(self.get_content_html_path()).with_context(|| format!("Failed to read {}'s content HTML file", self.title))?; + Ok(text) } // get date of last modification - fn get_last_modified(&mut self) -> anyhow::Result<chrono::NaiveDate> { + fn get_last_modified(&mut self) -> Result<chrono::NaiveDate> { use std::os::linux::fs::MetadataExt; - let pdf_last_modification = std::fs::metadata(self.get_pdf_path())?.st_mtime(); + let pdf_last_modification = std::fs::metadata(self.get_pdf_path()).with_context(|| format!("Failed to get {}'s PDF", self.title))?.st_mtime(); let html_path = std::fs::metadata(self.get_html_path()); - let html_last_modification = if let Ok(file) = html_path { + let html_last_modification = if let core::result::Result::Ok(file) = html_path { file.st_mtime() } else { 0 }; let date = chrono::NaiveDateTime::from_timestamp(std::cmp::max(pdf_last_modification, html_last_modification), 0).date(); self.last_update = date; - anyhow::Ok(date).with_context(|| format!("Failed to get last modified date for {}", self.title)) + Ok(date) } // get number of pages of pdf file - fn get_pages_num(&mut self) -> anyhow::Result<u32> { - let file = pdf::file::File::open(self.get_pdf_path())?; + fn get_pages_num(&mut self) -> Result<u32> { + let file = pdf::file::File::open(self.get_pdf_path()).with_context(|| format!("Failed to get {}'s PDF", self.title))?; self.number_of_pages = file.num_pages(); - anyhow::Ok(file.num_pages()).with_context(|| format!("Failed to number of pages for {}", self.title)) + Ok(file.num_pages()) } } |
