Remove error-chain

Closes #576
This commit is contained in:
Vincent Prouillet 2019-01-11 20:29:46 +01:00
parent 69fb399726
commit 5caf24f06c
23 changed files with 176 additions and 88 deletions

3
Cargo.lock generated
View file

@ -342,6 +342,7 @@ dependencies = [
"serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)",
"syntect 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "syntect 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
"utils 0.1.0",
] ]
[[package]] [[package]]
@ -616,7 +617,6 @@ dependencies = [
name = "errors" name = "errors"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"image 0.20.1 (registry+https://github.com/rust-lang/crates.io-index)", "image 0.20.1 (registry+https://github.com/rust-lang/crates.io-index)",
"syntect 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "syntect 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tera 0.11.20 (registry+https://github.com/rust-lang/crates.io-index)", "tera 0.11.20 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2229,7 +2229,6 @@ dependencies = [
"base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"config 0.1.0", "config 0.1.0",
"csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"errors 0.1.0", "errors 0.1.0",
"imageproc 0.1.0", "imageproc 0.1.0",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",

View file

@ -13,3 +13,4 @@ lazy_static = "1"
syntect = "3" syntect = "3"
errors = { path = "../errors" } errors = { path = "../errors" }
utils = { path = "../utils" }

View file

@ -1,6 +1,4 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::fs::File;
use std::io::prelude::*;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use chrono::Utc; use chrono::Utc;
@ -9,9 +7,10 @@ use syntect::parsing::{SyntaxSet, SyntaxSetBuilder};
use toml; use toml;
use toml::Value as Toml; use toml::Value as Toml;
use errors::{Result, ResultExt}; use errors::Result;
use highlighting::THEME_SET; use highlighting::THEME_SET;
use theme::Theme; use theme::Theme;
use utils::fs::read_file_with_error;
// We want a default base url for tests // We want a default base url for tests
static DEFAULT_BASE_URL: &'static str = "http://a-website.com"; static DEFAULT_BASE_URL: &'static str = "http://a-website.com";
@ -66,7 +65,13 @@ impl Taxonomy {
impl Default for Taxonomy { impl Default for Taxonomy {
fn default() -> Taxonomy { fn default() -> Taxonomy {
Taxonomy { name: String::new(), paginate_by: None, paginate_path: None, rss: false, lang: None } Taxonomy {
name: String::new(),
paginate_by: None,
paginate_path: None,
rss: false,
lang: None,
}
} }
} }
@ -172,15 +177,12 @@ impl Config {
/// Parses a config file from the given path /// Parses a config file from the given path
pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Config> { pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Config> {
let mut content = String::new();
let path = path.as_ref(); let path = path.as_ref();
let file_name = path.file_name().unwrap(); let file_name = path.file_name().unwrap();
File::open(path) let content = read_file_with_error(
.chain_err(|| { path,
format!("No `{:?}` file found. Are you in the right directory?", file_name) &format!("No `{:?}` file found. Are you in the right directory?", file_name),
})? )?;
.read_to_string(&mut content)?;
Config::parse(&content) Config::parse(&content)
} }

View file

@ -1,14 +1,16 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
extern crate toml;
#[macro_use]
extern crate errors;
extern crate chrono; extern crate chrono;
extern crate globset; extern crate globset;
extern crate toml;
#[macro_use] #[macro_use]
extern crate lazy_static; extern crate lazy_static;
extern crate syntect; extern crate syntect;
#[macro_use]
extern crate errors;
extern crate utils;
mod config; mod config;
pub mod highlighting; pub mod highlighting;
mod theme; mod theme;

View file

@ -1,11 +1,10 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::fs::File;
use std::io::prelude::*;
use std::path::PathBuf; use std::path::PathBuf;
use toml::Value as Toml; use toml::Value as Toml;
use errors::{Result, ResultExt}; use errors::Result;
use utils::fs::read_file_with_error;
/// Holds the data from a `theme.toml` file. /// Holds the data from a `theme.toml` file.
/// There are other fields than `extra` in it but Zola /// There are other fields than `extra` in it but Zola
@ -40,15 +39,12 @@ impl Theme {
/// Parses a theme file from the given path /// Parses a theme file from the given path
pub fn from_file(path: &PathBuf) -> Result<Theme> { pub fn from_file(path: &PathBuf) -> Result<Theme> {
let mut content = String::new(); let content = read_file_with_error(
File::open(path) path,
.chain_err(|| { "No `theme.toml` file found. \
"No `theme.toml` file found. \ Is the `theme` defined in your `config.toml present in the `themes` directory \
Is the `theme` defined in your `config.toml present in the `themes` directory \ and does it have a `theme.toml` inside?",
and does it have a `theme.toml` inside?" )?;
})?
.read_to_string(&mut content)?;
Theme::parse(&content) Theme::parse(&content)
} }
} }

View file

@ -4,7 +4,6 @@ version = "0.1.0"
authors = ["Vincent Prouillet <prouillet.vincent@gmail.com>"] authors = ["Vincent Prouillet <prouillet.vincent@gmail.com>"]
[dependencies] [dependencies]
error-chain = "0.12"
tera = "0.11" tera = "0.11"
toml = "0.4" toml = "0.4"
image = "0.20" image = "0.20"

View file

@ -1,27 +1,102 @@
#![allow(unused_doc_comments)]
#[macro_use]
extern crate error_chain;
extern crate image; extern crate image;
extern crate syntect; extern crate syntect;
extern crate tera; extern crate tera;
extern crate toml; extern crate toml;
error_chain! { use std::convert::Into;
errors {} use std::error::Error as StdError;
use std::fmt;
links { #[derive(Debug)]
Tera(tera::Error, tera::ErrorKind); pub enum ErrorKind {
} Msg(String),
Tera(tera::Error),
Io(::std::io::Error),
Toml(toml::de::Error),
Image(image::ImageError),
Syntect(syntect::LoadingError),
}
foreign_links { /// The Error type
Io(::std::io::Error); #[derive(Debug)]
Toml(toml::de::Error); pub struct Error {
Image(image::ImageError); /// Kind of error
Syntect(syntect::LoadingError); pub kind: ErrorKind,
pub source: Option<Box<dyn StdError>>,
}
unsafe impl Sync for Error {}
unsafe impl Send for Error {}
impl StdError for Error {
fn source(&self) -> Option<&(dyn StdError + 'static)> {
self.source.as_ref().map(|c| &**c)
} }
} }
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.kind {
ErrorKind::Msg(ref message) => write!(f, "{}", message),
ErrorKind::Tera(ref e) => write!(f, "{}", e),
ErrorKind::Io(ref e) => write!(f, "{}", e),
ErrorKind::Toml(ref e) => write!(f, "{}", e),
ErrorKind::Image(ref e) => write!(f, "{}", e),
ErrorKind::Syntect(ref e) => write!(f, "{}", e),
}
}
}
impl Error {
/// Creates generic error
pub fn msg(value: impl ToString) -> Self {
Self { kind: ErrorKind::Msg(value.to_string()), source: None }
}
/// Creates generic error with a cause
pub fn chain(value: impl ToString, source: impl Into<Box<dyn StdError>>) -> Self {
Self { kind: ErrorKind::Msg(value.to_string()), source: Some(source.into()) }
}
}
impl From<&str> for Error {
fn from(e: &str) -> Self {
Self::msg(e)
}
}
impl From<String> for Error {
fn from(e: String) -> Self {
Self::msg(e)
}
}
impl From<toml::de::Error> for Error {
fn from(e: toml::de::Error) -> Self {
Self { kind: ErrorKind::Toml(e), source: None }
}
}
impl From<syntect::LoadingError> for Error {
fn from(e: syntect::LoadingError) -> Self {
Self { kind: ErrorKind::Syntect(e), source: None }
}
}
impl From<tera::Error> for Error {
fn from(e: tera::Error) -> Self {
Self { kind: ErrorKind::Tera(e), source: None }
}
}
impl From<::std::io::Error> for Error {
fn from(e: ::std::io::Error) -> Self {
Self { kind: ErrorKind::Io(e), source: None }
}
}
impl From<image::ImageError> for Error {
fn from(e: image::ImageError) -> Self {
Self { kind: ErrorKind::Image(e), source: None }
}
}
/// Convenient wrapper around std::Result.
pub type Result<T> = ::std::result::Result<T, Error>;
// So we can use bail! in all other crates // So we can use bail! in all other crates
#[macro_export] #[macro_export]
macro_rules! bail { macro_rules! bail {

View file

@ -12,7 +12,7 @@ extern crate toml;
extern crate errors; extern crate errors;
extern crate utils; extern crate utils;
use errors::{Result, ResultExt}; use errors::{Result, Error};
use regex::Regex; use regex::Regex;
use std::path::Path; use std::path::Path;
@ -71,8 +71,8 @@ pub fn split_section_content(
content: &str, content: &str,
) -> Result<(SectionFrontMatter, String)> { ) -> Result<(SectionFrontMatter, String)> {
let (front_matter, content) = split_content(file_path, content)?; let (front_matter, content) = split_content(file_path, content)?;
let meta = SectionFrontMatter::parse(&front_matter).chain_err(|| { let meta = SectionFrontMatter::parse(&front_matter).map_err(|e| {
format!("Error when parsing front matter of section `{}`", file_path.to_string_lossy()) Error::chain(format!("Error when parsing front matter of section `{}`", file_path.to_string_lossy()), e)
})?; })?;
Ok((meta, content)) Ok((meta, content))
} }
@ -81,8 +81,8 @@ pub fn split_section_content(
/// Returns a parsed `PageFrontMatter` and the rest of the content /// Returns a parsed `PageFrontMatter` and the rest of the content
pub fn split_page_content(file_path: &Path, content: &str) -> Result<(PageFrontMatter, String)> { pub fn split_page_content(file_path: &Path, content: &str) -> Result<(PageFrontMatter, String)> {
let (front_matter, content) = split_content(file_path, content)?; let (front_matter, content) = split_content(file_path, content)?;
let meta = PageFrontMatter::parse(&front_matter).chain_err(|| { let meta = PageFrontMatter::parse(&front_matter).map_err(|e| {
format!("Error when parsing front matter of page `{}`", file_path.to_string_lossy()) Error::chain(format!("Error when parsing front matter of page `{}`", file_path.to_string_lossy()), e)
})?; })?;
Ok((meta, content)) Ok((meta, content))
} }

View file

@ -20,7 +20,7 @@ use image::{FilterType, GenericImageView};
use rayon::prelude::*; use rayon::prelude::*;
use regex::Regex; use regex::Regex;
use errors::{Result, ResultExt}; use errors::{Result, Error};
use utils::fs as ufs; use utils::fs as ufs;
static RESIZED_SUBDIR: &'static str = "processed_images"; static RESIZED_SUBDIR: &'static str = "processed_images";
@ -456,7 +456,7 @@ impl Processor {
let target = let target =
self.resized_path.join(Self::op_filename(*hash, op.collision_id, op.format)); self.resized_path.join(Self::op_filename(*hash, op.collision_id, op.format));
op.perform(&self.content_path, &target) op.perform(&self.content_path, &target)
.chain_err(|| format!("Failed to process image: {}", op.source)) .map_err(|e| Error::chain(format!("Failed to process image: {}", op.source), e))
}) })
.collect::<Result<()>>() .collect::<Result<()>>()
} }

