From 4846fc1f598aebf3fe1cfe57f1a6022fae2fa23e Mon Sep 17 00:00:00 2001 From: Joe Date: Sun, 1 Mar 2026 18:22:24 -0600 Subject: [PATCH] Refactor git module to utilize command-line git for repository operations - Replaced the use of the gix API with direct command-line calls to `git` for retrieving the repository root and current HEAD commit SHA, improving compatibility and reducing dependency on the gix library. - Updated the `git_changed_files_impl` function to use command-line `git diff` and `git ls-files` for tracking changes, enhancing performance and flexibility in detecting file modifications. - Improved error handling and logging for git operations, ensuring better feedback during execution. These changes aim to streamline git interactions and enhance the overall efficiency of the git module. --- Cargo.lock | 1159 ---------------------------------------------------- Cargo.toml | 2 +- TODO.txt | 339 --------------- src/git.rs | 446 ++++++++++---------- 4 files changed, 219 insertions(+), 1727 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d1f3f7b5..e5a99e61 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -63,12 +63,6 @@ dependencies = [ "cc", ] -[[package]] -name = "allocator-api2" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" - [[package]] name = "anes" version = "0.1.6" @@ -140,15 +134,6 @@ version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" -[[package]] -name = "arc-swap" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9f3647c145568cec02c42054e07bdf9a5a698e15b466fb2341bfc393cd24aa5" -dependencies = [ - "rustversion", -] - [[package]] name = "arraydeque" version = "0.5.1" @@ -206,7 +191,6 @@ dependencies = [ "flate2", "fs-err", "futures", - "gix", "globset", "http-body-util", "humantime", @@ -464,12 +448,6 @@ version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" -[[package]] -name = "bytesize" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bd91ee7b2422bcb158d90ef4d14f75ef67f340943fc4149891dcce8f8b972a3" - [[package]] name = "cast" version = "0.3.0" @@ -614,12 +592,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" -[[package]] -name = "clru" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbd0f76e066e64fdc5631e3bb46381254deab9ef1158292f27c8c57e3bf3fe59" - [[package]] name = "cmake" version = "0.1.57" @@ -852,20 +824,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "dashmap" -version = "6.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" -dependencies = [ - "cfg-if 1.0.4", - "crossbeam-utils", - "hashbrown 0.14.5", - "lock_api", - "once_cell", - "parking_lot_core", -] - [[package]] name = "data-encoding" version = "2.10.0" @@ -1066,16 +1024,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "faster-hex" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7223ae2d2f179b803433d9c830478527e92b8117eab39460edae7f1614d9fb73" -dependencies = [ - "heapless", - "serde", -] - [[package]] name = "fastrand" version = "2.3.0" @@ -1118,12 +1066,6 @@ dependencies = [ "miniz_oxide", ] -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - [[package]] name = "foldhash" version = "0.1.5" @@ -1340,907 +1282,6 @@ version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" -[[package]] -name = "gix" -version = "0.80.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa56fdbfe98258af2759818ddc3175cc581112660e74c3fd55669836d29a994" -dependencies = [ - "gix-actor", - "gix-archive", - "gix-attributes", - "gix-blame", - "gix-command", - "gix-commitgraph", - "gix-config", - "gix-credentials", - "gix-date", - "gix-diff", - "gix-dir", - "gix-discover", - "gix-error", - "gix-features", - "gix-filter", - "gix-fs", - "gix-glob", - "gix-hash", - "gix-hashtable", - "gix-ignore", - "gix-index", - "gix-lock", - "gix-mailmap", - "gix-negotiate", - "gix-object", - "gix-odb", - "gix-pack", - "gix-path", - "gix-pathspec", - "gix-prompt", - "gix-protocol", - "gix-ref", - "gix-refspec", - "gix-revision", - "gix-revwalk", - "gix-sec", - "gix-shallow", - "gix-status", - "gix-submodule", - "gix-tempfile", - "gix-trace", - "gix-transport", - "gix-traverse", - "gix-url", - "gix-utils", - "gix-validate", - "gix-worktree", - "gix-worktree-state", - "gix-worktree-stream", - "nonempty", - "parking_lot", - "regex", - "signal-hook", - "smallvec", - "thiserror 2.0.18", -] - -[[package]] -name = "gix-actor" -version = "0.40.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e5e5b518339d5e6718af108fd064d4e9ba33caf728cf487352873d76411df35" -dependencies = [ - "bstr", - "gix-date", - "gix-error", - "winnow", -] - -[[package]] -name = "gix-archive" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12fee3b0b2a30d01ceebd1ff134b187019b5eaedd2901c2e980d7264ee8758dd" -dependencies = [ - "bstr", - "gix-date", - "gix-error", - "gix-object", - "gix-worktree-stream", -] - -[[package]] -name = "gix-attributes" -version = "0.31.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c233d6eaa098c0ca5ce03236fd7a96e27f1abe72fad74b46003fbd11fe49563c" -dependencies = [ - "bstr", - "gix-glob", - "gix-path", - "gix-quote", - "gix-trace", - "kstring", - "smallvec", - "thiserror 2.0.18", - "unicode-bom", -] - -[[package]] -name = "gix-bitmap" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7add20f40d060db8c9b1314d499bac6ed7480f33eb113ce3e1cf5d6ff85d989" -dependencies = [ - "gix-error", -] - -[[package]] -name = "gix-blame" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2093922a26722186a2ea36615d581639299ca7d68241d8116d8c441da6f96b1a" -dependencies = [ - "gix-commitgraph", - "gix-date", - "gix-diff", - "gix-error", - "gix-hash", - "gix-object", - "gix-revwalk", - "gix-trace", - "gix-traverse", - "gix-worktree", - "smallvec", - "thiserror 2.0.18", -] - -[[package]] -name = "gix-chunk" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1096b6608fbe5d27fb4984e20f992b4e76fb8c613f6acb87d07c5831b53a6959" -dependencies = [ - "gix-error", -] - -[[package]] -name = "gix-command" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b849c65a609f50d02f8a2774fe371650b3384a743c79c2a070ce0da49b7fb7da" -dependencies = [ - "bstr", - "gix-path", - "gix-quote", - "gix-trace", - "shell-words", -] - -[[package]] -name = "gix-commitgraph" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aea2fcfa6bc7329cd094696ba76682b89bdb61cafc848d91b34abba1c1d7e040" -dependencies = [ - "bstr", - "gix-chunk", - "gix-error", - "gix-hash", - "memmap2", - "nonempty", -] - -[[package]] -name = "gix-config" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c24b190bd42b55724368c28ae750840b48e2038b9b5281202de6fca4ec1fce1" -dependencies = [ - "bstr", - "gix-config-value", - "gix-features", - "gix-glob", - "gix-path", - "gix-ref", - "gix-sec", - "memchr", - "smallvec", - "thiserror 2.0.18", - "unicode-bom", - "winnow", -] - -[[package]] -name = "gix-config-value" -version = "0.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "441a300bc3645a1f45cba495b9175f90f47256ce43f2ee161da0031e3ac77c92" -dependencies = [ - "bitflags 2.11.0", - "bstr", - "gix-path", - "libc", - "thiserror 2.0.18", -] - -[[package]] -name = "gix-credentials" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604b2d440d293a0017cbe60ee87fe10337f6e1d224dd6a147619e849e2be4623" -dependencies = [ - "bstr", - "gix-command", - "gix-config-value", - "gix-date", - "gix-path", - "gix-prompt", - "gix-sec", - "gix-trace", - "gix-url", - "thiserror 2.0.18", -] - -[[package]] -name = "gix-date" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c2f2155782090fd947c2f7904166b9f3c3da0d91358adb011f753ea3a55c0ff" -dependencies = [ - "bstr", - "gix-error", - "itoa", - "jiff", - "smallvec", -] - -[[package]] -name = "gix-diff" -version = "0.60.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60592771b104eda4e537c311e8239daef0df651d61e0e21855f7e6166416ff12" -dependencies = [ - "bstr", - "gix-attributes", - "gix-command", - "gix-filter", - "gix-fs", - "gix-hash", - "gix-index", - "gix-object", - "gix-path", - "gix-pathspec", - "gix-tempfile", - "gix-trace", - "gix-traverse", - "gix-worktree", - "imara-diff 0.1.8", - "imara-diff 0.2.0", - "thiserror 2.0.18", -] - -[[package]] -name = "gix-dir" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b483ca64cc32d9e33fa617be153ec90525ad77db51106a5f725805a066dc001" -dependencies = [ - "bstr", - "gix-discover", - "gix-fs", - "gix-ignore", - "gix-index", - "gix-object", - "gix-path", - "gix-pathspec", - "gix-trace", - "gix-utils", - "gix-worktree", - "thiserror 2.0.18", -] - -[[package]] -name = "gix-discover" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "810764b92e8cb95e4d91b7adfc5a14666434fd32ace02900dfb66aae71f845df" -dependencies = [ - "bstr", - "dunce", - "gix-fs", - "gix-path", - "gix-ref", - "gix-sec", - "thiserror 2.0.18", -] - -[[package]] -name = "gix-error" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dfe8025209bf2a72d97a6f2dff105b93e5ebcf131ffa3d3f1728ce4ac3767b" -dependencies = [ - "bstr", -] - -[[package]] -name = "gix-features" -version = "0.46.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a83a5fe8927de3bb02b0cfb87165dbfb49f04d4c297767443f2e1011ecc15bdd" -dependencies = [ - "bytes", - "bytesize", - "crc32fast", - "crossbeam-channel", - "gix-path", - "gix-trace", - "gix-utils", - "libc", - "once_cell", - "parking_lot", - "prodash", - "thiserror 2.0.18", - "walkdir", - "zlib-rs", -] - -[[package]] -name = "gix-filter" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eda328750accaac05ce7637298fd7d6ba0d5d7bdf49c21f899d0b97e3df822d" -dependencies = [ - "bstr", - "encoding_rs", - "gix-attributes", - "gix-command", - "gix-hash", - "gix-object", - "gix-packetline", - "gix-path", - "gix-quote", - "gix-trace", - "gix-utils", - "smallvec", - "thiserror 2.0.18", -] - -[[package]] -name = "gix-fs" -version = "0.19.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de4bd0d8e6c6ef03485205f8eecc0359042a866d26dba569075db1ebcc005970" -dependencies = [ - "bstr", - "fastrand", - "gix-features", - "gix-path", - "gix-utils", - "thiserror 2.0.18", -] - -[[package]] -name = "gix-glob" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b03e6cd88cc0dc1eafa1fddac0fb719e4e74b6ea58dd016e71125fde4a326bee" -dependencies = [ - "bitflags 2.11.0", - "bstr", - "gix-features", - "gix-path", -] - -[[package]] -name = "gix-hash" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8ced05d2d7b13bff08b2f7eb4e47cfeaf00b974c2ddce08377c4fe1f706b3eb" -dependencies = [ - "faster-hex", - "gix-features", - "sha1-checked", - "thiserror 2.0.18", -] - -[[package]] -name = "gix-hashtable" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52f1eecdd006390cbed81f105417dbf82a6fe40842022006550f2e32484101da" -dependencies = [ - "gix-hash", - "hashbrown 0.16.1", - "parking_lot", -] - -[[package]] -name = "gix-ignore" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8953d87c13267e296d547f0fc7eaa8aa8fa5b2a9a34ab1cd5857f25240c7d299" -dependencies = [ - "bstr", - "gix-glob", - "gix-path", - "gix-trace", - "unicode-bom", -] - -[[package]] -name = "gix-index" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13b28482b86662c8b78160e0750b097a35fd61185803a960681351b3a07de07e" -dependencies = [ - "bitflags 2.11.0", - "bstr", - "filetime", - "fnv", - "gix-bitmap", - "gix-features", - "gix-fs", - "gix-hash", - "gix-lock", - "gix-object", - "gix-traverse", - "gix-utils", - "gix-validate", - "hashbrown 0.16.1", - "itoa", - "libc", - "memmap2", - "rustix", - "smallvec", - "thiserror 2.0.18", -] - -[[package]] -name = "gix-lock" -version = "21.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbe09cf05ba7c679bba189acc29eeea137f643e7fff1b5dff879dfd45248be31" -dependencies = [ - "gix-tempfile", - "gix-utils", - "thiserror 2.0.18", -] - -[[package]] -name = "gix-mailmap" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7b4818da522786ec7e32a00884ee8fc40fa4c215c3997c0b15f7b62684d1199" -dependencies = [ - "bstr", - "gix-actor", - "gix-date", - "gix-error", -] - -[[package]] -name = "gix-negotiate" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a925ec9bc3664eaff9c7dc49bc857fe0de7e90ece6e092cb66ba923812824db" -dependencies = [ - "bitflags 2.11.0", - "gix-commitgraph", - "gix-date", - "gix-hash", - "gix-object", - "gix-revwalk", -] - -[[package]] -name = "gix-object" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "013eae8e072c6155191ac266950dfbc8d162408642571b32e2c6b3e4b03740fb" -dependencies = [ - "bstr", - "gix-actor", - "gix-date", - "gix-features", - "gix-hash", - "gix-hashtable", - "gix-path", - "gix-utils", - "gix-validate", - "itoa", - "smallvec", - "thiserror 2.0.18", - "winnow", -] - -[[package]] -name = "gix-odb" -version = "0.77.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8901a182923799e8857ac01bff6d7c6fecea999abd79a86dab638aadbb843f3" -dependencies = [ - "arc-swap", - "gix-features", - "gix-fs", - "gix-hash", - "gix-hashtable", - "gix-object", - "gix-pack", - "gix-path", - "gix-quote", - "parking_lot", - "tempfile", - "thiserror 2.0.18", -] - -[[package]] -name = "gix-pack" -version = "0.67.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a9f96f4058359d6874123f160e5b2044974829a29f3a71bb9c9218d1916c3" -dependencies = [ - "clru", - "gix-chunk", - "gix-error", - "gix-features", - "gix-hash", - "gix-hashtable", - "gix-object", - "gix-path", - "gix-tempfile", - "memmap2", - "parking_lot", - "smallvec", - "thiserror 2.0.18", - "uluru", -] - -[[package]] -name = "gix-packetline" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25429ee1ef792d9b653ee5de09bb525489fc8e6908334cfd5d5824269f0b7073" -dependencies = [ - "bstr", - "faster-hex", - "gix-trace", - "thiserror 2.0.18", -] - -[[package]] -name = "gix-path" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7163b1633d35846a52ef8093f390cec240e2d55da99b60151883035e5169cd85" -dependencies = [ - "bstr", - "gix-trace", - "gix-validate", - "thiserror 2.0.18", -] - -[[package]] -name = "gix-pathspec" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40e7636782b35bb1d3ade19ea7387278e96fd49f6963ab41bfca81cef4b61b20" -dependencies = [ - "bitflags 2.11.0", - "bstr", - "gix-attributes", - "gix-config-value", - "gix-glob", - "gix-path", - "thiserror 2.0.18", -] - -[[package]] -name = "gix-prompt" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5b43e9c81bce4e35d90e32405649d47e9fae2ab861d0edbc913fde4df2c6cc7" -dependencies = [ - "gix-command", - "gix-config-value", - "parking_lot", - "rustix", - "thiserror 2.0.18", -] - -[[package]] -name = "gix-protocol" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c64ec7b04c57df6e97a2ac4738a4a09897b88febd6ec4bd2c5d3ff3ad3849df" -dependencies = [ - "bstr", - "gix-credentials", - "gix-date", - "gix-features", - "gix-hash", - "gix-lock", - "gix-negotiate", - "gix-object", - "gix-ref", - "gix-refspec", - "gix-revwalk", - "gix-shallow", - "gix-trace", - "gix-transport", - "gix-utils", - "maybe-async", - "nonempty", - "thiserror 2.0.18", - "winnow", -] - -[[package]] -name = "gix-quote" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68533db71259c8776dd4e770d2b7b98696213ecdc1f5c9e3507119e274e0c578" -dependencies = [ - "bstr", - "gix-error", - "gix-utils", -] - -[[package]] -name = "gix-ref" -version = "0.60.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cc7b230945f02d706a49bcf823b671785ecd9e88e713b8bd2ca5db104c97add" -dependencies = [ - "gix-actor", - "gix-features", - "gix-fs", - "gix-hash", - "gix-lock", - "gix-object", - "gix-path", - "gix-tempfile", - "gix-utils", - "gix-validate", - "memmap2", - "thiserror 2.0.18", - "winnow", -] - -[[package]] -name = "gix-refspec" -version = "0.38.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb3dc194cdc1176fc20f39f233d0d516f83df843ea14a9eb758a2690f3e38d1e" -dependencies = [ - "bstr", - "gix-error", - "gix-glob", - "gix-hash", - "gix-revision", - "gix-validate", - "smallvec", - "thiserror 2.0.18", -] - -[[package]] -name = "gix-revision" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df9e31cd402edae08c3fdb67917b9fb75b0c9c9bd2fbed0c2dd9c0847039c556" -dependencies = [ - "bitflags 2.11.0", - "bstr", - "gix-commitgraph", - "gix-date", - "gix-error", - "gix-hash", - "gix-hashtable", - "gix-object", - "gix-revwalk", - "gix-trace", - "nonempty", -] - -[[package]] -name = "gix-revwalk" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "573f6e471d76c0796f0b8ed5a431521ea5d121a7860121a2a9703e9434ab1d52" -dependencies = [ - "gix-commitgraph", - "gix-date", - "gix-error", - "gix-hash", - "gix-hashtable", - "gix-object", - "smallvec", - "thiserror 2.0.18", -] - -[[package]] -name = "gix-sec" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e014df75f3d7f5c98b18b45c202422da6236a1c0c0a50997c3f41e601f3ad511" -dependencies = [ - "bitflags 2.11.0", - "gix-path", - "libc", - "windows-sys 0.61.2", -] - -[[package]] -name = "gix-shallow" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ee51037c8a27ddb1c7a6d6db2553d01e501d5b1dae7dc65e41905a70960e658" -dependencies = [ - "bstr", - "gix-hash", - "gix-lock", - "nonempty", - "thiserror 2.0.18", -] - -[[package]] -name = "gix-status" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d4b93da8aae2b5c4ec2aaa3663a0914789737ba17383c665e9270a74173e8f6" -dependencies = [ - "bstr", - "filetime", - "gix-diff", - "gix-dir", - "gix-features", - "gix-filter", - "gix-fs", - "gix-hash", - "gix-index", - "gix-object", - "gix-path", - "gix-pathspec", - "gix-worktree", - "portable-atomic", - "thiserror 2.0.18", -] - -[[package]] -name = "gix-submodule" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cba2022599491d620fbc77b3729dba0120862ce9b4af6e3c47d19a9f2a5d884" -dependencies = [ - "bstr", - "gix-config", - "gix-path", - "gix-pathspec", - "gix-refspec", - "gix-url", - "thiserror 2.0.18", -] - -[[package]] -name = "gix-tempfile" -version = "21.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d9ab2c89fe4bfd4f1d8700aa4516534c170d8a21ae2c554167374607c2eaf16" -dependencies = [ - "dashmap", - "gix-fs", - "libc", - "parking_lot", - "signal-hook", - "signal-hook-registry", - "tempfile", -] - -[[package]] -name = "gix-trace" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f69a13643b8437d4ca6845e08143e847a36ca82903eed13303475d0ae8b162e0" - -[[package]] -name = "gix-transport" -version = "0.55.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4d72f5094b9f851e348f2cbb840d026ffd8119fc28bc2bca1387eecd171c815" -dependencies = [ - "bstr", - "gix-command", - "gix-features", - "gix-packetline", - "gix-quote", - "gix-sec", - "gix-url", - "thiserror 2.0.18", -] - -[[package]] -name = "gix-traverse" -version = "0.54.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c99b3cf9dc87c13f1404e7b0e8c5e4bff4975d6f788831c02d6c006f3c76b4a0" -dependencies = [ - "bitflags 2.11.0", - "gix-commitgraph", - "gix-date", - "gix-hash", - "gix-hashtable", - "gix-object", - "gix-revwalk", - "smallvec", - "thiserror 2.0.18", -] - -[[package]] -name = "gix-url" -version = "0.35.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d28e8af3d42581190da884f013caf254d2fd4d6ab102408f08d21bfa11de6c8d" -dependencies = [ - "bstr", - "gix-path", - "percent-encoding", - "thiserror 2.0.18", -] - -[[package]] -name = "gix-utils" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "befcdbdfb1238d2854591f760a48711bed85e72d80a10e8f2f93f656746ef7c5" -dependencies = [ - "bstr", - "fastrand", - "unicode-normalization", -] - -[[package]] -name = "gix-validate" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ec1eff98d91941f47766367cba1be746bab662bad761d9891ae6f7882f7840b" -dependencies = [ - "bstr", -] - -[[package]] -name = "gix-worktree" -version = "0.49.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "005627fc149315f39473e3e94a50058dd5d345c490a23723f67f32ee9c505232" -dependencies = [ - "bstr", - "gix-attributes", - "gix-fs", - "gix-glob", - "gix-hash", - "gix-ignore", - "gix-index", - "gix-object", - "gix-path", - "gix-validate", -] - -[[package]] -name = "gix-worktree-state" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ffce16a83def3651ee4c9872960f4582652fbcc8bbee568c9bae6ffa23894" -dependencies = [ - "bstr", - "gix-features", - "gix-filter", - "gix-fs", - "gix-index", - "gix-object", - "gix-path", - "gix-worktree", - "io-close", - "thiserror 2.0.18", -] - -[[package]] -name = "gix-worktree-stream" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "805ff4ecc1c8ac02e8d1969521d54cd446fae7397f5db3f4d06c5f0fbaa4dd64" -dependencies = [ - "gix-attributes", - "gix-error", - "gix-features", - "gix-filter", - "gix-fs", - "gix-hash", - "gix-object", - "gix-path", - "gix-traverse", - "parking_lot", -] - [[package]] name = "globset" version = "0.4.18" @@ -2265,21 +1306,6 @@ dependencies = [ "zerocopy", ] -[[package]] -name = "hash32" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" -dependencies = [ - "byteorder 1.5.0", -] - -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" - [[package]] name = "hashbrown" version = "0.15.5" @@ -2295,8 +1321,6 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ - "allocator-api2", - "equivalent", "foldhash 0.2.0", ] @@ -2309,16 +1333,6 @@ dependencies = [ "hashbrown 0.16.1", ] -[[package]] -name = "heapless" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" -dependencies = [ - "hash32", - "stable_deref_trait", -] - [[package]] name = "heck" version = "0.5.0" @@ -2391,12 +1405,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" -[[package]] -name = "human_format" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaec953f16e5bcf6b8a3cb3aa959b17e5577dbd2693e94554c462c08be22624b" - [[package]] name = "humantime" version = "2.3.0" @@ -2587,25 +1595,6 @@ dependencies = [ "icu_properties", ] -[[package]] -name = "imara-diff" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17d34b7d42178945f775e84bc4c36dde7c1c6cdfea656d3354d009056f2bb3d2" -dependencies = [ - "hashbrown 0.15.5", -] - -[[package]] -name = "imara-diff" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f01d462f766df78ab820dd06f5eb700233c51f0f4c2e846520eaf4ba6aa5c5c" -dependencies = [ - "hashbrown 0.15.5", - "memchr", -] - [[package]] name = "indexmap" version = "2.13.0" @@ -2653,16 +1642,6 @@ dependencies = [ "tempfile", ] -[[package]] -name = "io-close" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cadcf447f06744f8ce713d2d6239bb5bde2c357a452397a9ed90c625da390bc" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "ipnet" version = "2.11.0" @@ -2707,12 +1686,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "819b44bc7c87d9117eb522f14d46e918add69ff12713c475946b0a29363ed1c2" dependencies = [ "jiff-static", - "jiff-tzdb-platform", "log", "portable-atomic", "portable-atomic-util", "serde_core", - "windows-sys 0.61.2", ] [[package]] @@ -2726,21 +1703,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "jiff-tzdb" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68971ebff725b9e2ca27a601c5eb38a4c5d64422c4cbab0c535f248087eda5c2" - -[[package]] -name = "jiff-tzdb-platform" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8" -dependencies = [ - "jiff-tzdb", -] - [[package]] name = "jni" version = "0.21.1" @@ -2819,15 +1781,6 @@ dependencies = [ "libc", ] -[[package]] -name = "kstring" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "558bf9508a558512042d3095138b1f7b8fe90c5467d94f9f1da28b3731c5dbd1" -dependencies = [ - "static_assertions", -] - [[package]] name = "lazy_static" version = "1.5.0" @@ -2953,32 +1906,12 @@ dependencies = [ "regex-automata", ] -[[package]] -name = "maybe-async" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cf92c10c7e361d6b99666ec1c6f9805b0bea2c3bd8c78dc6fe98ac5bd78db11" -dependencies = [ - "proc-macro2 1.0.106", - "quote 1.0.44", - "syn 2.0.117", -] - [[package]] name = "memchr" version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" -[[package]] -name = "memmap2" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" -dependencies = [ - "libc", -] - [[package]] name = "memofs" version = "0.3.1" @@ -3030,12 +1963,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "nonempty" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9737e026353e5cd0736f98eddae28665118eb6f6600902a7f50db585621fecb6" - [[package]] name = "normpath" version = "1.5.0" @@ -3417,17 +2344,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "prodash" -version = "31.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "962200e2d7d551451297d9fdce85138374019ada198e30ea9ede38034e27604c" -dependencies = [ - "bytesize", - "human_format", - "parking_lot", -] - [[package]] name = "profiling" version = "1.0.17" @@ -4272,16 +3188,6 @@ dependencies = [ "digest", ] -[[package]] -name = "sha1-checked" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89f599ac0c323ebb1c6082821a54962b839832b03984598375bff3975b804423" -dependencies = [ - "digest", - "sha1 0.10.6", -] - [[package]] name = "sha1_smol" version = "1.0.1" @@ -4308,38 +3214,12 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "shell-words" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc6fe69c597f9c37bfeeeeeb33da3530379845f10be461a66d16d03eca2ded77" - [[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "signal-hook" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b57709da74f9ff9f4a27dce9526eec25ca8407c45a7887243b031a58935fb8e" -dependencies = [ - "libc", - "signal-hook-registry", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" -dependencies = [ - "errno", - "libc", -] - [[package]] name = "simd-adler32" version = "0.3.8" @@ -4398,12 +3278,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "stdweb" version = "0.4.20" @@ -5004,42 +3878,18 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" -[[package]] -name = "uluru" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c8a2469e56e6e5095c82ccd3afb98dad95f7af7929aab6d8ba8d6e0f73657da" -dependencies = [ - "arrayvec 0.7.6", -] - [[package]] name = "unicase" version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" -[[package]] -name = "unicode-bom" -version = "2.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eec5d1121208364f6793f7d2e222bf75a915c19557537745b195b253dd64217" - [[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" -[[package]] -name = "unicode-normalization" -version = "0.1.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" -dependencies = [ - "tinyvec", -] - [[package]] name = "unicode-width" version = "0.1.14" @@ -5628,9 +4478,6 @@ name = "winnow" version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" -dependencies = [ - "memchr", -] [[package]] name = "winreg" @@ -5889,12 +4736,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "zlib-rs" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c745c48e1007337ed136dc99df34128b9faa6ed542d80a1c673cf55a6d7236c8" - [[package]] name = "zmij" version = "1.0.21" diff --git a/Cargo.toml b/Cargo.toml index 4557243d..dd7af375 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -113,7 +113,7 @@ dirs = "6" pathdiff = "0.2.3" blake3 = "1.8.3" -gix = { version = "0.80", default-features = true, features = ["blocking-network-client"] } + sha1 = "0.10" indexmap = { version = "2.13.0", features = ["serde"] } rmp-serde = "1.3.1" diff --git a/TODO.txt b/TODO.txt index 336669e8..c3dab351 100644 --- a/TODO.txt +++ b/TODO.txt @@ -76,281 +76,10 @@ could we find an endpoint for downloading the "client side" of any game on the p [Crates] publish as a crate https://crates.io/crates/rojo -[tree reconciling spooky!] -[INFO librojo::cli::serve] Listening: http://localhost:34873 -[INFO librojo::change_processor] VFS event: WRITE d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -[INFO librojo::change_processor] VFS: canonicalize OK for d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -> src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau affects IDs [Ref(Some(162268450181648175032536457080084761373))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau for instance Ref(Some(162268450181648175032536457080084761373)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -[INFO librojo::change_processor] VFS event applied: 0 added, 0 removed, 1 updated -[INFO librojo::change_processor] Tree reconciliation: corrected 4 added, 4 removed (14.0s) -[INFO librojo::change_processor] VFS event: WRITE d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS: canonicalize OK for d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -> src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\HUD.luau affects IDs [Ref(Some(294452550321273018071988539960330649902))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau for instance Ref(Some(294452550321273018071988539960330649902)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS event applied: 0 added, 0 removed, 1 updated -[INFO librojo::change_processor] VFS event: WRITE src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS: canonicalize OK for src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -> src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\HUD.luau affects IDs [Ref(Some(294452550321273018071988539960330649902))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau for instance Ref(Some(294452550321273018071988539960330649902)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS event applied: no changes -[INFO librojo::change_processor] Tree reconciliation: corrected 4 added, 4 removed (12.1s) -[INFO librojo::change_processor] VFS event: WRITE d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS: canonicalize OK for d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -> src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\HUD.luau affects IDs [Ref(Some(294452550321273018071988539960330649902))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau for instance Ref(Some(294452550321273018071988539960330649902)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS event applied: 0 added, 0 removed, 1 updated -[INFO librojo::change_processor] VFS event: WRITE src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS: canonicalize OK for src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -> src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\HUD.luau affects IDs [Ref(Some(294452550321273018071988539960330649902))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau for instance Ref(Some(294452550321273018071988539960330649902)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS event applied: no changes -[INFO librojo::change_processor] Tree reconciliation: corrected 4 added, 4 removed (13.3s) -[INFO librojo::change_processor] VFS event: WRITE d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS: canonicalize OK for d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -> src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\HUD.luau affects IDs [Ref(Some(294452550321273018071988539960330649902))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau for instance Ref(Some(294452550321273018071988539960330649902)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS event applied: 0 added, 0 removed, 1 updated -[INFO librojo::change_processor] VFS event: WRITE src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS: canonicalize OK for src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -> src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\HUD.luau affects IDs [Ref(Some(294452550321273018071988539960330649902))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau for instance Ref(Some(294452550321273018071988539960330649902)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS event applied: no changes -[INFO librojo::change_processor] Tree reconciliation: corrected 4 added, 4 removed (13.5s) -[INFO librojo::change_processor] VFS event: WRITE d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS: canonicalize OK for d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -> src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\HUD.luau affects IDs [Ref(Some(294452550321273018071988539960330649902))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau for instance Ref(Some(294452550321273018071988539960330649902)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS event applied: 0 added, 0 removed, 1 updated -[INFO librojo::change_processor] VFS event: WRITE src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS: canonicalize OK for src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -> src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\HUD.luau affects IDs [Ref(Some(294452550321273018071988539960330649902))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau for instance Ref(Some(294452550321273018071988539960330649902)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS event applied: no changes -[INFO librojo::change_processor] VFS event: WRITE d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS: canonicalize OK for d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -> src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\HUD.luau affects IDs [Ref(Some(294452550321273018071988539960330649902))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau for instance Ref(Some(294452550321273018071988539960330649902)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS event applied: no changes -[INFO librojo::change_processor] VFS event: WRITE src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS: canonicalize OK for src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -> src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\HUD.luau affects IDs [Ref(Some(294452550321273018071988539960330649902))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau for instance Ref(Some(294452550321273018071988539960330649902)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS event applied: no changes -[INFO librojo::change_processor] Tree reconciliation: corrected 4 added, 4 removed (14.0s) -[INFO librojo::change_processor] VFS event: WRITE d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS: canonicalize OK for d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -> src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\HUD.luau affects IDs [Ref(Some(294452550321273018071988539960330649902))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau for instance Ref(Some(294452550321273018071988539960330649902)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS event applied: 0 added, 0 removed, 1 updated -[INFO librojo::change_processor] VFS event: WRITE src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS: canonicalize OK for src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -> src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\HUD.luau affects IDs [Ref(Some(294452550321273018071988539960330649902))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau for instance Ref(Some(294452550321273018071988539960330649902)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS event applied: no changes -[INFO librojo::change_processor] Tree reconciliation: corrected 4 added, 4 removed (13.8s) -[INFO librojo::change_processor] VFS event: WRITE d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS: canonicalize OK for d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -> src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\HUD.luau affects IDs [Ref(Some(294452550321273018071988539960330649902))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau for instance Ref(Some(294452550321273018071988539960330649902)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS event applied: 0 added, 0 removed, 1 updated -[INFO librojo::change_processor] VFS event: WRITE src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS: canonicalize OK for src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -> src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\HUD.luau affects IDs [Ref(Some(294452550321273018071988539960330649902))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau for instance Ref(Some(294452550321273018071988539960330649902)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS event applied: no changes -[INFO librojo::change_processor] VFS event: WRITE d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS: canonicalize OK for d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -> src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\HUD.luau affects IDs [Ref(Some(294452550321273018071988539960330649902))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau for instance Ref(Some(294452550321273018071988539960330649902)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS event applied: no changes -[INFO librojo::change_processor] VFS event: WRITE src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS: canonicalize OK for src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -> src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\HUD.luau affects IDs [Ref(Some(294452550321273018071988539960330649902))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau for instance Ref(Some(294452550321273018071988539960330649902)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS event applied: no changes -[INFO librojo::change_processor] Tree reconciliation: corrected 4 added, 4 removed (13.0s) -[INFO librojo::change_processor] VFS event: WRITE d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS: canonicalize OK for d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -> src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\HUD.luau affects IDs [Ref(Some(294452550321273018071988539960330649902))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau for instance Ref(Some(294452550321273018071988539960330649902)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS event applied: 0 added, 0 removed, 1 updated -[INFO librojo::change_processor] VFS event: WRITE src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS: canonicalize OK for src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -> src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\HUD.luau affects IDs [Ref(Some(294452550321273018071988539960330649902))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau for instance Ref(Some(294452550321273018071988539960330649902)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS event applied: no changes -[INFO librojo::change_processor] VFS event: WRITE d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS: canonicalize OK for d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -> src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\HUD.luau affects IDs [Ref(Some(294452550321273018071988539960330649902))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau for instance Ref(Some(294452550321273018071988539960330649902)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS event applied: no changes -[INFO librojo::change_processor] VFS event: WRITE src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS: canonicalize OK for src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -> src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\HUD.luau affects IDs [Ref(Some(294452550321273018071988539960330649902))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau for instance Ref(Some(294452550321273018071988539960330649902)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS event applied: no changes -[INFO librojo::change_processor] Tree reconciliation: corrected 4 added, 4 removed (13.6s) -[INFO librojo::change_processor] VFS event: WRITE d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS: canonicalize OK for d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -> src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\HUD.luau affects IDs [Ref(Some(294452550321273018071988539960330649902))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau for instance Ref(Some(294452550321273018071988539960330649902)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS event applied: 0 added, 0 removed, 1 updated -[INFO librojo::change_processor] VFS event: WRITE src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS: canonicalize OK for src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -> src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\HUD.luau affects IDs [Ref(Some(294452550321273018071988539960330649902))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau for instance Ref(Some(294452550321273018071988539960330649902)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\HUD.luau -[INFO librojo::change_processor] VFS event applied: no changes -[INFO librojo::change_processor] Tree reconciliation: corrected 4 added, 4 removed (13.8s) -[INFO librojo::change_processor] VFS event: WRITE d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -[INFO librojo::change_processor] VFS: canonicalize OK for d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -> src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau affects IDs [Ref(Some(162268450181648175032536457080084761373))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau for instance Ref(Some(162268450181648175032536457080084761373)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -[INFO librojo::change_processor] VFS event applied: 0 added, 0 removed, 1 updated -[INFO librojo::change_processor] VFS event: WRITE src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -[INFO librojo::change_processor] VFS: canonicalize OK for src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -> src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau affects IDs [Ref(Some(162268450181648175032536457080084761373))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau for instance Ref(Some(162268450181648175032536457080084761373)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -[INFO librojo::change_processor] VFS event applied: no changes -[INFO librojo::change_processor] Tree reconciliation: corrected 4 added, 4 removed (12.5s) -[INFO librojo::change_processor] VFS event: WRITE d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -[INFO librojo::change_processor] VFS: canonicalize OK for d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -> src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau affects IDs [Ref(Some(162268450181648175032536457080084761373))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau for instance Ref(Some(162268450181648175032536457080084761373)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -[INFO librojo::change_processor] VFS event applied: 0 added, 0 removed, 1 updated -[INFO librojo::change_processor] VFS event: WRITE src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -[INFO librojo::change_processor] VFS: canonicalize OK for src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -> src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau affects IDs [Ref(Some(162268450181648175032536457080084761373))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau for instance Ref(Some(162268450181648175032536457080084761373)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -[INFO librojo::change_processor] VFS event applied: no changes -[INFO librojo::change_processor] Tree reconciliation: corrected 4 added, 4 removed (12.0s) -[INFO librojo::change_processor] VFS event: WRITE d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -[INFO librojo::change_processor] VFS: canonicalize OK for d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -> src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau affects IDs [Ref(Some(162268450181648175032536457080084761373))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau for instance Ref(Some(162268450181648175032536457080084761373)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -[INFO librojo::change_processor] VFS event applied: 0 added, 0 removed, 1 updated -[INFO librojo::change_processor] VFS event: WRITE src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -[INFO librojo::change_processor] VFS: canonicalize OK for src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -> src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau affects IDs [Ref(Some(162268450181648175032536457080084761373))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau for instance Ref(Some(162268450181648175032536457080084761373)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -[INFO librojo::change_processor] VFS event applied: no changes -[INFO librojo::change_processor] Tree reconciliation: corrected 4 added, 4 removed (13.6s) -[INFO librojo::web::api] Syncback: Updating properties for instance Ref(Some(235969869441813210778056584779662649683)): Source -[INFO librojo::web::api] Syncback: Updating properties for instance Ref(Some(291040600291607857644497431099122037291)): Source -[INFO librojo::change_processor] Two-way sync: Writing Source to d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Shared\Traits\Galaxy.luau -[INFO librojo::change_processor] Two-way sync: Writing Source to d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Shared\Traits\Magma.luau -[INFO librojo::change_processor] VFS event: WRITE d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Shared\Traits\Galaxy.luau -[INFO librojo::change_processor] VFS event SUPPRESSED (API syncback echo): d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Shared\Traits\Galaxy.luau -[INFO librojo::change_processor] VFS event: WRITE src\ReplicatedStorage\Shared\Traits\Galaxy.luau -[INFO librojo::change_processor] VFS: canonicalize OK for src\ReplicatedStorage\Shared\Traits\Galaxy.luau -> src\ReplicatedStorage\Shared\Traits\Galaxy.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Shared\Traits\Galaxy.luau affects IDs [Ref(Some(235969869441813210778056584779662649683))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Shared\Traits\Galaxy.luau for instance Ref(Some(235969869441813210778056584779662649683)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Shared\Traits\Galaxy.luau -[INFO librojo::change_processor] VFS event applied: no changes -[INFO librojo::change_processor] VFS event: WRITE d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Shared\Traits\Magma.luau -[INFO librojo::change_processor] VFS event SUPPRESSED (API syncback echo): d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Shared\Traits\Magma.luau -[INFO librojo::change_processor] VFS event: WRITE src\ReplicatedStorage\Shared\Traits\Magma.luau -[INFO librojo::change_processor] VFS: canonicalize OK for src\ReplicatedStorage\Shared\Traits\Magma.luau -> src\ReplicatedStorage\Shared\Traits\Magma.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Shared\Traits\Magma.luau affects IDs [Ref(Some(291040600291607857644497431099122037291))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Shared\Traits\Magma.luau for instance Ref(Some(291040600291607857644497431099122037291)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Shared\Traits\Magma.luau -[INFO librojo::change_processor] VFS event applied: no changes -[INFO librojo::change_processor] Tree reconciliation: corrected 4 added, 4 removed (12.5s) -[INFO librojo::change_processor] VFS event: WRITE d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -[INFO librojo::change_processor] VFS: canonicalize OK for d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -> src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau affects IDs [Ref(Some(162268450181648175032536457080084761373))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau for instance Ref(Some(162268450181648175032536457080084761373)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -[INFO librojo::change_processor] VFS event applied: 0 added, 0 removed, 1 updated -[INFO librojo::change_processor] VFS event: WRITE src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -[INFO librojo::change_processor] VFS: canonicalize OK for src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -> src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -[INFO librojo::change_processor] apply_patches: path src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau affects IDs [Ref(Some(162268450181648175032536457080084761373))] -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau for instance Ref(Some(162268450181648175032536457080084761373)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -[INFO librojo::change_processor] VFS event applied: no changes -[INFO librojo::change_processor] Tree reconciliation: corrected 4 added, 4 removed (12.3s) - - INFO [Studio] [Rojo] User selections: 0 push, 0 pull, 0 ignored - INFO [Studio] [Rojo] One-shot sync: disconnecting after initial sync complete -DEBUG Could not resolve path reference Part0 at path '@game/ServerScriptService/Services/EventService/Events/Sammy's Base/SammyBase/Computer Desk/Taco~3/Meshes_Tacos_Cube4' - instance not found in tree -DEBUG Could not resolve path reference Part0 at path '@game/Workspace/Events/FatSammy/Model/SammyArms/Arm~3/Meshes_SpyderSammyArms_spydersammy.007' - instance not found in tree -DEBUG Could not resolve path reference Part0 at path '@game/ServerScriptService/Services/EventService/Events/Sammy's Base/SammyBase/Computer Desk/Taco~3/Meshes_Tacos_Cube4' - instance not found in tree -DEBUG Could not resolve path reference Part0 at path '@game/Workspace/Events/FatSammy/Model/SammyArms/Arm/Meshes_SpyderSammyArms_spydersammy.005' - instance not found in tree -DEBUG Could not resolve path reference Part0 at path '@game/ServerScriptService/Services/EventService/Events/Sammy's Base/SammyBase/Computer Desk/Taco~2/Meshes_Tacos_Cube3' - instance not found in tree -DEBUG Could not resolve path reference Part0 at path '@game/ServerScriptService/Services/EventService/Events/Sammy's Base/SammyBase/Computer Desk/Taco~2/Meshes_Tacos_Cube3' - instance not found in tree -DEBUG Could not resolve path reference Part0 at path '@game/Workspace/Events/FatSammy/Model/SammyArms/Arm~2/Meshes_SpyderSammyArms_spydersammy.006' - instance not found in tree -DEBUG Could not resolve path reference Part0 at path '@game/ServerScriptService/Services/EventService/Events/Sammy's Base/SammyBase/Computer Desk/Taco~4/Meshes_Tacos_Cube5' - instance not found in tree -DEBUG Could not resolve path reference Part0 at path '@game/Workspace/Events/FatSammy/Model/SammyArms/Arm~4/Meshes_SpyderSammyArms_spydersammy.008' - instance not found in tree -DEBUG Could not resolve path reference Part0 at path '@game/ServerScriptService/Services/EventService/Events/Sammy's Base/SammyBase/Computer Desk/Taco~4/Meshes_Tacos_Cube5' - instance not found in tree -DEBUG Could not resolve path reference Part1 at path '@game/ServerStorage/Backlog/Fruttina Jetolina/Fruttina Jetolina/Halo' - instance not found in tree -DEBUG Could not resolve path reference Part0 at path '@game/ServerScriptService/Services/EventService/Events/Sammy's Base/SammyBase/Computer Desk/Taco/Meshes_Tacos_Cube1' - instance not found in tree -DEBUG Could not resolve path reference Part0 at path '@game/ServerScriptService/Services/EventService/Events/Sammy's Base/SammyBase/Computer Desk/Taco~4/Meshes_Tacos_Cube5' - instance not found in tree -DEBUG Could not resolve path reference Part0 at path '@game/ServerScriptService/Services/EventService/Events/Sammy's Base/SammyBase/Computer Desk/Taco/Meshes_Tacos_Cube1' - instance not found in tree -DEBUG Could not resolve path reference Part0 at path '@game/ServerScriptService/Services/EventService/Events/Sammy's Base/SammyBase/Computer Desk/Taco~3/Meshes_Tacos_Cube4' - instance not found in tree -DEBUG Could not resolve path reference Part1 at path '@game/ServerStorage/Backlog/Crabo Biscotto/Crabo Biscotto/Halo' - instance not found in tree -DEBUG Could not resolve path reference Part0 at path '@game/ServerScriptService/Services/EventService/Events/Sammy's Base/SammyBase/Computer Desk/Taco/Meshes_Tacos_Cube1' - instance not found in tree -DEBUG Could not resolve path reference Part0 at path '@game/ServerScriptService/Services/EventService/Events/Sammy's Base/SammyBase/Computer Desk/Taco~2/Meshes_Tacos_Cube3' - instance not found in tree - INFO Tree reconciliation: corrected 12 added, 12 removed (54.6s) - - DEBUG Loading project file from \\?\D:\UserGenerated\steal-a-brainrot\default.project.json5 - INFO Tree reconciliation: corrected 4 added, 4 removed (45.3s) - -CONSTANTLY happening everytime i modify a file: -[INFO librojo::change_processor] Tree reconciliation: corrected 4 added, 4 removed (22.1s) - -I'm really confused why this was slamming over and over saying 4 added, 4 removed - seems like a bug. -We need to investigate Tree reconciliation, make sure it's parallel, etc. -I'd really like to just reconcile specific paths that were modified - but i'm not sure if that just defeats the purpose.. need to explore this topic later. -Worst case - we reconcile only on connect, but do so in mega-parallel - [vscode file watcher] Also, we need to explore how VSCode deals with this. They seem to have ZERO issues. Maybe we can have a mode to tie into the vscode file watcher ourselves? luau-lsp does this. -[logging] -console logging is now: - INFO Input file 'd:\UserGenerated\steal-a-brainrot\.\Project.rbxl' not found, downloading place 120148879522453... - INFO Loaded cookie from Windows Credentials (user_id: 2882755487). - INFO Downloaded in 0.77s - WARN Performing lossy string conversion on property StringValue.Value because it did not contain UTF-8. -This may cause unexpected or broken behavior in your final results if you rely on this property being non UTF-8. -when it used to be this format: -[INFO librojo::change_processor] compute_and_apply_changes: checking path d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau for instance Ref(Some(162268450181648175032536457080084761373)) -[INFO librojo::change_processor] compute_and_apply_changes: path EXISTS via VFS, re-snapshotting d:\UserGenerated\escape-tsunami\src\ReplicatedStorage\Client\Controllers\UI\CurrenciesUI.luau -[INFO librojo::change_processor] VFS event applied: no changes -[INFO librojo::change_processor] Tree reconciliation: corrected 4 added, 4 removed (12.3s) - -please fix this regression. - [fix dedup] dedup is broken due to relying on sort order recreate broken state by forcing random order in all matching dedup systems of the incoming children list @@ -361,62 +90,10 @@ in all 3 matchers, simply randomize the order of the children - this will break can we allow the terminal to stay so i can like run some git commands myself without having to make a whole new terminal? [mcp] -* DONE: sync - - add modes: - - standard (default): what we currently have where if there are changes it waits for the user to act - - manual: user must always interact - - fastfail: if there are non auto selected changes, immediately fail without waiting for the user to reject - - dryrun: just checks what would be done and then returns out immediately - - provide the agent hashes of the current scripts on studio involved in the merge - - allow the agent to specify patches it wants to accept automatically - - for sciprts, need to include a hash of the file ON roblox studio currently to signify there wasn't MORE new changes in the mid-term - - for properties, just include what we are accepting -* DONE: get_script PATH [from draft?] - - allows the agent to read a script currently on studio - - the core purpose of this endpoint is to utilize with sync when failures occur due to other people changing things, and then allow us to grab their changes, compare against the previous git version we have and then integrate their changes and then sending another sync with the expected hash of the file on roblox to allow it to auto-accept (via an mcp override we specify in the json of the request to sync) - - by default directly reads the Source property on the script - - optional to allow the agent to read the draft - - this is needed when an agent tries to sync and it fails due to a conflict since we don't send back sources in the failure - - agen't can complete merges by itself with properties, so we don't need a way for the agent to read properties for things - - the PATH will be: ReplicatedStorage/Some/Path/Abc - like a direct instance path, not a atlas aware path. - - we should steal this system fully: D:\UserGenerated\studio-rust-mcp-server\plugin\Utils\Paths.luau - - in the sync feedback it gives, we should include Paths.GetRelativePath so the agent is able to find it via the read_script ALONGSIDE the current info we can give so it can also find it on the Atlas filesystem - - investigate this further, because i just want to give the agent the best possible way to query roblox instances, and also atlas instances on the filesystem. if using this Paths module is an overstep and we can accomplish it with a fully atlas-based approach, that's fine - aslong as it works CONSISTENTLY and is simple. -* DONE: port all of the basic MCP endpoints offered via https://github.com/Roblox/studio-rust-mcp-server - - integrate them into how we've done our mcp in atlas - - make sure to handle the placeid filtering like we already do when establishing the connection - - we've done some actual fixes over at D:\UserGenerated\studio-rust-mcp-server on these, we should probably pull those fixed versions! we don't need that whole studio selection system from over there, though. - - we don't need to restructure ours to be like this, but i like the .md doc setup. -* DONE: add logging for all agent connect/disconnects in the terminal - - also add logging for commands (including the json) it runs and the resulting json. try to keep this on one line please, json compact. -* DONE: ensure all mcp route documentation is well formed and gives the agent knowledge on how to use this system to the fullest. - - I did .md based docs over with my D:\UserGenerated\studio-rust-mcp-server codebase, we should probably switch to this as it's cleaner - - Instruct on good sync flow, with get_script merging. - - If user requests get_script and we havn't sync'd yet, just do a dryrun sync to get the instance id map going. * syncback - invokes plugin based syncback - ensure this doesn't interrupt the connection of the mcp, since i think we shutdown the api? we should just not shutdown the api or something -[logging] -* I want to add verbose logging .atlas in the directory being synced from - - Need to add to project template .gitignore for .atlas/ -* We should do rolling logs, and it should compress them automatically -* Will the existing logging infra take care of this? -* I want to have it include trace logging -* I also want to forward the roblox logs continously via the mcp connection and log them to the serve output, such they will end up in the rolling logs - - Make sure to retain the log-level (print, warn, error, etc) - - I'm open to having these actually divert and not send in the rust logging system and go to it's own file, and maybe a separate rust logger so we don't need to create our own infrastructure - - We could also just save logging output WHILST we are synced to the serve (would even work for one-shot) so as to not have a bunch of useless log info, though I think the mcp one is stronger. -* See: https://create.roblox.com/docs/reference/engine/classes/LogService - - We should adapt the rojo logger to route through this, as it offers better level info - - Listen to MessageOut to get the log info we are wanting. - - Is this actually the one we want? I might be confused, check the docs, this looks new. -* The goal with these trace logging is so that when others are using this tool, we can actually debug real issues by having them send me their logs. - -[sync] -right now sync is running REALLY slow -we need to create an agent loop so it can benchmark the plugin + rust side automatically over and over to determine the root cause of this slowness - [automated review of all changes done, similar to cursor agent review for the game] it's a discord bot we send discord channels @@ -445,10 +122,6 @@ additional inspo: https://cursor.com/dashboard?tab=bugbot - need to ensure that only certain perm users can use the bot - we need to make sure not just any public server with a bot link can just run this, because it will be using my system resources and could be insecure. this is a proprietary tool. -[git] -complete audit of our git module to see what we can leverage the gix api directly instead of hard coding in really slow ways ourselves -we can probably just call built-in functions to accomplish a lot of that hardcore tasks we are doing that would give 10-100x speedups - [path canonicalize] DEBUG Loading project file from D:\UserGenerated\steal-a-brainrot\default.project.json5 DEBUG Prefetch walk: 248397 files + 74573 dirs from 1 root(s) in 2.2s @@ -456,15 +129,3 @@ DEBUG Prefetch I/O: read 248397 files in 702.5ms, canonicalize 322970 paths in 3 DEBUG Prefetch maps: 322970 is_file + 74573 children dirs built DEBUG Prefetch total: 248397 files + 322970 canonical paths in 7.9s get rid of this bulk path canonaclize where possible, it seems utterly pointless in most cases - -[git really slow] -DEBUG [TIMING] compute_git_metadata: open_repo 1ms -DEBUG [TIMING] compute_git_metadata: using 1 project prefixes -DEBUG [TIMING] compute_git_metadata: status iterator created 155ms -DEBUG [TIMING] compute_git_metadata: status iteration 2191ms (3 tracked, 0 untracked) -DEBUG [TIMING] compute_git_metadata: git_changed_files_impl 2347ms (3 tracked, 0 untracked) -DEBUG [TIMING] compute_git_metadata: tree resolution 0ms (3 changed -> 3 resolved) -DEBUG [TIMING] compute_git_metadata: batch_check_hashes 389ms (9 refs) -DEBUG [TIMING] compute_git_metadata: total 2739ms (3 changed_ids, 3 script_hashes, 0 new_file_ids) - INFO [Studio] [Rojo] One-shot mode: skipping all auto-accept paths, requiring explicit confirmation - diff --git a/src/git.rs b/src/git.rs index 7d0d82f0..2f5dfe68 100644 --- a/src/git.rs +++ b/src/git.rs @@ -1,12 +1,13 @@ use std::{ collections::{HashMap, HashSet}, + io::Write, path::{Path, PathBuf}, + process::{Command, Stdio}, sync::{Arc, Mutex}, time::Instant, }; use anyhow::Context; -use gix::bstr::{BString, ByteSlice}; use rbx_dom_weak::types::Ref; use sha1::{Digest, Sha1}; @@ -15,21 +16,40 @@ use crate::{ web::interface::GitMetadata, }; -fn open_repo(path: &Path) -> Option { - gix::discover(path).ok() -} - pub fn git_repo_root(project_root: &Path) -> Option { - let repo = open_repo(project_root)?; - repo.workdir().map(|p| p.to_owned()) + let output = Command::new("git") + .args(["rev-parse", "--show-toplevel"]) + .current_dir(project_root) + .output() + .ok()?; + + if !output.status.success() { + return None; + } + + let stdout = String::from_utf8_lossy(&output.stdout); + let path_str = stdout.trim(); + if path_str.is_empty() { + return None; + } + + Some(PathBuf::from(path_str)) } /// Returns the current HEAD commit SHA, or `None` if there are no commits /// or the project is not in a git repo. pub fn git_head_commit(repo_root: &Path) -> Option { - let repo = open_repo(repo_root)?; - let head_id = repo.head_id().ok()?; - let hex = head_id.to_hex().to_string(); + let output = Command::new("git") + .args(["rev-parse", "HEAD"]) + .current_dir(repo_root) + .output() + .ok()?; + + if !output.status.success() { + return None; + } + + let hex = String::from_utf8_lossy(&output.stdout).trim().to_string(); if hex.len() == 40 && hex.bytes().all(|b| b.is_ascii_hexdigit()) { Some(hex) } else { @@ -52,74 +72,85 @@ impl ChangedFiles { } } -fn resolve_tree_id(repo: &gix::Repository, rev: &str) -> Option { - let id = repo.rev_parse_single(rev.as_bytes()).ok()?; - let tree = id.object().ok()?.peel_to_tree().ok()?; - Some(tree.id().detach()) -} - fn git_changed_files_impl( - repo: &gix::Repository, + repo_root: &Path, initial_head: Option<&str>, project_prefixes: &[String], ) -> Option { let mut tracked = HashSet::new(); let mut untracked = HashSet::new(); - let patterns: Vec = project_prefixes - .iter() - .map(|p| BString::from(p.as_str())) - .collect(); + let base = initial_head.unwrap_or("HEAD"); let t = Instant::now(); - let mut platform = match repo.status(gix::progress::Discard) { - Ok(p) => p, - Err(e) => { - log::warn!("Failed to initialize git status: {}", e); - return None; - } - }; - if let Some(ih) = initial_head { - if let Some(tree_id) = resolve_tree_id(repo, ih) { - platform = platform.head_tree(tree_id); + let mut diff_cmd = Command::new("git"); + diff_cmd + .args(["diff", base, "--name-only"]) + .current_dir(repo_root); + if !project_prefixes.is_empty() { + diff_cmd.arg("--"); + for prefix in project_prefixes { + diff_cmd.arg(prefix); } } + let diff_output = diff_cmd.output().ok()?; - let iter = match platform.into_iter(patterns) { - Ok(i) => i, - Err(e) => { - log::warn!("Failed to create git status iterator: {}", e); - return None; - } - }; - log::debug!( - "[TIMING] compute_git_metadata: status iterator created {}ms", - t.elapsed().as_millis() - ); - - let t = Instant::now(); - for item in iter { - let item = match item { - Ok(i) => i, - Err(_) => continue, - }; - match &item { - gix::status::Item::TreeIndex(_) => { - tracked.insert(PathBuf::from(item.location().to_str_lossy().as_ref())); + if diff_output.status.success() { + for line in String::from_utf8_lossy(&diff_output.stdout).lines() { + let trimmed = line.trim(); + if !trimmed.is_empty() { + tracked.insert(PathBuf::from(trimmed)); } - gix::status::Item::IndexWorktree(iw_item) => match iw_item { - gix::status::index_worktree::Item::DirectoryContents { .. } => { - untracked.insert(PathBuf::from(item.location().to_str_lossy().as_ref())); - } - _ => { - tracked.insert(PathBuf::from(item.location().to_str_lossy().as_ref())); - } - }, + } + } else { + log::debug!("git diff {} failed (possibly no commits yet)", base); + } + + let mut cached_cmd = Command::new("git"); + cached_cmd + .args(["diff", "--cached", "--name-only"]) + .current_dir(repo_root); + if !project_prefixes.is_empty() { + cached_cmd.arg("--"); + for prefix in project_prefixes { + cached_cmd.arg(prefix); } } + if let Ok(cached_output) = cached_cmd.output() { + if cached_output.status.success() { + for line in String::from_utf8_lossy(&cached_output.stdout).lines() { + let trimmed = line.trim(); + if !trimmed.is_empty() { + tracked.insert(PathBuf::from(trimmed)); + } + } + } + } + + let mut ls_cmd = Command::new("git"); + ls_cmd + .args(["ls-files", "--others", "--exclude-standard"]) + .current_dir(repo_root); + if !project_prefixes.is_empty() { + ls_cmd.arg("--"); + for prefix in project_prefixes { + ls_cmd.arg(prefix); + } + } + if let Ok(untracked_output) = ls_cmd.output() { + if untracked_output.status.success() { + for line in String::from_utf8_lossy(&untracked_output.stdout).lines() { + let trimmed = line.trim(); + if !trimmed.is_empty() { + untracked.insert(PathBuf::from(trimmed)); + } + } + } + } + log::debug!( - "[TIMING] compute_git_metadata: status iteration {}ms ({} tracked, {} untracked)", + "[TIMING] compute_git_metadata: git_changed_files_impl {}ms ({} tracked, {} untracked)", t.elapsed().as_millis(), tracked.len(), untracked.len() @@ -128,53 +159,69 @@ fn git_changed_files_impl( Some(ChangedFiles { tracked, untracked }) } -fn resolve_object_ref(repo: &gix::Repository, object_ref: &str) -> Option { - if let Some(path) = object_ref.strip_prefix(":0:") { - let index = repo.open_index().ok()?; - let bstr_path: &gix::bstr::BStr = path.as_bytes().as_bstr(); - let entry = index.entry_by_path(bstr_path)?; - Some(entry.id.to_hex().to_string()) - } else if let Some((rev, path)) = object_ref.split_once(':') { - let id = repo.rev_parse_single(rev.as_bytes()).ok()?; - let tree = id.object().ok()?.peel_to_tree().ok()?; - let entry = tree.lookup_entry_by_path(path).ok()??; - Some(entry.object_id().to_hex().to_string()) - } else { - None +fn git_batch_check_hashes_impl(repo_root: &Path, object_refs: &[String]) -> Vec> { + if object_refs.is_empty() { + return Vec::new(); } -} -fn git_batch_check_hashes_impl( - repo: &gix::Repository, - object_refs: &[String], -) -> Vec> { - object_refs - .iter() - .map(|r| resolve_object_ref(repo, r)) + let mut child = match Command::new("git") + .args(["cat-file", "--batch-check"]) + .current_dir(repo_root) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::null()) + .spawn() + { + Ok(c) => c, + Err(e) => { + log::warn!("Failed to spawn git cat-file --batch-check: {}", e); + return object_refs.iter().map(|_| None).collect(); + } + }; + + if let Some(mut stdin) = child.stdin.take() { + for r in object_refs { + let _ = writeln!(stdin, "{}", r); + } + } + + let output = match child.wait_with_output() { + Ok(o) => o, + Err(e) => { + log::warn!("git cat-file --batch-check failed: {}", e); + return object_refs.iter().map(|_| None).collect(); + } + }; + + let stdout = String::from_utf8_lossy(&output.stdout); + stdout + .lines() + .map(|line| { + let parts: Vec<&str> = line.split_whitespace().collect(); + if parts.len() >= 2 && parts[1] != "missing" { + let sha = parts[0]; + if sha.len() == 40 && sha.bytes().all(|b| b.is_ascii_hexdigit()) { + return Some(sha.to_string()); + } + } + None + }) .collect() } #[cfg(test)] fn git_show(repo_root: &Path, object_ref: &str) -> Option { - let repo = open_repo(repo_root)?; - if let Some(path) = object_ref.strip_prefix(":0:") { - let index = repo.open_index().ok()?; - let bstr_path: &gix::bstr::BStr = path.as_bytes().as_bstr(); - let entry = index.entry_by_path(bstr_path)?; - let obj = repo.find_object(entry.id).ok()?; - String::from_utf8(obj.data.to_vec()).ok() - } else if object_ref.contains(':') { - let (rev, path) = object_ref.split_once(':')?; - let id = repo.rev_parse_single(rev.as_bytes()).ok()?; - let tree = id.object().ok()?.peel_to_tree().ok()?; - let entry = tree.lookup_entry_by_path(path).ok()??; - let obj = entry.id().object().ok()?; - String::from_utf8(obj.data.to_vec()).ok() - } else { - let id = repo.rev_parse_single(object_ref.as_bytes()).ok()?; - let obj = id.object().ok()?; - String::from_utf8(obj.data.to_vec()).ok() + let output = Command::new("git") + .args(["show", object_ref]) + .current_dir(repo_root) + .output() + .ok()?; + + if !output.status.success() { + return None; } + + String::from_utf8(output.stdout).ok() } #[cfg(test)] @@ -217,16 +264,32 @@ pub struct GitIndexCache { impl GitIndexCache { pub fn new(project_root: &Path) -> Option { - let repo = open_repo(project_root)?; - let repo_root = repo.workdir()?.to_owned(); - let index = repo.open_index().ok()?; + let repo_root = git_repo_root(project_root)?; + + let output = Command::new("git") + .args(["ls-files", "--stage"]) + .current_dir(&repo_root) + .output() + .ok()?; + + if !output.status.success() { + return None; + } let mut entries = HashMap::new(); - for entry in index.entries() { - let path_bstr = entry.path(&index); - let path_str = path_bstr.to_str().ok()?; - let rel_path = PathBuf::from(path_str); - let hash_hex = entry.id.to_hex().to_string(); + let stdout = String::from_utf8_lossy(&output.stdout); + for line in stdout.lines() { + // Format: \t + let (meta, path) = match line.split_once('\t') { + Some(pair) => pair, + None => continue, + }; + let parts: Vec<&str> = meta.split_whitespace().collect(); + if parts.len() < 2 { + continue; + } + let hash_hex = parts[1].to_string(); + let rel_path = PathBuf::from(path); let abs_path = repo_root.join(&rel_path); let project_rel = abs_path @@ -263,7 +326,7 @@ pub fn git_add(repo_root: &Path, paths: &[PathBuf]) { return; } - let output = match std::process::Command::new("git") + let output = match Command::new("git") .arg("add") .arg("--") .args(paths) @@ -287,7 +350,7 @@ pub fn git_add(repo_root: &Path, paths: &[PathBuf]) { /// Returns true if the given file path is staged in the git index. pub fn git_is_staged(repo_root: &Path, file: &str) -> bool { - let output = match std::process::Command::new("git") + let output = match Command::new("git") .args(["diff", "--cached", "--name-only"]) .current_dir(repo_root) .output() @@ -301,7 +364,7 @@ pub fn git_is_staged(repo_root: &Path, file: &str) -> bool { /// Stage all worktree files and create a commit. pub fn git_add_all_and_commit(dir: &Path, message: &str) { - let add = std::process::Command::new("git") + let add = Command::new("git") .args(["add", "-A"]) .current_dir(dir) .output(); @@ -317,7 +380,7 @@ pub fn git_add_all_and_commit(dir: &Path, message: &str) { _ => {} } - let commit = std::process::Command::new("git") + let commit = Command::new("git") .args(["commit", "-m", message]) .current_dir(dir) .output(); @@ -336,7 +399,7 @@ pub fn git_add_all_and_commit(dir: &Path, message: &str) { /// Initialize a new git repository with line-ending config for cross-platform consistency. pub fn git_init_repo(dir: &Path) -> anyhow::Result<()> { - let init = std::process::Command::new("git") + let init = Command::new("git") .arg("init") .current_dir(dir) .output() @@ -345,20 +408,15 @@ pub fn git_init_repo(dir: &Path) -> anyhow::Result<()> { anyhow::bail!("git init failed: {}", String::from_utf8_lossy(&init.stderr)); } - let config = std::process::Command::new("git") + let _ = Command::new("git") .args(["config", "--local", "core.autocrlf", "false"]) .current_dir(dir) .output(); - if let Ok(o) = &config { - if !o.status.success() { - log::warn!("Failed to set core.autocrlf"); - } - } - let _ = std::process::Command::new("git") + let _ = Command::new("git") .args(["config", "--local", "core.eol", "lf"]) .current_dir(dir) .output(); - let _ = std::process::Command::new("git") + let _ = Command::new("git") .args(["config", "--local", "core.safecrlf", "false"]) .current_dir(dir) .output(); @@ -368,7 +426,7 @@ pub fn git_init_repo(dir: &Path) -> anyhow::Result<()> { /// Shallow-clone a git repository into `target_dir`, depth 1. pub fn git_clone_shallow(url: &str, target_dir: &Path) -> anyhow::Result<()> { - let output = std::process::Command::new("git") + let output = Command::new("git") .args(["clone", "--depth", "1", url]) .arg(target_dir) .output() @@ -390,13 +448,10 @@ struct ResolvedInstance { /// Computes git metadata for the two-way sync confirmation UI. /// -/// `repo_root` must be the git repository root (from `git_repo_root()`), -/// cached at session start by `ServeSession`. -/// /// Uses a three-phase approach to avoid holding the tree lock during I/O: -/// 1. Use gix to get changed files scoped to project prefixes (no lock) +/// 1. Run git commands to get changed files scoped to project prefixes (no lock) /// 2. Briefly lock tree to resolve file paths to instance Refs and class names -/// 3. Direct object/index lookups to get blob hashes (no lock) +/// 3. Single `git cat-file --batch-check` to get blob hashes (no lock) pub fn compute_git_metadata( tree_handle: &Arc>, repo_root: &Path, @@ -406,28 +461,7 @@ pub fn compute_git_metadata( let total_t = Instant::now(); let t = Instant::now(); - let repo = match open_repo(repo_root) { - Some(r) => r, - None => { - return GitMetadata { - changed_ids: Vec::new(), - script_committed_hashes: HashMap::new(), - new_file_ids: Vec::new(), - }; - } - }; - log::debug!( - "[TIMING] compute_git_metadata: open_repo {}ms", - t.elapsed().as_millis() - ); - - log::debug!( - "[TIMING] compute_git_metadata: using {} project prefixes", - project_prefixes.len() - ); - - let t = Instant::now(); - let changed_files = match git_changed_files_impl(&repo, initial_head, project_prefixes) { + let changed_files = match git_changed_files_impl(repo_root, initial_head, project_prefixes) { Some(files) => files, None => { log::debug!( @@ -552,7 +586,7 @@ pub fn compute_git_metadata( } let t = Instant::now(); - let batch_hashes = git_batch_check_hashes_impl(&repo, &object_refs); + let batch_hashes = git_batch_check_hashes_impl(repo_root, &object_refs); log::debug!( "[TIMING] compute_git_metadata: batch_check_hashes {}ms ({} refs)", t.elapsed().as_millis(), @@ -602,7 +636,7 @@ pub fn compute_git_metadata( /// which can cause git to report them as modified due to timestamp changes. pub fn refresh_git_index(project_dir: &Path) { log::info!("Refreshing git index..."); - let output = match std::process::Command::new("git") + let output = match Command::new("git") .args(["update-index", "--refresh"]) .current_dir(project_dir) .output() @@ -643,33 +677,22 @@ mod tests { } fn git_stage(dir: &Path, file: &str) { - let repo = open_repo(dir).expect("repo not found"); - git_add(repo.workdir().unwrap_or(dir), &[PathBuf::from(file)]); + git_add(dir, &[PathBuf::from(file)]); } - fn git_is_staged(dir: &Path, file: &str) -> bool { - let repo = open_repo(dir).expect("repo not found"); - let index = match repo.open_index() { - Ok(i) => i, - Err(_) => return false, - }; - let bstr_path: &gix::bstr::BStr = file.as_bytes().as_bstr(); - let index_entry = match index.entry_by_path(bstr_path) { - Some(e) => e, - None => return false, - }; - - let head_blob_id = repo - .head_commit() - .ok() - .and_then(|c| c.tree().ok()) - .and_then(|t| t.lookup_entry_by_path(file).ok().flatten()) - .map(|e| e.object_id()); - - match head_blob_id { - Some(head_id) => index_entry.id != head_id, - None => true, - } + fn git_hash_object(dir: &Path, content: &[u8]) -> String { + let output = Command::new("git") + .args(["hash-object", "--stdin"]) + .current_dir(dir) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .and_then(|mut child| { + child.stdin.take().unwrap().write_all(content).unwrap(); + child.wait_with_output() + }) + .expect("git hash-object failed"); + String::from_utf8(output.stdout).unwrap().trim().to_string() } // ----------------------------------------------------------------------- @@ -703,22 +726,6 @@ mod tests { assert_ne!(h1, h2); } - fn git_hash_object(dir: &Path, content: &[u8]) -> String { - let output = std::process::Command::new("git") - .args(["hash-object", "--stdin"]) - .current_dir(dir) - .stdin(std::process::Stdio::piped()) - .stdout(std::process::Stdio::piped()) - .spawn() - .and_then(|mut child| { - use std::io::Write; - child.stdin.take().unwrap().write_all(content).unwrap(); - child.wait_with_output() - }) - .expect("git hash-object failed"); - String::from_utf8(output.stdout).unwrap().trim().to_string() - } - #[test] fn blob_sha1_matches_git_hash_object() { let dir = tempdir().unwrap(); @@ -772,8 +779,7 @@ mod tests { fs::write(dir.path().join("file.luau"), "content").unwrap(); git_commit_all(dir.path(), "init"); - let repo = open_repo(dir.path()).unwrap(); - let changed = git_changed_files_impl(&repo, None, &[]); + let changed = git_changed_files_impl(dir.path(), None, &[]); assert!(changed.is_some()); assert!(changed.unwrap().is_empty()); } @@ -786,8 +792,7 @@ mod tests { git_commit_all(dir.path(), "init"); fs::write(dir.path().join("script.luau"), "modified").unwrap(); - let repo = open_repo(dir.path()).unwrap(); - let changed = git_changed_files_impl(&repo, None, &[]).unwrap(); + let changed = git_changed_files_impl(dir.path(), None, &[]).unwrap(); assert!(changed.tracked.contains(&PathBuf::from("script.luau"))); assert!(changed.untracked.is_empty()); } @@ -801,8 +806,7 @@ mod tests { fs::write(dir.path().join("script.luau"), "staged version").unwrap(); git_stage(dir.path(), "script.luau"); - let repo = open_repo(dir.path()).unwrap(); - let changed = git_changed_files_impl(&repo, None, &[]).unwrap(); + let changed = git_changed_files_impl(dir.path(), None, &[]).unwrap(); assert!(changed.tracked.contains(&PathBuf::from("script.luau"))); } @@ -814,8 +818,7 @@ mod tests { git_commit_all(dir.path(), "init"); fs::write(dir.path().join("new_file.luau"), "new").unwrap(); - let repo = open_repo(dir.path()).unwrap(); - let changed = git_changed_files_impl(&repo, None, &[]).unwrap(); + let changed = git_changed_files_impl(dir.path(), None, &[]).unwrap(); assert!(changed.untracked.contains(&PathBuf::from("new_file.luau"))); assert!(!changed.tracked.contains(&PathBuf::from("new_file.luau"))); } @@ -828,8 +831,7 @@ mod tests { git_commit_all(dir.path(), "init"); fs::remove_file(dir.path().join("to_delete.luau")).unwrap(); - let repo = open_repo(dir.path()).unwrap(); - let changed = git_changed_files_impl(&repo, None, &[]).unwrap(); + let changed = git_changed_files_impl(dir.path(), None, &[]).unwrap(); assert!(changed.tracked.contains(&PathBuf::from("to_delete.luau"))); } @@ -844,8 +846,7 @@ mod tests { fs::write(dir.path().join("will_modify.luau"), "new").unwrap(); fs::write(dir.path().join("untracked.luau"), "brand new").unwrap(); - let repo = open_repo(dir.path()).unwrap(); - let changed = git_changed_files_impl(&repo, None, &[]).unwrap(); + let changed = git_changed_files_impl(dir.path(), None, &[]).unwrap(); let all = changed.all(); assert!(all.contains(&PathBuf::from("will_modify.luau"))); assert!(all.contains(&PathBuf::from("untracked.luau"))); @@ -860,8 +861,7 @@ mod tests { git_init(dir.path()); fs::write(dir.path().join("new.luau"), "content").unwrap(); - let repo = open_repo(dir.path()).unwrap(); - let changed = git_changed_files_impl(&repo, None, &[]); + let changed = git_changed_files_impl(dir.path(), None, &[]); assert!(changed.is_some()); assert!(changed .unwrap() @@ -878,8 +878,7 @@ mod tests { git_commit_all(dir.path(), "init"); fs::write(dir.path().join("src/module.luau"), "modified").unwrap(); - let repo = open_repo(dir.path()).unwrap(); - let changed = git_changed_files_impl(&repo, None, &[]).unwrap(); + let changed = git_changed_files_impl(dir.path(), None, &[]).unwrap(); assert!(changed.tracked.contains(&PathBuf::from("src/module.luau"))); } @@ -895,15 +894,13 @@ mod tests { fs::write(dir.path().join("script.luau"), "modified").unwrap(); git_commit_all(dir.path(), "edit"); - let repo = open_repo(dir.path()).unwrap(); - - let without = git_changed_files_impl(&repo, None, &[]).unwrap(); + let without = git_changed_files_impl(dir.path(), None, &[]).unwrap(); assert!( !without.all().contains(&PathBuf::from("script.luau")), "without initial_head, committed file should NOT appear" ); - let with = git_changed_files_impl(&repo, Some(&initial_head), &[]).unwrap(); + let with = git_changed_files_impl(dir.path(), Some(&initial_head), &[]).unwrap(); assert!( with.tracked.contains(&PathBuf::from("script.luau")), "with initial_head, committed file should appear" @@ -1002,15 +999,14 @@ mod tests { } // ----------------------------------------------------------------------- - // git_batch_check_hashes (via resolve_object_ref) + // git_batch_check_hashes (via git cat-file --batch-check) // ----------------------------------------------------------------------- #[test] fn batch_check_empty_refs() { let dir = tempdir().unwrap(); git_init(dir.path()); - let repo = open_repo(dir.path()).unwrap(); - let results = git_batch_check_hashes_impl(&repo, &[]); + let results = git_batch_check_hashes_impl(dir.path(), &[]); assert!(results.is_empty()); } @@ -1021,9 +1017,8 @@ mod tests { fs::write(dir.path().join("script.luau"), "local x = 42\nreturn x").unwrap(); git_commit_all(dir.path(), "init"); - let repo = open_repo(dir.path()).unwrap(); let refs = vec!["HEAD:script.luau".to_string()]; - let results = git_batch_check_hashes_impl(&repo, &refs); + let results = git_batch_check_hashes_impl(dir.path(), &refs); assert_eq!(results.len(), 1); let batch_hash = results[0].as_ref().unwrap(); @@ -1039,9 +1034,8 @@ mod tests { fs::write(dir.path().join("dummy.luau"), "x").unwrap(); git_commit_all(dir.path(), "init"); - let repo = open_repo(dir.path()).unwrap(); let refs = vec!["HEAD:nonexistent.luau".to_string()]; - let results = git_batch_check_hashes_impl(&repo, &refs); + let results = git_batch_check_hashes_impl(dir.path(), &refs); assert_eq!(results.len(), 1); assert!(results[0].is_none()); } @@ -1053,9 +1047,8 @@ mod tests { fs::write(dir.path().join("a.luau"), "content a").unwrap(); git_commit_all(dir.path(), "init"); - let repo = open_repo(dir.path()).unwrap(); let refs = vec!["HEAD:a.luau".to_string(), ":0:a.luau".to_string()]; - let results = git_batch_check_hashes_impl(&repo, &refs); + let results = git_batch_check_hashes_impl(dir.path(), &refs); assert_eq!(results.len(), 2); assert!(results[0].is_some()); assert_eq!(results[0], results[1]); @@ -1074,9 +1067,8 @@ mod tests { fs::write(dir.path().join("b.luau"), "staged version").unwrap(); git_stage(dir.path(), "b.luau"); - let repo = open_repo(dir.path()).unwrap(); let refs = vec!["HEAD:b.luau".to_string(), ":0:b.luau".to_string()]; - let results = git_batch_check_hashes_impl(&repo, &refs); + let results = git_batch_check_hashes_impl(dir.path(), &refs); assert_eq!(results.len(), 2); assert!(results[0].is_some()); assert!(results[1].is_some()); @@ -1098,7 +1090,6 @@ mod tests { fs::write(dir.path().join("b.luau"), "content b modified").unwrap(); git_stage(dir.path(), "b.luau"); - let repo = open_repo(dir.path()).unwrap(); let refs = vec![ "HEAD:a.luau".to_string(), ":0:a.luau".to_string(), @@ -1106,7 +1097,7 @@ mod tests { ":0:b.luau".to_string(), "HEAD:nonexistent.luau".to_string(), ]; - let results = git_batch_check_hashes_impl(&repo, &refs); + let results = git_batch_check_hashes_impl(dir.path(), &refs); assert_eq!(results.len(), 5); assert_eq!(results[0], results[1]); // a: HEAD == staged @@ -1135,9 +1126,8 @@ mod tests { fs::write(dir.path().join("src/init.luau"), "init content").unwrap(); git_commit_all(dir.path(), "init"); - let repo = open_repo(dir.path()).unwrap(); let refs = vec!["HEAD:src/init.luau".to_string()]; - let results = git_batch_check_hashes_impl(&repo, &refs); + let results = git_batch_check_hashes_impl(dir.path(), &refs); assert_eq!(results.len(), 1); assert_eq!( results[0].as_ref().unwrap(), @@ -1215,7 +1205,7 @@ mod tests { } // ----------------------------------------------------------------------- - // Hash consistency: our SHA1 matches gix blob hashing + // Hash consistency: our SHA1 matches git hash-object // ----------------------------------------------------------------------- #[test]