Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ edition = "2021"
readme = "README.md"
# Own version (decoupled from workspace.version): data-beans evolves its CLI /
# QC API independently of the shared utility crates.
version = "0.10.1"
version = "0.10.2"
rust-version = "1.91"
# Ship only the sources, README and license: nothing else in the working tree
# (data stores, saved name lists, scratch files) can end up on crates.io.
Expand Down Expand Up @@ -97,7 +97,7 @@ ratatui = { version = "0.30", default-features = false, features = ["crossterm"]
# Detachable sessions for the views; no pictures, so no graphics.
legume-tui = { version = "0.3.2", optional = true, default-features = false, features = ["clap", "logs"] }
# Its `tui` view (`data-beans mcp watch`) comes on with data-beans' `tui`.
legume-mcp = { version = "0.3", optional = true }
legume-mcp = { version = "0.4", optional = true }
legume-plot = { version = "0.3.2", optional = true }
base64 = { version = "0.22", optional = true }

Expand All @@ -106,5 +106,5 @@ base64 = { version = "0.22", optional = true }
# tests/detach_session.rs.
legume-tui = { version = "0.3.2", default-features = false, features = ["testing"] }
# tests/mcp_server.rs follows a server through the watch pane.
legume-mcp = { version = "0.3", features = ["tui"] }
legume-mcp = { version = "0.4", features = ["tui"] }
ratatui = { version = "0.30", default-features = false, features = ["crossterm"] }
13 changes: 10 additions & 3 deletions src/mcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ impl Arguments {

/// `out`, or, when the agent names none, `{name}{ext}` in today's
/// results folder, `-2`, `-3`… added to `name` (before `ext`) while
/// `taken` says a name is in use.
/// `taken` says a name is in use, or a running job writes it.
fn out_or(
&self,
cx: &Call,
Expand All @@ -508,7 +508,7 @@ impl Arguments {
k => dir.join(format!("{name}-{k}{ext}")),
})
.map(|p| p.to_string_lossy().into_owned())
.find(|p| !taken(p))
.find(|p| !held(cx, &[p]) && !taken(p))
.context("no free name in the results folder")
}

Expand All @@ -518,7 +518,8 @@ impl Arguments {
self.out_or(cx, (name, ""), |c| {
backend_target(c).map_or(true, |t| {
let stem = strip_backend_suffix(&t.effective);
being_written(stem).is_some()
held(cx, &[&t.effective, &t.found])
|| being_written(stem).is_some()
|| outputs_beside(stem).map_or(true, |v| !v.is_empty())
})
})
Expand Down Expand Up @@ -664,6 +665,12 @@ fn fresh(path: &str) -> Result<()> {
/// a command has made its outputs, only this says they are spoken for.
static WRITING: Mutex<Vec<String>> = Mutex::new(Vec::new());

/// Whether a running job writes one of `paths`, however spelled.
fn held(cx: &Call, paths: &[&str]) -> bool {
let paths: Vec<PathBuf> = paths.iter().map(PathBuf::from).collect();
cx.ensure_free(&paths).is_err()
}

/// Whether two stems name some file alike: one is the other, or a file
/// named after it.
fn overlap(a: &str, b: &str) -> bool {
Expand Down
Loading