View file

@ -8,7 +8,7 @@ use slug::slugify;
use tera::{Context as TeraContext, Tera}; use tera::{Context as TeraContext, Tera};
use config::Config; use config::Config;
use errors::{Result, ResultExt}; use errors::{Result, Error};
use front_matter::{split_page_content, InsertAnchor, PageFrontMatter}; use front_matter::{split_page_content, InsertAnchor, PageFrontMatter};
use library::Library; use library::Library;
use rendering::{render_content, Header, RenderContext}; use rendering::{render_content, Header, RenderContext};
@ -234,7 +234,7 @@ impl Page {
context.tera_context.insert("page", &SerializingPage::from_page_basic(self, None)); context.tera_context.insert("page", &SerializingPage::from_page_basic(self, None));
let res = render_content(&self.raw_content, &context) let res = render_content(&self.raw_content, &context)
.chain_err(|| format!("Failed to render content of {}", self.file.path.display()))?; .map_err(|e| Error::chain(format!("Failed to render content of {}", self.file.path.display()), e))?;
self.summary = res.summary_len.map(|l| res.body[0..l].to_owned()); self.summary = res.summary_len.map(|l| res.body[0..l].to_owned());
self.content = res.body; self.content = res.body;
@ -258,7 +258,7 @@ impl Page {
context.insert("lang", &self.lang); context.insert("lang", &self.lang);
render_template(&tpl_name, tera, &context, &config.theme) render_template(&tpl_name, tera, &context, &config.theme)
.chain_err(|| format!("Failed to render page '{}'", self.file.path.display())) .map_err(|e| Error::chain(format!("Failed to render page '{}'", self.file.path.display()), e))
} }
/// Creates a vectors of asset URLs. /// Creates a vectors of asset URLs.

