diff --git a/Cargo.toml b/Cargo.toml index f1a51d54..97c2be12 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,6 +40,9 @@ ws = { version = "0.7", optional = true} [dev-dependencies] tempdir = "0.3.4" +[build-dependencies] +error-chain = "0.10" + [features] default = ["output", "watch", "serve"] debug = [] diff --git a/build.rs b/build.rs index 25884ef3..9d45b3de 100644 --- a/build.rs +++ b/build.rs @@ -3,28 +3,93 @@ use std::process::Command; use std::env; use std::path::Path; +#[macro_use] +extern crate error_chain; -fn main() { +#[cfg(windows)] +mod execs { + pub const NPM: &'static str = "npm.cmd"; + pub const STYLUS: &'static str = "stylus.cmd"; +} +#[cfg(not(windows))] +mod execs { + pub const NPM: &'static str = "npm"; + pub const STYLUS: &'static str = "stylus"; +} + + +error_chain!{ + foreign_links { + Io(std::io::Error); + } +} + +fn program_exists(program: &str) -> Result<()> { + Command::new(program) + .arg("-v") + .output() + .chain_err(|| format!("Please install '{}'!", program))?; + Ok(()) +} + +fn npm_package_exists(package: &str) -> Result<()> { + let status = Command::new(execs::NPM) + .args(&["list", "-g"]) + .arg(package) + .output(); + + match status { + Ok(ref out) if out.status.success() => Ok(()), + _ => { + bail!("Missing npm package '{0}' \ + install with: 'npm -g install {0}'", + package) + }, + } +} + +pub enum Resource<'a> { + Program(&'a str), + Package(&'a str), +} +use Resource::{Program, Package}; + +impl<'a> Resource<'a> { + pub fn exists(&self) -> Result<()> { + match *self { + Program(name) => program_exists(name), + Package(name) => npm_package_exists(name), + } + } +} + +fn run() -> Result<()> { if let Ok(_) = env::var("CARGO_FEATURE_REGENERATE_CSS") { + // Check dependencies + Program(execs::NPM).exists()?; + Program("node").exists().or(Program("nodejs").exists())?; + Package("nib").exists()?; + Package("stylus").exists()?; // Compile stylus stylesheet to css - let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); - + let manifest_dir = env::var("CARGO_MANIFEST_DIR") + .chain_err(|| "Please run the script with: 'cargo build'!")?; let theme_dir = Path::new(&manifest_dir).join("src/theme/"); let stylus_dir = theme_dir.join("stylus/book.styl"); - if !Command::new("stylus") - .arg(format!("{}", stylus_dir.to_str().unwrap())) + if !Command::new(execs::STYLUS) + .arg(stylus_dir) .arg("--out") - .arg(format!("{}", theme_dir.to_str().unwrap())) + .arg(theme_dir) .arg("--use") .arg("nib") - .status() - .unwrap() + .status()? .success() { - panic!("Stylus encoutered an error"); + bail!("Stylus encoutered an error"); } } - + Ok(()) } + +quick_main!(run);