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.
This commit is contained in:
Joe 2026-03-12 16:35:44 -05:00
parent 6325935557
commit 4ddc4a3e31
5 changed files with 36 additions and 74 deletions

View file

@ -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()

View file

@ -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<HashSet<PathBuf>>), ServeSessionError> {
) -> Result<(Project, RojoTree, Option<HashSet<PathBuf>>, Vec<PathBuf>), 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,

View file

@ -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<String> = attributes
.iter()
.filter_map(|(name, _)| {

View file

@ -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);