View file

@ -5,7 +5,7 @@ use slotmap::Key;
use tera::{Context as TeraContext, Tera}; use tera::{Context as TeraContext, Tera};
use config::Config; use config::Config;
use errors::{Result, ResultExt}; use errors::{Result, Error};
use front_matter::{split_section_content, SectionFrontMatter}; use front_matter::{split_section_content, SectionFrontMatter};
use rendering::{render_content, Header, RenderContext}; use rendering::{render_content, Header, RenderContext};
use utils::fs::{find_related_assets, read_file}; use utils::fs::{find_related_assets, read_file};
@ -172,7 +172,7 @@ impl Section {
context.tera_context.insert("section", &SerializingSection::from_section_basic(self, None)); context.tera_context.insert("section", &SerializingSection::from_section_basic(self, None));
let res = render_content(&self.raw_content, &context) let res = render_content(&self.raw_content, &context)
.chain_err(|| format!("Failed to render content of {}", self.file.path.display()))?; .map_err(|e| Error::chain(format!("Failed to render content of {}", self.file.path.display()), e))?;
self.content = res.body; self.content = res.body;
self.toc = res.toc; self.toc = res.toc;
Ok(()) Ok(())
@ -190,7 +190,7 @@ impl Section {
context.insert("lang", &self.lang); context.insert("lang", &self.lang);
render_template(tpl_name, tera, &context, &config.theme) render_template(tpl_name, tera, &context, &config.theme)
.chain_err(|| format!("Failed to render section '{}'", self.file.path.display())) .map_err(|e| Error::chain(format!("Failed to render section '{}'", self.file.path.display()), e))
} }
/// Is this the index section? /// Is this the index section?

