Skip to content

feat: stream archive to stdout when compress output is - - #1093

Open
Mathjk wants to merge 2 commits into
ouch-org:mainfrom
Mathjk:fix/compress-stdout
Open

Mathjk wants to merge 2 commits into
ouch-org:mainfrom
Mathjk:fix/compress-stdout

Conversation

@Mathjk

@Mathjk Mathjk commented Sep 30, 2026

Copy link
Copy Markdown

Refs #1092. Complements #110 (which covers - = stdin for decompress; this is the compress-side twin).

Bug

ouch compress <files> - created a literal file named - on disk (or, without --format, a confusing "Cannot compress to -" error hinting at -.tar.gz).

Fix — stream to stdout, --format required

Since stdout has no extension to detect a format from, - requires --format — mirroring ouch decompress -, which already reads stdin on - and likewise requires --format (precedent also in #687).

  • commands/mod.rs: on is_path_stdin(&output_path) the output writer is io::stdout(); conflict resolution, the size report, and partial-file cleanup are skipped for the stdout target.
  • commands/compress.rs: compress_files takes impl Write instead of fs::File (wrapped in the existing BufWriter).
  • check.rs: dedicated error — Cannot compress to "-" (stdout) + --format hint — replaces the nonsense -.tar.gz suggestion.
  • All diagnostics already go to stderr, so the piped stream stays clean.
  • args.rs help documents - → stdout; tests/integration.rs gains a compress_to_stdout test (error without --format, tar stream, no literal - file, decompress roundtrip).

Verified

  • ouch compress a.txt - --format tar | wc -c → 2048; file says POSIX tar archive
  • compress a.txt sub - --format tar > out.tar → tar tf lists entries; INFO logs on stderr
  • Roundtrip: compress … - --format tar.gz | decompress - --format tar.gz -d out → files extracted
  • zip/gz stream correctly; normal compress f out.zip unchanged
  • | head -c 100 → quiet truncation, exit 0

cargo test all green (53 unit + 58 integration + ui/mime); fmt/clippy -D warnings clean (default + --no-default-features).

Open to maintainer choice on whether bare - could default to a format instead of requiring the flag — easy to relax.

Passing - as the output path now writes the archive bytes to stdout
instead of creating a file literally named -, matching the convention
used by tar and by `ouch decompress`, which already reads stdin on -.

Since stdout has no extension, --format is required to pick the format;
without it a dedicated error suggests the flag instead of hinting at
output names like "-.tar.gz". All diagnostics already go to stderr, so
the piped stream stays clean.

Conflict resolution, the output-size report, and partial-file cleanup
are skipped for the stdout target. compress_files now takes a generic
Write instead of fs::File to support this.

Refs: ouch-org#1092
@valoq

valoq commented Oct 4, 2026 •

Copy link
Copy Markdown
Collaborator
  • mod.rs:106: there is no terminal check and binary data is always written to a tty
  • compress.rs:208: only tar flushes (line 158). For other formats, final write errors are lost. This bug already existed but stdout output makes it common.

@Mathjk

Mathjk commented Oct 8, 2026

Copy link
Copy Markdown
Author

Addressed in 6cbdf71. compress - on a tty now errors out with a hint; redirected output still works. A writer.flush()? after the match covers all formats — final write errors propagate instead of being dropped. Known limit: gzp's flush never reaches the sink, so its error surfaces as a panic in Drop rather than a clean Err; a real fix needs per-format finish(), happy to do it if you want it in this PR. Tests added.

@valoq

valoq commented Oct 8, 2026

Copy link
Copy Markdown
Collaborator

With output "-" a file that stdout is redirected to inside the compressed directory is not skipped

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants