From cf0b2fd4f47b1a0a3910e7aef6d9b3c8e7b95209 Mon Sep 17 00:00:00 2001 From: Jonathan Cammisuli Date: Wed, 16 Aug 2023 14:02:02 -0400 Subject: [PATCH] fix(core): handle symlinks on debian for watch events (#18636) --- Cargo.lock | 10 +++++ packages/nx/Cargo.toml | 1 + packages/nx/src/native/watch/types.rs | 5 +++ packages/nx/src/native/watch/utils.rs | 37 ++++++++++++++++++- .../nx/src/native/watch/watch_filterer.rs | 7 +++- 5 files changed, 58 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4275246ff42b9..9e404a1793260 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1353,6 +1353,7 @@ dependencies = [ "napi-build", "napi-derive", "once_cell", + "os_type", "rayon", "regex", "swc_common", @@ -1378,6 +1379,15 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "os_type" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e24d44c0eea30167516ed8f6daca4b5e3eebcde1bde1e4e6e08b809fb02c7ba5" +dependencies = [ + "regex", +] + [[package]] name = "overload" version = "0.1.1" diff --git a/packages/nx/Cargo.toml b/packages/nx/Cargo.toml index dc4e73bd37c46..41d207956ddd8 100644 --- a/packages/nx/Cargo.toml +++ b/packages/nx/Cargo.toml @@ -14,6 +14,7 @@ ignore = '0.4' ignore-files = "1.3.0" itertools = "0.10.5" once_cell = "1.18.0" +os_type = "2.6.0" napi = { version = '2.12.6', default-features = false, features = ['anyhow', 'napi4', 'tokio_rt'] } napi-derive = '2.9.3' regex = "1.9.1" diff --git a/packages/nx/src/native/watch/types.rs b/packages/nx/src/native/watch/types.rs index 4a4453a3ebc22..11923203952ed 100644 --- a/packages/nx/src/native/watch/types.rs +++ b/packages/nx/src/native/watch/types.rs @@ -4,6 +4,8 @@ use std::path::PathBuf; use tracing::trace; use watchexec_events::{Event, Tag}; +use crate::native::watch::utils::transform_event; + #[napi(string_enum)] #[derive(Debug)] /// Newly created files will have the `update` EventType as well. @@ -52,6 +54,9 @@ pub(super) struct WatchEventInternal { impl From<&Event> for WatchEventInternal { fn from(value: &Event) -> Self { + let transformed = transform_event(value); + let value = transformed.as_ref().unwrap_or(value); + let path = value.paths().next().expect("there should always be a path"); let event_kind = value diff --git a/packages/nx/src/native/watch/utils.rs b/packages/nx/src/native/watch/utils.rs index e70e42d13de91..62a3a4922f4e8 100644 --- a/packages/nx/src/native/watch/utils.rs +++ b/packages/nx/src/native/watch/utils.rs @@ -1,6 +1,10 @@ use ignore::WalkBuilder; use ignore_files::IgnoreFile; -use std::path::PathBuf; +use once_cell::sync::Lazy; +use os_type::{OSInformation, OSType}; +use std::{fs, path::PathBuf}; +use tracing::trace; +use watchexec_events::{Event, Tag}; pub(super) fn get_ignore_files>(root: T) -> Vec { let root = root.as_ref(); @@ -45,3 +49,34 @@ pub(super) fn get_ignore_files>(root: T) -> Vec { // .map(|result| result.path().into()) // .collect() // } + +static OS_PLATFORM: Lazy = Lazy::new(os_type::current_platform); + +pub(super) fn transform_event(watch_event: &Event) -> Option { + if OS_PLATFORM.os_type == OSType::Debian { + let tags = watch_event + .tags + .clone() + .into_iter() + .map(|tag| match tag { + Tag::Path { path, file_type } => { + trace!("canonicalizing {:?}", path); + let real_path = fs::canonicalize(&path).unwrap_or(path); + trace!("real path {:?}", real_path); + Tag::Path { + path: real_path, + file_type, + } + } + _ => tag, + }) + .collect(); + + Some(Event { + tags, + metadata: watch_event.metadata.clone(), + }) + } else { + None + } +} diff --git a/packages/nx/src/native/watch/watch_filterer.rs b/packages/nx/src/native/watch/watch_filterer.rs index a94941d8c41ac..2ed067c5e99ff 100644 --- a/packages/nx/src/native/watch/watch_filterer.rs +++ b/packages/nx/src/native/watch/watch_filterer.rs @@ -6,6 +6,8 @@ use watchexec_events::filekind::{CreateKind, FileEventKind, ModifyKind, RemoveKi use watchexec_events::{Event, FileType, Priority, Source, Tag}; use watchexec_filterer_ignore::IgnoreFilterer; +use crate::native::watch::utils::transform_event; + #[derive(Debug)] pub struct WatchFilterer { pub inner: IgnoreFilterer, @@ -13,7 +15,10 @@ pub struct WatchFilterer { /// Used to filter out events that that come from watchexec impl Filterer for WatchFilterer { - fn check_event(&self, event: &Event, priority: Priority) -> Result { + fn check_event(&self, watch_event: &Event, priority: Priority) -> Result { + let transformed = transform_event(watch_event); + let event = transformed.as_ref().unwrap_or(watch_event); + if !self.inner.check_event(event, priority)? { return Ok(false); }