Batch Trace Folder: refuse a folder too big to list in full

list_dir cuts its listing before sorting, so a cut listing could skip any image. The batch now
stops with an error instead of tracing part of the folder.
This commit is contained in:
Don Omondi
2026-11-04 20:12:06 +07:00
committed by bflatastic
parent 7c04fd8973
commit 7790c37eb3
2 changed files with 25 additions and 2 deletions
+24 -1
View File
@@ -32,7 +32,12 @@ fn images(folder: &str, deep: bool, depth: usize, out: &mut Vec<String>) -> Resu
if depth > MAX_DEPTH {
return Err(bad("imageTrace.batchFolder", format!("folders deeper than {MAX_DEPTH} levels")));
}
let (entries, _) = super::list_dir(folder, MAX_FILES.saturating_mul(2))?;
let max = MAX_FILES.saturating_mul(2);
let (entries, truncated) = super::list_dir(folder, max)?;
// The listing is cut before it is sorted, so a cut one could skip any image: refuse it.
if truncated {
return Err(bad("imageTrace.batchFolder", format!("{folder}: more than {max} files and folders")));
}
let mut subdirs = vec![];
for e in entries {
let name = e.get("name").and_then(Value::as_str).unwrap_or("");
@@ -177,4 +182,22 @@ mod tests {
}
let _ = std::fs::remove_dir_all(&dir);
}
/// A folder too big to list in full is refused rather than traced in part.
#[test]
fn batch_trace_folder_refuses_a_folder_it_cannot_list_in_full() {
let dir = std::env::temp_dir().join(format!("vc-batch-trace-big-{}", std::process::id()));
let _ = std::fs::remove_dir_all(&dir);
let src = dir.join("in");
std::fs::create_dir_all(&src).unwrap();
for i in 0..=super::MAX_FILES * 2 {
std::fs::write(src.join(format!("note-{i}.txt")), "").unwrap();
}
png(&src.join("logo.png"), true);
let mut s = Session::new();
let e = s.execute("imageTrace.batchFolder", &json!({"folder": src, "destinationFolder": dir.join("out")})).unwrap_err();
assert!(e.to_string().contains("more than"), "{e}");
assert!(!dir.join("out").exists(), "nothing traced");
let _ = std::fs::remove_dir_all(&dir);
}
}
+1 -1
View File
@@ -1885,7 +1885,7 @@ already walks Image Trace. Short agent entry points:
`preset` (Default by default; with `expand`, as Make and Expand), saves it into `destinationFolder` as
`<name>.<ext>` in `format` (`vectorcraft` by default; `svg`, `pdf`, `ai`, `eps`), with `-2`, `-3`… added when the
name is taken so no file is replaced, and closes it again whether it traced or not; the active document stays
active. Up to 500 images and 8 folder levels; not on the web. The app asks for both folders (#4921).
active. Up to 500 images and 8 folder levels (a folder with more than 1,000 entries is refused); not on the web. The app asks for both folders (#4921).
→ `{traced: [{path, output}], failed: [{path, error}], format}`
- Live Paint: `livePaint.make`, `livePaint.merge`, `livePaint.fill {group?, point}`, `livePaint.strokeEdge`,
`livePaint.info {group}`, `livePaint.release`, `livePaint.expand`, and `livePaint.gapOptions {ids?, detect?, size?,