diff --git a/src/build/csl.rs b/src/build/csl.rs index 6ca99ce..f69758c 100644 --- a/src/build/csl.rs +++ b/src/build/csl.rs @@ -1,12 +1,12 @@ use zip::ZipArchive; use mktemp::Temp; use std::path::PathBuf; -use utils::get_exe_dir; +use utils::{get_exe_dir, result_override}; use std::fs::File; use std::io::{Read, Write}; use config::consts::CSL_FILE_NAME; -pub fn get_csl_path() -> PathBuf { +fn get_csl_path() -> PathBuf { return get_exe_dir().join(CSL_FILE_NAME); } @@ -15,19 +15,27 @@ fn get_temp_file() -> PathBuf { return Temp::new_file().expect("Failed to create temporary file").to_path_buf(); } + +fn get_csl_data(csl_name: String) -> Result { + let zip_file = try!(result_override(File::open(get_csl_path()), "Failed to read CSL zip".into())); + let mut archive = try!(result_override(ZipArchive::new(zip_file), "Failed to load zip file".into())); + debug_assert!(archive.len() >= 10); + let mut csl_zip_file = try!(result_override(archive.by_name(&format!("{}.csl", csl_name)), format!("Can't find CSL {}.", csl_name))); + debug_assert!(csl_zip_file.size() > 0); + let mut csl_buffer = String::new(); + try!(result_override(csl_zip_file.read_to_string(&mut csl_buffer), "Failed to read CSL".into())); + return Ok(csl_buffer); +} + +pub fn is_valid_csl(csl_name: String) -> bool { + return get_csl_data(csl_name).is_ok(); +} + + pub fn unpack_csl(csl_name: String) -> PathBuf { let file = get_temp_file(); - let zip_file = File::open(get_csl_path()).expect("Failed to read CSL zip"); - let mut archive = ZipArchive::new(zip_file).expect("Failed to load zip file"); - debug_assert!(archive.len() >= 10); - let mut csl_zip_file = archive.by_name(&format!("{}.csl", csl_name)).expect(&format!( - "Failed to find CSL {}.", - csl_name - )); - debug_assert!(csl_zip_file.size() > 0); let mut csl_temp = File::create(&file).expect("Failed to open temporary file"); - let mut csl_buffer = String::new(); - csl_zip_file.read_to_string(&mut csl_buffer).expect("Failed to read CSL"); + let mut csl_buffer = get_csl_data(csl_name).unwrap(); csl_temp.write_all(csl_buffer.as_bytes()).expect("Failed to write CSL to temporary file"); return file; } diff --git a/src/build/mod.rs b/src/build/mod.rs index d570d96..cf47a5c 100644 --- a/src/build/mod.rs +++ b/src/build/mod.rs @@ -1,6 +1,6 @@ pub mod pandoc; pub mod process; -mod csl; +pub mod csl; use config::Config; diff --git a/src/config/validate.rs b/src/config/validate.rs index 040224d..d23f60d 100644 --- a/src/config/validate.rs +++ b/src/config/validate.rs @@ -1,10 +1,12 @@ use serde_yaml::Value; use std::vec::Vec; - -pub type ValidationResult = Result<(), String>; - use config::read; use config::validate_types::check_config_types; +use utils::resolve_path; +use build::csl::is_valid_csl; + + +pub type ValidationResult = Result<(), String>; fn check_required_keys(config: Value) -> ValidationResult { @@ -45,6 +47,26 @@ fn check_output_files(config: Value) -> ValidationResult { return Ok(()); } +fn check_references(config: Value) -> ValidationResult { + if config.get("references").is_none() { + return Ok(()); + } + let references = config.get("references").unwrap(); + let bibliography = resolve_path(references.get("bibliography").unwrap().as_str().unwrap().into()); + let valid_extensions = vec!["bib", "bibtex", "copac", "json", "yaml", "enl", "xml", "wos", "medline", "mods", "ris"]; + if !bibliography.exists() { + return Err(format!("Can't find bibliography at {}.", bibliography.display())); + } + if !valid_extensions.contains(&bibliography.extension().unwrap().to_str().unwrap()) { + return Err(format!("Bibliography extension must be one of {:?}.", valid_extensions)); + } + let csl = references.get("csl").unwrap().as_str().unwrap(); + if !is_valid_csl(csl.into()) { + return Err(format!("{} isnt a valid CSL config.", csl)); + } + return Ok(()); +} + pub fn unwrap_group(config: Value, funcs: Vec<&Fn(Value) -> ValidationResult>) -> ValidationResult { for func in funcs.iter() { try!(func(config.clone())); @@ -56,6 +78,6 @@ pub fn unwrap_group(config: Value, funcs: Vec<&Fn(Value) -> ValidationResult>) - pub fn validate(config: Value) -> ValidationResult { return unwrap_group( config, - vec![&check_required_keys, &check_config_types, &check_input_files, &check_output_files] + vec![&check_required_keys, &check_config_types, &check_input_files, &check_output_files, &check_references] ); } diff --git a/src/utils.rs b/src/utils.rs index 1a8780a..63b00ee 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,7 +1,7 @@ use std::fmt::Debug; use std::process::exit; use std::io::{self, Write}; -use std::env::current_exe; +use std::env::{current_exe, current_dir}; use std::path::PathBuf; @@ -40,3 +40,8 @@ pub fn get_exe_dir() -> PathBuf { .expect("Failed to get exe directory") .to_path_buf(); } + +pub fn resolve_path(path: String) -> PathBuf { + let base_dir = current_dir().unwrap(); + return base_dir.join(path); +} diff --git a/test-files/bib.yaml b/test-files/bib.yaml new file mode 100644 index 0000000..5ca622d --- /dev/null +++ b/test-files/bib.yaml @@ -0,0 +1,42 @@ +--- +references: +- id: item1 + type: book + author: + - family: Doe + given: John + issued: + - year: '2005' + title: First book + publisher: Cambridge University Press + publisher-place: Cambridge + +- id: item2 + type: article-journal + author: + - family: Doe + given: John + issued: + - year: '2006' + title: Article + container-title: Journal of Generic Studies + page: '33-34' + volume: '6' + +- id: item3 + type: chapter + author: + - family: Doe + given: John + - family: Roe + given: Jenny + editor: + - family: Smith + given: Sam + issued: + - year: '2007' + title: Why water is wet + container-title: Third book + publisher: Oxford University Press + publisher-place: Oxford +... diff --git a/test-files/mdp.yml b/test-files/mdp.yml index 689d43d..819b5f6 100644 --- a/test-files/mdp.yml +++ b/test-files/mdp.yml @@ -8,3 +8,6 @@ input: output: pdf: output.pdf title: test title +references: + bibliography: bib.yaml + csl: apaaaaa