From b8b12d4fe5bae40e52cde7cb7f51ae2ffd003dc4 Mon Sep 17 00:00:00 2001 From: Kim Hermansson Date: Wed, 2 Oct 2019 20:46:18 +0200 Subject: [PATCH 1/3] Added support for gitignore files. The watch command will now ignore files based on gitignore. This can be useful for when your editor creates cache or swap files. --- .gitignore | 2 ++ Cargo.lock | 16 ++++++++++++++++ Cargo.toml | 3 ++- src/cmd/watch.rs | 40 +++++++++++++++++++++++++++++++++++++--- src/utils/mod.rs | 10 ++-------- 5 files changed, 59 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 1bf91cda47..3a85a380a7 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,5 @@ book-example/book .vscode tests/dummy_book/book/ +# Ignore Jetbrains specific files. +.idea/ diff --git a/Cargo.lock b/Cargo.lock index 76bae9838e..82be48cce1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -385,6 +385,19 @@ dependencies = [ "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "gitignore" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "glob" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "handlebars" version = "2.0.2" @@ -659,6 +672,7 @@ dependencies = [ "elasticlunr-rs 2.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gitignore 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "handlebars 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "iron 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1703,6 +1717,8 @@ dependencies = [ "checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" "checksum getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" "checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" +"checksum gitignore 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f5beed3b526478bebc1dd164b7aa770ae709f918a7b978fcb4afdaf3bbee8dfd" +"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum handlebars 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "91ef1ac30f2eaaa2b835fce73c57091cb6b9fc62b7eef285efbf980b0f20001b" "checksum hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e1de41fb8dba9714efd92241565cdff73f78508c95697dd56787d3cba27e2353" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" diff --git a/Cargo.toml b/Cargo.toml index 974fa90f42..5690cacbaa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,6 +38,7 @@ toml-query = "0.9" # Watch feature notify = { version = "4.0", optional = true } +gitignore = { version = "1.0", optional = true } # Serve feature iron = { version = "0.6", optional = true } @@ -57,7 +58,7 @@ walkdir = "2.0" default = ["output", "watch", "serve", "search"] debug = [] output = [] -watch = ["notify"] +watch = ["notify", "gitignore"] serve = ["iron", "staticfile", "ws"] search = ["elasticlunr-rs", "ammonia"] diff --git a/src/cmd/watch.rs b/src/cmd/watch.rs index bf903f90a7..eab099909d 100644 --- a/src/cmd/watch.rs +++ b/src/cmd/watch.rs @@ -48,10 +48,38 @@ pub fn execute(args: &ArgMatches) -> Result<()> { Ok(()) } +fn remove_ignored_files<'a, 'b>(book_root: &'a PathBuf, paths: &'b [PathBuf]) -> Vec<&'b PathBuf> { + let gitignore_path = book_root.with_file_name(".gitignore"); + + match gitignore::File::new(gitignore_path.as_path()) { + Ok(exclusion_checker) => paths + .iter() + .filter(|path| match exclusion_checker.is_excluded(path) { + Ok(exclude) => !exclude, + Err(error) => { + warn!( + "Unable to determine if {:?} is excluded: {:?}. Including it.", + &path, error + ); + true + } + }) + .collect(), + Err(error) => { + warn!( + "Unable to read gitignore file at {:?} file: {:?}. All files will be allowed.", + gitignore_path, + error + ); + paths.iter().collect() + } + } +} + /// Calls the closure when a book source file is changed, blocking indefinitely. pub fn trigger_on_change(book: &MDBook, closure: F) where - F: Fn(Vec, &Path), + F: Fn(Vec<&PathBuf>, &Path), { use notify::DebouncedEvent::*; use notify::RecursiveMode::*; @@ -96,8 +124,14 @@ where _ => None, } }) - .collect(); + .collect::>(); - closure(paths, &book.root); + if !paths.is_empty() { + let paths = remove_ignored_files(&book.root, &paths[..]); + + if !paths.is_empty() { + closure(paths, &book.root); + } + } } } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 36764b35f8..9542edb330 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -448,18 +448,12 @@ more text with spaces #[test] fn it_converts_single_quotes() { - assert_eq!( - convert_quotes_to_curly("'one', 'two'"), - "‘one’, ‘two’" - ); + assert_eq!(convert_quotes_to_curly("'one', 'two'"), "‘one’, ‘two’"); } #[test] fn it_converts_double_quotes() { - assert_eq!( - convert_quotes_to_curly(r#""one", "two""#), - "“one”, “two”" - ); + assert_eq!(convert_quotes_to_curly(r#""one", "two""#), "“one”, “two”"); } #[test] From c2f48f592c6cf554fc6541cc213cb8f1275da220 Mon Sep 17 00:00:00 2001 From: Kim Hermansson Date: Wed, 2 Oct 2019 21:08:17 +0200 Subject: [PATCH 2/3] Ran cargo fmt. --- src/cmd/watch.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cmd/watch.rs b/src/cmd/watch.rs index eab099909d..d00e5b87e5 100644 --- a/src/cmd/watch.rs +++ b/src/cmd/watch.rs @@ -68,8 +68,7 @@ fn remove_ignored_files<'a, 'b>(book_root: &'a PathBuf, paths: &'b [PathBuf]) -> Err(error) => { warn!( "Unable to read gitignore file at {:?} file: {:?}. All files will be allowed.", - gitignore_path, - error + gitignore_path, error ); paths.iter().collect() } From 0a7a7f854a9a1eb9f8971b5288ca4949c4d5da73 Mon Sep 17 00:00:00 2001 From: Kim Hermansson Date: Thu, 3 Oct 2019 08:16:05 +0200 Subject: [PATCH 3/3] Made the code a bit tidier based on input from other Rust programmers. Changed the type of the closure back to use PathBuf, not &PathBuf. Reduced nesting. --- src/cmd/watch.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/cmd/watch.rs b/src/cmd/watch.rs index d00e5b87e5..fe1f188c5c 100644 --- a/src/cmd/watch.rs +++ b/src/cmd/watch.rs @@ -48,7 +48,11 @@ pub fn execute(args: &ArgMatches) -> Result<()> { Ok(()) } -fn remove_ignored_files<'a, 'b>(book_root: &'a PathBuf, paths: &'b [PathBuf]) -> Vec<&'b PathBuf> { +fn remove_ignored_files(book_root: &PathBuf, paths: &[PathBuf]) -> Vec { + if paths.is_empty() { + return vec![]; + } + let gitignore_path = book_root.with_file_name(".gitignore"); match gitignore::File::new(gitignore_path.as_path()) { @@ -64,13 +68,14 @@ fn remove_ignored_files<'a, 'b>(book_root: &'a PathBuf, paths: &'b [PathBuf]) -> true } }) + .map(|path| path.to_path_buf()) .collect(), Err(error) => { warn!( "Unable to read gitignore file at {:?} file: {:?}. All files will be allowed.", gitignore_path, error ); - paths.iter().collect() + paths.iter().map(|path| path.to_path_buf()).collect() } } } @@ -78,7 +83,7 @@ fn remove_ignored_files<'a, 'b>(book_root: &'a PathBuf, paths: &'b [PathBuf]) -> /// Calls the closure when a book source file is changed, blocking indefinitely. pub fn trigger_on_change(book: &MDBook, closure: F) where - F: Fn(Vec<&PathBuf>, &Path), + F: Fn(Vec, &Path), { use notify::DebouncedEvent::*; use notify::RecursiveMode::*; @@ -125,12 +130,10 @@ where }) .collect::>(); - if !paths.is_empty() { - let paths = remove_ignored_files(&book.root, &paths[..]); + let paths = remove_ignored_files(&book.root, &paths[..]); - if !paths.is_empty() { - closure(paths, &book.root); - } + if !paths.is_empty() { + closure(paths, &book.root); } } }