Skip to content

Commit af3801e

Browse files
Frandoclaude
andcommitted
feat: add patchbay.toml config and recursive sim directory scanning
- When no sims are specified on CLI, look for patchbay.toml or .patchbay.toml in project root with `simulations = "path/to/sims"` - Recursive directory scanning for *.toml sim files in subdirectories Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent bd53b9a commit af3801e

2 files changed

Lines changed: 60 additions & 10 deletions

File tree

patchbay-runner/src/main.rs

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
mod sim;
44

55
use std::{
6-
collections::HashMap, path::PathBuf, process::Command as ProcessCommand, time::Duration,
6+
collections::HashMap,
7+
path::{Path, PathBuf},
8+
process::Command as ProcessCommand,
9+
time::Duration,
710
};
811

912
use anyhow::{anyhow, bail, Context, Result};
@@ -163,6 +166,7 @@ async fn tokio_main() -> Result<()> {
163166
Some(p) => p,
164167
None => std::env::current_dir().context("resolve current directory")?,
165168
};
169+
let sims = resolve_sim_args(sims, &project_root)?;
166170
let res = sim::run_sims(
167171
sims,
168172
work_dir,
@@ -192,6 +196,7 @@ async fn tokio_main() -> Result<()> {
192196
Some(p) => p,
193197
None => std::env::current_dir().context("resolve current directory")?,
194198
};
199+
let sims = resolve_sim_args(sims, &project_root)?;
195200
sim::prepare_sims(
196201
sims,
197202
work_dir,
@@ -229,6 +234,43 @@ async fn tokio_main() -> Result<()> {
229234
}
230235
}
231236

237+
/// When no sim paths are given on the CLI, look for `patchbay.toml` or
238+
/// `.patchbay.toml` in the project root and use its `simulations` path.
239+
fn resolve_sim_args(sims: Vec<PathBuf>, project_root: &Path) -> Result<Vec<PathBuf>> {
240+
if !sims.is_empty() {
241+
return Ok(sims);
242+
}
243+
let candidates = [
244+
project_root.join("patchbay.toml"),
245+
project_root.join(".patchbay.toml"),
246+
];
247+
for path in &candidates {
248+
if path.is_file() {
249+
let text = std::fs::read_to_string(path)
250+
.with_context(|| format!("read {}", path.display()))?;
251+
let cfg: PatchbayConfig = toml::from_str(&text)
252+
.with_context(|| format!("parse {}", path.display()))?;
253+
let sims_dir = project_root.join(&cfg.simulations);
254+
if !sims_dir.exists() {
255+
bail!(
256+
"{}: simulations path '{}' does not exist",
257+
path.display(),
258+
sims_dir.display()
259+
);
260+
}
261+
println!("patchbay: using simulations from {}", sims_dir.display());
262+
return Ok(vec![sims_dir]);
263+
}
264+
}
265+
bail!("no sim files specified and no patchbay.toml found in {}", project_root.display())
266+
}
267+
268+
#[derive(Deserialize)]
269+
struct PatchbayConfig {
270+
/// Path to sims directory (relative to project root).
271+
simulations: String,
272+
}
273+
232274
/// Resolve `testdir-current` inside the cargo target directory.
233275
///
234276
/// Runs `cargo metadata` to find the target directory, then appends

patchbay-runner/src/sim/runner.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -465,15 +465,7 @@ fn expand_sim_inputs(inputs: &[PathBuf]) -> Result<Vec<PathBuf>> {
465465
}
466466
if input.is_dir() {
467467
let mut dir_sims = Vec::new();
468-
for ent in std::fs::read_dir(input)
469-
.with_context(|| format!("read sim dir {}", input.display()))?
470-
{
471-
let ent = ent?;
472-
let path = ent.path();
473-
if path.is_file() && path.extension().and_then(|s| s.to_str()) == Some("toml") {
474-
dir_sims.push(path);
475-
}
476-
}
468+
collect_toml_files(input, &mut dir_sims)?;
477469
dir_sims.sort();
478470
sims.extend(dir_sims);
479471
continue;
@@ -485,6 +477,22 @@ fn expand_sim_inputs(inputs: &[PathBuf]) -> Result<Vec<PathBuf>> {
485477
Ok(sims)
486478
}
487479

480+
/// Recursively collect `*.toml` files from a directory.
481+
fn collect_toml_files(dir: &Path, out: &mut Vec<PathBuf>) -> Result<()> {
482+
for ent in
483+
std::fs::read_dir(dir).with_context(|| format!("read sim dir {}", dir.display()))?
484+
{
485+
let ent = ent?;
486+
let path = ent.path();
487+
if path.is_dir() {
488+
collect_toml_files(&path, out)?;
489+
} else if path.is_file() && path.extension().and_then(|s| s.to_str()) == Some("toml") {
490+
out.push(path);
491+
}
492+
}
493+
Ok(())
494+
}
495+
488496
async fn assemble_binaries_for_run(
489497
sims: &[PathBuf],
490498
run_root: &Path,

0 commit comments

Comments
 (0)