Skip to content

CLI support, settings persistence, and project restructuring - #4

Open
martesi wants to merge 15 commits into
RaidingForPants:mainfrom
martesi:cli
Open

CLI support, settings persistence, and project restructuring#4
martesi wants to merge 15 commits into
RaidingForPants:mainfrom
martesi:cli

Conversation

@martesi

@martesi martesi commented Aug 4, 2026

Copy link
Copy Markdown

Summary

Introduces a dual-mode CLI/GUI tool (hd2-repatcher / hd2-repatcher-cli), decouples the patching engine from Tkinter, adds persistent game-data-path caching, and sets up packaging, CI, and a release pipeline.

Features introduced

  • New CLI entry point (cli.py): hd2-repatcher-cli --game <path> <PATCH_FOLDER> [<PATCH_FOLDER> ...] processes one or more mod folders non-interactively and reports results to stdout/stderr, with a non-zero exit code if any patch file is corrupted. Falls back to the GUI when invoked with no arguments.
  • Cached game data path (settings.py): the selected game data folder is persisted to %LOCALAPPDATA%\hd2-repatcher\settings.json (via platformdirs), so -g/--game only needs to be passed once. --no-game-path-caching opts a given -g invocation out of overwriting the cache — useful for mod-manager integrations that always want to pass the path explicitly.
  • Drag-and-drop support for the console build: dropping folder(s) onto hd2-repatcher-cli.exe runs the CLI path with the cached game path, and the process pauses with "Press Enter to exit..." (pause_if_owns_console in cli.py) so the auto-spawned console window doesn't disappear before the result can be read.
  • Packaging via pyproject.toml: pip install -e . now installs both hd2-repatcher and hd2-repatcher-cli console-script entry points; requirements.txt is removed in favor of declared dependencies (lz4, platformdirs) plus test/build extras.
  • Build script (build.ps1) automating the two-exe PyInstaller build.
  • CI/CD: .github/workflows/test.yml runs pytest on every push/PR (windows-latest); .github/workflows/release.yml builds both executables and drafts a GitHub release with them attached on tag push or manual dispatch.
  • Test (tests/): added tests covering features added in this PR.
  • README.md: documents installation (prebuilt exe vs. source), CLI usage/flags, settings location, and a manual verification procedure for the patching logic.

Behavior changes

  • Engine no longer owns a GUI or sys.exit. update_unit_mods.py lost its module-level Tk root, select_folder/select_data_folder (moved to gui.py), and the top-level while True loop. process_patch_folder(directory) -> PatchResult replaces the old update_all()/messagebox-driven flow, returning a structured dataclass (patches_found, updated, no_units, corrupted_files) instead of talking to Tkinter directly — gui.py and cli.py each render it their own way.
  • Game data validity check extracted and hardened: is_valid_game_data_path() replaces the inline os.path.exists(...) and ... checks and now also confirms the path is a directory (os.path.isdir) before checking for the marker files (9ba626afa44a3aa3 / bundles.nxa).
  • Engine initialization extracted: init_game_resources(path) replaces the ad hoc slim_init(...)/load_game_resources() pairing that used to be inlined in the GUI loop.

Caveat: two executables

The original building produces an executable without an extra console window; however, that also stops the CLI from functioning as intended. If the extra window doesn't cause much hassle for others, we could remove the old build and keep CLI only.

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.

1 participant