mirror of
https://github.com/cobalt-org/cobalt.rs
synced 2024-11-15 00:17:29 +00:00
chore: Switch to failure
This commit is contained in:
parent
6dee6d44ff
commit
6fb1bbbcd7
24 changed files with 156 additions and 183 deletions
21
Cargo.lock
generated
21
Cargo.lock
generated
|
@ -203,7 +203,8 @@ dependencies = [
|
|||
"deunicode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"exitfailure 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ghp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ignore 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -372,14 +373,6 @@ dependencies = [
|
|||
"backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "error-chain"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "escargot"
|
||||
version = "0.3.1"
|
||||
|
@ -389,6 +382,14 @@ dependencies = [
|
|||
"serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "exitfailure"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure"
|
||||
version = "0.1.5"
|
||||
|
@ -1746,8 +1747,8 @@ dependencies = [
|
|||
"checksum encoding_rs 0.8.14 (registry+https://github.com/rust-lang/crates.io-index)" = "a69d152eaa438a291636c1971b0a370212165ca8a75759eb66818c5ce9b538f7"
|
||||
"checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e"
|
||||
"checksum error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9435d864e017c3c6afeac1654189b06cdb491cf2ff73dbf0d73b0f292f42ff8"
|
||||
"checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02"
|
||||
"checksum escargot 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "19db1f7e74438642a5018cdf263bb1325b2e792f02dd0a3ca6d6c0f0d7b1d5a5"
|
||||
"checksum exitfailure 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2ff5bd832af37f366c6c194d813a11cd90ac484f124f079294f28e357ae40515"
|
||||
"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
|
||||
"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
|
||||
"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
||||
|
|
|
@ -35,7 +35,8 @@ pulldown-cmark = {version="0.2", default-features = false}
|
|||
notify = "4.0"
|
||||
ghp = "0.1"
|
||||
regex = "1.1"
|
||||
error-chain = "0.12"
|
||||
failure = "0.1"
|
||||
exitfailure = "0.5"
|
||||
lazy_static = "1.1"
|
||||
itertools = "0.8"
|
||||
ignore = "0.4"
|
||||
|
|
|
@ -4,6 +4,7 @@ use std::path;
|
|||
|
||||
use clap;
|
||||
use env_logger;
|
||||
use failure::ResultExt;
|
||||
|
||||
use crate::error::*;
|
||||
use cobalt;
|
||||
|
@ -41,7 +42,7 @@ pub fn get_config(matches: &clap::ArgMatches) -> Result<cobalt::ConfigBuilder> {
|
|||
// Fetch config information if available
|
||||
let mut config = if let Some(config_path) = config_path {
|
||||
cobalt::ConfigBuilder::from_file(config_path)
|
||||
.chain_err(|| format!("Error reading config file {:?}", config_path))?
|
||||
.with_context(|_| failure::format_err!("Error reading config file {:?}", config_path))?
|
||||
} else {
|
||||
let cwd = env::current_dir().expect("How does this fail?");
|
||||
cobalt::ConfigBuilder::from_cwd(cwd)?
|
||||
|
|
|
@ -60,7 +60,7 @@ pub fn clean(config: &cobalt::Config) -> Result<()> {
|
|||
}
|
||||
};
|
||||
if cwd.starts_with(&destdir) {
|
||||
bail!(
|
||||
failure::bail!(
|
||||
"Attempting to delete current directory ({:?}), \
|
||||
Cancelling the operation",
|
||||
destdir
|
||||
|
@ -116,7 +116,7 @@ fn import(config: &cobalt::Config, branch: &str, message: &str) -> Result<()> {
|
|||
info!("Importing {:?} to {}", config.destination, branch);
|
||||
|
||||
if !config.destination.is_dir() {
|
||||
bail!("`{:?}` is not a directory", config.destination);
|
||||
failure::bail!("`{:?}` is not a directory", config.destination);
|
||||
}
|
||||
ghp::import_dir(&config.destination, branch, message)?;
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ pub fn debug_command(matches: &clap::ArgMatches) -> Result<()> {
|
|||
println!("{}", name);
|
||||
}
|
||||
}
|
||||
_ => bail!(matches.usage()),
|
||||
_ => failure::bail!(matches.usage().to_owned()),
|
||||
},
|
||||
("files", Some(matches)) => {
|
||||
let config = args::get_config(matches)?;
|
||||
|
@ -80,14 +80,14 @@ pub fn debug_command(matches: &clap::ArgMatches) -> Result<()> {
|
|||
}
|
||||
}
|
||||
None => {
|
||||
bail!("Must specify collection");
|
||||
failure::bail!("Must specify collection");
|
||||
}
|
||||
_ => {
|
||||
bail!("Collection is not yet supported");
|
||||
failure::bail!("Collection is not yet supported");
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => bail!(matches.usage()),
|
||||
_ => failure::bail!(matches.usage().to_owned()),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -1,29 +1,2 @@
|
|||
use std::io;
|
||||
use std::sync;
|
||||
|
||||
use clap;
|
||||
use cobalt;
|
||||
use ghp;
|
||||
use hyper;
|
||||
use notify;
|
||||
use serde_yaml;
|
||||
|
||||
error_chain! {
|
||||
|
||||
links {
|
||||
}
|
||||
|
||||
foreign_links {
|
||||
Clap(clap::Error);
|
||||
Cobalt(cobalt::Error);
|
||||
Ghp(ghp::Error);
|
||||
Hyper(hyper::Error);
|
||||
Io(io::Error);
|
||||
Notify(notify::Error);
|
||||
Recv(sync::mpsc::RecvError);
|
||||
SerdeYaml(serde_yaml::Error);
|
||||
}
|
||||
|
||||
errors {
|
||||
}
|
||||
}
|
||||
pub use failure::Error;
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
|
|
@ -1,18 +1,8 @@
|
|||
#![warn(warnings)]
|
||||
|
||||
extern crate cobalt;
|
||||
extern crate env_logger;
|
||||
extern crate ghp;
|
||||
extern crate hyper;
|
||||
extern crate notify;
|
||||
extern crate serde_yaml;
|
||||
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
|
||||
#[macro_use]
|
||||
extern crate error_chain;
|
||||
|
||||
#[macro_use]
|
||||
extern crate clap;
|
||||
|
||||
|
@ -29,13 +19,17 @@ mod serve;
|
|||
use std::alloc;
|
||||
|
||||
use clap::{App, AppSettings};
|
||||
use failure::ResultExt;
|
||||
|
||||
use crate::error::*;
|
||||
|
||||
#[global_allocator]
|
||||
static GLOBAL: alloc::System = alloc::System;
|
||||
|
||||
quick_main!(run);
|
||||
fn main() -> std::result::Result<(), exitfailure::ExitFailure> {
|
||||
run()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run() -> Result<()> {
|
||||
let app_cli = App::new("Cobalt")
|
||||
|
@ -76,10 +70,10 @@ fn run() -> Result<()> {
|
|||
"import" => build::import_command(matches),
|
||||
"debug" => debug::debug_command(matches),
|
||||
_ => {
|
||||
bail!(global_matches.usage());
|
||||
failure::bail!(global_matches.usage().to_owned());
|
||||
}
|
||||
}
|
||||
.chain_err(|| format!("{} command failed", command))?;
|
||||
.with_context(|_| failure::format_err!("{} command failed", command))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ use std::path;
|
|||
|
||||
use clap;
|
||||
use cobalt::cobalt_model;
|
||||
use failure::ResultExt;
|
||||
|
||||
use crate::args;
|
||||
use crate::error::*;
|
||||
|
@ -26,7 +27,7 @@ pub fn init_command(matches: &clap::ArgMatches) -> Result<()> {
|
|||
let directory = matches.value_of("DIRECTORY").unwrap();
|
||||
|
||||
create_new_project(&directory.to_string())
|
||||
.chain_err(|| "Could not create a new cobalt project")?;
|
||||
.with_context(|_| failure::err_msg("Could not create a new cobalt project"))?;
|
||||
info!("Created new project at {}", directory);
|
||||
|
||||
Ok(())
|
||||
|
@ -73,7 +74,7 @@ pub fn new_command(matches: &clap::ArgMatches) -> Result<()> {
|
|||
let ext = matches.value_of("with-ext");
|
||||
|
||||
create_new_document(&config, title, file, ext)
|
||||
.chain_err(|| format!("Could not create `{}`", title))?;
|
||||
.with_context(|_| failure::format_err!("Could not create `{}`", title))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -119,7 +120,7 @@ pub fn rename_command(matches: &clap::ArgMatches) -> Result<()> {
|
|||
let file = file;
|
||||
|
||||
rename_document(&config, source, title, file)
|
||||
.chain_err(|| format!("Could not rename `{}`", title))?;
|
||||
.with_context(|_| failure::format_err!("Could not rename `{}`", title))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -145,7 +146,8 @@ pub fn publish_command(matches: &clap::ArgMatches) -> Result<()> {
|
|||
let config = args::get_config(matches)?;
|
||||
let config = config.build()?;
|
||||
|
||||
publish_document(&config, &file).chain_err(|| format!("Could not publish `{:?}`", file))?;
|
||||
publish_document(&config, &file)
|
||||
.with_context(|_| failure::format_err!("Could not publish `{:?}`", file))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -256,9 +258,10 @@ pub fn create_new_document(
|
|||
};
|
||||
|
||||
let rel_file = file.strip_prefix(&config.source).map_err(|_| {
|
||||
format!(
|
||||
"New file {:?} not project directory ({:?})",
|
||||
file, config.source
|
||||
failure::format_err!(
|
||||
"New file {} not project directory ({})",
|
||||
file.display(),
|
||||
config.source.display()
|
||||
)
|
||||
})?;
|
||||
|
||||
|
@ -279,9 +282,9 @@ pub fn create_new_document(
|
|||
{
|
||||
pages.slug.as_str()
|
||||
} else {
|
||||
bail!(
|
||||
"Target file wouldn't be a member of any collection: {:?}",
|
||||
file
|
||||
failure::bail!(
|
||||
"Target file wouldn't be a member of any collection: {}",
|
||||
file.display()
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -290,17 +293,17 @@ pub fn create_new_document(
|
|||
.join(format!("_defaults/{}.{}", file_type, extension));
|
||||
let source = if source_path.is_file() {
|
||||
cobalt_model::files::read_file(&source_path)
|
||||
.chain_err(|| format!("Failed to read default: {:?}", source_path))?
|
||||
.with_context(|_| failure::format_err!("Failed to read default: {:?}", source_path))?
|
||||
} else {
|
||||
debug!(
|
||||
"No custom default provided ({:?}), falling back to built-in",
|
||||
source_path
|
||||
);
|
||||
if extension != "md" {
|
||||
bail!(
|
||||
"No builtin default for `{}` files, only `md`: {:?}",
|
||||
failure::bail!(
|
||||
"No builtin default for `{}` files, only `md`: {}",
|
||||
extension,
|
||||
file
|
||||
file.display()
|
||||
);
|
||||
}
|
||||
// For custom collections, use a post default.
|
||||
|
@ -331,7 +334,7 @@ fn create_file_for_path(path: &path::Path, content: &str) -> Result<()> {
|
|||
.write(true)
|
||||
.create_new(true)
|
||||
.open(path)
|
||||
.chain_err(|| format!("Failed to create file {:?}", path))?;
|
||||
.with_context(|_| failure::format_err!("Failed to create file {}", path.display()))?;
|
||||
|
||||
file.write_all(content.as_bytes())?;
|
||||
|
||||
|
@ -389,7 +392,7 @@ pub fn rename_document(
|
|||
.merge_path(rel_src)
|
||||
.merge(pages.default.clone())
|
||||
} else {
|
||||
bail!(
|
||||
failure::bail!(
|
||||
"Target file wouldn't be a member of any collection: {:?}",
|
||||
target
|
||||
);
|
||||
|
@ -461,7 +464,7 @@ fn move_from_drafts_to_posts(
|
|||
);
|
||||
if let Some(parent) = target.parent() {
|
||||
fs::create_dir_all(parent)
|
||||
.map_err(|e| format!("Could not create {:?}: {}", parent, e))?;
|
||||
.with_context(|_| failure::format_err!("Could not create {}", parent.display()))?;
|
||||
}
|
||||
fs::rename(file, &target)?;
|
||||
Ok(target)
|
||||
|
|
|
@ -8,7 +8,7 @@ use std::time;
|
|||
|
||||
use clap;
|
||||
use cobalt::cobalt_model;
|
||||
use error_chain::ChainedError;
|
||||
use failure::ResultExt;
|
||||
use hyper;
|
||||
use hyper::server::{Request, Response, Server};
|
||||
use hyper::uri::RequestUri;
|
||||
|
@ -170,18 +170,20 @@ fn watch(config: &cobalt_model::Config) -> Result<()> {
|
|||
// Files::includes_file
|
||||
let source = path::Path::new(&config.source)
|
||||
.canonicalize()
|
||||
.chain_err(|| "Failed in processing source")?;
|
||||
.with_context(|_| failure::err_msg("Failed in processing source"))?;
|
||||
|
||||
let (tx, rx) = channel();
|
||||
let mut watcher =
|
||||
notify::watcher(tx, time::Duration::from_secs(1)).chain_err(|| "Notify error")?;
|
||||
let mut watcher = notify::watcher(tx, time::Duration::from_secs(1))
|
||||
.with_context(|_| failure::err_msg("Notify error"))?;
|
||||
watcher
|
||||
.watch(&source, notify::RecursiveMode::Recursive)
|
||||
.chain_err(|| "Notify error")?;
|
||||
.with_context(|_| failure::err_msg("Notify error"))?;
|
||||
info!("Watching {:?} for changes", &config.source);
|
||||
|
||||
loop {
|
||||
let event = rx.recv().chain_err(|| "Notify error")?;
|
||||
let event = rx
|
||||
.recv()
|
||||
.with_context(|_| failure::err_msg("Notify error"))?;
|
||||
let event_path = match event {
|
||||
notify::DebouncedEvent::Create(ref path)
|
||||
| notify::DebouncedEvent::NoticeWrite(ref path)
|
||||
|
@ -209,7 +211,8 @@ fn watch(config: &cobalt_model::Config) -> Result<()> {
|
|||
if rebuild {
|
||||
let result = build::build(config.clone());
|
||||
if let Err(fail) = result {
|
||||
error!("build failed\n{}", fail.display_chain());
|
||||
let fail: exitfailure::ExitFailure = fail.into();
|
||||
error!("build failed\n{:?}", fail);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ use std::fs;
|
|||
use std::io::Write;
|
||||
use std::path;
|
||||
|
||||
use failure::ResultExt;
|
||||
use jsonfeed;
|
||||
use jsonfeed::Feed;
|
||||
use liquid;
|
||||
|
@ -147,9 +148,13 @@ fn generate_doc(
|
|||
);
|
||||
|
||||
doc.render_excerpt(&globals, &context.liquid, &context.markdown)
|
||||
.chain_err(|| format!("Failed to render excerpt for {:?}", doc.file_path))?;
|
||||
.with_context(|_| {
|
||||
failure::format_err!("Failed to render excerpt for {}", doc.file_path.display())
|
||||
})?;
|
||||
doc.render_content(&globals, &context.liquid, &context.markdown)
|
||||
.chain_err(|| format!("Failed to render content for {:?}", doc.file_path))?;
|
||||
.with_context(|_| {
|
||||
failure::format_err!("Failed to render content for {}", doc.file_path.display())
|
||||
})?;
|
||||
|
||||
// Refresh `page` with the `excerpt` / `content` attribute
|
||||
globals.insert(
|
||||
|
@ -158,7 +163,9 @@ fn generate_doc(
|
|||
);
|
||||
let doc_html = doc
|
||||
.render(&globals, &context.liquid, &context.layouts)
|
||||
.chain_err(|| format!("Failed to render for {:?}", doc.file_path))?;
|
||||
.with_context(|_| {
|
||||
failure::format_err!("Failed to render for {}", doc.file_path.display())
|
||||
})?;
|
||||
files::write_document_file(doc_html, context.destination.join(&doc.file_path))?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -291,7 +298,7 @@ fn parse_drafts(
|
|||
let default_front = collection.default.clone().set_draft(true);
|
||||
|
||||
let doc = Document::parse(&file_path, &new_path, default_front)
|
||||
.chain_err(|| format!("Failed to parse {:?}", rel_src))?;
|
||||
.with_context(|_| failure::format_err!("Failed to parse {}", rel_src.display()))?;
|
||||
documents.push(doc);
|
||||
}
|
||||
Ok(())
|
||||
|
@ -311,12 +318,15 @@ fn parse_layouts(files: &files::Files) -> HashMap<String, String> {
|
|||
.strip_prefix(files.root())
|
||||
.expect("file was found under the root");
|
||||
|
||||
let layout_data = files::read_file(&file_path)
|
||||
.map_err(|e| format!("Failed to load layout {:?}: {}", rel_src, e))?;
|
||||
let layout_data = files::read_file(&file_path).with_context(|_| {
|
||||
failure::format_err!("Failed to load layout {}", rel_src.display())
|
||||
})?;
|
||||
|
||||
let path = rel_src
|
||||
.to_str()
|
||||
.ok_or_else(|| format!("File name not valid liquid path: {:?}", rel_src))?
|
||||
.ok_or_else(|| {
|
||||
failure::format_err!("File name not valid liquid path: {}", rel_src.display())
|
||||
})?
|
||||
.to_owned();
|
||||
|
||||
Ok((path, layout_data))
|
||||
|
@ -347,7 +357,7 @@ fn parse_pages(
|
|||
let default_front = collection.default.clone();
|
||||
|
||||
let doc = Document::parse(&file_path, rel_src, default_front)
|
||||
.chain_err(|| format!("Failed to parse {:?}", rel_src))?;
|
||||
.with_context(|_| failure::format_err!("Failed to parse {}", rel_src.display()))?;
|
||||
if !doc.front.is_draft || collection.include_drafts {
|
||||
documents.push(doc);
|
||||
}
|
||||
|
@ -374,7 +384,7 @@ fn create_rss(
|
|||
let link = collection
|
||||
.base_url
|
||||
.as_ref()
|
||||
.ok_or(ErrorKind::ConfigFileMissingFields)?;
|
||||
.ok_or_else(|| failure::err_msg("`base_url` is required for RSS support"))?;
|
||||
|
||||
let items: Result<Vec<rss::Item>> = documents.iter().map(|doc| doc.to_rss(link)).collect();
|
||||
let items = items?;
|
||||
|
@ -384,14 +394,16 @@ fn create_rss(
|
|||
.link(link.to_owned())
|
||||
.description(description.to_owned())
|
||||
.items(items)
|
||||
.build()?;
|
||||
.build()
|
||||
.map_err(|s| failure::err_msg(s))?;
|
||||
|
||||
let rss_string = channel.to_string();
|
||||
trace!("RSS data: {}", rss_string);
|
||||
|
||||
// create target directories if any exist
|
||||
if let Some(parent) = rss_path.parent() {
|
||||
fs::create_dir_all(parent).map_err(|e| format!("Could not create {:?}: {}", parent, e))?;
|
||||
fs::create_dir_all(parent)
|
||||
.with_context(|_| failure::format_err!("Could not create {}", parent.display()))?;
|
||||
}
|
||||
|
||||
let mut rss_file = fs::File::create(&rss_path)?;
|
||||
|
@ -421,7 +433,7 @@ fn create_jsonfeed(
|
|||
let link = collection
|
||||
.base_url
|
||||
.as_ref()
|
||||
.ok_or(ErrorKind::ConfigFileMissingFields)?;
|
||||
.ok_or_else(|| failure::err_msg("`base_url` is required for jsonfeed support"))?;
|
||||
|
||||
let jsonitems = documents.iter().map(|doc| doc.to_jsonfeed(link)).collect();
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ impl AssetsBuilder {
|
|||
|
||||
let sass = sass.build();
|
||||
|
||||
let source = source.ok_or_else(|| "No asset source provided")?;
|
||||
let source = source.ok_or_else(|| failure::err_msg("No asset source provided"))?;
|
||||
|
||||
let mut files = files::FilesBuilder::new(source)?;
|
||||
for line in ignore {
|
||||
|
|
|
@ -70,10 +70,10 @@ impl CollectionBuilder {
|
|||
default,
|
||||
} = self;
|
||||
|
||||
let title = title.ok_or("Collection is missing a `title`")?;
|
||||
let title = title.ok_or_else(|| failure::err_msg("Collection is missing a `title`"))?;
|
||||
let slug = slug.unwrap_or_else(|| slug::slugify(&title));
|
||||
|
||||
let source = source.ok_or_else(|| "No asset source provided")?;
|
||||
let source = source.ok_or_else(|| failure::err_msg("No asset source provided"))?;
|
||||
|
||||
let dir = dir.unwrap_or_else(|| slug.clone());
|
||||
let pages = Self::build_files(&source, &dir, &template_extensions, &ignore)?;
|
||||
|
@ -129,7 +129,7 @@ impl CollectionBuilder {
|
|||
ignore: &[String],
|
||||
) -> Result<files::Files> {
|
||||
if dir.starts_with('/') {
|
||||
bail!("Collection dir {} must be a relative path", dir)
|
||||
failure::bail!("Collection dir {} must be a relative path", dir)
|
||||
}
|
||||
let dir = files::cleanup_path(dir);
|
||||
let mut pages = files::FilesBuilder::new(source)?;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::fmt;
|
||||
use std::path;
|
||||
|
||||
use failure::ResultExt;
|
||||
use liquid;
|
||||
use serde_yaml;
|
||||
|
||||
|
@ -316,7 +317,7 @@ impl ConfigBuilder {
|
|||
let config = file_path
|
||||
.map(|p| {
|
||||
debug!("Using config file {:?}", &p);
|
||||
Self::from_file(&p).chain_err(|| format!("Error reading config file {:?}", p))
|
||||
Self::from_file(&p).with_context(|_| format!("Error reading config file {:?}", p))
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
warn!("No _cobalt.yml file found in current directory, using default config.");
|
||||
|
@ -353,7 +354,7 @@ impl ConfigBuilder {
|
|||
}
|
||||
|
||||
if template_extensions.is_empty() {
|
||||
return Err("`template_extensions` should not be empty.".into());
|
||||
failure::bail!("`template_extensions` should not be empty.");
|
||||
}
|
||||
|
||||
let source = files::cleanup_path(&source);
|
||||
|
|
|
@ -6,6 +6,7 @@ use std::iter::FromIterator;
|
|||
use std::path;
|
||||
|
||||
use crate::error::Result;
|
||||
use failure::ResultExt;
|
||||
use ignore::gitignore::{Gitignore, GitignoreBuilder};
|
||||
use ignore::Match;
|
||||
use normalize_line_endings::normalized;
|
||||
|
@ -266,12 +267,18 @@ pub fn read_file<P: AsRef<path::Path>>(path: P) -> Result<String> {
|
|||
pub fn copy_file(src_file: &path::Path, dest_file: &path::Path) -> Result<()> {
|
||||
// create target directories if any exist
|
||||
if let Some(parent) = dest_file.parent() {
|
||||
fs::create_dir_all(parent).map_err(|e| format!("Could not create {:?}: {}", parent, e))?;
|
||||
fs::create_dir_all(parent)
|
||||
.with_context(|_| failure::format_err!("Could not create {}", parent.display()))?;
|
||||
}
|
||||
|
||||
debug!("Copying {:?} to {:?}", src_file, dest_file);
|
||||
fs::copy(src_file, dest_file)
|
||||
.map_err(|e| format!("Could not copy {:?} into {:?}: {}", src_file, dest_file, e))?;
|
||||
fs::copy(src_file, dest_file).with_context(|_| {
|
||||
failure::format_err!(
|
||||
"Could not copy {} into {}",
|
||||
src_file.display(),
|
||||
dest_file.display()
|
||||
)
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -285,11 +292,12 @@ pub fn write_document_file<S: AsRef<str>, P: AsRef<path::Path>>(
|
|||
fn write_document_file_internal(content: &str, dest_file: &path::Path) -> Result<()> {
|
||||
// create target directories if any exist
|
||||
if let Some(parent) = dest_file.parent() {
|
||||
fs::create_dir_all(parent).map_err(|e| format!("Could not create {:?}: {}", parent, e))?;
|
||||
fs::create_dir_all(parent)
|
||||
.with_context(|_| failure::format_err!("Could not create {}", parent.display()))?;
|
||||
}
|
||||
|
||||
let mut file = fs::File::create(dest_file)
|
||||
.map_err(|e| format!("Could not create {:?}: {}", dest_file, e))?;
|
||||
.with_context(|_| failure::format_err!("Could not create {}", dest_file.display()))?;
|
||||
|
||||
file.write_all(content.as_bytes())?;
|
||||
trace!("Wrote {}", dest_file.display());
|
||||
|
|
|
@ -418,9 +418,9 @@ impl FrontmatterBuilder {
|
|||
|
||||
let permalink = permalink.unwrap_or_else(|| PATH_ALIAS.to_owned());
|
||||
let permalink = if !permalink.starts_with('/') {
|
||||
let resolved = *PERMALINK_ALIASES
|
||||
.get(permalink.as_str())
|
||||
.ok_or_else(|| format!("Unsupported permalink alias '{}'", permalink))?;
|
||||
let resolved = *PERMALINK_ALIASES.get(permalink.as_str()).ok_or_else(|| {
|
||||
failure::format_err!("Unsupported permalink alias '{}'", permalink)
|
||||
})?;
|
||||
resolved.to_owned()
|
||||
} else {
|
||||
permalink
|
||||
|
@ -428,7 +428,7 @@ impl FrontmatterBuilder {
|
|||
|
||||
if let Some(ref tags) = tags {
|
||||
if tags.iter().any(|x| x.trim().is_empty()) {
|
||||
return Err("Empty strings are not allowed in tags".into());
|
||||
failure::bail!("Empty strings are not allowed in tags");
|
||||
}
|
||||
}
|
||||
let tags = if tags.as_ref().map(|t| t.len()).unwrap_or(0) == 0 {
|
||||
|
@ -439,8 +439,8 @@ impl FrontmatterBuilder {
|
|||
|
||||
let fm = Frontmatter {
|
||||
permalink,
|
||||
slug: slug.ok_or_else(|| "No slug")?,
|
||||
title: title.ok_or_else(|| "No title")?,
|
||||
slug: slug.ok_or_else(|| failure::err_msg("No slug"))?,
|
||||
title: title.ok_or_else(|| failure::err_msg("No title"))?,
|
||||
description,
|
||||
excerpt,
|
||||
categories: categories.unwrap_or_else(|| vec![]),
|
||||
|
@ -456,7 +456,7 @@ impl FrontmatterBuilder {
|
|||
};
|
||||
|
||||
if !cfg!(feature = "pagination-unstable") && fm.pagination.is_some() {
|
||||
Err("Unsupported `pagination` field".into())
|
||||
failure::bail!("Unsupported `pagination` field");
|
||||
} else {
|
||||
Ok(fm)
|
||||
}
|
||||
|
|
|
@ -77,7 +77,8 @@ impl SassCompiler {
|
|||
SassOutputStyle::Compact => sass_rs::OutputStyle::Compact,
|
||||
SassOutputStyle::Compressed => sass_rs::OutputStyle::Compressed,
|
||||
};
|
||||
let content = sass_rs::compile_file(file_path, sass_opts)?;
|
||||
let content =
|
||||
sass_rs::compile_file(file_path, sass_opts).map_err(|e| failure::err_msg(e))?;
|
||||
|
||||
let rel_src = file_path
|
||||
.strip_prefix(source)
|
||||
|
|
|
@ -2,6 +2,7 @@ use std::ffi::OsStr;
|
|||
use std::fs;
|
||||
use std::path;
|
||||
|
||||
use failure::ResultExt;
|
||||
use liquid;
|
||||
use serde_json;
|
||||
use serde_yaml;
|
||||
|
@ -74,7 +75,7 @@ fn deep_insert(
|
|||
let mut map = data_map;
|
||||
for part in path.iter() {
|
||||
let key = part.to_str().ok_or_else(|| {
|
||||
format!(
|
||||
failure::format_err!(
|
||||
"The data from {:?} can't be loaded as it contains non utf-8 characters",
|
||||
path
|
||||
)
|
||||
|
@ -86,7 +87,7 @@ fn deep_insert(
|
|||
.or_insert_with(|| liquid::value::Value::Object(liquid::value::Object::new()))
|
||||
.as_object_mut()
|
||||
.ok_or_else(|| {
|
||||
format!(
|
||||
failure::format_err!(
|
||||
"Aborting: Duplicate in data tree. Would overwrite {:?} ",
|
||||
path
|
||||
)
|
||||
|
@ -99,7 +100,7 @@ fn deep_insert(
|
|||
|
||||
match target_map.insert(target_key.into(), data) {
|
||||
None => Ok(()),
|
||||
_ => Err(format!(
|
||||
_ => Err(failure::format_err!(
|
||||
"The data from {:?} can't be loaded: the key already exists",
|
||||
file_path
|
||||
)
|
||||
|
@ -122,7 +123,7 @@ fn load_data(data_path: &path::Path) -> Result<liquid::value::Value> {
|
|||
let text = files::read_file(data_path)?;
|
||||
data = toml::from_str(&text)?;
|
||||
} else {
|
||||
bail!(
|
||||
failure::bail!(
|
||||
"Failed to load of data {:?}: unknown file type '{:?}'.\n\
|
||||
Supported data files extensions are: yml, yaml, json and toml.",
|
||||
data_path,
|
||||
|
@ -148,10 +149,10 @@ fn insert_data_dir(data: &mut liquid::value::Object, data_root: &path::Path) ->
|
|||
.expect("Files will always return with a stem");
|
||||
let file_stem = String::from(file_stem.to_str().unwrap());
|
||||
let data_fragment = load_data(&full_path)
|
||||
.chain_err(|| format!("Loading data from {:?} failed", full_path))?;
|
||||
.with_context(|_| format!("Loading data from {:?} failed", full_path))?;
|
||||
|
||||
deep_insert(data, rel_path, file_stem, data_fragment)
|
||||
.chain_err(|| format!("Merging data into {:?} failed", rel_path))?;
|
||||
.with_context(|_| format!("Merging data into {:?} failed", rel_path))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -48,7 +48,10 @@ impl LiquidBuilder {
|
|||
fn highlight(theme: String) -> Result<Box<liquid::compiler::ParseBlock>> {
|
||||
let result: Result<()> = match syntax_highlight::has_syntax_theme(&theme) {
|
||||
Ok(true) => Ok(()),
|
||||
Ok(false) => Err(format!("Syntax theme '{}' is unsupported", theme).into()),
|
||||
Ok(false) => Err(failure::format_err!(
|
||||
"Syntax theme '{}' is unsupported",
|
||||
theme
|
||||
)),
|
||||
Err(err) => {
|
||||
warn!("Syntax theme named '{}' ignored. Reason: {}", theme, err);
|
||||
Ok(())
|
||||
|
|
|
@ -4,6 +4,7 @@ use std::default::Default;
|
|||
use std::path::{Path, PathBuf};
|
||||
|
||||
use chrono::{Datelike, Timelike};
|
||||
use failure::ResultExt;
|
||||
use itertools;
|
||||
use jsonfeed;
|
||||
use liquid;
|
||||
|
@ -206,7 +207,9 @@ impl Document {
|
|||
let (file_path, url_path) = {
|
||||
let perma_attributes = permalink_attributes(&front, rel_path);
|
||||
let url_path = permalink::explode_permalink(&front.permalink, &perma_attributes)
|
||||
.chain_err(|| format!("Failed to create permalink `{}`", front.permalink))?;
|
||||
.with_context(|_| {
|
||||
failure::format_err!("Failed to create permalink `{}`", front.permalink)
|
||||
})?;
|
||||
let file_path = permalink::format_url_as_file(&url_path);
|
||||
(file_path, url_path)
|
||||
};
|
||||
|
@ -228,7 +231,8 @@ impl Document {
|
|||
let guid = rss::GuidBuilder::default()
|
||||
.value(link.clone())
|
||||
.permalink(true)
|
||||
.build()?;
|
||||
.build()
|
||||
.map_err(|e| failure::err_msg(e))?;
|
||||
|
||||
let item = rss::ItemBuilder::default()
|
||||
.title(Some(self.front.title.clone()))
|
||||
|
@ -236,7 +240,8 @@ impl Document {
|
|||
.guid(Some(guid))
|
||||
.pub_date(self.front.published_date.map(|date| date.to_rfc2822()))
|
||||
.description(self.description_to_str())
|
||||
.build()?;
|
||||
.build()
|
||||
.map_err(|e| failure::err_msg(e))?;
|
||||
Ok(item)
|
||||
}
|
||||
|
||||
|
@ -350,25 +355,26 @@ impl Document {
|
|||
) -> Result<String> {
|
||||
if let Some(ref layout) = self.front.layout {
|
||||
let layout_data_ref = layouts.get(layout).ok_or_else(|| {
|
||||
format!(
|
||||
"Layout {} does not exist (referenced in {:?}).",
|
||||
layout, self.file_path
|
||||
failure::format_err!(
|
||||
"Layout {} does not exist (referenced in {}).",
|
||||
layout,
|
||||
self.file_path.display()
|
||||
)
|
||||
})?;
|
||||
|
||||
let template = parser
|
||||
.parse(layout_data_ref)
|
||||
.chain_err(|| format!("Failed to parse layout {:?}", layout))?;
|
||||
.with_context(|_| failure::format_err!("Failed to parse layout {:?}", layout))?;
|
||||
let content_html = template
|
||||
.render(globals)
|
||||
.chain_err(|| format!("Failed to render layout {:?}", layout))?;
|
||||
.with_context(|_| failure::format_err!("Failed to render layout {:?}", layout))?;
|
||||
Ok(content_html)
|
||||
} else {
|
||||
let content_html = globals
|
||||
.get("page")
|
||||
.ok_or("Internal error: page isn't in globals")?
|
||||
.ok_or_else(|| failure::err_msg("Internal error: page isn't in globals"))?
|
||||
.get(&liquid::value::Scalar::new("content"))
|
||||
.ok_or("Internal error: page.content isn't in globals")?
|
||||
.ok_or_else(|| failure::err_msg("Internal error: page.content isn't in globals"))?
|
||||
.render()
|
||||
.to_string();
|
||||
|
||||
|
|
32
src/error.rs
32
src/error.rs
|
@ -1,30 +1,2 @@
|
|||
use std::io;
|
||||
|
||||
error_chain! {
|
||||
|
||||
links {
|
||||
}
|
||||
|
||||
foreign_links {
|
||||
Io(io::Error);
|
||||
Liquid(liquid::Error);
|
||||
WalkDir(walkdir::Error);
|
||||
SerdeYaml(serde_yaml::Error);
|
||||
SerdeJson(serde_json::Error);
|
||||
Toml(toml::de::Error);
|
||||
Ignore(ignore::Error);
|
||||
}
|
||||
|
||||
errors {
|
||||
ConfigFileMissingFields {
|
||||
description("missing fields in config file")
|
||||
display("name, description and link need to be defined in the config file to \
|
||||
generate RSS")
|
||||
}
|
||||
|
||||
UnsupportedPlatform(functionality: &'static str, platform: &'static str) {
|
||||
description("functionality is not implemented for this platform")
|
||||
display("{} is not implemented for the {} platform", functionality, platform)
|
||||
}
|
||||
}
|
||||
}
|
||||
pub use failure::Error;
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
|
|
@ -3,9 +3,6 @@
|
|||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
#[macro_use]
|
||||
extern crate error_chain;
|
||||
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
|
||||
|
|
|
@ -249,7 +249,10 @@ fn distribute_posts_by_tags<'a>(
|
|||
for post in all_posts {
|
||||
if let Some(tags) = extract_tags(post) {
|
||||
for tag in tags {
|
||||
let tag = tag.as_scalar().ok_or("Should have string tags")?.to_str();
|
||||
let tag = tag
|
||||
.as_scalar()
|
||||
.ok_or_else(|| failure::err_msg("Should have string tags"))?
|
||||
.to_str();
|
||||
// add_to_tag(&tag.to_string(), post, &mut per_tags)
|
||||
let cur_tag = per_tags.entry(tag.to_string()).or_insert(vec![]);
|
||||
cur_tag.push(post);
|
||||
|
|
|
@ -12,7 +12,7 @@ use pulldown_cmark as cmark;
|
|||
use crate::error;
|
||||
|
||||
pub fn has_syntax_theme(_name: &str) -> error::Result<bool> {
|
||||
bail!("Themes are unsupported in this build.");
|
||||
failure::bail!("Themes are unsupported in this build.");
|
||||
}
|
||||
|
||||
pub fn list_syntax_themes<'a>() -> Vec<&'a String> {
|
||||
|
|
25
tests/mod.rs
25
tests/mod.rs
|
@ -1,17 +1,11 @@
|
|||
#[macro_use]
|
||||
extern crate difference;
|
||||
|
||||
extern crate assert_fs;
|
||||
extern crate cobalt;
|
||||
extern crate error_chain;
|
||||
extern crate walkdir;
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::path::Path;
|
||||
|
||||
use assert_fs::prelude::*;
|
||||
use error_chain::ChainedError;
|
||||
use walkdir::WalkDir;
|
||||
|
||||
macro_rules! assert_contains {
|
||||
|
@ -155,13 +149,9 @@ pub fn syntax_highlight() {
|
|||
pub fn incomplete_rss() {
|
||||
let err = run_test("incomplete_rss");
|
||||
assert!(err.is_err());
|
||||
|
||||
let err = err.unwrap_err();
|
||||
assert_eq!(
|
||||
format!("{}", err),
|
||||
"name, description and link need to be defined in the config file to generate RSS"
|
||||
);
|
||||
assert_eq!(err.description(), "missing fields in config file");
|
||||
let err: exitfailure::ExitFailure = err.unwrap_err().into();
|
||||
let error_message = format!("{:?}", err);
|
||||
assert_contains!(error_message, "base_url");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -179,10 +169,12 @@ pub fn liquid_raw() {
|
|||
pub fn no_extends_error() {
|
||||
let err = run_test("no_extends_error");
|
||||
assert!(err.is_err());
|
||||
let err: exitfailure::ExitFailure = err.unwrap_err().into();
|
||||
let error_message = format!("{:?}", err);
|
||||
assert_contains!(
|
||||
format!("{}", err.unwrap_err().display_chain()),
|
||||
error_message,
|
||||
"Layout default_nonexistent.liquid does not exist (referenced in \
|
||||
\"index.html\")"
|
||||
index.html)"
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -220,7 +212,8 @@ pub fn ignore_files() {
|
|||
pub fn yaml_error() {
|
||||
let err = run_test("yaml_error");
|
||||
assert!(err.is_err());
|
||||
let error_message = format!("{}", err.unwrap_err().display_chain());
|
||||
let err: exitfailure::ExitFailure = err.unwrap_err().into();
|
||||
let error_message = format!("{:?}", err);
|
||||
assert_contains!(error_message, "unexpected character");
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue