From 3cda2936790ed1977050963d9372dc995a9fde3c Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Thu, 6 Nov 2025 19:13:38 -0800 Subject: [PATCH] fix bug where deleted binary files could not be retrieved --- rust/plugin/src/file_utils.rs | 7 ++- rust/plugin/src/godot_project_driver.rs | 71 +++++++++++++++++++++---- 2 files changed, 63 insertions(+), 15 deletions(-) diff --git a/rust/plugin/src/file_utils.rs b/rust/plugin/src/file_utils.rs index 3223fb6b..14a3f06f 100644 --- a/rust/plugin/src/file_utils.rs +++ b/rust/plugin/src/file_utils.rs @@ -110,6 +110,9 @@ impl FileContent { // NOTE: Probably not appropriate to put here, should have this in BranchState pub fn hydrate_content_at(file_entry: ObjId, doc: &Automerge, path: &String, heads: &Vec) -> Result> { + if let Ok(Some((_, _))) = doc.get_at(&file_entry, "deleted", &heads) { + return Ok(FileContent::Deleted); + } let structured_content = doc .get_at(&file_entry, "structured_content", heads) .unwrap() @@ -120,10 +123,6 @@ impl FileContent { return Ok(FileContent::Scene(scene)); } - if let Ok(Some((_, _))) = doc.get_at(&file_entry, "deleted", &heads) { - return Ok(FileContent::Deleted); - } - // try to read file as text let content = doc.get_at(&file_entry, "content", &heads); diff --git a/rust/plugin/src/godot_project_driver.rs b/rust/plugin/src/godot_project_driver.rs index ff8538b3..9d31e6c3 100644 --- a/rust/plugin/src/godot_project_driver.rs +++ b/rust/plugin/src/godot_project_driver.rs @@ -919,6 +919,10 @@ impl DriverState { change_type }); + if let Ok(Some((_, _))) = tx.get(&file_entry, "deleted") { + let _ = tx.delete(&file_entry, "deleted"); + } + // delete url in file entry if it previously had one if let Ok(Some((_, _))) = tx.get(&file_entry, "url") { let _ = tx.delete(&file_entry, "url"); @@ -942,10 +946,25 @@ impl DriverState { // write scene entries to doc for (path, godot_scene) in scene_entries { // get the change flag - let change_type = match tx.get(&files, &path) { - Ok(Some(_)) => ChangeType::Modified, - _ => ChangeType::Added + let (file_entry, change_type) = match tx.get(&files, &path) { + Ok(Some((automerge::Value::Object(ObjType::Map), file_entry))) => (file_entry, ChangeType::Modified), + _ => (tx.put_object(&files, &path, ObjType::Map).unwrap(), ChangeType::Added) }; + + if let Ok(Some((_, _))) = tx.get(&file_entry, "deleted") { + let _ = tx.delete(&file_entry, "deleted"); + } + + // delete content in file entry if it previously had one + if let Ok(Some((_, _))) = tx.get(&file_entry, "content") { + let _ = tx.delete(&file_entry, "content"); + } + + // delete url in file entry if it previously had one + if let Ok(Some((_, _))) = tx.get(&file_entry, "url") { + let _ = tx.delete(&file_entry, "url"); + } + godot_scene.reconcile(&mut tx, path.clone()); changes.push(ChangedFile { path, @@ -956,14 +975,27 @@ impl DriverState { // write binary entries to doc for (path, binary_doc_handle) in binary_entries { // get the change flag - let change_type = match tx.get(&files, &path) { - Ok(Some(_)) => ChangeType::Modified, - _ => ChangeType::Added + let (file_entry, change_type) = match tx.get(&files, &path) { + Ok(Some((automerge::Value::Object(ObjType::Map), file_entry))) => (file_entry, ChangeType::Modified), + _ => (tx.put_object(&files, &path, ObjType::Map).unwrap(), ChangeType::Added) }; - let file_entry = tx.put_object(&files, &path, ObjType::Map); + if let Ok(Some((_, _))) = tx.get(&file_entry, "deleted") { + let _ = tx.delete(&file_entry, "deleted"); + } + + // delete structured content in file entry if it previously had one + if let Ok(Some((_, _))) = tx.get(&file_entry, "structured_content") { + let _ = tx.delete(&file_entry, "structured_content"); + } + + // delete content in file entry if it previously had one + if let Ok(Some((_, _))) = tx.get(&file_entry, "content") { + let _ = tx.delete(&file_entry, "content"); + } + let _ = tx.put( - file_entry.unwrap(), + file_entry, "url", format!("automerge:{}", &binary_doc_handle.document_id()), ); @@ -975,11 +1007,28 @@ impl DriverState { } for path in deleted_entries { - let _ = tx.delete(&files, &path); - changes.push(ChangedFile { - path, + changes.push(ChangedFile { + path: path.clone(), change_type: ChangeType::Removed }); + let file_entry = match tx.get(&files, &path) { + Ok(Some((automerge::Value::Object(ObjType::Map), file_entry))) => file_entry, + _ => { + continue; + } + }; + + // do NOT delete the url if it previously had one, we need it to know which linked docs to retrieved + // delete structured content in file entry if it previously had one + if let Ok(Some((_, _))) = tx.get(&file_entry, "structured_content") { + let _ = tx.delete(&file_entry, "structured_content"); + } + + if let Ok(Some((_, _))) = tx.get(&file_entry, "content") { + let _ = tx.delete(&file_entry, "content"); + } + + let _ = tx.put(&file_entry, "deleted", true); } commit_with_attribution_and_timestamp(