Synchronize the client and select installed language packs (#3)

The launcher synchronizes the current native client, retains manifest-listed ruRU archives and launches the game with WOW_LOCALE=auto. Includes the prepared cleanup of obsolete Extentions directories in both client roots while preserving manifest-required files and unrelated user state.

Version: 1.0.7+10. Deployment now judges native OpenSSL commands by their exit codes while retaining key and signature verification.

Verified on Windows through FVM: full format/analyze, all 76 tests, production dry run, x64 runtime imports and DSA installer signature. The original dirty checkout was preserved. Publication follows the localized client release.
This commit was merged in pull request #3.
This commit is contained in:
2026-10-10 16:50:35 +03:00
parent d3d19bfaeb
commit f834c5fa86
11 changed files with 862 additions and 259 deletions
+44 -7
View File
@@ -137,7 +137,8 @@ Path safety rules:
## Ignored Directories
The launcher excludes these top-level directories from verification:
Unmanaged files in these directories outside `Data/` and `WoW/Data/` are
preserved and excluded from verification:
- `Cache`
- `Errors`
@@ -145,6 +146,8 @@ The launcher excludes these top-level directories from verification:
- `Screenshots`
- `WTF`
- `benilla-config`
- `.moonwell_launcher`
- `Interface/AddOns`
Files under these directories:
@@ -152,15 +155,38 @@ Files under these directories:
- do not participate in local `buildHash`
- are not compared against server manifest
Inside `Data/` and `WoW/Data/`, the manifest is authoritative for every file,
including nested files whose names contain `wtf`, `cache`, or `addons`.
The exclusions above do not exempt files inside Data from cleanup.
## Local Scan
For every non-ignored file in the installation directory, the launcher computes:
For every existing manifest file in the installation directory, the launcher computes:
- normalized relative path
- file size in bytes
- file `sha256`
The result is stored as a `ClientInstallationSnapshot`.
The result is stored as a `ClientInstallationSnapshot`. Paths are always relative
to the selected installation root, including files in nested directories.
The scan separately collects stale paths without hashing their contents:
- every file absent from the manifest in `Data/` and `WoW/Data/`
- every file absent from the manifest in obsolete `Extentions/` and
`WoW/Extentions/` directories, including unused subdirectories and the
Extentions directory itself when no manifest files require it
- `WoW.exe` and `*.dll` absent from the manifest directly in the installation
root or `WoW/` (binary names are matched without case sensitivity)
- unused Data subdirectories, ordered after their children; the Data roots and
directories needed by manifest files are retained
These paths do not contribute to `buildHash`, but prevent sync from completing
until cleanup and final verification succeed. Other unmanaged files are preserved.
On Windows, manifest membership checks for cleanup ignore path letter case.
Directory links are not traversed during cleanup. Links absent from the manifest
inside Data are removed as links, and deletion through a parent pointing outside
the installation is rejected. Directory deletion is never recursive.
## Hash Cache
@@ -224,15 +250,15 @@ The current sync flow is:
2. Scan local installation.
3. Compute local `buildHash`.
4. Compare local files to manifest files by `path`, `size`, and `sha256`.
5. Identify stale local files that are not present in the manifest.
5. Identify stale paths in the cleanup areas described above.
6. If local `buildHash` matches server `buildHash` and there are no stale files
and no mismatches, finish successfully.
7. Delete stale local files outside ignored directories.
7. Delete stale paths, including unused Data subdirectories after their children.
8. Download changed and missing files.
9. Verify every downloaded file by `sha256`.
10. Re-scan the installation.
11. Recompute local `buildHash`.
12. Fail if final snapshot still differs from manifest.
12. Fail if final snapshot still differs from manifest or stale paths remain.
## Pause and Resume Semantics
@@ -263,6 +289,8 @@ When the user presses `Play`:
- `WOW_HOST=<auth-address>`
- `WOW_DATA=<absolute-data-directory>`
- `BENILLA_HOME=<install-root>/benilla-config`
- `WOW_LOCALE=auto` (select the installed `Data/ruRU` or `WoW/Data/ruRU` language pack,
otherwise English; override any locale inherited from the launcher's parent)
6. launcher retains a process handle; while the process is alive, it disables repeated game launches
and client synchronization
7. when the process exits, the launcher returns to the ready-to-play state
@@ -274,6 +302,10 @@ If the executable, data directory, or auth endpoint is missing or invalid,
launch fails with an error. A consumed ticket cannot authenticate again; close
the client and press Play for a fresh ticket after a session ends.
Language archives are ordinary client-manifest entries, including their nested paths,
sizes and SHA-256 hashes. Synchronization verifies and retains required `ruRU` files
and removes obsolete archives under the same manifest-authoritative Data policy.
## Error Behavior
The launcher surfaces errors for:
@@ -295,8 +327,13 @@ The automated tests cover:
- deterministic `buildHash`
- path normalization used by `buildHash`
- exclusion of ignored directories during local scan
- preservation of user state and unrelated unmanaged files during cleanup
- removal of unmanaged Data files, unused subdirectories, WoW.exe, DLLs, and
obsolete Extentions directories
- preservation of manifest-listed DLLs and WoW.exe
- cache cleanup behavior
- safe path resolution
- sync flow with fully up-to-date client
- sync flow with stale files and changed files
- cleanup when all manifest files are already up to date
- rejection of stale paths remaining after final verification
+4
View File
@@ -169,6 +169,10 @@ for all endpoint, bucket, key, and signing-path overrides.
The script stops on the first failed command.
External commands are judged by their exit codes. Windows PowerShell may display
normal OpenSSL stderr notices as error records; they do not fail a successful
command. Key matching and installer-signature verification still must pass.
- Failure before S3 upload leaves production unchanged.
- Failure after S3 upload but before AppCast publication leaves clients on the
preceding AppCast. Fix the issue and rerun the same release.