Automated Notes:
This release is a major codebase optimization and bug fix release, focusing on performance improvements, code cleanup, and reliability fixes.
Breaking Changes
- Differ Package Removed: The
go-bsdiffbinary diffing library and all related code have been completely removed from the project.- The generator always used full-file replacement (
os.ReadFile) - the bsdiff path was never triggered. - This removes
github.com/gabstv/go-bsdiffand its indirect dependency ongithub.com/dsnet/compressfrom the dependency tree. - The
Differfield has been removed from both theGeneratorandApplierstructs.
- The generator always used full-file replacement (
New Features
-
Magic-Byte Compression Detection: The patch applier now detects compression format from the first 4 bytes of the patch file (
{= JSON,\x28\xB5\x2F\xFD= zstd,\x1F\x8B= gzip) instead of trying each decompressor in sequence until one succeeds. This eliminates wasted decode attempts and speeds up patch loading. -
Streaming Patch Loading:
LoadPatch()has been rewritten to use streaming file I/O instead of reading the entire patch file into memory. Large patches are now processed with constant memory usage proportional to the decompressed JSON, not the compressed file size.
Enhancements & Improvements
-
Multi-Part Splitting for Reverse Patches: The
--crp(create reverse patch) flag now correctly respects the--splitsizeoption. Previously, reverse patches were never split regardless of size. -
Compression Level Passthrough:
SavePatch()now accepts a compression level parameter instead of hardcoding level 3. The--levelflag is now fully respected for all patch types, including multi-part patches. -
Redundant SHA-256 Removed: The generator no longer re-computes SHA-256 checksums on every changed file - the scanner already computed these into the manifest. This saves approximately 12-20 seconds per 10GB of changed data.
-
Improved Buffer Sizing: Buffered reader sizes reduced from 64MB to 64KB for streaming JSON decoding. The 64MB buffers provided no throughput benefit for the streaming decoder while consuming excessive memory.
-
Deduplicated Key File Detection: The
detectKeyFile()helper replaced 6 copy-pasted instances of theprogram.exe/game.exe/app.exe/main.exedetection loop across all three generation modes. -
Encoder Deduplication:
generator/main.gonow delegates toutils.SavePatch()instead of duplicating the entire streaming JSON pipeline. This removed approximately 210 lines of duplicated encoding functions and 4 unused imports.
Bug Fixes
-
Same-Name Directory Crash Fixed: Using
--from-dirand--to-dirwith identical folder names (e.g., both pointing to a folder named "MyApp") no longer crashes with a "version is already registered" error. -
Reverse Filename Collision Fixed: When generating reverse patches with
--crpfrom same-named directories, the reverse patch now uses a_revsuffix (e.g.,App-to-App_rev.patch) instead of overwriting the forward patch file. -
Executable Creation with Multi-Part Patches Fixed: Creating self-contained executables with
--create-exeno longer fails with "file not found" when--splitsizecauses the patch to be split into multiple parts. The system now correctly locates the.01.patchfile.
Housekeeping & Refactoring
-
Removed Dead Code: Removed the unused
VerifyAfterfield fromPatchOptions, cleaned up ~20 lines of nonsensical dead code inmultipart.go, and removed unused Config fields (PreservePerms,VerifySignatures,SigningKeyPath). -
Documentation Updated: Architecture diagrams and component descriptions updated to reflect the removed differ package and current code structure. Data structures documentation corrected to match actual code behavior.
-
Expanded Test Suite: Added 8 new optimization tests (tests 61-68) to
advanced-test.ps1covering key file detection, compression level passthrough, streaming LoadPatch, and reverse patch roundtrip verification.