mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-10-22 21:41:37 +00:00
Fix change_processor crash when path is a directory during two-way sync
The change processor was crashing because fs::write and fs::remove_file were being called on directory paths instead of file paths. This happens with init scripts where the instigating source points to the directory instead of the init file. Added resolve_init_path to find the actual init file in a directory, and used remove_dir_all for directory removal. Fixes #1206
This commit is contained in:
parent
9bbb1edd79
commit
4038990227
1 changed files with 52 additions and 3 deletions
|
|
@ -2,7 +2,7 @@ use crossbeam_channel::{select, Receiver, RecvError, Sender};
|
|||
use jod_thread::JoinHandle;
|
||||
use memofs::{IoResultExt, Vfs, VfsEvent};
|
||||
use rbx_dom_weak::types::{Ref, Variant};
|
||||
use std::path::PathBuf;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::{
|
||||
fs,
|
||||
sync::{Arc, Mutex},
|
||||
|
|
@ -200,7 +200,19 @@ impl JobThreadContext {
|
|||
if let Some(instance) = tree.get_instance(id) {
|
||||
if let Some(instigating_source) = &instance.metadata().instigating_source {
|
||||
match instigating_source {
|
||||
InstigatingSource::Path(path) => fs::remove_file(path).unwrap(),
|
||||
InstigatingSource::Path(path) => {
|
||||
if path.is_dir() {
|
||||
if let Err(err) = fs::remove_dir_all(path) {
|
||||
log::warn!(
|
||||
"Failed to remove directory {}: {}",
|
||||
path.display(),
|
||||
err
|
||||
);
|
||||
}
|
||||
} else {
|
||||
fs::remove_file(path).unwrap();
|
||||
}
|
||||
}
|
||||
InstigatingSource::ProjectNode { .. } => {
|
||||
log::warn!(
|
||||
"Cannot remove instance {:?}, it's from a project file",
|
||||
|
|
@ -244,7 +256,17 @@ impl JobThreadContext {
|
|||
match instigating_source {
|
||||
InstigatingSource::Path(path) => {
|
||||
if let Some(Variant::String(value)) = changed_value {
|
||||
fs::write(path, value).unwrap();
|
||||
match resolve_init_path(path) {
|
||||
Some(resolved) => {
|
||||
fs::write(&resolved, value).unwrap();
|
||||
}
|
||||
None => {
|
||||
log::warn!(
|
||||
"Could not resolve init file for directory {}, skipping write",
|
||||
path.display()
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log::warn!("Cannot change Source to non-string value.");
|
||||
}
|
||||
|
|
@ -280,6 +302,33 @@ impl JobThreadContext {
|
|||
}
|
||||
}
|
||||
|
||||
// If the path is a directory, try to find the init file inside it.
|
||||
// Returns None if it's a directory but no init file exists.
|
||||
fn resolve_init_path(path: &Path) -> Option<PathBuf> {
|
||||
if !path.is_dir() {
|
||||
return Some(path.to_path_buf());
|
||||
}
|
||||
|
||||
const INIT_FILENAMES: &[&str] = &[
|
||||
"init.luau",
|
||||
"init.lua",
|
||||
"init.server.luau",
|
||||
"init.server.lua",
|
||||
"init.client.luau",
|
||||
"init.client.lua",
|
||||
"init.csv",
|
||||
];
|
||||
|
||||
for filename in INIT_FILENAMES {
|
||||
let candidate = path.join(filename);
|
||||
if candidate.is_file() {
|
||||
return Some(candidate);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn compute_and_apply_changes(tree: &mut RojoTree, vfs: &Vfs, id: Ref) -> Option<AppliedPatchSet> {
|
||||
let metadata = tree
|
||||
.get_metadata(id)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue