From 84253019c21970e01e95f25bf0e6ccbcf7414c98 Mon Sep 17 00:00:00 2001 From: Joe Date: Sun, 1 Mar 2026 14:50:04 -0600 Subject: [PATCH] Refactor PatchTree tests and enhance git index change detection - Updated the `changedProperties` structure in `PatchTree.spec.lua` to use a nested table format for `Source`, improving data consistency. - Introduced a new `repStorageId` in `PatchTree.spec.lua` for better instance mapping. - Refactored the `collect_tree_index_changes` function in `git.rs` to utilize a HashMap for tree entries, streamlining the detection of index changes. - Enhanced the `flatten_tree` function to improve the collection of paths in the git repository. These changes aim to improve the clarity and efficiency of both the PatchTree tests and the git index change detection logic. --- plugin/src/PatchTree.spec.lua | 7 +++++-- src/git.rs | 27 +++++++++++---------------- src/web/api.rs | 18 ++++++++++++++++-- 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/plugin/src/PatchTree.spec.lua b/plugin/src/PatchTree.spec.lua index 0fdeaddc..fe3db772 100644 --- a/plugin/src/PatchTree.spec.lua +++ b/plugin/src/PatchTree.spec.lua @@ -755,7 +755,7 @@ return function() table.insert(patch.updated, { id = id1, changedName = nil, - changedProperties = { Source = "-- changed" }, + changedProperties = { Source = { String = "-- changed" } }, }) local gitMetadata = { @@ -862,7 +862,7 @@ return function() table.insert(patch.updated, { id = childId, - changedProperties = { Source = "return {}" }, + changedProperties = { Source = { String = "return {}" } }, }) local tree = PatchTree.build(patch, instanceMap, { "Property", "Current", "Incoming" }) @@ -898,6 +898,9 @@ return function() -- Use a service-level instance (direct child of DataModel) local repStorage = game:GetService("ReplicatedStorage") + local repStorageId = HttpService:GenerateGUID(false) + instanceMap:insert(repStorageId, repStorage) + local testObj = Instance.new("Folder") testObj.Name = "TopLevel" testObj.Parent = repStorage diff --git a/src/git.rs b/src/git.rs index a3280ce8..b9348a2a 100644 --- a/src/git.rs +++ b/src/git.rs @@ -190,17 +190,14 @@ fn collect_tree_index_changes( Err(_) => return, }; + let mut tree_entries: HashMap = HashMap::new(); + flatten_tree(repo, &tree, "", &mut tree_entries); + for entry in index.entries() { let path_bstr = entry.path(index); let path_str = path_bstr.to_str_lossy(); - let tree_entry_id = tree - .lookup_entry_by_path(path_str.as_ref()) - .ok() - .flatten() - .map(|e| e.object_id()); - - match tree_entry_id { + match tree_entries.remove(path_str.as_ref()) { Some(tid) if tid == entry.id => {} _ => { tracked.insert(PathBuf::from(path_str.as_ref())); @@ -208,15 +205,16 @@ fn collect_tree_index_changes( } } - collect_tree_only_paths(repo, &tree, "", index, tracked); + for path in tree_entries.into_keys() { + tracked.insert(PathBuf::from(path)); + } } -fn collect_tree_only_paths( +fn flatten_tree( repo: &gix::Repository, tree: &gix::Tree<'_>, prefix: &str, - index: &gix::index::File, - tracked: &mut HashSet, + out: &mut HashMap, ) { for entry in tree.iter() { let entry = match entry { @@ -233,14 +231,11 @@ fn collect_tree_only_paths( if entry.mode().is_tree() { if let Ok(sub_obj) = entry.id().object() { if let Ok(sub_tree) = sub_obj.peel_to_tree() { - collect_tree_only_paths(repo, &sub_tree, &full_path, index, tracked); + flatten_tree(repo, &sub_tree, &full_path, out); } } } else if entry.mode().is_blob() || entry.mode().is_executable() { - let path_as_bstr: &gix::bstr::BStr = full_path.as_bytes().as_bstr(); - if index.entry_by_path(path_as_bstr).is_none() { - tracked.insert(PathBuf::from(&full_path)); - } + out.insert(full_path, entry.id().detach()); } } } diff --git a/src/web/api.rs b/src/web/api.rs index 67a1e5e4..df9714a6 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -7,6 +7,7 @@ use std::{ path::{Path, PathBuf}, str::FromStr, sync::{Arc, Mutex}, + time::Instant, }; use bytes::Bytes; @@ -392,6 +393,8 @@ impl ApiService { /// Get a summary of information about the server async fn handle_api_rojo(&self) -> Response> { + let handler_start = Instant::now(); + let root_instance_id = self.serve_session.tree().get_root_id(); let ignore_hidden_services = self.serve_session.ignore_hidden_services(); @@ -408,15 +411,26 @@ impl ApiService { .serve_session .initial_head_commit() .map(|s| s.to_owned()); - tokio::task::spawn_blocking(move || { + let t = Instant::now(); + let result = tokio::task::spawn_blocking(move || { crate::git::compute_git_metadata(&tree_handle, &repo_root, initial_head.as_deref()) }) .await - .ok() + .ok(); + log::trace!( + "[TIMING] handle_api_rojo: compute_git_metadata {}ms", + t.elapsed().as_millis() + ); + result } else { None }; + log::trace!( + "[TIMING] handle_api_rojo: total {}ms", + handler_start.elapsed().as_millis() + ); + msgpack_ok(&ServerInfoResponse { server_version: SERVER_VERSION.to_owned(), protocol_version: PROTOCOL_VERSION,