perf: short circuit remapping detection on recursive symlink (#1225)
This commit is contained in:
parent
a656830790
commit
bc958792af
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::utils;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
collections::{hash_map::Entry, HashMap},
|
collections::{hash_map::Entry, HashMap},
|
||||||
|
@ -172,13 +173,15 @@ impl Remapping {
|
||||||
|
|
||||||
let dir = dir.as_ref();
|
let dir = dir.as_ref();
|
||||||
let is_inside_node_modules = dir.ends_with("node_modules");
|
let is_inside_node_modules = dir.ends_with("node_modules");
|
||||||
|
|
||||||
// iterate over all dirs that are children of the root
|
// iterate over all dirs that are children of the root
|
||||||
for dir in walkdir::WalkDir::new(dir)
|
for dir in walkdir::WalkDir::new(dir)
|
||||||
.follow_links(true)
|
.follow_links(true)
|
||||||
.min_depth(1)
|
.min_depth(1)
|
||||||
.max_depth(1)
|
.max_depth(1)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(std::result::Result::ok)
|
.filter_entry(|e| !is_hidden(e))
|
||||||
|
.filter_map(Result::ok)
|
||||||
.filter(|e| e.file_type().is_dir())
|
.filter(|e| e.file_type().is_dir())
|
||||||
{
|
{
|
||||||
let depth1_dir = dir.path();
|
let depth1_dir = dir.path();
|
||||||
|
@ -487,6 +490,11 @@ fn is_lib_dir(dir: &Path) -> bool {
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if the file is _hidden_
|
||||||
|
fn is_hidden(entry: &walkdir::DirEntry) -> bool {
|
||||||
|
entry.file_name().to_str().map(|s| s.starts_with('.')).unwrap_or(false)
|
||||||
|
}
|
||||||
|
|
||||||
/// Finds all remappings in the directory recursively
|
/// Finds all remappings in the directory recursively
|
||||||
fn find_remapping_candidates(
|
fn find_remapping_candidates(
|
||||||
current_dir: &Path,
|
current_dir: &Path,
|
||||||
|
@ -506,8 +514,8 @@ fn find_remapping_candidates(
|
||||||
.min_depth(1)
|
.min_depth(1)
|
||||||
.max_depth(1)
|
.max_depth(1)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(std::result::Result::ok)
|
.filter_entry(|e| !is_hidden(e))
|
||||||
.filter(|entry| !entry.file_name().to_str().map(|s| s.starts_with('.')).unwrap_or(false))
|
.filter_map(Result::ok)
|
||||||
{
|
{
|
||||||
let entry: walkdir::DirEntry = entry;
|
let entry: walkdir::DirEntry = entry;
|
||||||
|
|
||||||
|
@ -518,6 +526,26 @@ fn find_remapping_candidates(
|
||||||
{
|
{
|
||||||
is_candidate = true;
|
is_candidate = true;
|
||||||
} else if entry.file_type().is_dir() {
|
} else if entry.file_type().is_dir() {
|
||||||
|
// if the dir is a symlink to a parent dir we short circuit here
|
||||||
|
// `walkdir` will catch symlink loops, but this check prevents that we end up scanning a
|
||||||
|
// workspace like
|
||||||
|
// ```text
|
||||||
|
// my-package/node_modules
|
||||||
|
// ├── dep/node_modules
|
||||||
|
// ├── symlink to `my-package`
|
||||||
|
// ```
|
||||||
|
if entry.path_is_symlink() {
|
||||||
|
if let Ok(target) = utils::canonicalize(entry.path()) {
|
||||||
|
// the symlink points to a parent dir of the current window
|
||||||
|
if open.components().count() > target.components().count() &&
|
||||||
|
utils::common_ancestor(open, &target).is_some()
|
||||||
|
{
|
||||||
|
// short-circuiting
|
||||||
|
return Vec::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let subdir = entry.path();
|
let subdir = entry.path();
|
||||||
// we skip commonly used subdirs that should not be searched for recursively
|
// we skip commonly used subdirs that should not be searched for recursively
|
||||||
if !(subdir.ends_with("tests") || subdir.ends_with("test") || subdir.ends_with("demo"))
|
if !(subdir.ends_with("tests") || subdir.ends_with("test") || subdir.ends_with("demo"))
|
||||||
|
|
Loading…
Reference in New Issue