mirror of
https://github.com/l0ng-ai/tty7.git
synced 2026-09-21 16:02:20 +00:00
fix(cli): check the inherited workspace before run --keep spawns
`run --keep` resolves `--ws` against the machine tree before it spawns anything, and takes `$TTY7_WS` on trust — it only parses the id. Filing the pane happens after the spawn, so a shell whose workspace has since been removed, or one opened against another machine, started the pane and then failed to file it. The pane kept running with nothing holding it. Measured against a live daemon: with a `$TTY7_WS` this machine does not have, `run --keep` exited 1 with a clear message and left a `sleep` behind, `pane ls --all` reporting `"orphans":1`. With `--ws` spelled out, the same bad id spawned nothing. Recoverable — `pane ls --all` finds it and `pane close` ends it, both documented — but nobody asked for the pane, and `$TTY7_WS` is the *documented default* for `--keep`, so this is the ordinary path rather than an exotic one. Resolving the inherited id is now the same check the explicit one gets, and only when `--keep` needs it: a plain `run` uses the workspace as an ownership stamp, where a stale id costs nothing and the round trip to find out would. The spawn still precedes the filing — `TabCreate` names the pane the daemon assigned, so it has to, and `run_keep_spawns_first_then_files_the_pane_into_the_workspace` pins that. What moved is only where the workspace is checked.
This commit is contained in:
@@ -405,6 +405,21 @@ fn run(args: RunArgs, ctx: &Context, backend: &mut dyn Backend) -> Result<Outcom
|
||||
pass --ws, or run inside a tty7 shell where $TTY7_WS names one"
|
||||
);
|
||||
}
|
||||
// `--keep` files the pane into its workspace *after* the spawn, so a
|
||||
// `$TTY7_WS` that no longer names one here — a workspace since removed, or
|
||||
// a shell opened against another machine — started the pane and then failed
|
||||
// the filing, leaving it running with nothing holding it. Recoverable
|
||||
// (`pane ls --all`, then `pane close`), but nobody asked for the pane.
|
||||
//
|
||||
// The `--ws` arm above has always resolved before spawning. This is that
|
||||
// check for the inherited id, and only when `--keep` needs it: a plain
|
||||
// `run` uses the workspace as an ownership stamp, where a stale id costs
|
||||
// nothing and a round trip to find out would.
|
||||
if args.keep && args.ws.is_none() {
|
||||
let id = workspace.expect("checked above: --keep requires a workspace");
|
||||
let machine = fetch_machine(backend)?;
|
||||
resolve::workspace(&machine, &address::WorkspaceAddress::Id(id))?;
|
||||
}
|
||||
let pane = backend.run_spawn(RunSpec {
|
||||
workspace,
|
||||
cwd: args.cwd.clone(),
|
||||
@@ -2831,6 +2846,29 @@ mod tests {
|
||||
assert!(matches!(out, Outcome::Exit(0, _)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn run_keep_with_a_tty7_ws_this_machine_lost_spawns_nothing() {
|
||||
// The shell that set `$TTY7_WS` may have outlived its workspace, or be
|
||||
// pointed at another machine. Filing happens after the spawn, so
|
||||
// checking only at that point started the pane and then failed — an
|
||||
// orphan nobody asked for, recoverable but only through
|
||||
// `pane ls --all`. The `--ws` arm resolves before spawning; this is
|
||||
// the same guarantee for the inherited id.
|
||||
let mut backend = mock();
|
||||
let ctx = Context {
|
||||
ws: Some("11111111-2222-3333-4444-555555555555".to_string()),
|
||||
..Context::default()
|
||||
};
|
||||
let err = execute(
|
||||
cli(&["tty7", "run", "--keep", "--", "make"]),
|
||||
&ctx,
|
||||
&mut backend,
|
||||
)
|
||||
.expect_err("a workspace this machine does not have cannot hold a kept pane");
|
||||
assert!(err.to_string().contains("no workspace with id"), "{err}");
|
||||
assert!(backend.runs.is_empty(), "nothing must be spawned");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn run_keep_without_a_workspace_names_the_fix() {
|
||||
let mut backend = mock();
|
||||
|
||||
Reference in New Issue
Block a user