diff --git a/README.md b/README.md index 7a58b8b..ab587a4 100644 --- a/README.md +++ b/README.md @@ -120,7 +120,7 @@ Three honest caveats, with the full detail in `man party`: | `party who [--short]` | Show invited and attached users for the current party. | | `party status` | Show the caller's own state: hosting, attached, or idle. | | `party close` | Tear down the party server and its roster entry. Host-only. | -| `party clean` | Remove the caller's own dead party dirs: crash leftovers whose tmux server is gone. | +| `party clean` | Remove the caller's own dead party dirs: crash leftovers whose tmux server is gone. Rescues a non-empty transcript first. | | `party log [--stop]` | Record the party into its private dir via `tmux pipe-pane` (host only), group-readable. `--stop` ends it. | | `party join [name] [--passive]` | Join a party. Auto-attaches when one is running; picker otherwise. `--passive` attaches read-only to the host's view (watcher mode). Read-only invitees always join passive. | | `party leave` | Detach and clean up the per-guest session. | diff --git a/party b/party index ada8c15..6339573 100755 --- a/party +++ b/party @@ -1005,6 +1005,21 @@ EOF echo "party clean: skipping $d (server is live; use party close)." >&2 continue fi + + # A crash-orphaned transcript is the same "lost the night's log" + # accident cmd_close's rescue exists for; the server here is + # already confirmed dead by the liveness check above, so unlike + # close there's no pipe-pane `cat` still draining and no + # quiescence poll is needed before moving it. + if [ -s "$d/log" ]; then + _cn_name=${d##*"party-$USER:"} + _cn_name=${_cn_name%.d} + _cn_dest="$HOME/party-$_cn_name-$(date -u '+%Y%m%d-%H%M%S').log" + if mv "$d/log" "$_cn_dest" 2>/dev/null; then + echo "party clean: transcript saved to $_cn_dest" + fi + fi + rm -rf "$d" echo "removed $d" removed=$((removed+1)) diff --git a/party.1 b/party.1 index 61b3afd..96cd041 100644 --- a/party.1 +++ b/party.1 @@ -146,6 +146,9 @@ Host-only. Remove the caller's own dead party directories: crash leftovers whose tmux server no longer answers. Never touches live parties, other users' directories, or symlinks. +A non-empty transcript left by +.Cm log +is saved to the caller's home directory first. .It Cm log Op Fl -stop Op Fl -party Ar name Record the party into .Pa log diff --git a/tests/85-clean.bats b/tests/85-clean.bats index a4fe68f..d326843 100644 --- a/tests/85-clean.bats +++ b/tests/85-clean.bats @@ -22,6 +22,18 @@ teardown() { teardown_party_sandbox; } [ ! -d "$PARTY_SOCKET_DIR/party-$USER:ghost.d" ] } +@test "clean rescues a non-empty transcript before removing the dir" { + export HOME="$PARTY_TMP/home" + mkdir -p "$HOME" + ensure_party_dir "$USER" crashed + printf 'the night\n' > "$PARTY_SOCKET_DIR/party-$USER:crashed.d/log" + run "$PARTY_BIN" clean + [ "$status" -eq 0 ] + [[ "$output" == *"transcript saved to"* ]] + [ ! -d "$PARTY_SOCKET_DIR/party-$USER:crashed.d" ] + grep -q "the night" "$HOME"/party-crashed-*.log +} + @test "clean removes a crash-before-bind dir (no sock at all)" { mkdir "$PARTY_SOCKET_DIR/party-$USER:stillborn.d" run "$PARTY_BIN" clean