Merge pull request #2229 from leonzchang/fix/normalize-path
Fix `mdbook serve` unexpected panic
This commit is contained in:
commit
8d4193fb46
|
@ -980,6 +980,7 @@ dependencies = [
|
||||||
"notify-debouncer-mini",
|
"notify-debouncer-mini",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"opener",
|
"opener",
|
||||||
|
"pathdiff",
|
||||||
"predicates",
|
"predicates",
|
||||||
"pretty_assertions",
|
"pretty_assertions",
|
||||||
"pulldown-cmark",
|
"pulldown-cmark",
|
||||||
|
@ -1159,6 +1160,12 @@ dependencies = [
|
||||||
"windows-targets",
|
"windows-targets",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pathdiff"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "percent-encoding"
|
name = "percent-encoding"
|
||||||
version = "2.3.0"
|
version = "2.3.0"
|
||||||
|
|
|
@ -28,6 +28,7 @@ log = "0.4.17"
|
||||||
memchr = "2.5.0"
|
memchr = "2.5.0"
|
||||||
opener = "0.6.1"
|
opener = "0.6.1"
|
||||||
pulldown-cmark = { version = "0.9.3", default-features = false }
|
pulldown-cmark = { version = "0.9.3", default-features = false }
|
||||||
|
pathdiff = "0.2.1"
|
||||||
regex = "1.8.1"
|
regex = "1.8.1"
|
||||||
serde = { version = "1.0.163", features = ["derive"] }
|
serde = { version = "1.0.163", features = ["derive"] }
|
||||||
serde_json = "1.0.96"
|
serde_json = "1.0.96"
|
||||||
|
|
|
@ -4,6 +4,7 @@ use ignore::gitignore::Gitignore;
|
||||||
use mdbook::errors::Result;
|
use mdbook::errors::Result;
|
||||||
use mdbook::utils;
|
use mdbook::utils;
|
||||||
use mdbook::MDBook;
|
use mdbook::MDBook;
|
||||||
|
use pathdiff::diff_paths;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::mpsc::channel;
|
use std::sync::mpsc::channel;
|
||||||
use std::thread::sleep;
|
use std::thread::sleep;
|
||||||
|
@ -86,12 +87,21 @@ fn find_gitignore(book_root: &Path) -> Option<PathBuf> {
|
||||||
.find(|p| p.exists())
|
.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> {
|
fn filter_ignored_files(ignore: Gitignore, paths: &[PathBuf]) -> Vec<PathBuf> {
|
||||||
|
let ignore_root = ignore
|
||||||
|
.path()
|
||||||
|
.canonicalize()
|
||||||
|
.expect("ignore root canonicalize error");
|
||||||
|
|
||||||
paths
|
paths
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|path| {
|
.filter(|path| {
|
||||||
|
let relative_path =
|
||||||
|
diff_paths(&path, &ignore_root).expect("One of the paths should be an absolute");
|
||||||
!ignore
|
!ignore
|
||||||
.matched_path_or_any_parents(path, path.is_dir())
|
.matched_path_or_any_parents(&relative_path, relative_path.is_dir())
|
||||||
.is_ignore()
|
.is_ignore()
|
||||||
})
|
})
|
||||||
.map(|path| path.to_path_buf())
|
.map(|path| path.to_path_buf())
|
||||||
|
@ -176,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(¤t_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(¤t_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])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue