diff --git a/Cargo.toml b/Cargo.toml index 2beec26a..45a6e58b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,7 +39,7 @@ topological-sort = "0.2.2" # Watch feature notify = { version = "6.1.1", optional = true } notify-debouncer-mini = { version = "0.4.1", optional = true } -ignore = { version = "0.4.20", optional = true } +ignore = { version = "0.4.20" } pathdiff = { version = "0.2.1", optional = true } # Serve feature @@ -61,7 +61,7 @@ walkdir = "2.3.3" [features] default = ["watch", "serve", "search"] -watch = ["dep:notify", "dep:notify-debouncer-mini", "dep:ignore", "dep:pathdiff"] +watch = ["dep:notify", "dep:notify-debouncer-mini", "dep:pathdiff"] serve = ["dep:futures-util", "dep:tokio", "dep:warp"] search = ["dep:elasticlunr-rs", "dep:ammonia"] diff --git a/src/renderer/html_handlebars/hbs_renderer.rs b/src/renderer/html_handlebars/hbs_renderer.rs index 30d4c84b..5081ba99 100644 --- a/src/renderer/html_handlebars/hbs_renderer.rs +++ b/src/renderer/html_handlebars/hbs_renderer.rs @@ -14,6 +14,7 @@ use std::path::{Path, PathBuf}; use crate::utils::fs::get_404_output_file; use handlebars::Handlebars; +use ignore::gitignore::GitignoreBuilder; use log::{debug, trace, warn}; use once_cell::sync::Lazy; use regex::{Captures, Regex}; @@ -602,7 +603,23 @@ impl Renderer for HtmlHandlebars { .context("Unable to emit redirects")?; // Copy all remaining files, avoid a recursive copy from/to the book build dir - utils::fs::copy_files_except_ext(&src_dir, destination, true, Some(&build_dir), &["md"])?; + let mut builder = GitignoreBuilder::new(&src_dir); + let mdbook_ignore = src_dir.join(".mdbookignore"); + if mdbook_ignore.exists() { + if let Some(err) = builder.add(mdbook_ignore) { + warn!("Unable to load '.mdbookignore' file: {}", err); + } + } + builder.add_line(None, "*.md")?; + let ignore = builder.build()?; + + utils::fs::copy_files_except_ext( + &src_dir, + destination, + true, + Some(&build_dir), + Some(&ignore), + )?; Ok(()) } diff --git a/src/utils/fs.rs b/src/utils/fs.rs index d0d56760..93299e8c 100644 --- a/src/utils/fs.rs +++ b/src/utils/fs.rs @@ -1,4 +1,5 @@ use crate::errors::*; +use ignore::gitignore::Gitignore; use log::{debug, trace}; use std::fs::{self, File}; use std::io::Write; @@ -92,13 +93,13 @@ pub fn copy_files_except_ext( to: &Path, recursive: bool, avoid_dir: Option<&PathBuf>, - ext_blacklist: &[&str], + ignore: Option<&Gitignore>, ) -> Result<()> { debug!( "Copying all files from {} to {} (blacklist: {:?}), avoiding {:?}", from.display(), to.display(), - ext_blacklist, + ignore, avoid_dir ); @@ -126,6 +127,13 @@ pub fn copy_files_except_ext( } } + if let Some(ignore) = ignore { + let path = entry.path(); + if ignore.matched(&path, path.is_dir()).is_ignore() { + continue; + } + } + // check if output dir already exists if !to.join(entry.file_name()).exists() { fs::create_dir(&to.join(entry.file_name()))?; @@ -136,15 +144,17 @@ pub fn copy_files_except_ext( &to.join(entry.file_name()), true, avoid_dir, - ext_blacklist, + ignore, )?; } else if metadata.is_file() { // Check if it is in the blacklist - if let Some(ext) = entry.path().extension() { - if ext_blacklist.contains(&ext.to_str().unwrap()) { + if let Some(ignore) = ignore { + let path = entry.path(); + if ignore.matched(&path, path.is_dir()).is_ignore() { continue; } } + debug!( "creating path for file: {:?}", &to.join( @@ -245,6 +255,7 @@ pub fn get_404_output_file(input_404: &Option) -> String { #[cfg(test)] mod tests { use super::copy_files_except_ext; + use ignore::gitignore::GitignoreBuilder; use std::{fs, io::Result, path::Path}; #[cfg(target_os = "windows")] @@ -298,9 +309,19 @@ mod tests { panic!("Could not create output/sub_dir_exists: {}", err); } - if let Err(e) = - copy_files_except_ext(tmp.path(), &tmp.path().join("output"), true, None, &["md"]) - { + let ignore = GitignoreBuilder::new(tmp.path()) + .add_line(None, "*.md") + .expect("Unable to add '*.md' to gitignore builder") + .build() + .expect("Unable to build gitignore"); + + if let Err(e) = copy_files_except_ext( + tmp.path(), + &tmp.path().join("output"), + true, + None, + Some(&ignore), + ) { panic!("Error while executing the function:\n{:?}", e); }