From ff5480765c1e1b00395b084a734e0308c635d6a8 Mon Sep 17 00:00:00 2001 From: thomaslaurenson Date: Sun, 22 Mar 2026 14:31:47 +1300 Subject: [PATCH 1/8] chore: Bumped GitHub actions workflow versions --- .github/workflows/build.yml | 6 +++--- .github/workflows/prerelease.yml | 12 ++++++------ .github/workflows/release.yml | 12 ++++++------ .github/workflows/test.yml | 4 ++-- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 727b935..d6ec4dc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -61,7 +61,7 @@ jobs: echo "Binary created: mpqcli-linux-${{ matrix.arch }}-${{ matrix.libc }}" - name: Upload binary as artifact - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: mpqcli-linux-${{ matrix.arch }}-${{ matrix.libc }} path: mpqcli-linux-${{ matrix.arch }}-${{ matrix.libc }} @@ -93,7 +93,7 @@ jobs: run: cp build/bin/Release/mpqcli.exe build/bin/mpqcli-windows-amd64.exe - name: Upload Artifact - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: mpqcli-windows-amd64.exe path: build/bin/mpqcli-windows-amd64.exe @@ -118,7 +118,7 @@ jobs: docker save mpqcli -o mpqcli-docker.tar - name: Upload Docker image as artifact - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: mpqcli-docker path: mpqcli-docker.tar diff --git a/.github/workflows/prerelease.yml b/.github/workflows/prerelease.yml index 7742253..0208597 100644 --- a/.github/workflows/prerelease.yml +++ b/.github/workflows/prerelease.yml @@ -15,27 +15,27 @@ jobs: uses: actions/checkout@v6 - name: Download Linux GLIBC binary - uses: actions/download-artifact@v7 + uses: actions/download-artifact@v8 with: name: mpqcli-linux-amd64-glibc - name: Download Linux MUSL binary - uses: actions/download-artifact@v7 + uses: actions/download-artifact@v8 with: name: mpqcli-linux-amd64-musl - name: Download Linux ARM64 GLIBC binary - uses: actions/download-artifact@v7 + uses: actions/download-artifact@v8 with: name: mpqcli-linux-arm64-glibc - name: Download Linux ARM64 MUSL binary - uses: actions/download-artifact@v7 + uses: actions/download-artifact@v8 with: name: mpqcli-linux-arm64-musl - name: Download Windows binary - uses: actions/download-artifact@v7 + uses: actions/download-artifact@v8 with: name: mpqcli-windows-amd64.exe @@ -67,7 +67,7 @@ jobs: runs-on: ubuntu-24.04 steps: - name: Download Docker image artifact - uses: actions/download-artifact@v7 + uses: actions/download-artifact@v8 with: name: mpqcli-docker diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bcf553c..6bb09bd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,27 +15,27 @@ jobs: uses: actions/checkout@v6 - name: Download Linux GLIBC binary - uses: actions/download-artifact@v7 + uses: actions/download-artifact@v8 with: name: mpqcli-linux-amd64-glibc - name: Download Linux MUSL binary - uses: actions/download-artifact@v7 + uses: actions/download-artifact@v8 with: name: mpqcli-linux-amd64-musl - name: Download Linux ARM64 GLIBC binary - uses: actions/download-artifact@v7 + uses: actions/download-artifact@v8 with: name: mpqcli-linux-arm64-glibc - name: Download Linux ARM64 MUSL binary - uses: actions/download-artifact@v7 + uses: actions/download-artifact@v8 with: name: mpqcli-linux-arm64-musl - name: Download Windows binary - uses: actions/download-artifact@v7 + uses: actions/download-artifact@v8 with: name: mpqcli-windows-amd64.exe @@ -65,7 +65,7 @@ jobs: runs-on: ubuntu-24.04 steps: - name: Download Docker image artifact - uses: actions/download-artifact@v7 + uses: actions/download-artifact@v8 with: name: mpqcli-docker diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 21e33ab..7c48608 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -35,7 +35,7 @@ jobs: submodules: false - name: Download Linux binary (${{ matrix.arch }} ${{ matrix.libc }}) - uses: actions/download-artifact@v7 + uses: actions/download-artifact@v8 with: name: mpqcli-linux-${{ matrix.arch }}-${{ matrix.libc }} path: build/bin @@ -73,7 +73,7 @@ jobs: submodules: false - name: Download Windows binary - uses: actions/download-artifact@v7 + uses: actions/download-artifact@v8 with: name: mpqcli-windows-amd64.exe path: build/bin/Release From 2294995ea5660721fb3d99eed38449fa225414c4 Mon Sep 17 00:00:00 2001 From: thomaslaurenson Date: Sun, 22 Mar 2026 14:32:19 +1300 Subject: [PATCH 2/8] docs: Added GitHub issue templates for bug and feature --- .github/ISSUE_TEMPLATE/bug_report.yml | 76 ++++++++++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 1 + .github/ISSUE_TEMPLATE/feature_request.yml | 28 ++++++++ 3 files changed, 105 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..73818c4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,76 @@ +name: Bug Report +description: Report a bug or unexpected behaviour in mpqcli. +title: "[Bug]: " +body: + - type: markdown + attributes: + value: | + Please fill in as much detail as possible. The more context you provide, the faster the bug can be investigated. + + - type: input + id: version + attributes: + label: mpqcli version + description: Run `mpqcli version` and paste the output here. + placeholder: "0.9.8" + validations: + required: true + + - type: dropdown + id: os + attributes: + label: Host OS + options: + - Linux + - Windows + - WSL (Windows Subsystem for Linux) + - macOS + - Other + validations: + required: true + + - type: dropdown + id: install-method + attributes: + label: Installation method + options: + - Prebuilt binary + - Docker + - Built from source + - Other + validations: + required: true + + - type: input + id: command + attributes: + label: mpqcli command + description: The exact command you ran. + placeholder: "mpqcli list wow-patch.mpq" + validations: + required: true + + - type: textarea + id: expected + attributes: + label: Expected behaviour + description: What did you expect to happen? + validations: + required: true + + - type: textarea + id: actual + attributes: + label: Actual behaviour / error output + description: What actually happened? Paste any error messages or unexpected output here. + render: shell + validations: + required: true + + - type: textarea + id: context + attributes: + label: Additional context + description: Anything else that might be relevant (e.g. MPQ archive source, file sizes, related issues). + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..3ba13e0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1 @@ +blank_issues_enabled: false diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..b8022e6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,28 @@ +name: Feature Request +description: Suggest a new feature or improvement for mpqcli. +title: "[Feature]: " +body: + - type: textarea + id: problem + attributes: + label: Problem + description: What problem does this feature solve, or what is currently missing? + placeholder: "When I run mpqcli ..., I cannot ..." + validations: + required: true + + - type: textarea + id: solution + attributes: + label: Proposed solution + description: Describe the feature or change you would like to see. + validations: + required: true + + - type: textarea + id: context + attributes: + label: Additional context + description: Any other context, examples, or references that might be useful. + validations: + required: false From 5b83d63ab46ecd018f1586ea9bc593120b6e4ebf Mon Sep 17 00:00:00 2001 From: thomaslaurenson Date: Sun, 22 Mar 2026 14:32:39 +1300 Subject: [PATCH 3/8] docs: Added contributing guidelines document --- CONTRIBUTING.md | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..b986f50 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,47 @@ +# Contributing + +Contributions are welcome. Please read the guidelines below before opening a pull request. + +## Before You Start + +If you are unsure whether a feature fits the project, or whether an existing tool could already be combined with `mpqcli` to achieve the same result, open an issue first. This avoids wasted effort and keeps the project focused. + +**mpqcli follows the Unix philosophy.** The tool is designed to do one thing well and to compose with other tools via pipes and redirection. If you find yourself wanting to add functionality that could be handled by a separate tool — for example, sorting the output of `list` — the right answer is usually to pipe the output to that tool rather than adding it here. + +## Requirements for a Pull Request + +### 1. Builds on your platform + +Make sure the project builds cleanly on your development machine before opening a PR: + +``` +make build_linux # Linux +make build_windows # Windows +``` + +A PR automatically triggers the CI build workflow, which compiles and tests across all supported Linux targets (AMD64 and ARM64, glibc and musl). You are not expected to reproduce all of those locally. + +### 2. Tests pass + +Run the test suite before submitting: + +``` +make test_create_venv # first-time setup only +make test_mpqcli +``` + +All tests must pass without errors. + +### 3. New features should include tests + +If your change adds or modifies user-facing functionality — such as a new subcommand flag or a change in output format — please include a corresponding test in the `test/` directory. The existing test files (`test_list.py`, `test_add.py`, etc.) are good references for the test style and fixtures used. + +### 4. Match the existing code style + +There is no enforced formatter. Write C++ that looks consistent with the surrounding code, and Python tests that follow the style of the existing test files. + +## Workflow Summary + +1. Fork the repository and create a branch for your change +2. Make your changes and verify they build and all tests pass +3. Open a pull request with a clear description of what was changed and why From e2d58fe2f8b6b9f0705657562fcbe18c0d862805 Mon Sep 17 00:00:00 2001 From: thomaslaurenson Date: Sun, 22 Mar 2026 14:32:56 +1300 Subject: [PATCH 4/8] chore: Updated License file --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 20517da..198f1c6 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 Thomas Laurenson +Copyright (c) 2023-2026 Thomas Laurenson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 9b88d133a8cd4af4052b00cf9159ade00bec0f39 Mon Sep 17 00:00:00 2001 From: thomaslaurenson Date: Sun, 22 Mar 2026 14:53:59 +1300 Subject: [PATCH 5/8] fix: Wrong default value in list all help docs --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 84263ee..591e77f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -161,7 +161,7 @@ int main(int argc, char **argv) { list->add_option("-l,--listfile", baseListfileName, "File listing content of an MPQ archive") ->check(CLI::ExistingFile); list->add_flag("-d,--detailed", listDetailed, "File listing with additional columns (default false)"); - list->add_flag("-a,--all", listAll, "File listing including hidden files (default true)"); + list->add_flag("-a,--all", listAll, "File listing including hidden files (default false)"); list->add_option("-p,--property", listProperties, "Prints only specific property values") ->check(CLI::IsMember(validFileListProperties)); From 58d17c01c7d9d3c35a9daf2183f280e0b831c7e6 Mon Sep 17 00:00:00 2001 From: thomaslaurenson Date: Sun, 22 Mar 2026 14:57:45 +1300 Subject: [PATCH 6/8] fix: Linting error in tests --- Makefile | 8 ++++---- test/test_create.py | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 47d53e9..ca0e8f1 100644 --- a/Makefile +++ b/Makefile @@ -47,19 +47,19 @@ docker_glibc_run: ## Run the glibc Docker image # TEST test_create_venv: ## Create Python venv and install test dependencies - python3 -m venv ./venv - . ./venv/bin/activate && \ + python3 -m venv ./.venv + . ./.venv/bin/activate && \ pip3 install -r test/requirements.txt test_mpqcli: ## Run pytest test suite - . ./venv/bin/activate && \ + . ./.venv/bin/activate && \ python3 -m pytest test -s test_clean: ## Remove test data directory rm -rf test/data test_lint: ## Run ruff linter on test directory - . ./venv/bin/activate && \ + . ./.venv/bin/activate && \ ruff check ./test # CLEAN diff --git a/test/test_create.py b/test/test_create.py index d8d662f..9674314 100644 --- a/test/test_create.py +++ b/test/test_create.py @@ -192,8 +192,8 @@ def test_create_mpq_from_file(binary_path, generate_test_files): ) assert result.returncode == 0, f"mpqcli failed with error: {result.stderr}" - assert target_file.exists(), f"MPQ file was not created)" - assert target_file.stat().st_size > 0, f"MPQ file is empty)" + assert target_file.exists(), "MPQ file was not created" + assert target_file.stat().st_size > 0, "MPQ file is empty" verify_archive_file_content(binary_path, target_file, {"enUS test.txt"}) @@ -225,8 +225,8 @@ def test_create_mpq_from_file_with_nameinarchive_parameter(binary_path, generate ) assert result.returncode == 0, f"mpqcli failed with error: {result.stderr}" - assert target_file.exists(), f"MPQ file was not created)" - assert target_file.stat().st_size > 0, f"MPQ file is empty)" + assert target_file.exists(), "MPQ file was not created" + assert target_file.stat().st_size > 0, "MPQ file is empty" verify_archive_file_content(binary_path, target_file, {"enUS messages\\important.txt"}) @@ -254,7 +254,7 @@ def test_create_mpq_from_directory_with_nameinarchive_parameter(binary_path, gen ) assert result.returncode == 1, f"mpqcli failed with error: {result.stderr}" - assert not target_file.exists(), f"MPQ file was created)" + assert not target_file.exists(), "MPQ file was created" def test_create_mpq_with_illegal_locale(binary_path, generate_test_files): From 5b9e2af027ba1b5109eec98f4a713fc3075cad9a Mon Sep 17 00:00:00 2001 From: thomaslaurenson Date: Sun, 22 Mar 2026 15:09:42 +1300 Subject: [PATCH 7/8] docs: Updated readme and made more consistent --- README.md | 180 +++++++++++++++++++++++++++--------------------------- 1 file changed, 90 insertions(+), 90 deletions(-) diff --git a/README.md b/README.md index c50e7cd..cd1f439 100644 --- a/README.md +++ b/README.md @@ -4,22 +4,22 @@ ![Release Version](https://img.shields.io/github/v/release/TheGrayDot/mpqcli?style=flat) -![Release downloads](https://img.shields.io/github/downloads/thegraydot/mpqcli/total?label=release_downloads) ![Package downloads](https://img.shields.io/badge/package_downloads-208-green) +![Release downloads](https://img.shields.io/github/downloads/thegraydot/mpqcli/total?label=release_downloads) ![Package downloads](https://img.shields.io/badge/package_downloads-262-green) -A command line tool to create, add, remove, list, extract, read, and verify MPQ archives using the [StormLib library](https://github.com/ladislav-zezula/StormLib). +A command-line tool to create, add, remove, list, extract, read, and verify MPQ archives using the [StormLib library](https://github.com/ladislav-zezula/StormLib). > ⚠️ **Warning:** This project is under active development and will change functionality between released versions until version 1.0.0. ## Overview -**This is a command-line tool, designed for automation and built with the Unix philosophy in mind.** It is designed to work seamlessly with other command-line tools, supporting piping, redirection, and integration into shell scripts and workflows. For example: +**This is a command-line tool, designed for automation and built with the Unix philosophy in mind.** It is designed to work seamlessly with other command-line tools, supporting piping, redirection, and integration into shell scripts and workflows. For example: - Run one command to create an MPQ archive from a directory of files or a single file - Run one command to list all files in an MPQ archive - Pipe the output to `grep` or other tools to search, filter, or process files - Redirect output to files or other commands for further automation -If you require an MPQ tool with a graphical interface (GUI) and explicit support for more MPQ archive versions - I would recommend using [Ladik's MPQ Editor](http://www.zezula.net/en/mpq/download.html). +If you require an MPQ tool with a graphical interface (GUI) and explicit support for more MPQ archive versions — I would recommend using [Ladik's MPQ Editor](http://www.zezula.net/en/mpq/download.html). ## Download @@ -29,13 +29,13 @@ Pre-built binaries are available for Linux and Windows. Linux/WSL: -``` +```bash curl -fsSL https://raw.githubusercontent.com/thegraydot/mpqcli/main/scripts/install.sh | bash ``` Microsoft Windows: -``` +```powershell irm https://raw.githubusercontent.com/thegraydot/mpqcli/main/scripts/install.ps1 | iex ``` @@ -47,19 +47,19 @@ The Docker image for `mpqcli` is hosted on [GitHub Container Registry (GHCR)](ht To download the latest version of the `mpqcli` Docker image, run: -``` +```bash docker pull ghcr.io/thegraydot/mpqcli:latest ``` You can run `mpqcli` commands directly using the Docker container. For example: -``` +```bash docker run ghcr.io/thegraydot/mpqcli:latest version ``` To use local files in the container, mount a directory from your host system. In the following example, the `-v` argument is used to mount the present working directory to `/data` directory in the container. Then the `mpqcli` container runs the `list` subcommand with `/data/example.mpq` as the target MPQ archive. -``` +```bash docker run -v $(pwd):/data ghcr.io/thegraydot/mpqcli:latest list /data/example.mpq ``` @@ -80,14 +80,14 @@ The `mpqcli` program has the following subcommands: ## Command Examples -Many of the examples use the MPQ archive file, named `wow-patch.mpq`, from a Vanilla World of Warcraft patch file, named `WoW-1.10.0-to-1.10.1-enGB-patch.zip`. If you want to replicate these examples, you can [download the `wow-patch.mpq` file](https://archive.org/download/World_of_Warcraft_Client_and_Installation_Archive/Patches/1.x/WoW-1.10.0-to-1.10.1-enGB-patch.zip/wow-patch.mpq) from the Internet Archive. +Many of the examples use the MPQ archive file, named `wow-patch.mpq`, from a original (Vanilla) World of Warcraft patch file, named `WoW-1.10.0-to-1.10.1-enGB-patch.zip`. If you want to replicate these examples, you can [download the `wow-patch.mpq` file](https://archive.org/download/World_of_Warcraft_Client_and_Installation_Archive/Patches/1.x/WoW-1.10.0-to-1.10.1-enGB-patch.zip/wow-patch.mpq) from the Internet Archive. ### Print information about an MPQ archive The `info` subcommand prints a list of useful information (property keys and values) of an MPQ archive. -``` -mpqcli info wow-patch.mpq +```bash +$ mpqcli info wow-patch.mpq Archive size: 1798918 File count: 65 Format version: 1 @@ -101,17 +101,18 @@ Signature type: Weak The `info` subcommand supports the following properties: +- `archive-size` +- `file-count` - `format-version` - `header-offset` - `header-size` -- `archive-size` -- `file-count` +- `max-files` - `signature-type` You can use the `-p` or `--property` argument with the `info` subcommand to print just the value of a specific property. This can be useful for automation, for example, to determine the signature type of a directory of MPQ archives. -``` -mpqcli info -p file-count wow-patch.mpq +```bash +$ mpqcli info -p file-count wow-patch.mpq 65 ``` @@ -119,8 +120,8 @@ mpqcli info -p file-count wow-patch.mpq Create an MPQ file from a target directory. Automatically adds `(listfile)` to the archive, and will skip this file if it exists in the target directory. -``` -mpqcli create +```bash +$ mpqcli create ``` The default mode of operation for the `create` subcommand is to take everything from the "target" directory (and below) and recursively add it to the archive. The directory structure is retained. Windows-style backslash path separators are used (`\`), as per the observed behavior in most MPQ archives. @@ -129,17 +130,17 @@ The default mode of operation for the `create` subcommand is to take everything Target a specific game version by using the `-g` or `--game` argument. This will automatically set the correct archive format version and settings, although they can be overridden. -``` -mpqcli create -g starcraft -mpqcli create --game wow-wotlk --sector-size 16384 --version 3 # World of WarCraft - Wrath of the Lich King, but with non-standard sector size and MPQ version +```bash +$ mpqcli create -g starcraft +$ mpqcli create --game wow-wotlk --sector-size 16384 --version 3 # World of Warcraft - Wrath of the Lich King, but with non-standard sector size and MPQ version ``` ### Create an MPQ archive from a single file Create an MPQ file from a single file. -``` -mpqcli create --game diablo2 +```bash +$ mpqcli create --game diablo2 ``` This will put the given file in the root of the MPQ archive. By optionally providing a path in the `--name-in-archive` parameter, the name that the file has in the MPQ archive can be changed, and it can be put in a directory. @@ -148,23 +149,23 @@ This will put the given file in the root of the MPQ archive. By optionally provi Use the `-s` or `--sign` argument to cryptographically sign an MPQ archive with the Blizzard weak signature. -``` -mpqcli create --version 1 --sign +```bash +$ mpqcli create --version 1 --sign ``` ### Create an MPQ archive with a given locale Use the `--locale` argument to specify the locale that all added files will have in the archive. Note that subsequent added files will have the default locale unless the `--locale` argument is specified again. -``` -mpqcli create --locale koKR +```bash +$ mpqcli create --locale koKR ``` ### Add a file to an existing archive Add a local file to an already existing MPQ archive. -``` +```bash $ echo "For The Horde" > fth.txt $ mpqcli add fth.txt wow-patch.mpq [+] Adding file: fth.txt @@ -172,7 +173,7 @@ $ mpqcli add fth.txt wow-patch.mpq Alternatively, you can add a file under a specific file name using the `-f` or `--filename-in-archive` argument. -``` +```bash $ echo "For The Alliance" > fta.txt $ mpqcli add fta.txt wow-patch.mpq --filename-in-archive "alliance.txt" [+] Adding file: alliance.txt @@ -180,7 +181,7 @@ $ mpqcli add fta.txt wow-patch.mpq --filename-in-archive "alliance.txt" Alternatively, you can add a file to a specific subdirectory using the `-d` or `--directory-in-archive` argument. -``` +```bash $ echo "For The Swarm" > fts.txt $ mpqcli add fts.txt wow-patch.mpq --directory-in-archive texts [+] Adding file: texts\fts.txt @@ -188,15 +189,15 @@ $ mpqcli add fts.txt wow-patch.mpq --directory-in-archive texts Alternatively, you can add a file under a specific directory and filename using the `-p` or `--path` argument. -``` +```bash $ echo "For The Swarm" > fts.txt $ mpqcli add fts.txt wow-patch.mpq --path "texts\swarm.txt" [+] Adding file: texts\swarm.txt ``` -To overwrite a file in an MPQ archive, set the `--overwrite` flag: +To overwrite a file in an MPQ archive, set the `w` or `--overwrite` flag: -``` +```bash $ echo "For The Horde" > allegiance.txt $ mpqcli add allegiance.txt wow-patch.mpq [+] Adding file: allegiance.txt @@ -209,11 +210,11 @@ $ mpqcli add allegiance.txt wow-patch.mpq --overwrite ``` -### Add files to an MPQ archive with a given locale +### Add a file to an MPQ archive with a given locale Use the `--locale` argument to specify the locale that the added file will have in the archive. Note that subsequent added files will have the default locale unless the `--locale` argument is specified again. -``` +```bash $ mpqcli add allianz.txt wow-patch.mpq --locale deDE [+] Adding file for locale deDE: allianz.txt ``` @@ -222,8 +223,8 @@ $ mpqcli add allianz.txt wow-patch.mpq --locale deDE Target a specific game version by using the `-g` or `--game` argument. This will automatically set the correct encryption rules and MPQ flags, although they can be overridden. -``` -$ mpqcli add khwhat1.wav archive.mpq --game wc2 # In StarCraft and WarCraft II MPQs, wav files are compressed in ADPCM form +```bash +$ mpqcli add khwhat1.wav archive.mpq --game wc2 # In StarCraft and Warcraft II MPQs, wav files are compressed in ADPCM form [+] Adding file: khwhat1.wav ``` @@ -232,7 +233,7 @@ $ mpqcli add khwhat1.wav archive.mpq --game wc2 # In StarCraft and WarCraft II Remove a file from an existing MPQ archive. -``` +```bash $ mpqcli remove fth.txt wow-patch.mpq [-] Removing file: fth.txt ``` @@ -241,17 +242,16 @@ $ mpqcli remove fth.txt wow-patch.mpq Use the `--locale` argument to specify the locale of the file to be removed. -``` +```bash $ mpqcli remove alianza.txt wow-patch.mpq --locale esES [-] Removing file for locale esES: alianza.txt ``` - ### List all files in an MPQ archive Pretty simple, list files in an MPQ archive. Useful to "pipe" to other tools, such as `grep` (see below for examples). -``` +```bash $ mpqcli list wow-patch.mpq BM_COKETENT01.BLP Blizzard_CraftUI.xml @@ -266,7 +266,7 @@ realmlist.wtf Similar to the `ls` command with the `-l` and `-a` options, additional detailed information can be included with the `list` subcommand. The `-a` option includes printing "special" files used in MPQ archives including: `(listfile)`, `(attributes)` and `(signature)`. -``` +```bash $ mpqcli list -d -a wow-patch.mpq 88604 enUS 2006-03-29 02:02:37 BM_COKETENT01.BLP 243 enUS 2006-04-04 21:28:14 Blizzard_CraftUI.xml @@ -310,7 +310,7 @@ The `list` subcommand supports listing the following properties: You can use the `-p` or `--property` argument with the `list` subcommand to print the given properties. Many properties can be given, and they will be printed in the order given. -``` +```bash $ mpqcli list -d -a Patch_rt.mpq -p hash-index -p locale -p flags ... 10893 enUS ixmn glue\ScorePv\pMain.pcx @@ -329,7 +329,7 @@ $ mpqcli list -d -a Patch_rt.mpq -p hash-index -p locale -p flags Older MPQ archives do not contain (complete) file paths of their content. By using the `-l` or `--listfile` argument, one can provide an external listfile that lists the content of the MPQ archive, so that the listed files will have the correct paths. Listfiles can be downloaded on [Ladislav Zezula's site](http://www.zezula.net/en/mpq/download.html). -``` +```bash $ mpqcli list -l /path/to/listfile StarDat.mpq ``` @@ -337,8 +337,8 @@ $ mpqcli list -l /path/to/listfile StarDat.mpq The output will be saved in a folder with the same name as the target MPQ file, without the extension. -``` -mpqcli extract wow-patch.mpq +```bash +$ mpqcli extract wow-patch.mpq [*] Extracted: BM_COKETENT01.BLP [*] Extracted: Blizzard_CraftUI.xml [*] Extracted: CreatureSoundData.dbc @@ -350,34 +350,34 @@ mpqcli extract wow-patch.mpq ### Extract all files to a target directory -Extract files to a specific target directory, which, will be created if it doesn't already exist. In this example, `patch-1.10` is the user-specified output directory. +Extract files to a specific target directory, which will be created if it doesn't already exist. In this example, `patch-1.10` is the user-specified output directory. -``` -mpqcli extract -o patch-1.10 wow-patch.mpq +```bash +$ mpqcli extract -o patch-1.10 wow-patch.mpq ``` ### Extract all files with an external listfile Older MPQ archives do not contain (complete) file paths of their content. By providing an external listfile that lists the content of the MPQ archive, the extracted files will have the correct names and paths. Listfiles can be downloaded on [Ladislav Zezula's site](http://www.zezula.net/en/mpq/download.html). -``` -mpqcli extract -l path/to/listfile War2Dat.mpq +```bash +$ mpqcli extract -l path/to/listfile War2Dat.mpq ``` ### Extract one specific file Extract a single file using the `-f` option. If the target file in the MPQ archive is nested (in a directory) you need to include the full path. Similar to the examples above, you can use the `-o` argument to specify the output directory. -``` -mpqcli extract -f "Documentation\Layout\Greeting.html" "World of Warcraft_1.12.1.5875/Data/base.MPQ" +```bash +$ mpqcli extract -f "Documentation\Layout\Greeting.html" "World of Warcraft_1.12.1.5875/Data/base.MPQ" ``` ### Extract one specific file with locale Use the `--locale` argument to specify the locale of the file to extract. If there is no file with the requested name and locale, the default locale will be used instead. -``` -mpqcli extract -f "rez\gluBNRes.res" Patch_rt.mpq --locale deDE +```bash +$ mpqcli extract -f "rez\gluBNRes.res" Patch_rt.mpq --locale deDE ``` @@ -385,8 +385,8 @@ mpqcli extract -f "rez\gluBNRes.res" Patch_rt.mpq --locale deDE Read the `patch.cmd` file from an MPQ archive and print the file contents to stdout. Even though the subcommand always outputs bytes, plaintext files will be human-readable. -``` -mpqcli read patch.cmd wow-patch.mpq +```bash +$ mpqcli read patch.cmd wow-patch.mpq * set the product patch name PatchVersion This patch upgrades World of Warcraft from version 1.10.0.5195 to version 1.10.1.5230. * make sure that we don't patch version 1.10.1.5230 or greater @@ -402,14 +402,14 @@ PatchSize 1992294400 The tool will always print output in bytes and is designed to be "piped" or redirected. For example, redirect the binary `WoW.exe` file from a WoW patch to a local file: -``` -mpqcli read "WoW.exe" wow-patch.mpq > WoW.exe +```bash +$ mpqcli read "WoW.exe" wow-patch.mpq > WoW.exe ``` Another example, piping the bytes to the `xxd` tool. -``` -mpqcli read "WoW.exe" wow-patch.mpq | xxd +```bash +$ mpqcli read "WoW.exe" wow-patch.mpq | xxd 00000000: 1800 0404 de2a a5da 3240 4500 3250 4500 .....*..2@E.2PE. 00000010: 69ac 2703 0859 c601 0a7a 4500 8942 5344 i.'..Y...zE..BSD 00000020: 4946 4634 30a0 2905 8203 f244 0482 3250 IFF40.)....D..2P @@ -420,45 +420,45 @@ mpqcli read "WoW.exe" wow-patch.mpq | xxd Use the `--locale` argument to specify the locale of the file to read. If there is no file with the requested name and locale, the default locale will be used instead. -``` -mpqcli read "rez\stat_txt.tbl" Patch_rt.mpq --locale ptPT +```bash +$ mpqcli read "rez\stat_txt.tbl" Patch_rt.mpq --locale ptPT ``` ### Verify an MPQ archive -Check the digital signature of an MPQ archive, by verifying the signature in the archive with a collection of known Blizzard public keys (bundled in Stormlib library). The tool will print if verification is successful or fails, as well as return `0` for success and any other value for failure. +Check the digital signature of an MPQ archive by verifying the signature in the archive with a collection of known Blizzard public keys (bundled in StormLib library). The tool will print if verification suceeds or fails, as well as return `0` for success and any other value for failure. -``` -mpqcli verify wow-patch.mpq +```bash +$ mpqcli verify wow-patch.mpq [*] Verify success ``` If verification passes, a zero (`0`) exit status will be returned. This can be helpful to verify a large number of MPQ archives without the need to review the status message that is printed out. -``` -echo $? +```bash +$ echo $? 0 ``` ### Verify an MPQ archive and print the digital signature -Check the digital signature of an MPQ archive, by verifying the signature in the archive and also printing the digital signature value in bytes using the `-p` or `--print` argument. +Check the digital signature of an MPQ archive, by verifying the signature in the archive and also printing the digital signature value in hexidecimal using the `-p` or `--print` argument. -``` -mpqcli verify -p wow-patch.mpq > signature +```bash +$ mpqcli verify -p wow-patch.mpq > signature ``` ## Advanced Command Examples ### Search and extract files on Linux -The `mpqcli` tool has no native search feature - instead, it is designed to be integrated with other, external operating system tools. For example, `mpqcli list` can be "piped" to `grep` in Linux or `Select-String` in Windows Powershell to perform searching. +The `mpqcli` tool has no native search feature — instead, it is designed to be integrated with other, external operating system tools. For example, `mpqcli list` can be "piped" to `grep` in Linux or `Select-String` in Windows PowerShell to perform searching. -The following command lists all files in an MPQ archive, and each filename is filtered using `grep` - selecting files with `exe` in their name, which is then passed back to `mpqcli extract`. The result: search and extract all `exe` files. +The following command lists all files in an MPQ archive, and each filename is filtered using `grep` — selecting files ending in `.exe` (note: `.` is a regex wildcard matching any character; use `\.exe` for a strictly literal match) — which is then passed back to `mpqcli extract`. The result: search and extract all `exe` files. -``` -mpqcli list wow-patch.mpq | grep -i ".exe" | xargs -I@ mpqcli extract -f "@" wow-patch.mpq +```bash +$ mpqcli list wow-patch.mpq | grep -i \.exe | xargs -I@ mpqcli extract -f "@" wow-patch.mpq [*] Extracted: Launcher.exe [*] Extracted: BackgroundDownloader.exe [*] Extracted: WoW.exe @@ -469,8 +469,8 @@ mpqcli list wow-patch.mpq | grep -i ".exe" | xargs -I@ mpqcli extract -f "@" wow Note that directories are specified with backslashes, which need to be escaped (due to how grep and xargs handles them). The following example extracts all `dat` files in the `arr` directory from the `StarDat.mpq` archive and handles escaping via `sed`. -``` -mpqcli list -l scbw.txt StarDat.mpq | grep -i "arr\\\.*dat$" | sort | sed 's|\\|\\\\|g' | xargs -I@ mpqcli extract -f "@" -k StarDat.mpq +```bash +$ mpqcli list -l scbw.txt StarDat.mpq | grep -i "arr\\\.*dat$" | sort | sed 's|\\|\\\\|g' | xargs -I@ mpqcli extract -f "@" -k StarDat.mpq [*] Extracted: arr/flingy.dat [*] Extracted: arr/images.dat [*] Extracted: arr/mapdata.dat @@ -486,10 +486,10 @@ mpqcli list -l scbw.txt StarDat.mpq | grep -i "arr\\\.*dat$" | sort | sed 's|\\| ### Search and extract files on Windows -The following command lists all files in an MPQ archive, and each filename is filtered using `grep` - selecting files with `exe` in their name, which is then passed back to `mpqcli extract`. The result: search and extract all `exe` files. +The following command lists all files in an MPQ archive, and each filename is filtered using `Select-String` — selecting files ending in `.exe` (note: `.` is a regex wildcard matching any character; use `\.exe` for a strictly literal match) — which is then passed back to `mpqcli extract`. The result: search and extract all `exe` files. -``` -mpqcli.exe list wow-patch.mpq | Select-String -Pattern ".exe" | ForEach-Object { mpqcli.exe extract -f $_ wow-patch.mpq } +```powershell +mpqcli.exe list wow-patch.mpq | Select-String -Pattern \.exe | ForEach-Object { mpqcli.exe extract -f $_ wow-patch.mpq } ``` ## Building @@ -498,12 +498,12 @@ mpqcli.exe list wow-patch.mpq | Select-String -Pattern ".exe" | ForEach-Object { - cmake - C++ 17 compiler -- StormLib (provided as Git submodule) -- CLI11 (provided as GitSubmodule) +- StormLib (provided as Git Submodule) +- CLI11 (provided as Git Submodule) ### Linux -``` +```bash git clone --recursive https://github.com/TheGrayDot/mpqcli.git cd mpqcli cmake -B build @@ -514,7 +514,7 @@ The `mpqcli` binary will be available in: `./build/bin/mpqcli` ### Windows -``` +```bash git clone --recursive https://github.com/TheGrayDot/mpqcli.git cd mpqcli cmake -B build @@ -531,23 +531,23 @@ This project requires the [StormLib](https://github.com/ladislav-zezula/StormLib ### CLI11 -This project also uses the [CLI11](https://github.com/CLIUtils/CLI11) command line parser for C++11. It provides simple and easy-to-use CLI arguments. +This project also uses the [CLI11](https://github.com/CLIUtils/CLI11) command line parser for C++11 and beyond. It provides simple and easy-to-use CLI arguments. ## Tests -This project implements End-to-end (E2E) testing, sometimes referred to as system testing or integration testing. This methodology is used because it verifies application functionality by simulating actual usage by an end user. Testing includes creating a variety of MPQ archives, as well as dynamically downloading some small (~1-5MB) MPQ archives from the Internet Archive. The Python programming language coupled with the [pytest framework](https://github.com/pytest-dev/pytest) is used to implement testing, mainly due to ease of implementation. +This project implements End-to-end (E2E) testing, sometimes referred to as system testing or integration testing. This methodology is used because it verifies application functionality by simulating actual usage by an end user. Testing includes creating a variety of MPQ archives, as well as dynamically downloading some small (~1-5MB) MPQ archives from the Internet Archive. The Python programming language coupled with the [pytest framework](https://github.com/pytest-dev/pytest) is used to implement testing, mainly due to ease of implementation. To configure the testing environment you will need Python installed, as well as the required `pytest` package. On a Debian-based Linux system, the following will configure the environment: -``` +```bash sudo apt install python3-venv python3-pip -python3 -m venv test/venv -source test/venv/bin/activate +python3 -m venv test/.venv +source test/.venv/bin/activate pip3 install -r test/requirements.txt ``` Then you can run the tests using: -``` +```bash python3 -m pytest test -s ``` From 61f695df39f15a218817b7cc92510c6d9bf0bd51 Mon Sep 17 00:00:00 2001 From: thomaslaurenson Date: Sun, 22 Mar 2026 15:10:19 +1300 Subject: [PATCH 8/8] chore: Updated changelog and version to 0.9.8 --- CHANGELOG.md | 20 ++++++++++++++++++++ CMakeLists.txt | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 251e14f..221c1eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # Changelog +## 0.9.8 - 2026-03-22 + +### Added + +- The `create` subcommand now supports a single file +- The `add` and `create` subcommands have additional arguments for specifiying the file location in the MPQ archive (`name-in-archive` and `dir-in-archive`) +- The `add` subcommand can now overwrite existing files if requested (`overwrite`) + +### Fixed + +- Several memory leaks + +### Thanks + +- Thanks to @sjoblomj for adding more features and fixes in this release + ## 0.9.7 - 2026-02-23 ### Added @@ -23,6 +39,10 @@ - Improved locale printing and display throughout +### Thanks + +- A big thank you to @sjoblomj for adding so many features in this release + ## 0.9.6 - 2025-12-23 ### Added diff --git a/CMakeLists.txt b/CMakeLists.txt index 3811bf2..5145361 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.10) -project(MPQCLI VERSION 0.9.7) +project(MPQCLI VERSION 0.9.8) # Options option(BUILD_MPQCLI "Build the mpqcli CLI app" ON)