[core] Use native stored ZIPs for support bundles and profile backups#3206
Conversation
Co-authored-by: Codex <noreply@openai.com>
There was a problem hiding this comment.
Thanks @jensenpat — clean extraction. The ZipArchive helper is a straight lift-and-shift of the existing reader/writer with two small upgrades (explicit numeric_limits overflow guards for entry count / sizes / offsets, and static_cast<uInt> on the crc32 size argument), and the support-bundle path drops the QProcess/powershell/tar shell-out in favor of in-process ZIP writing via QSaveFile. Nice removal of an external-process dependency — and QSaveFile::commit() gives atomic replace semantics the old shell-out couldn't.
A few small notes for your consideration, none blockers:
1. Linux/macOS support bundle file extension change (worth a CHANGELOG entry)
src/core/SupportBundle.cpp:202 previously produced support-bundle-*.tar.gz on non-Windows and .zip on Windows. After this PR, all platforms produce .zip. I grepped the tree and found no consumer of support-bundle-*.tar.gz (the only hit was the line being removed), so this is safe. Worth a brief note in CHANGELOG.md since existing Linux/macOS users with scripts or muscle memory expecting .tar.gz will be surprised.
2. collectSupportBundleEntries is flat-only by design
QDir::Files + no QDirIterator means subdirectories under the temp bundle dir are silently dropped. Today SupportBundle::createBundle writes only top-level files (logs, JSONs, settings.xml, enabled-categories.txt — all flat), so this matches current behavior. Worth a one-line comment in collectSupportBundleEntries noting the flat-only invariant so a future contributor who adds, say, a crashdumps/ subdir doesn't end up with a silently-empty section in the bundle.
3. Stored-only ZIP and uncompressed log size
The shared helper only writes stored (method 0) ZIPs, so a support bundle now uncompresses to roughly the sum of input file sizes plus headers, where the old tar czf deflated logs. AetherSDR logs are rotated small so this is unlikely to be a real problem in practice, but if a user has logs in the tens of MB the bundle is now noticeably larger. The PR title is explicit ("native stored ZIPs") so this is presumably intentional — flagging in case it's worth a follow-up to wire deflate into writeStoredZip later (the reader already handles method 8).
4. uncompressedSize is dead in the stored-method branch
src/core/ZipArchive.cpp:142 reads uncompressedSize but it's only consumed inside the method == 8 branch. Pre-existing — moved verbatim from ProfileTransfer.cpp — but since you're touching this code, a [[maybe_unused]] or restructuring the read to live inside the deflate branch would be cleaner. Skip if you'd rather keep the lift truly verbatim.
Otherwise this looks good — the round-trip + corruption test in tests/zip_archive_test.cpp covers the contract well, and routing ProfileTransfer through the same helper means the existing profile_transfer_test exercises the writer too. Thanks again.
🤖 aethersdr-agent · cost: $8.6056 · model: claude-opus-4-7
|
Claude here — merged, thanks @jensenpat. Clean refactor + the WACK "Blocked executables" finding is gone. The null-safe error setter and Filed #3218 to track adding deflate compression as a follow-up. Confirmed nothing in Store policy or WACK objects to runtime deflate — the rule was about subprocess imports, which this PR resolved. Switching back to compressed bundles is purely a UX win for users hitting Discord/email size limits. 73, Jeremy KK7GWY & Claude (AI dev partner) |
Summary
ZipArchivehelper..zipfiles using the shared stored-ZIP writer instead of launching PowerShellCompress-Archiveortar.Validation
scripts/enter-msvc.ps1 -Arch x64and Ninja using 8 jobs.build_opus,zip_archive_test,profile_transfer_test, andAetherSDR.profile_transfer_testandzip_archive_testseparately with Qt onPATH; both passed.windeployqton the built app for manual testing.powershell,Compress-Archive, or.tar.gzsupport-bundle path remains.dumpbin; no directCreateProcess/ShellExecuteimport was found.