forked from rojo-rbx/rojo
fix: handle dotted names and .lua extension in meta path + name check
Two bugs:
1. Meta stem fallback used raw instance name (unslugged), so names with
forbidden chars like '/' would create bogus directory components in
the meta path. Fix: fallback now slugifies + init-prefixes, matching
name_for_inst.
2. AdjacentMetadata name check used split('.').next() to extract the
filesystem stem, breaking dotted names like "Name.new" (stem became
"Name", mismatched the instance name, wrote an unnecessary name
property). Fix: check the conditions that cause name_for_inst to
diverge (invalid chars or init-prefix) directly instead of comparing
path stems.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -117,7 +117,19 @@ pub fn syncback_csv<'sync>(
|
|||||||
.and_then(|s| s.strip_suffix(ext.as_str()))
|
.and_then(|s| s.strip_suffix(ext.as_str()))
|
||||||
.map(str::to_owned)
|
.map(str::to_owned)
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| new_inst.name.clone());
|
.unwrap_or_else(|| {
|
||||||
|
let name = &new_inst.name;
|
||||||
|
let base = if crate::syncback::validate_file_name(name).is_err() {
|
||||||
|
crate::syncback::slugify_name(name)
|
||||||
|
} else {
|
||||||
|
name.clone()
|
||||||
|
};
|
||||||
|
if base.to_lowercase() == "init" {
|
||||||
|
format!("_{base}")
|
||||||
|
} else {
|
||||||
|
base
|
||||||
|
}
|
||||||
|
});
|
||||||
fs_snapshot.add_file(
|
fs_snapshot.add_file(
|
||||||
parent.join(format!("{meta_stem}.meta.json")),
|
parent.join(format!("{meta_stem}.meta.json")),
|
||||||
serde_json::to_vec_pretty(&meta).context("cannot serialize metadata")?,
|
serde_json::to_vec_pretty(&meta).context("cannot serialize metadata")?,
|
||||||
|
|||||||
@@ -166,7 +166,19 @@ pub fn syncback_lua<'sync>(
|
|||||||
.and_then(|s| s.strip_suffix(ext.as_str()))
|
.and_then(|s| s.strip_suffix(ext.as_str()))
|
||||||
.map(str::to_owned)
|
.map(str::to_owned)
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| snapshot.new_inst().name.clone());
|
.unwrap_or_else(|| {
|
||||||
|
let name = &snapshot.new_inst().name;
|
||||||
|
let base = if crate::syncback::validate_file_name(name).is_err() {
|
||||||
|
crate::syncback::slugify_name(name)
|
||||||
|
} else {
|
||||||
|
name.clone()
|
||||||
|
};
|
||||||
|
if base.to_lowercase() == "init" {
|
||||||
|
format!("_{base}")
|
||||||
|
} else {
|
||||||
|
base
|
||||||
|
}
|
||||||
|
});
|
||||||
fs_snapshot.add_file(
|
fs_snapshot.add_file(
|
||||||
parent_location.join(format!("{meta_stem}.meta.json")),
|
parent_location.join(format!("{meta_stem}.meta.json")),
|
||||||
serde_json::to_vec_pretty(&meta).context("cannot serialize metadata")?,
|
serde_json::to_vec_pretty(&meta).context("cannot serialize metadata")?,
|
||||||
|
|||||||
@@ -154,17 +154,12 @@ impl AdjacentMetadata {
|
|||||||
.old_inst()
|
.old_inst()
|
||||||
.and_then(|inst| inst.metadata().specified_name.clone())
|
.and_then(|inst| inst.metadata().specified_name.clone())
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
// Write name when the filesystem path doesn't match the
|
// Write name when name_for_inst would produce a different
|
||||||
// instance name (invalid chars or init-prefix).
|
// filesystem stem (slugification or init-prefix).
|
||||||
if snapshot.old_inst().is_none() {
|
if snapshot.old_inst().is_none() {
|
||||||
let instance_name = &snapshot.new_inst().name;
|
let instance_name = &snapshot.new_inst().name;
|
||||||
let fs_stem = path
|
|
||||||
.file_name()
|
|
||||||
.and_then(|n| n.to_str())
|
|
||||||
.map(|s| s.split('.').next().unwrap_or(s))
|
|
||||||
.unwrap_or("");
|
|
||||||
if validate_file_name(instance_name).is_err()
|
if validate_file_name(instance_name).is_err()
|
||||||
|| fs_stem != instance_name.as_str()
|
|| instance_name.to_lowercase() == "init"
|
||||||
{
|
{
|
||||||
Some(instance_name.clone())
|
Some(instance_name.clone())
|
||||||
} else {
|
} else {
|
||||||
@@ -428,16 +423,12 @@ impl DirectoryMetadata {
|
|||||||
.old_inst()
|
.old_inst()
|
||||||
.and_then(|inst| inst.metadata().specified_name.clone())
|
.and_then(|inst| inst.metadata().specified_name.clone())
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
// Write name when the directory name doesn't match the
|
// Write name when name_for_inst would produce a different
|
||||||
// instance name (invalid chars or init-prefix).
|
// directory name (slugification or init-prefix).
|
||||||
if snapshot.old_inst().is_none() {
|
if snapshot.old_inst().is_none() {
|
||||||
let instance_name = &snapshot.new_inst().name;
|
let instance_name = &snapshot.new_inst().name;
|
||||||
let fs_name = path
|
|
||||||
.file_name()
|
|
||||||
.and_then(|n| n.to_str())
|
|
||||||
.unwrap_or("");
|
|
||||||
if validate_file_name(instance_name).is_err()
|
if validate_file_name(instance_name).is_err()
|
||||||
|| fs_name != instance_name.as_str()
|
|| instance_name.to_lowercase() == "init"
|
||||||
{
|
{
|
||||||
Some(instance_name.clone())
|
Some(instance_name.clone())
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -66,7 +66,19 @@ pub fn syncback_txt<'sync>(
|
|||||||
.and_then(|s| s.strip_suffix(ext.as_str()))
|
.and_then(|s| s.strip_suffix(ext.as_str()))
|
||||||
.map(str::to_owned)
|
.map(str::to_owned)
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| new_inst.name.clone());
|
.unwrap_or_else(|| {
|
||||||
|
let name = &new_inst.name;
|
||||||
|
let base = if crate::syncback::validate_file_name(name).is_err() {
|
||||||
|
crate::syncback::slugify_name(name)
|
||||||
|
} else {
|
||||||
|
name.clone()
|
||||||
|
};
|
||||||
|
if base.to_lowercase() == "init" {
|
||||||
|
format!("_{base}")
|
||||||
|
} else {
|
||||||
|
base
|
||||||
|
}
|
||||||
|
});
|
||||||
fs_snapshot.add_file(
|
fs_snapshot.add_file(
|
||||||
parent.join(format!("{meta_stem}.meta.json")),
|
parent.join(format!("{meta_stem}.meta.json")),
|
||||||
serde_json::to_vec_pretty(&meta).context("could not serialize metadata")?,
|
serde_json::to_vec_pretty(&meta).context("could not serialize metadata")?,
|
||||||
|
|||||||
Reference in New Issue
Block a user