From 4ddc4a3e3129401f43d2f147f08b250b8afce792 Mon Sep 17 00:00:00 2001 From: Joe Date: Thu, 12 Mar 2026 16:35:44 -0500 Subject: [PATCH] feat: add .gitignore for logs and refactor ServeSession to include path_roots in init_tree return - Introduced a new .gitignore file to exclude log files from version control. - Modified the `init_tree` function in `ServeSession` to return `path_roots`, enhancing the function's utility. - Cleaned up commented-out code in `sourcemap.rs`, `patch_apply.rs`, and `tree.rs` for better readability and maintainability. --- .cursor/.gitignore | 1 + src/cli/sourcemap.rs | 2 - src/serve_session.rs | 79 ++++++++++++------------------------- src/snapshot/patch_apply.rs | 5 --- src/snapshot/tree.rs | 23 +++++------ 5 files changed, 36 insertions(+), 74 deletions(-) create mode 100644 .cursor/.gitignore diff --git a/.cursor/.gitignore b/.cursor/.gitignore new file mode 100644 index 00000000..df1a13b2 --- /dev/null +++ b/.cursor/.gitignore @@ -0,0 +1 @@ +/logs \ No newline at end of file diff --git a/src/cli/sourcemap.rs b/src/cli/sourcemap.rs index 45db803c..64143b06 100644 --- a/src/cli/sourcemap.rs +++ b/src/cli/sourcemap.rs @@ -88,8 +88,6 @@ impl SourcemapCommand { filter_non_scripts }; - // Pre-build a rayon threadpool with a low number of threads to avoid - // dynamic creation overhead on systems with a high number of cpus. rayon::ThreadPoolBuilder::new() .num_threads(num_cpus::get().min(6)) .build_global() diff --git a/src/serve_session.rs b/src/serve_session.rs index 50212629..b69f6cc9 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -17,7 +17,7 @@ use crate::{ session_id::SessionId, snapshot::{ apply_patch_set, compute_patch_set, AppliedPatchSet, InstanceContext, InstanceSnapshot, - PatchSet, PathIgnoreRule, RojoTree, + PatchSet, RojoTree, }, snapshot_middleware::{is_script_relevant_path, snapshot_from_vfs, INIT_FILE_PRIORITY}, }; @@ -330,7 +330,8 @@ impl ServeSession { fn init_tree( vfs: &Vfs, start_path: &Path, - ) -> Result<(Project, RojoTree, Option>), ServeSessionError> { + ) -> Result<(Project, RojoTree, Option>, Vec), ServeSessionError> + { log::trace!("Starting new ServeSession at path {}", start_path.display()); let root_project = Project::load_initial_project(vfs, start_path)?; @@ -421,69 +422,39 @@ impl ServeSession { vfs.clear_prefetch_cache(); let patch_start = Instant::now(); - let watch_ignore_rules = root_project.path_ignore_rules(); - std::thread::scope(|s| { - s.spawn(|| { - use walkdir::WalkDir; - let watch_start = Instant::now(); - let mut watch_count: usize = 0; - - if cfg!(target_os = "macos") { - // macOS kqueue: one FD per watched path. Walk each $path - // root, skip globIgnorePaths subtrees, and watch every - // non-ignored file and directory non-recursively. File - // watches are required because kqueue directory watches - // only fire for structural changes, not child content edits. - let passes_ignore = |entry: &walkdir::DirEntry| -> bool { - if let Some(name) = entry.file_name().to_str() { - if matches!(name, ".git" | ".hg" | ".svn") { - return false; - } - } - watch_ignore_rules - .iter() - .all(|rule: &PathIgnoreRule| rule.passes(entry.path())) - }; - vfs.set_watch_recursive(false); - for root in &path_roots { - for entry in WalkDir::new(root) - .into_iter() - .filter_entry(&passes_ignore) - .flatten() - { - let _ = vfs.watch(entry.path()); - watch_count += 1; - } - } - vfs.set_watch_recursive(true); - } else { - // Linux/Windows: inotify uses a single FD for all watches, - // RDCW uses one handle per directory. Recursive watches are - // cheap and directory watches already cover child file - // events. globIgnorePaths filtering is handled by the - // change processor's event filter. + if vfs.is_watch_enabled() { + std::thread::scope(|s| { + s.spawn(|| { + let watch_start = Instant::now(); + let mut watch_count: usize = 0; for root in &path_roots { let _ = vfs.watch(root); watch_count += 1; } - } - log::debug!( - "Set up {} watches in {:.1?}", - watch_count, - watch_start.elapsed(), - ); - }); + log::debug!( + "Set up {} watches in {:.1?}", + watch_count, + watch_start.elapsed(), + ); + }); + log::trace!("Computing initial patch set"); + let patch_set = compute_patch_set(snapshot, &tree, root_id); + + log::trace!("Applying initial patch set"); + apply_patch_set(&mut tree, patch_set); + }); + } else { log::trace!("Computing initial patch set"); let patch_set = compute_patch_set(snapshot, &tree, root_id); log::trace!("Applying initial patch set"); apply_patch_set(&mut tree, patch_set); - }); + } log::debug!("Watch + patch in {:.1?}", patch_start.elapsed()); - Ok((root_project, tree, walked_paths)) + Ok((root_project, tree, walked_paths, path_roots)) } /// Start a new serve session from the given in-memory filesystem and start @@ -500,7 +471,7 @@ impl ServeSession { let start_path = start_path.as_ref(); let start_time = Instant::now(); - let (root_project, tree, _walked_paths) = Self::init_tree(&vfs, start_path)?; + let (root_project, tree, _walked_paths, _path_roots) = Self::init_tree(&vfs, start_path)?; let session_id = SessionId::new(); let message_queue = MessageQueue::new(); @@ -576,7 +547,7 @@ impl ServeSession { let start_path = start_path.as_ref(); let start_time = Instant::now(); - let (root_project, tree, walked_paths) = Self::init_tree(&vfs, start_path)?; + let (root_project, tree, walked_paths, _path_roots) = Self::init_tree(&vfs, start_path)?; Ok(Self { change_processor: None, diff --git a/src/snapshot/patch_apply.rs b/src/snapshot/patch_apply.rs index 150bfd6d..41830f49 100644 --- a/src/snapshot/patch_apply.rs +++ b/src/snapshot/patch_apply.rs @@ -42,8 +42,6 @@ pub fn apply_patch_set(tree: &mut RojoTree, patch_set: PatchSet) -> AppliedPatch { profiling::scope!("updates"); - // Updates need to be applied after additions, which reduces the complexity - // of updates significantly. for update_patch in patch_set.updated_instances { apply_update_child(&mut context, tree, update_patch); } @@ -109,8 +107,6 @@ struct PatchApplyContext { #[profiling::function] fn finalize_patch_application(context: PatchApplyContext, tree: &mut RojoTree) -> AppliedPatchSet { for id in context.has_refs_to_rewrite { - // This should always succeed since instances marked as added in our - // patch should be added without fail. let mut instance = tree .get_instance_mut(id) .expect("Invalid instance ID in deferred property map"); @@ -181,7 +177,6 @@ fn finalize_patch_application(context: PatchApplyContext, tree: &mut RojoTree) - _ => continue, }; - // Remove all Rojo ref-related attributes let keys_to_remove: Vec = attributes .iter() .filter_map(|(name, _)| { diff --git a/src/snapshot/tree.rs b/src/snapshot/tree.rs index 39716437..57dd451a 100644 --- a/src/snapshot/tree.rs +++ b/src/snapshot/tree.rs @@ -125,28 +125,25 @@ impl RojoTree { // // We need to insert the NeedsPivotMigration property with a value of false on // every instance that inherits from Model for pivots to build correctly. - let hack_needs_pivot_migration = match snapshot.class_name.as_ref() { - // This is not a future proof way to do this but the last time a - // descendant of Model was added was in 2020 so it's probably fine. + let needs_pivot = match snapshot.class_name.as_ref() { "Model" | "Actor" | "Tool" | "HopperBin" | "Flag" | "WorldModel" | "Workspace" - | "Status" - if !snapshot - .properties - .contains_key(&ustr("NeedsPivotMigration")) => - { - vec![("NeedsPivotMigration", Variant::Bool(false))] - } - _ => Vec::new(), + | "Status" => !snapshot + .properties + .contains_key(&ustr("NeedsPivotMigration")), + _ => false, }; let is_script = is_script_class(snapshot.class_name.as_ref()); - let builder = InstanceBuilder::empty() + let mut builder = InstanceBuilder::empty() .with_class(snapshot.class_name) .with_name(snapshot.name.into_owned()) - .with_properties(hack_needs_pivot_migration) .with_properties(snapshot.properties); + if needs_pivot { + builder = builder.with_property("NeedsPivotMigration", Variant::Bool(false)); + } + let referent = self.inner.insert(parent_ref, builder); self.insert_metadata(referent, snapshot.metadata);