This commit is contained in:
warsam 2026-05-03 17:32:54 -07:00 • committed by GitHub
commit 4e9f86b15b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 141 additions and 5 deletions

3
.gitattributes vendored
View file

@ -1 +1,2 @@
*.lua linguist-language=Luau
*.lua linguist-language=Luau
rojo-test/**/*.txt text eol=lf

View file

@ -39,6 +39,7 @@ Making a new release? Simply add the new header with the version and date undern
* Fixed a bug where the notification timeout thread would fail to cancel on unmount ([#1211])
* Added a "Forget" option to the sync reminder notification to avoid being reminded for that place in the future ([#1215])
* Improves relative path calculation for sourcemap generation to avoid issues with Windows UNC paths. ([#1217])
* Fixed server crash when deleting folders ([#1220])
[#1176]: https://github.com/rojo-rbx/rojo/pull/1176
[#1179]: https://github.com/rojo-rbx/rojo/pull/1179
@ -48,6 +49,7 @@ Making a new release? Simply add the new header with the version and date undern
[#1211]: https://github.com/rojo-rbx/rojo/pull/1211
[#1215]: https://github.com/rojo-rbx/rojo/pull/1215
[#1217]: https://github.com/rojo-rbx/rojo/pull/1217
[#1220]: https://github.com/rojo-rbx/rojo/pull/1220
## [7.7.0-rc.1] (November 27th, 2025)

View file

@ -0,0 +1,16 @@
---
source: tests/tests/serve.rs
expression: "read_response.intern_and_redact(&mut redactions, root_id)"
---
instances:
id-2:
Children: []
ClassName: Folder
Id: id-2
Metadata:
ignoreUnknownInstances: false
Name: remove_folder
Parent: "00000000000000000000000000000000"
Properties: {}
messageCursor: 1
sessionId: id-1

View file

@ -0,0 +1,38 @@
---
source: tests/tests/serve.rs
expression: "read_response.intern_and_redact(&mut redactions, root_id)"
---
instances:
id-2:
Children:
- id-3
ClassName: Folder
Id: id-2
Metadata:
ignoreUnknownInstances: false
Name: remove_folder
Parent: "00000000000000000000000000000000"
Properties: {}
id-3:
Children:
- id-4
ClassName: Folder
Id: id-3
Metadata:
ignoreUnknownInstances: false
Name: my-folder
Parent: id-2
Properties: {}
id-4:
Children: []
ClassName: StringValue
Id: id-4
Metadata:
ignoreUnknownInstances: false
Name: test
Parent: id-3
Properties:
Value:
String: "This file is inside my-folder\n"
messageCursor: 0
sessionId: id-1

View file

@ -0,0 +1,13 @@
---
source: tests/tests/serve.rs
expression: redactions.redacted_yaml(info)
---
expectedPlaceIds: ~
gameId: ~
placeId: ~
projectName: remove_folder
protocolVersion: 5
rootInstanceId: id-2
serverVersion: "[server-version]"
sessionId: id-1
unexpectedPlaceIds: ~

View file

@ -0,0 +1,13 @@
---
source: tests/tests/serve.rs
expression: "socket_packet.intern_and_redact(&mut redactions, ())"
---
body:
messageCursor: 1
messages:
- added: {}
removed:
- id-3
updated: []
packetType: messages
sessionId: id-1

View file

@ -0,0 +1,6 @@
{
"name": "remove_folder",
"tree": {
"$path": "src"
}
}

View file

@ -0,0 +1 @@
This file is inside my-folder

View file

@ -172,12 +172,23 @@ impl JobThreadContext {
self.apply_patches(self.vfs.canonicalize(&path).unwrap())
}
VfsEvent::Remove(path) => {
// MemoFS does not track parent removals yet, so we can canonicalize
// the parent path safely and then append the removed path's file name.
// Try to canonicalize the parent path and append the removed path's
// file name. If the parent no longer exists (e.g., a folder and its
// contents were deleted together), we skip processing since the
// parent's removal event will handle cleaning up the instances.
let parent = path.parent().unwrap();
let file_name = path.file_name().unwrap();
let parent_normalized = self.vfs.canonicalize(parent).unwrap();
self.apply_patches(parent_normalized.join(file_name))
match self.vfs.canonicalize(parent) {
Ok(parent_normalized) => self.apply_patches(parent_normalized.join(file_name)),
Err(err) => {
log::debug!(
"Parent path no longer exists for removed path {}: {}",
path.display(),
err
);
Vec::new()
}
}
}
_ => {
log::warn!("Unhandled VFS event: {:?}", event);

View file

@ -126,6 +126,41 @@ fn remove_file() {
});
}
/// Test that removing a folder (directory) with contents doesn't crash the server.
/// This is a regression test for a bug where deleting a folder would cause a panic
/// due to the parent path no longer existing when processing child removal events.
#[test]
fn remove_folder() {
run_serve_test("remove_folder", |session, mut redactions| {
let info = session.get_api_rojo().unwrap();
let root_id = info.root_instance_id;
assert_yaml_snapshot!("remove_folder_info", redactions.redacted_yaml(info));
let read_response = session.get_api_read(root_id).unwrap();
assert_yaml_snapshot!(
"remove_folder_all",
read_response.intern_and_redact(&mut redactions, root_id)
);
fs::remove_dir_all(session.path().join("src/my-folder")).unwrap();
let socket_packet = session
.get_api_socket_packet(SocketPacketType::Messages, 0)
.unwrap();
assert_yaml_snapshot!(
"remove_folder_subscribe",
socket_packet.intern_and_redact(&mut redactions, ())
);
let read_response = session.get_api_read(root_id).unwrap();
assert_yaml_snapshot!(
"remove_folder_all-2",
read_response.intern_and_redact(&mut redactions, root_id)
);
});
}
#[test]
fn edit_init() {
run_serve_test("edit_init", |session, mut redactions| {