Add these options to bz-show:
--output-dir DIRECTORY Create a bug directory beneath DIRECTORY
--download-attachments Download eligible attachments into that directory
--download-attachments must require --output-dir. --output and
--output-dir must be mutually exclusive. Requiring an explicit directory
prevents a read-looking command from unexpectedly writing files into the
current directory.
The layout should be deterministic:
DIRECTORY/
bug-1234567/
bug-1234567.md
attachment-890123-original-name.txt
Prefixing the attachment ID prevents collisions between attachments with the
same submitted filename. Do not download obsolete attachments or
text/x-phabricator-request pseudo-attachments. Continue listing all attachment
metadata in the Markdown summary so omitted downloads remain visible.
Implement with Red/Green TDD
- Extend argument-parsing tests with valid
--output-dir and
--download-attachments cases, plus errors for incompatible or incomplete
option combinations.
- Add focused tests for an attachment filename function. It must:
- discard directory components from both slash styles;
- replace control characters and unsafe separators;
- handle empty names,
. and ..;
- preserve a useful extension where possible;
- prefix the numeric attachment ID; and
- always return a single filename, never a path.
- Add focused tests for strict base64 decoding. Reject malformed base64 rather
than writing partial or surprising bytes.
- Add an injectable filesystem boundary for
runShowCommand, similar to the
existing CliIo boundary, or extract a documented bundle writer whose
behavior can be tested using directories under cache/tmp.
- Create the output directories with user-only permissions where the platform
supports them. Write the Markdown and attachments with mode 0o600, matching
the existing private Markdown output behavior.
- Decide overwrite behavior before performing any writes. The initial version
should fail if an attachment target already exists. It may update the
deterministic Markdown summary only after all attachment target paths have
been validated, so a filename conflict cannot leave a partially updated
bundle.
- Fetch eligible attachments one at a time through
Bugzilla.attachment(id).
Decode and write each body, then verify the decoded byte length against the
metadata size when Bugzilla supplies a nonzero size. Treat a mismatch as a
failed download and report the attachment ID and filename.
- Write status messages to stderr, keeping stdout available for Markdown and
machine-readable output. Never print attachment bodies, base64 data, or API
keys.
- If one download fails, stop and return a nonzero exit code. Report which
files were already written; do not delete pre-existing user files or attempt
an unsafe rollback.
- Update
showCommandHelp and README.md with the layout, filtering rules,
permissions, overwrite behavior, and an example invocation.
- Add end-to-end
runShowCommand tests covering a successful bundle, skipped
obsolete and Phabricator attachments, duplicate submitted filenames,
malformed base64, size mismatch, an existing destination, and a failed
attachment API request.
- Run
pnpm test src/__test__/cli-show.test.ts, then pnpm tsc.
Acceptance criteria:
- No attachment body is fetched unless
--download-attachments is present.
- Every generated path remains beneath the selected bug directory.
- Existing attachment files are never silently overwritten.
- Downloaded bytes match Bugzilla's decoded attachment data and remain
compressed if the attachment was compressed.
- A normal
bz-show invocation remains stdout-only and creates no files.
Add these options to
bz-show:--download-attachmentsmust require--output-dir.--outputand--output-dirmust be mutually exclusive. Requiring an explicit directoryprevents a read-looking command from unexpectedly writing files into the
current directory.
The layout should be deterministic:
Prefixing the attachment ID prevents collisions between attachments with the
same submitted filename. Do not download obsolete attachments or
text/x-phabricator-requestpseudo-attachments. Continue listing all attachmentmetadata in the Markdown summary so omitted downloads remain visible.
Implement with Red/Green TDD
--output-dirand--download-attachmentscases, plus errors for incompatible or incompleteoption combinations.
.and..;than writing partial or surprising bytes.
runShowCommand, similar to theexisting
CliIoboundary, or extract a documented bundle writer whosebehavior can be tested using directories under
cache/tmp.supports them. Write the Markdown and attachments with mode
0o600, matchingthe existing private Markdown output behavior.
should fail if an attachment target already exists. It may update the
deterministic Markdown summary only after all attachment target paths have
been validated, so a filename conflict cannot leave a partially updated
bundle.
Bugzilla.attachment(id).Decode and write each body, then verify the decoded byte length against the
metadata size when Bugzilla supplies a nonzero size. Treat a mismatch as a
failed download and report the attachment ID and filename.
machine-readable output. Never print attachment bodies, base64 data, or API
keys.
files were already written; do not delete pre-existing user files or attempt
an unsafe rollback.
showCommandHelpandREADME.mdwith the layout, filtering rules,permissions, overwrite behavior, and an example invocation.
runShowCommandtests covering a successful bundle, skippedobsolete and Phabricator attachments, duplicate submitted filenames,
malformed base64, size mismatch, an existing destination, and a failed
attachment API request.
pnpm test src/__test__/cli-show.test.ts, thenpnpm tsc.Acceptance criteria:
--download-attachmentsis present.compressed if the attachment was compressed.
bz-showinvocation remains stdout-only and creates no files.