diff --git a/src/book/book.rs b/src/book/book.rs index 61e89909..09914271 100644 --- a/src/book/book.rs +++ b/src/book/book.rs @@ -2,14 +2,14 @@ use std::fmt::{self, Display, Formatter}; use std::path::{Path, PathBuf}; use std::collections::VecDeque; use std::fs::File; -use std::io::Read; +use std::io::{Read, Write}; use super::summary::{parse_summary, Summary, Link, SummaryItem, SectionNumber}; use errors::*; /// Load a book into memory from its `src/` directory. -pub fn load_book>(src_dir: P) -> Result { +pub fn load_book>(src_dir: P, create_if_not_present: bool) -> Result { let src_dir = src_dir.as_ref(); let summary_md = src_dir.join("SUMMARY.md"); @@ -18,11 +18,9 @@ pub fn load_book>(src_dir: P) -> Result { .chain_err(|| "Couldn't open SUMMARY.md")? .read_to_string(&mut summary_content)?; - let summary = parse_summary(&summary_content).chain_err( - || "Summary parsing failed", - )?; + let summary = parse_summary(&summary_content).chain_err(|| "Summary parsing failed")?; - load_book_from_disk(&summary, src_dir) + load_book_from_disk(&summary, src_dir, create_if_not_present) } @@ -88,7 +86,7 @@ impl Chapter { /// /// You need to pass in the book's source directory because all the links in /// `SUMMARY.md` give the chapter locations relative to it. -fn load_book_from_disk>(summary: &Summary, src_dir: P) -> Result { +fn load_book_from_disk>(summary: &Summary, src_dir: P, create_if_not_present: bool) -> Result { debug!("[*] Loading the book from disk"); let src_dir = src_dir.as_ref(); @@ -98,18 +96,29 @@ fn load_book_from_disk>(summary: &Summary, src_dir: P) -> Result< let summary_items = prefix.chain(numbered).chain(suffix); - let chapters = summary_items - .map(|i| load_summary_item(i, src_dir)) - .collect::>() - .chain_err(|| "Couldn't load chapters from disk")?; + let mut chapters = Vec::new(); + + for summary_item in summary_items { + let chapter = load_summary_item(summary_item, src_dir, create_if_not_present)?; + chapters.push(chapter); + } Ok(Book { sections: chapters }) } -fn load_summary_item>(item: &SummaryItem, src_dir: P) -> Result { +fn load_summary_item>(item: &SummaryItem, src_dir: P, create_if_not_present: bool) -> Result { match *item { SummaryItem::Separator => Ok(BookItem::Separator), - SummaryItem::Link(ref link) => load_chapter(link, src_dir).map(|c| BookItem::Chapter(c)), + SummaryItem::Link(ref link) => { + let file = src_dir.as_ref().join(&link.location); + + if create_if_not_present && !file.exists() { + let text = format!("# {}", link.name); + File::create(&file)?.write_all(text.as_bytes())?; + } + + load_chapter(link, src_dir).map(|c| BookItem::Chapter(c)) + }, } } @@ -137,7 +146,7 @@ fn load_chapter>(link: &Link, src_dir: P) -> Result { let sub_items = link.nested_items .iter() - .map(|i| load_summary_item(i, src_dir)) + .map(|i| load_summary_item(i, src_dir, false)) .collect::>>()?; ch.sub_items = sub_items; @@ -190,6 +199,7 @@ mod tests { use super::*; use tempdir::TempDir; use std::io::Write; + use std::fs; const DUMMY_SRC: &'static str = " # Dummy Chapter @@ -276,7 +286,7 @@ And here is some more text. ], }); - let got = load_summary_item(&SummaryItem::Link(root), temp.path()).unwrap(); + let got = load_summary_item(&SummaryItem::Link(root), temp.path(), false).unwrap(); assert_eq!(got, should_be); } @@ -298,7 +308,7 @@ And here is some more text. ], }; - let got = load_book_from_disk(&summary, temp.path()).unwrap(); + let got = load_book_from_disk(&summary, temp.path(), false).unwrap(); assert_eq!(got, should_be); } @@ -362,4 +372,21 @@ And here is some more text. assert_eq!(chapter_names, should_be); } -} \ No newline at end of file + + #[test] + fn create_missing_book_items() { + let (link, temp) = dummy_link(); + let summary = Summary { + numbered_chapters: vec![SummaryItem::Link(link)], + ..Default::default() + }; + + let chapter_1 = temp.path().join("chapter_1.md"); + fs::remove_file(&chapter_1).unwrap(); + assert!(!chapter_1.exists()); + + load_book_from_disk(&summary, temp.path(), true).unwrap(); + + assert!(chapter_1.exists()); + } +} diff --git a/src/book/mod.rs b/src/book/mod.rs index b78fc263..60b583dd 100644 --- a/src/book/mod.rs +++ b/src/book/mod.rs @@ -495,7 +495,7 @@ impl MDBook { // Construct book fn parse_summary(&mut self) -> Result<()> { let src = self.config.get_source(); - let book = load_book(&src)?; + let book = load_book(&src, self.create_missing)?; self.content = Some(book); Ok(()) diff --git a/tests/loading.rs b/tests/loading.rs index 356c7e81..beaa2197 100644 --- a/tests/loading.rs +++ b/tests/loading.rs @@ -16,6 +16,6 @@ fn load_the_example_book() { .join("book-example") .join("src"); - let book = load_book(example_src_dir).unwrap(); + let book = load_book(example_src_dir, false).unwrap(); println!("{:#?}", book); }