mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-01 13:47:21 -06:00
Batch: keep a backslash in a source file name on Linux and macOS
Destination and Override Save/Export paths reject only the current platform's path separators, so a folder batch writes `a\b.svg` into the destination folder on systems where that is one file name.
This commit is contained in:
@@ -326,11 +326,11 @@ fn safe_extension(ext: &str) -> bool {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn output_path(folder: &str, stem: &str, ext: &str) -> Option<std::path::PathBuf> {
|
||||
use std::path::Path;
|
||||
if stem.is_empty() || matches!(stem, "." | "..") || stem.contains(['/', '\\']) || !safe_extension(ext) {
|
||||
if stem.is_empty() || matches!(stem, "." | "..") || stem.contains(std::path::is_separator) || !safe_extension(ext) {
|
||||
return None;
|
||||
}
|
||||
let name = format!("{stem}.{ext}");
|
||||
if name.contains(['/', '\\']) {
|
||||
if name.contains(std::path::is_separator) {
|
||||
return None;
|
||||
}
|
||||
let path = Path::new(folder).join(name);
|
||||
@@ -511,6 +511,74 @@ mod tests {
|
||||
assert!(dest.join("b.svg").is_file(), "b.svg written");
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn batch_folder_keeps_backslash_in_source_file_name() {
|
||||
let src = tmp("backslash-src");
|
||||
let dest = tmp("backslash-dest");
|
||||
write_svg(&src, "a\\b.svg", "#f00");
|
||||
let mut s = Session::new();
|
||||
let r = s
|
||||
.execute(
|
||||
"action.batch",
|
||||
&json!({
|
||||
"source": "folder",
|
||||
"folder": src.to_string_lossy(),
|
||||
"destination": "folder",
|
||||
"destinationFolder": dest.to_string_lossy(),
|
||||
"stopOnError": true,
|
||||
"commands": [{"command": "object.unlockAll", "params": {}}]
|
||||
}),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(r["count"], 1, "{r}");
|
||||
assert_eq!(r["failed"], 0, "{r}");
|
||||
assert_eq!(r["stopped"], false, "{r}");
|
||||
assert!(dest.join("a\\b.svg").is_file(), "{r}");
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn batch_folder_override_export_keeps_backslash_in_source_file_name() {
|
||||
let src = tmp("backslash-export-src");
|
||||
let dest = tmp("backslash-export-dest");
|
||||
write_svg(&src, "a\\b.svg", "#f00");
|
||||
let mut s = Session::new();
|
||||
let r = s
|
||||
.execute(
|
||||
"action.batch",
|
||||
&json!({
|
||||
"source": "folder",
|
||||
"folder": src.to_string_lossy(),
|
||||
"destination": "folder",
|
||||
"destinationFolder": dest.to_string_lossy(),
|
||||
"stopOnError": true,
|
||||
"commands": [{"command": "document.export", "params": {"format": "svg"}}]
|
||||
}),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(r["count"], 1, "{r}");
|
||||
assert_eq!(r["failed"], 0, "{r}");
|
||||
assert_eq!(r["stopped"], false, "{r}");
|
||||
assert_eq!(file_names(&dest), ["a\\b.svg"], "{r}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn output_path_accepts_only_platform_file_name_separators() {
|
||||
let folder = tmp("output-path");
|
||||
let folder = folder.to_string_lossy();
|
||||
let backslash = output_path(&folder, "a\\b", "svg");
|
||||
#[cfg(windows)]
|
||||
assert!(backslash.is_none());
|
||||
#[cfg(not(windows))]
|
||||
assert_eq!(backslash, Some(std::path::Path::new(folder.as_ref()).join("a\\b.svg")));
|
||||
for stem in ["a/b", ".", "..", ""] {
|
||||
assert!(output_path(&folder, stem, "svg").is_none(), "{stem:?}");
|
||||
}
|
||||
#[cfg(windows)]
|
||||
assert_eq!(std::path::Path::new("a\\b.svg").file_stem(), Some(std::ffi::OsStr::new("b")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn batch_skips_open_steps_when_override_open() {
|
||||
let src = tmp("open");
|
||||
|
||||
Reference in New Issue
Block a user