View file

@ -4,7 +4,7 @@ use slotmap::Key;
use tera::{to_value, Context, Tera, Value}; use tera::{to_value, Context, Tera, Value};
use config::Config; use config::Config;
use errors::{Result, ResultExt}; use errors::{Result, Error};
use utils::templates::render_template; use utils::templates::render_template;
use content::{Section, SerializingPage, SerializingSection}; use content::{Section, SerializingPage, SerializingSection};
@ -222,7 +222,7 @@ impl<'a> Paginator<'a> {
context.insert("paginator", &self.build_paginator_context(pager)); context.insert("paginator", &self.build_paginator_context(pager));
render_template(&self.template, tera, &context, &config.theme) render_template(&self.template, tera, &context, &config.theme)
.chain_err(|| format!("Failed to render pager {}", pager.index)) .map_err(|e| Error::chain(format!("Failed to render pager {}", pager.index), e))
} }
} }

View file

@ -5,7 +5,7 @@ use slug::slugify;
use tera::{Context, Tera}; use tera::{Context, Tera};
use config::{Config, Taxonomy as TaxonomyConfig}; use config::{Config, Taxonomy as TaxonomyConfig};
use errors::{Result, ResultExt}; use errors::{Result, Error};
use utils::templates::render_template; use utils::templates::render_template;
use content::SerializingPage; use content::SerializingPage;
@ -145,7 +145,7 @@ impl Taxonomy {
context.insert("current_path", &format!("/{}/{}", self.kind.name, item.slug)); context.insert("current_path", &format!("/{}/{}", self.kind.name, item.slug));
render_template(&format!("{}/single.html", self.kind.name), tera, &context, &config.theme) render_template(&format!("{}/single.html", self.kind.name), tera, &context, &config.theme)
.chain_err(|| format!("Failed to render single term {} page.", self.kind.name)) .map_err(|e| Error::chain(format!("Failed to render single term {} page.", self.kind.name), e))
} }
pub fn render_all_terms( pub fn render_all_terms(
@ -164,7 +164,7 @@ impl Taxonomy {
context.insert("current_path", &self.kind.name); context.insert("current_path", &self.kind.name);
render_template(&format!("{}/list.html", self.kind.name), tera, &context, &config.theme) render_template(&format!("{}/list.html", self.kind.name), tera, &context, &config.theme)
.chain_err(|| format!("Failed to render a list of {} page.", self.kind.name)) .map_err(|e| Error::chain(format!("Failed to render a list of {} page.", self.kind.name), e))
} }
pub fn to_serialized<'a>(&'a self, library: &'a Library) -> SerializedTaxonomy<'a> { pub fn to_serialized<'a>(&'a self, library: &'a Library) -> SerializedTaxonomy<'a> {
@ -334,7 +334,7 @@ mod tests {
let err = taxonomies.unwrap_err(); let err = taxonomies.unwrap_err();
// no path as this is created by Default // no path as this is created by Default
assert_eq!( assert_eq!(
err.description(), format!("{}", err),
"Page `` has taxonomy `tags` which is not defined in config.toml" "Page `` has taxonomy `tags` which is not defined in config.toml"
); );
} }
@ -442,7 +442,7 @@ mod tests {
let err = taxonomies.unwrap_err(); let err = taxonomies.unwrap_err();
// no path as this is created by Default // no path as this is created by Default
assert_eq!( assert_eq!(
err.description(), format!("{}", err),
"Page `` has taxonomy `tags` which is not available in that language" "Page `` has taxonomy `tags` which is not available in that language"
); );
} }

View file

@ -4,7 +4,7 @@ use regex::Regex;
use tera::{to_value, Context, Map, Value}; use tera::{to_value, Context, Map, Value};
use context::RenderContext; use context::RenderContext;
use errors::{Result, ResultExt}; use errors::{Result, Error};
// This include forces recompiling this source file if the grammar file changes. // This include forces recompiling this source file if the grammar file changes.
// Uncomment it when doing changes to the .pest file // Uncomment it when doing changes to the .pest file
@ -116,7 +116,7 @@ fn render_shortcode(
let res = context let res = context
.tera .tera
.render(&tpl_name, &tera_context) .render(&tpl_name, &tera_context)
.chain_err(|| format!("Failed to render {} shortcode", name))?; .map_err(|e| Error::chain(format!("Failed to render {} shortcode", name), e))?;
// Small hack to avoid having multiple blank lines because of Tera tags for example // Small hack to avoid having multiple blank lines because of Tera tags for example
// A blank like will cause the markdown parser to think we're out of HTML and start looking // A blank like will cause the markdown parser to think we're out of HTML and start looking

View file

@ -660,7 +660,7 @@ fn can_show_error_message_for_invalid_external_links() {
let res = render_content("[a link](http://google.comy)", &context); let res = render_content("[a link](http://google.comy)", &context);
assert!(res.is_err()); assert!(res.is_err());
let err = res.unwrap_err(); let err = res.unwrap_err();
assert!(err.description().contains("Link http://google.comy is not valid")); assert!(format!("{}", err).contains("Link http://google.comy is not valid"));
} }
#[test] #[test]

View file

@ -30,7 +30,7 @@ use sass_rs::{compile_file, Options as SassOptions, OutputStyle};
use tera::{Context, Tera}; use tera::{Context, Tera};
use config::{get_config, Config}; use config::{get_config, Config};
use errors::{Result, ResultExt}; use errors::{Result, Error};
use front_matter::InsertAnchor; use front_matter::InsertAnchor;
use library::{ use library::{
find_taxonomies, sort_actual_pages_by_date, Library, Page, Paginator, Section, Taxonomy, find_taxonomies, sort_actual_pages_by_date, Library, Page, Paginator, Section, Taxonomy,
@ -87,7 +87,7 @@ impl Site {
format!("{}/{}", path.to_string_lossy().replace("\\", "/"), "templates/**/*.*ml"); format!("{}/{}", path.to_string_lossy().replace("\\", "/"), "templates/**/*.*ml");
// Only parsing as we might be extending templates from themes and that would error // Only parsing as we might be extending templates from themes and that would error
// as we haven't loaded them yet // as we haven't loaded them yet
let mut tera = Tera::parse(&tpl_glob).chain_err(|| "Error parsing templates")?; let mut tera = Tera::parse(&tpl_glob).map_err(|e| Error::chain("Error parsing templates", e))?;
if let Some(theme) = config.theme.clone() { if let Some(theme) = config.theme.clone() {
// Grab data from the extra section of the theme // Grab data from the extra section of the theme
config.merge_with_theme(&path.join("themes").join(&theme).join("theme.toml"))?; config.merge_with_theme(&path.join("themes").join(&theme).join("theme.toml"))?;
@ -104,9 +104,9 @@ impl Site {
format!("themes/{}/templates/**/*.*ml", theme) format!("themes/{}/templates/**/*.*ml", theme)
); );
let mut tera_theme = let mut tera_theme =
Tera::parse(&theme_tpl_glob).chain_err(|| "Error parsing templates from themes")?; Tera::parse(&theme_tpl_glob).map_err(|e| Error::chain("Error parsing templates from themes", e))?;
rewrite_theme_paths(&mut tera_theme, &theme); rewrite_theme_paths(&mut tera_theme, &theme);
// TODO: same as below // TODO: we do that twice, make it dry?
if theme_path.join("templates").join("robots.txt").exists() { if theme_path.join("templates").join("robots.txt").exists() {
tera_theme tera_theme
.add_template_file(theme_path.join("templates").join("robots.txt"), None)?; .add_template_file(theme_path.join("templates").join("robots.txt"), None)?;
@ -470,7 +470,7 @@ impl Site {
pub fn clean(&self) -> Result<()> { pub fn clean(&self) -> Result<()> {
if self.output_path.exists() { if self.output_path.exists() {
// Delete current `public` directory so we can start fresh // Delete current `public` directory so we can start fresh
remove_dir_all(&self.output_path).chain_err(|| "Couldn't delete output directory")?; remove_dir_all(&self.output_path).map_err(|e| Error::chain("Couldn't delete output directory", e))?;
} }
Ok(()) Ok(())

View file

@ -11,7 +11,6 @@ pulldown-cmark = "0.2"
toml = "0.4" toml = "0.4"
csv = "1" csv = "1"
serde_json = "1.0" serde_json = "1.0"
error-chain = "0.12"
reqwest = "0.9" reqwest = "0.9"
url = "1.5" url = "1.5"

View file

@ -1,5 +1,3 @@
extern crate error_chain;
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};

View file

@ -25,7 +25,7 @@ pub mod global_fns;
use tera::{Context, Tera}; use tera::{Context, Tera};
use errors::{Result, ResultExt}; use errors::{Result, Error};
lazy_static! { lazy_static! {
pub static ref ZOLA_TERA: Tera = { pub static ref ZOLA_TERA: Tera = {
@ -57,5 +57,5 @@ pub fn render_redirect_template(url: &str, tera: &Tera) -> Result<String> {
context.insert("url", &url); context.insert("url", &url);
tera.render("internal/alias.html", &context) tera.render("internal/alias.html", &context)
.chain_err(|| format!("Failed to render alias for '{}'", url)) .map_err(|e| Error::chain(format!("Failed to render alias for '{}'", url), e))
} }

View file

@ -4,7 +4,7 @@ use std::path::{Path, PathBuf};
use std::time::SystemTime; use std::time::SystemTime;
use walkdir::WalkDir; use walkdir::WalkDir;
use errors::{Result, ResultExt}; use errors::{Result, Error};
pub fn is_path_in_directory(parent: &Path, path: &Path) -> Result<bool> { pub fn is_path_in_directory(parent: &Path, path: &Path) -> Result<bool> {
let canonical_path = path let canonical_path = path
@ -19,7 +19,8 @@ pub fn is_path_in_directory(parent: &Path, path: &Path) -> Result<bool> {
/// Create a file with the content given /// Create a file with the content given
pub fn create_file(path: &Path, content: &str) -> Result<()> { pub fn create_file(path: &Path, content: &str) -> Result<()> {
let mut file = File::create(&path).chain_err(|| format!("Failed to create {:?}", path))?; let mut file = File::create(&path)
.map_err(|e| Error::chain(format!("Failed to create {:?}", path), e))?;
file.write_all(content.as_bytes())?; file.write_all(content.as_bytes())?;
Ok(()) Ok(())
} }
@ -37,7 +38,7 @@ pub fn ensure_directory_exists(path: &Path) -> Result<()> {
pub fn create_directory(path: &Path) -> Result<()> { pub fn create_directory(path: &Path) -> Result<()> {
if !path.exists() { if !path.exists() {
create_dir_all(path) create_dir_all(path)
.chain_err(|| format!("Was not able to create folder {}", path.display()))?; .map_err(|e| Error::chain(format!("Was not able to create folder {}", path.display()), e))?;
} }
Ok(()) Ok(())
} }
@ -46,7 +47,7 @@ pub fn create_directory(path: &Path) -> Result<()> {
pub fn read_file(path: &Path) -> Result<String> { pub fn read_file(path: &Path) -> Result<String> {
let mut content = String::new(); let mut content = String::new();
File::open(path) File::open(path)
.chain_err(|| format!("Failed to open '{:?}'", path.display()))? .map_err(|e| Error::chain(format!("Failed to open '{:?}'", path.display()), e))?
.read_to_string(&mut content)?; .read_to_string(&mut content)?;
// Remove utf-8 BOM if any. // Remove utf-8 BOM if any.
@ -57,6 +58,19 @@ pub fn read_file(path: &Path) -> Result<String> {
Ok(content) Ok(content)
} }
/// Return the content of a file, with error handling added.
/// The default error message is overwritten by the message given.
/// That means it is allocation 2 strings, oh well
pub fn read_file_with_error(path: &Path, message: &str) -> Result<String> {
let res = read_file(&path);
if res.is_ok() {
return res;
}
let mut err = Error::msg(message);
err.source = res.unwrap_err().source;
Err(err)
}
/// Looks into the current folder for the path and see if there's anything that is not a .md /// Looks into the current folder for the path and see if there's anything that is not a .md
/// file. Those will be copied next to the rendered .html file /// file. Those will be copied next to the rendered .html file
pub fn find_related_assets(path: &Path) -> Vec<PathBuf> { pub fn find_related_assets(path: &Path) -> Vec<PathBuf> {

View file

@ -4,4 +4,5 @@
{% block doc_content %} {% block doc_content %}
<h1>{{page.title}}</h1> <h1>{{page.title}}</h1>
{{page.content | safe}} {{page.content | safe}}
{{hey}}
{% endblock doc_content %} {% endblock doc_content %}

View file

@ -36,7 +36,7 @@ use ctrlc;
use notify::{watcher, RecursiveMode, Watcher}; use notify::{watcher, RecursiveMode, Watcher};
use ws::{Message, Sender, WebSocket}; use ws::{Message, Sender, WebSocket};
use errors::{Result, ResultExt}; use errors::{Result, Error as ZolaError};
use site::Site; use site::Site;
use utils::fs::copy_file; use utils::fs::copy_file;
@ -179,23 +179,23 @@ pub fn serve(
let mut watcher = watcher(tx, Duration::from_secs(1)).unwrap(); let mut watcher = watcher(tx, Duration::from_secs(1)).unwrap();
watcher watcher
.watch("content/", RecursiveMode::Recursive) .watch("content/", RecursiveMode::Recursive)
.chain_err(|| "Can't watch the `content` folder. Does it exist?")?; .map_err(|e| ZolaError::chain("Can't watch the `content` folder. Does it exist?", e))?;
watcher watcher
.watch(config_file, RecursiveMode::Recursive) .watch(config_file, RecursiveMode::Recursive)
.chain_err(|| "Can't watch the `config` file. Does it exist?")?; .map_err(|e| ZolaError::chain("Can't watch the `config` file. Does it exist?", e))?;
if Path::new("static").exists() { if Path::new("static").exists() {
watching_static = true; watching_static = true;
watcher watcher
.watch("static/", RecursiveMode::Recursive) .watch("static/", RecursiveMode::Recursive)
.chain_err(|| "Can't watch the `static` folder.")?; .map_err(|e| ZolaError::chain("Can't watch the `static` folder.", e))?;
} }
if Path::new("templates").exists() { if Path::new("templates").exists() {
watching_templates = true; watching_templates = true;
watcher watcher
.watch("templates/", RecursiveMode::Recursive) .watch("templates/", RecursiveMode::Recursive)
.chain_err(|| "Can't watch the `templates` folder.")?; .map_err(|e| ZolaError::chain("Can't watch the `templates` folder.", e))?;
} }
// Sass support is optional so don't make it an error to no have a sass folder // Sass support is optional so don't make it an error to no have a sass folder

View file

@ -1,4 +1,5 @@
use std::env; use std::env;
use std::error::Error as StdError;
use std::io::Write; use std::io::Write;
use std::time::Instant; use std::time::Instant;
@ -6,7 +7,6 @@ use atty;
use chrono::Duration; use chrono::Duration;
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
use errors::Error;
use site::Site; use site::Site;
lazy_static! { lazy_static! {
@ -91,13 +91,15 @@ pub fn report_elapsed_time(instant: Instant) {
} }
/// Display an error message and the actual error(s) /// Display an error message and the actual error(s)
pub fn unravel_errors(message: &str, error: &Error) { pub fn unravel_errors(message: &str, error: &StdError) {
if !message.is_empty() { if !message.is_empty() {
self::error(message); self::error(message);
} }
self::error(&format!("Error: {}", error)); self::error(&format!("Error: {}", error));
for e in error.iter().skip(1) { let mut cause = error.source();
while let Some(e) = cause {
self::error(&format!("Reason: {}", e)); self::error(&format!("Reason: {}", e));
cause = e.source();
} }
} }