summaryrefslogtreecommitdiffstats
path: root/vendor/mdbook/src/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/mdbook/src/cmd')
-rw-r--r--vendor/mdbook/src/cmd/watch.rs73
1 files changed, 63 insertions, 10 deletions
diff --git a/vendor/mdbook/src/cmd/watch.rs b/vendor/mdbook/src/cmd/watch.rs
index e9806e1cd..80b9ff1b1 100644
--- a/vendor/mdbook/src/cmd/watch.rs
+++ b/vendor/mdbook/src/cmd/watch.rs
@@ -4,6 +4,7 @@ use ignore::gitignore::Gitignore;
use mdbook::errors::Result;
use mdbook::utils;
use mdbook::MDBook;
+use pathdiff::diff_paths;
use std::path::{Path, PathBuf};
use std::sync::mpsc::channel;
use std::thread::sleep;
@@ -86,12 +87,21 @@ fn find_gitignore(book_root: &Path) -> Option<PathBuf> {
.find(|p| p.exists())
}
+// Note: The usage of `canonicalize` may encounter occasional failures on the Windows platform, presenting a potential risk.
+// For more details, refer to [Pull Request #2229](https://github.com/rust-lang/mdBook/pull/2229#discussion_r1408665981).
fn filter_ignored_files(ignore: Gitignore, paths: &[PathBuf]) -> Vec<PathBuf> {
+ let ignore_root = ignore
+ .path()
+ .canonicalize()
+ .expect("ignore root canonicalize error");
+
paths
.iter()
.filter(|path| {
+ let relative_path =
+ diff_paths(&path, &ignore_root).expect("One of the paths should be an absolute");
!ignore
- .matched_path_or_any_parents(path, path.is_dir())
+ .matched_path_or_any_parents(&relative_path, relative_path.is_dir())
.is_ignore()
})
.map(|path| path.to_path_buf())
@@ -108,8 +118,7 @@ where
// Create a channel to receive the events.
let (tx, rx) = channel();
- let mut debouncer = match notify_debouncer_mini::new_debouncer(Duration::from_secs(1), None, tx)
- {
+ let mut debouncer = match notify_debouncer_mini::new_debouncer(Duration::from_secs(1), tx) {
Ok(d) => d,
Err(e) => {
error!("Error while trying to watch the files:\n\n\t{:?}", e);
@@ -130,11 +139,16 @@ where
let _ = watcher.watch(&book.root.join("book.toml"), NonRecursive);
for dir in &book.config.build.extra_watch_dirs {
- let path = dir.canonicalize().unwrap();
- if let Err(e) = watcher.watch(&path, Recursive) {
+ let path = book.root.join(dir);
+ let canonical_path = path.canonicalize().unwrap_or_else(|e| {
+ error!("Error while watching extra directory {path:?}:\n {e}");
+ std::process::exit(1);
+ });
+
+ if let Err(e) = watcher.watch(&canonical_path, Recursive) {
error!(
"Error while watching extra directory {:?}:\n {:?}",
- path, e
+ canonical_path, e
);
std::process::exit(1);
}
@@ -152,10 +166,8 @@ where
let paths: Vec<_> = all_events
.filter_map(|event| match event {
Ok(events) => Some(events),
- Err(errors) => {
- for error in errors {
- log::warn!("error while watching for changes: {error}");
- }
+ Err(error) => {
+ log::warn!("error while watching for changes: {error}");
None
}
})
@@ -174,3 +186,44 @@ where
}
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use ignore::gitignore::GitignoreBuilder;
+ use std::env;
+
+ #[test]
+ fn test_filter_ignored_files() {
+ let current_dir = env::current_dir().unwrap();
+
+ let ignore = GitignoreBuilder::new(&current_dir)
+ .add_line(None, "*.html")
+ .unwrap()
+ .build()
+ .unwrap();
+ let should_remain = current_dir.join("record.text");
+ let should_filter = current_dir.join("index.html");
+
+ let remain = filter_ignored_files(ignore, &[should_remain.clone(), should_filter]);
+ assert_eq!(remain, vec![should_remain])
+ }
+
+ #[test]
+ fn filter_ignored_files_should_handle_parent_dir() {
+ let current_dir = env::current_dir().unwrap();
+
+ let ignore = GitignoreBuilder::new(&current_dir)
+ .add_line(None, "*.html")
+ .unwrap()
+ .build()
+ .unwrap();
+
+ let parent_dir = current_dir.join("..");
+ let should_remain = parent_dir.join("record.text");
+ let should_filter = parent_dir.join("index.html");
+
+ let remain = filter_ignored_files(ignore, &[should_remain.clone(), should_filter]);
+ assert_eq!(remain, vec![should_remain])
+ }
+}