mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-10-23 05:51:39 +00:00
Remove canonicalization functionality from VFS and related components
- Eliminated the `canonicalize` method from the `VfsBackend` trait and its implementations in `InMemoryFs`, `NoopBackend`, and `StdBackend`, simplifying the interface and reducing complexity. - Updated various parts of the codebase to remove references to canonicalization, including tests and prefetch cache handling, ensuring consistency across the project. - Adjusted logging and comments to reflect the removal of path normalization logic, enhancing clarity and maintainability. These changes aim to streamline the VFS implementation by focusing on core functionalities without the overhead of path canonicalization.
This commit is contained in:
parent
65f10f111c
commit
fc8a6e9b9c
21 changed files with 123 additions and 440 deletions
|
|
@ -99,11 +99,6 @@ impl ChangeProcessor {
|
|||
// (non-serve commands). never() blocks forever without selecting.
|
||||
let critical_error_receiver =
|
||||
critical_error_receiver.unwrap_or_else(crossbeam_channel::never);
|
||||
// Canonicalize project_root so path comparisons work with the
|
||||
// \\?\ prefix that std::fs::canonicalize adds on Windows.
|
||||
let project_root = std::fs::canonicalize(&project_root).unwrap_or(project_root);
|
||||
let project_file_path =
|
||||
std::fs::canonicalize(&project_file_path).unwrap_or(project_file_path);
|
||||
let task = JobThreadContext {
|
||||
tree,
|
||||
vfs,
|
||||
|
|
@ -306,23 +301,8 @@ impl JobThreadContext {
|
|||
None
|
||||
}
|
||||
|
||||
/// Canonicalize a path for use as a suppression map key.
|
||||
fn suppression_key(path: &Path) -> PathBuf {
|
||||
if let Ok(canonical) = std::fs::canonicalize(path) {
|
||||
canonical
|
||||
} else if let Some(parent) = path.parent() {
|
||||
if let Ok(canonical_parent) = std::fs::canonicalize(parent) {
|
||||
if let Some(file_name) = path.file_name() {
|
||||
canonical_parent.join(file_name)
|
||||
} else {
|
||||
path.to_path_buf()
|
||||
}
|
||||
} else {
|
||||
path.to_path_buf()
|
||||
}
|
||||
} else {
|
||||
path.to_path_buf()
|
||||
}
|
||||
path.to_path_buf()
|
||||
}
|
||||
|
||||
/// Suppress the next Create/Write VFS event for the given path.
|
||||
|
|
@ -686,49 +666,33 @@ impl JobThreadContext {
|
|||
_ => None,
|
||||
};
|
||||
if let Some(ref path) = event_path {
|
||||
let canonical = std::fs::canonicalize(path).ok();
|
||||
let mut suppressed = self.suppressed_paths.lock().unwrap();
|
||||
// Determine which key matches: try canonical first (most likely
|
||||
// to match what suppress_path stored), then fall back to raw.
|
||||
let matched_key = canonical
|
||||
.as_ref()
|
||||
.filter(|c| suppressed.contains_key(c.as_path()))
|
||||
.cloned()
|
||||
.or_else(|| {
|
||||
if suppressed.contains_key(path) {
|
||||
Some(path.clone())
|
||||
} else {
|
||||
None
|
||||
let key = path.clone();
|
||||
if let Some(counts) = suppressed.get_mut(key.as_path()) {
|
||||
let should_suppress = match &event {
|
||||
VfsEvent::Remove(_) if counts.0 > 0 => {
|
||||
counts.0 -= 1;
|
||||
true
|
||||
}
|
||||
});
|
||||
if let Some(key) = matched_key {
|
||||
if let Some(counts) = suppressed.get_mut(&key) {
|
||||
let should_suppress = match &event {
|
||||
VfsEvent::Remove(_) if counts.0 > 0 => {
|
||||
counts.0 -= 1;
|
||||
true
|
||||
}
|
||||
VfsEvent::Create(_) | VfsEvent::Write(_) if counts.1 > 0 => {
|
||||
counts.1 -= 1;
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
if counts.0 == 0 && counts.1 == 0 {
|
||||
suppressed.remove(&key);
|
||||
}
|
||||
if should_suppress {
|
||||
drop(suppressed);
|
||||
// Still commit so VFS stays consistent, but skip patching.
|
||||
self.vfs
|
||||
.commit_event(&event)
|
||||
.expect("Error applying VFS change");
|
||||
log::info!(
|
||||
"VFS event SUPPRESSED (API syncback echo): {}",
|
||||
self.display_path(path)
|
||||
);
|
||||
return Vec::new();
|
||||
VfsEvent::Create(_) | VfsEvent::Write(_) if counts.1 > 0 => {
|
||||
counts.1 -= 1;
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
if counts.0 == 0 && counts.1 == 0 {
|
||||
suppressed.remove(&key);
|
||||
}
|
||||
if should_suppress {
|
||||
drop(suppressed);
|
||||
self.vfs
|
||||
.commit_event(&event)
|
||||
.expect("Error applying VFS change");
|
||||
log::info!(
|
||||
"VFS event SUPPRESSED (API syncback echo): {}",
|
||||
self.display_path(path)
|
||||
);
|
||||
return Vec::new();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -763,107 +727,81 @@ impl JobThreadContext {
|
|||
// of the tree. Calculate and apply all of these changes.
|
||||
let applied_patches = match event {
|
||||
VfsEvent::Create(path) | VfsEvent::Write(path) => {
|
||||
match self.vfs.canonicalize(&path) {
|
||||
Ok(canonical_path) => {
|
||||
log::info!(
|
||||
"VFS: canonicalize OK for {} -> {}",
|
||||
self.display_path(&path),
|
||||
self.display_path(&canonical_path)
|
||||
);
|
||||
self.apply_patches(canonical_path)
|
||||
}
|
||||
Err(_) => {
|
||||
// The path doesn't exist on disk. Two possible causes:
|
||||
//
|
||||
// 1. Phantom event from a rename we performed — macOS FSEvents
|
||||
// can deliver a stale CREATE for the old path. If a pending
|
||||
// suppression exists for this path, consume it and skip.
|
||||
//
|
||||
// 2. The file was deleted between the event firing and us
|
||||
// processing it. Fall back to parent-directory canonicalize
|
||||
// (same strategy as the Remove handler) so the tree can
|
||||
// reconcile the disappearance.
|
||||
let consumed = {
|
||||
let key = Self::suppression_key(&path);
|
||||
let mut suppressed = self.suppressed_paths.lock().unwrap();
|
||||
if let Some(counts) = suppressed.get_mut(&key) {
|
||||
if counts.0 > 0 || counts.1 > 0 {
|
||||
// Drain whichever counter is available
|
||||
if counts.1 > 0 {
|
||||
counts.1 -= 1;
|
||||
} else {
|
||||
counts.0 -= 1;
|
||||
}
|
||||
if counts.0 == 0 && counts.1 == 0 {
|
||||
suppressed.remove(&key);
|
||||
}
|
||||
true
|
||||
if path.exists() {
|
||||
self.apply_patches(path)
|
||||
} else {
|
||||
// The path doesn't exist on disk. Two possible causes:
|
||||
//
|
||||
// 1. Phantom event from a rename we performed — macOS FSEvents
|
||||
// can deliver a stale CREATE for the old path. If a pending
|
||||
// suppression exists for this path, consume it and skip.
|
||||
//
|
||||
// 2. The file was deleted between the event firing and us
|
||||
// processing it. Fall back to parent directory so the tree
|
||||
// can reconcile the disappearance.
|
||||
let consumed = {
|
||||
let key = Self::suppression_key(&path);
|
||||
let mut suppressed = self.suppressed_paths.lock().unwrap();
|
||||
if let Some(counts) = suppressed.get_mut(&key) {
|
||||
if counts.0 > 0 || counts.1 > 0 {
|
||||
if counts.1 > 0 {
|
||||
counts.1 -= 1;
|
||||
} else {
|
||||
false
|
||||
counts.0 -= 1;
|
||||
}
|
||||
if counts.0 == 0 && counts.1 == 0 {
|
||||
suppressed.remove(&key);
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
};
|
||||
} else {
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
if consumed {
|
||||
if consumed {
|
||||
log::info!(
|
||||
"VFS: phantom Create/Write for non-existent {} — \
|
||||
consumed pending suppression (likely stale rename event)",
|
||||
self.display_path(&path)
|
||||
);
|
||||
Vec::new()
|
||||
} else {
|
||||
let parent = path.parent().unwrap();
|
||||
let file_name = path.file_name().unwrap();
|
||||
if parent.exists() {
|
||||
let resolved = parent.join(file_name);
|
||||
log::info!(
|
||||
"VFS: phantom Create/Write for non-existent {} — \
|
||||
consumed pending suppression (likely stale rename event)",
|
||||
self.display_path(&path)
|
||||
"VFS: Create/Write for vanished file {} — \
|
||||
resolved via parent to {}",
|
||||
self.display_path(&path),
|
||||
self.display_path(&resolved)
|
||||
);
|
||||
self.apply_patches(resolved)
|
||||
} else {
|
||||
log::info!(
|
||||
"VFS: Skipping Create/Write for {} — \
|
||||
parent no longer exists",
|
||||
self.display_path(&path),
|
||||
);
|
||||
Vec::new()
|
||||
} else {
|
||||
// No suppression — the file genuinely vanished. Use the
|
||||
// parent-directory fallback so the tree can reconcile.
|
||||
let parent = path.parent().unwrap();
|
||||
let file_name = path.file_name().unwrap();
|
||||
match self.vfs.canonicalize(parent) {
|
||||
Ok(parent_normalized) => {
|
||||
let resolved = parent_normalized.join(file_name);
|
||||
log::info!(
|
||||
"VFS: Create/Write for vanished file {} — \
|
||||
resolved via parent to {}",
|
||||
self.display_path(&path),
|
||||
self.display_path(&resolved)
|
||||
);
|
||||
self.apply_patches(resolved)
|
||||
}
|
||||
Err(err) => {
|
||||
log::info!(
|
||||
"VFS: Skipping Create/Write for {} — \
|
||||
parent no longer exists: {}",
|
||||
self.display_path(&path),
|
||||
err
|
||||
);
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
VfsEvent::Remove(path) => {
|
||||
// MemoFS does not track parent removals yet, so we can canonicalize
|
||||
// the parent path safely and then append the removed path's file name.
|
||||
// However, if the parent was also deleted (e.g., when deleting a directory
|
||||
// tree), canonicalize will fail - in that case, just skip this event.
|
||||
let parent = path.parent().unwrap();
|
||||
let file_name = path.file_name().unwrap();
|
||||
match self.vfs.canonicalize(parent) {
|
||||
Ok(parent_normalized) => {
|
||||
let resolved = parent_normalized.join(file_name);
|
||||
log::info!("VFS: Remove resolved to {}", self.display_path(&resolved));
|
||||
self.apply_patches(resolved)
|
||||
}
|
||||
Err(err) => {
|
||||
log::info!(
|
||||
"VFS: Skipping remove event for {} — parent no longer exists: {}",
|
||||
self.display_path(&path),
|
||||
err
|
||||
);
|
||||
Vec::new()
|
||||
}
|
||||
if parent.exists() {
|
||||
log::info!("VFS: Remove for {}", self.display_path(&path));
|
||||
self.apply_patches(path)
|
||||
} else {
|
||||
log::info!(
|
||||
"VFS: Skipping remove event for {} — parent no longer exists",
|
||||
self.display_path(&path),
|
||||
);
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
|
|
|
|||
|
|
@ -263,8 +263,7 @@ pub(crate) fn write_sourcemap(
|
|||
) -> anyhow::Result<()> {
|
||||
let tree = session.tree();
|
||||
|
||||
let canonical_project_dir = std::fs::canonicalize(session.root_dir())
|
||||
.unwrap_or_else(|_| session.root_dir().to_path_buf());
|
||||
let canonical_project_dir = session.root_dir().to_path_buf();
|
||||
|
||||
let root_node = recurse_create_node(
|
||||
&tree,
|
||||
|
|
@ -306,8 +305,7 @@ pub(crate) fn write_sourcemap_from_syncback(
|
|||
project_dir: &Path,
|
||||
output: &Path,
|
||||
) -> anyhow::Result<()> {
|
||||
let canonical_project_dir =
|
||||
std::fs::canonicalize(project_dir).unwrap_or_else(|_| project_dir.to_path_buf());
|
||||
let canonical_project_dir = project_dir.to_path_buf();
|
||||
|
||||
let root_node =
|
||||
recurse_create_node_from_dom(dom, dom.root_ref(), instance_paths, &canonical_project_dir);
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ pub struct ServeSession {
|
|||
}
|
||||
|
||||
/// Collect all filesystem paths reachable from the project tree's `$path`
|
||||
/// entries, then read file contents and compute canonical paths in parallel.
|
||||
/// entries, then read file contents in parallel.
|
||||
fn prefetch_project_files(project: &Project) -> io::Result<PrefetchCache> {
|
||||
use rayon::prelude::*;
|
||||
use std::collections::HashMap;
|
||||
|
|
@ -153,7 +153,6 @@ fn prefetch_project_files(project: &Project) -> io::Result<PrefetchCache> {
|
|||
if roots.is_empty() {
|
||||
return Ok(PrefetchCache {
|
||||
files: HashMap::new(),
|
||||
canonical: HashMap::new(),
|
||||
is_file: HashMap::new(),
|
||||
children: HashMap::new(),
|
||||
});
|
||||
|
|
@ -208,24 +207,11 @@ fn prefetch_project_files(project: &Project) -> io::Result<PrefetchCache> {
|
|||
.collect();
|
||||
|
||||
let read_elapsed = read_start.elapsed();
|
||||
let canon_start = Instant::now();
|
||||
|
||||
let canonical_data: Vec<_> = entries
|
||||
.par_iter()
|
||||
.filter_map(|e| {
|
||||
let path = e.path().to_path_buf();
|
||||
std::fs::canonicalize(&path).ok().map(|c| (path, c))
|
||||
})
|
||||
.collect();
|
||||
|
||||
let canon_elapsed = canon_start.elapsed();
|
||||
|
||||
log::debug!(
|
||||
"Prefetch I/O: read {} files in {:.1?}, canonicalize {} paths in {:.1?}",
|
||||
"Prefetch I/O: read {} files in {:.1?}",
|
||||
file_data.len(),
|
||||
read_elapsed,
|
||||
canonical_data.len(),
|
||||
canon_elapsed,
|
||||
);
|
||||
|
||||
let mut is_file_map: HashMap<std::path::PathBuf, bool> = HashMap::new();
|
||||
|
|
@ -257,7 +243,6 @@ fn prefetch_project_files(project: &Project) -> io::Result<PrefetchCache> {
|
|||
|
||||
Ok(PrefetchCache {
|
||||
files: file_data.into_iter().collect::<HashMap<_, _>>(),
|
||||
canonical: canonical_data.into_iter().collect::<HashMap<_, _>>(),
|
||||
is_file: is_file_map,
|
||||
children: children_map,
|
||||
})
|
||||
|
|
@ -287,9 +272,8 @@ impl ServeSession {
|
|||
match prefetch_project_files(&root_project) {
|
||||
Ok(cache) => {
|
||||
log::debug!(
|
||||
"Prefetch total: {} files + {} canonical paths in {:.1?}",
|
||||
"Prefetch total: {} files in {:.1?}",
|
||||
cache.files.len(),
|
||||
cache.canonical.len(),
|
||||
prefetch_start.elapsed()
|
||||
);
|
||||
vfs.set_prefetch_cache(cache);
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ pub fn snapshot_csv(
|
|||
.metadata(
|
||||
InstanceMetadata::new()
|
||||
.instigating_source(path)
|
||||
.relevant_paths(vec![vfs.canonicalize(path)?]),
|
||||
.relevant_paths(vec![path.to_path_buf()]),
|
||||
);
|
||||
|
||||
AdjacentMetadata::read_and_apply_all(vfs, path, name, &mut snapshot)?;
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ pub fn snapshot_dir_no_meta(
|
|||
children
|
||||
};
|
||||
|
||||
let normalized_path = vfs.canonicalize(path)?;
|
||||
let normalized_path = path.to_path_buf();
|
||||
let relevant_paths = vec![
|
||||
normalized_path.clone(),
|
||||
// TODO: We shouldn't need to know about Lua existing in this
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ pub fn snapshot_json(
|
|||
.metadata(
|
||||
InstanceMetadata::new()
|
||||
.instigating_source(path)
|
||||
.relevant_paths(vec![vfs.canonicalize(path)?])
|
||||
.relevant_paths(vec![path.to_path_buf()])
|
||||
.context(context),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ pub fn snapshot_json_model(
|
|||
snapshot.metadata = snapshot
|
||||
.metadata
|
||||
.instigating_source(path)
|
||||
.relevant_paths(vec![vfs.canonicalize(path)?])
|
||||
.relevant_paths(vec![path.to_path_buf()])
|
||||
.context(context)
|
||||
.specified_id(id)
|
||||
.schema(schema)
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ pub fn snapshot_lua(
|
|||
.metadata(
|
||||
InstanceMetadata::new()
|
||||
.instigating_source(path)
|
||||
.relevant_paths(vec![vfs.canonicalize(path)?])
|
||||
.relevant_paths(vec![path.to_path_buf()])
|
||||
.context(context),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -147,10 +147,7 @@ pub fn snapshot_project(
|
|||
// We SHOULD NOT mark the project file as a relevant path for any
|
||||
// nodes that aren't roots. They'll be updated as part of the project
|
||||
// file being updated.
|
||||
snapshot
|
||||
.metadata
|
||||
.relevant_paths
|
||||
.push(vfs.canonicalize(path)?);
|
||||
snapshot.metadata.relevant_paths.push(path.to_path_buf());
|
||||
|
||||
Ok(Some(snapshot))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ pub fn snapshot_rbxm(
|
|||
.metadata(
|
||||
InstanceMetadata::new()
|
||||
.instigating_source(path)
|
||||
.relevant_paths(vec![vfs.canonicalize(path)?])
|
||||
.relevant_paths(vec![path.to_path_buf()])
|
||||
.context(context),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ pub fn snapshot_rbxmx(
|
|||
.metadata(
|
||||
InstanceMetadata::new()
|
||||
.instigating_source(path)
|
||||
.relevant_paths(vec![vfs.canonicalize(path)?])
|
||||
.relevant_paths(vec![path.to_path_buf()])
|
||||
.context(context),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ pub fn snapshot_toml(
|
|||
.metadata(
|
||||
InstanceMetadata::new()
|
||||
.instigating_source(path)
|
||||
.relevant_paths(vec![vfs.canonicalize(path)?])
|
||||
.relevant_paths(vec![path.to_path_buf()])
|
||||
.context(context),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ pub fn snapshot_txt(
|
|||
.metadata(
|
||||
InstanceMetadata::new()
|
||||
.instigating_source(path)
|
||||
.relevant_paths(vec![vfs.canonicalize(path)?])
|
||||
.relevant_paths(vec![path.to_path_buf()])
|
||||
.context(context),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ pub fn snapshot_yaml(
|
|||
.metadata(
|
||||
InstanceMetadata::new()
|
||||
.instigating_source(path)
|
||||
.relevant_paths(vec![vfs.canonicalize(path)?])
|
||||
.relevant_paths(vec![path.to_path_buf()])
|
||||
.context(context),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -254,15 +254,6 @@ pub fn syncback_loop_with_stats(
|
|||
|
||||
let project_path = project.folder_location();
|
||||
|
||||
fn strip_unc_prefix(p: PathBuf) -> PathBuf {
|
||||
let path_str = p.to_string_lossy();
|
||||
if path_str.starts_with(r"\\?\") || path_str.starts_with("//?/") {
|
||||
PathBuf::from(&path_str[4..])
|
||||
} else {
|
||||
p
|
||||
}
|
||||
}
|
||||
|
||||
let phase_timer = std::time::Instant::now();
|
||||
let existing_paths: HashSet<PathBuf> = if !incremental {
|
||||
let mut paths = HashSet::new();
|
||||
|
|
@ -407,10 +398,7 @@ pub fn syncback_loop_with_stats(
|
|||
continue;
|
||||
}
|
||||
}
|
||||
let canonical_dir = std::fs::canonicalize(dir)
|
||||
.map(strip_unc_prefix)
|
||||
.unwrap_or_else(|_| dir.clone());
|
||||
for entry in walkdir::WalkDir::new(&canonical_dir)
|
||||
for entry in walkdir::WalkDir::new(dir)
|
||||
.follow_links(true)
|
||||
.into_iter()
|
||||
.filter_entry(|e| {
|
||||
|
|
@ -661,14 +649,10 @@ pub fn syncback_loop_with_stats(
|
|||
if !incremental && !existing_paths.is_empty() {
|
||||
log::debug!("Clean mode: checking for orphaned files to remove");
|
||||
|
||||
let canonical_project_path = strip_unc_prefix(
|
||||
std::fs::canonicalize(project_path).unwrap_or_else(|_| project_path.to_path_buf()),
|
||||
);
|
||||
|
||||
let added_paths: HashSet<PathBuf> = fs_snapshot
|
||||
.added_paths()
|
||||
.into_iter()
|
||||
.map(|p| strip_unc_prefix(canonical_project_path.join(p)))
|
||||
.map(|p| project_path.join(p))
|
||||
.collect();
|
||||
|
||||
let mut added_dir_prefixes: HashSet<PathBuf> = HashSet::new();
|
||||
|
|
@ -681,10 +665,7 @@ pub fn syncback_loop_with_stats(
|
|||
}
|
||||
}
|
||||
|
||||
let project_file = strip_unc_prefix(
|
||||
std::fs::canonicalize(&project.file_location)
|
||||
.unwrap_or_else(|_| project.file_location.clone()),
|
||||
);
|
||||
let project_file = project.file_location.clone();
|
||||
|
||||
// Collect ALL paths explicitly referenced via $path in the project.
|
||||
// These paths should NOT be removed during orphan cleanup because they
|
||||
|
|
@ -706,12 +687,9 @@ pub fn syncback_loop_with_stats(
|
|||
) {
|
||||
if let Some(ref path_node) = node.path {
|
||||
let resolved = base_path.join(path_node.path());
|
||||
let canonical = std::fs::canonicalize(&resolved)
|
||||
.map(strip_unc_prefix)
|
||||
.unwrap_or_else(|_| resolved.clone());
|
||||
protected.insert(canonical.clone());
|
||||
protected.insert(resolved.clone());
|
||||
if !instance_path.is_empty() {
|
||||
mappings.push((canonical, instance_path.to_string()));
|
||||
mappings.push((resolved, instance_path.to_string()));
|
||||
}
|
||||
}
|
||||
for (name, child) in &node.children {
|
||||
|
|
@ -881,9 +859,7 @@ pub fn syncback_loop_with_stats(
|
|||
}
|
||||
current_ancestor = Some(old_path);
|
||||
|
||||
let relative_path = old_path
|
||||
.strip_prefix(&canonical_project_path)
|
||||
.unwrap_or(old_path);
|
||||
let relative_path = old_path.strip_prefix(project_path).unwrap_or(old_path);
|
||||
|
||||
log::debug!("Removing orphaned path: {}", relative_path.display());
|
||||
if old_path.is_dir() {
|
||||
|
|
|
|||
|
|
@ -358,23 +358,8 @@ impl ApiService {
|
|||
}
|
||||
}
|
||||
|
||||
/// Canonicalize a path for use as a suppression map key.
|
||||
fn suppression_key(path: &Path) -> PathBuf {
|
||||
if let Ok(canonical) = std::fs::canonicalize(path) {
|
||||
canonical
|
||||
} else if let Some(parent) = path.parent() {
|
||||
if let Ok(canonical_parent) = std::fs::canonicalize(parent) {
|
||||
if let Some(file_name) = path.file_name() {
|
||||
canonical_parent.join(file_name)
|
||||
} else {
|
||||
path.to_path_buf()
|
||||
}
|
||||
} else {
|
||||
path.to_path_buf()
|
||||
}
|
||||
} else {
|
||||
path.to_path_buf()
|
||||
}
|
||||
path.to_path_buf()
|
||||
}
|
||||
|
||||
/// Suppress the next Create/Write VFS event for the given path.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue