update README: add check_names.py, update Python version, migrating existing mods section
- Documents check_names.py (--fix, --fix-ids, status codes table) - Adds Migrating Existing Mods section for servers with pre-existing mods - Updates Python requirement from 3.11 to 3.9 - Updates test count from 71 to 85 - Updates check_deps example output to show 3.9.2 - Adds check_names.py to folder structure Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
191
README.md
191
README.md
@@ -19,10 +19,12 @@ Python toolchain for managing Arma 3 mod presets: parse launcher exports, compar
|
|||||||
- [report_missing.py](#report_missingpy)
|
- [report_missing.py](#report_missingpy)
|
||||||
- [sync_missing.py](#sync_missingpy)
|
- [sync_missing.py](#sync_missingpy)
|
||||||
- [update_mods.py](#update_modspy)
|
- [update_mods.py](#update_modspy)
|
||||||
|
- [check_names.py](#check_namespy)
|
||||||
- [run.py](#runpy)
|
- [run.py](#runpy)
|
||||||
6. [Folder Structure](#folder-structure)
|
6. [Migrating Existing Mods](#migrating-existing-mods)
|
||||||
7. [Moving to a New Device](#moving-to-a-new-device)
|
7. [Folder Structure](#folder-structure)
|
||||||
8. [Running Tests](#running-tests)
|
8. [Moving to a New Device](#moving-to-a-new-device)
|
||||||
|
9. [Running Tests](#running-tests)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -30,7 +32,7 @@ Python toolchain for managing Arma 3 mod presets: parse launcher exports, compar
|
|||||||
|
|
||||||
| Requirement | Version | Notes |
|
| Requirement | Version | Notes |
|
||||||
|-------------|---------|-------|
|
|-------------|---------|-------|
|
||||||
| Python | >= 3.11 | `python --version` |
|
| Python | >= 3.9 | `python --version` |
|
||||||
| requests | any | `pip install requests` |
|
| requests | any | `pip install requests` |
|
||||||
| tqdm | any | `pip install tqdm` |
|
| tqdm | any | `pip install tqdm` |
|
||||||
| Windows or Linux | — | Windows uses junctions, Linux uses symlinks |
|
| Windows or Linux | — | Windows uses junctions, Linux uses symlinks |
|
||||||
@@ -115,9 +117,9 @@ Step 4/4: Link mods — creates junctions/symlinks in Arma 3 Server di
|
|||||||
### Skip flags
|
### Skip flags
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python run.py --skip-fetch --skip-link # parse + compare only
|
python run.py --skip-fetch --skip-link # parse + compare only
|
||||||
python run.py --skip-parse --skip-compare --skip-fetch # link only
|
python run.py --skip-parse --skip-compare --skip-fetch # link only
|
||||||
python run.py --skip-parse --skip-compare --skip-fetch --group shared # link one group only
|
python run.py --skip-parse --skip-compare --skip-fetch --group shared
|
||||||
```
|
```
|
||||||
|
|
||||||
| Flag | Skips |
|
| Flag | Skips |
|
||||||
@@ -128,6 +130,8 @@ python run.py --skip-parse --skip-compare --skip-fetch --group shared # link on
|
|||||||
| `--skip-link` | Step 4 (linking) |
|
| `--skip-link` | Step 4 (linking) |
|
||||||
| `--group GROUP` | Link step: only link this one group (e.g. `shared`) |
|
| `--group GROUP` | Link step: only link this one group (e.g. `shared`) |
|
||||||
|
|
||||||
|
> **Safe to re-run.** Every step is idempotent — existing files are skipped, already-linked mods are skipped.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Individual Scripts
|
## Individual Scripts
|
||||||
@@ -141,8 +145,8 @@ python check_deps.py
|
|||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
Python 3.11.9 OK
|
Python 3.9.2 OK
|
||||||
OS Windows
|
OS Windows Server
|
||||||
|
|
||||||
requests 2.33.0 OK
|
requests 2.33.0 OK
|
||||||
tqdm 4.67.3 OK
|
tqdm 4.67.3 OK
|
||||||
@@ -236,7 +240,7 @@ Total mods to consider: 72
|
|||||||
Building server index... 87 mods indexed
|
Building server index... 87 mods indexed
|
||||||
|
|
||||||
[1/70] @ace -> downloads/shared/@ace/ (group: shared)
|
[1/70] @ace -> downloads/shared/@ace/ (group: shared)
|
||||||
addons/ace_common/... 5.2 MB [████████████] 100%
|
addons/ace_common/... 5.2 MB [################] 100%
|
||||||
...
|
...
|
||||||
Done 42 downloaded 8.2 MB
|
Done 42 downloaded 8.2 MB
|
||||||
|
|
||||||
@@ -281,13 +285,6 @@ python link_mods.py status --group shared
|
|||||||
python link_mods.py link --group shared
|
python link_mods.py link --group shared
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
|
||||||
Linking group: shared -> C:\...\Arma 3 Server
|
|
||||||
|
|
||||||
[+] @ace linked
|
|
||||||
[=] @cba_a3 already linked
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Remove links
|
#### Remove links
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -298,14 +295,14 @@ Prompts for confirmation before removing links. Removing a link does **not** del
|
|||||||
|
|
||||||
#### List available groups
|
#### List available groups
|
||||||
|
|
||||||
Omit `--group` to see all available groups:
|
Omit `--group` to see what groups exist:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python link_mods.py status
|
python link_mods.py status
|
||||||
```
|
```
|
||||||
|
|
||||||
> **Windows note:** Creates NTFS directory junctions (`mklink /J`). No administrator rights required.
|
> **Windows:** Creates NTFS directory junctions (`mklink /J`). No administrator rights required.
|
||||||
> **Linux note:** Creates standard symlinks (`os.symlink`).
|
> **Linux:** Creates standard symlinks (`os.symlink`).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -338,7 +335,7 @@ Cross-referencing 72 required mods...
|
|||||||
|
|
||||||
### sync_missing.py
|
### sync_missing.py
|
||||||
|
|
||||||
Re-check the server for mods that were previously missing and download any that have since been added.
|
Re-check the server for mods that were previously missing and download any that have since been added to the server.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python sync_missing.py
|
python sync_missing.py
|
||||||
@@ -373,15 +370,15 @@ Re-checking server index... 89 mods indexed
|
|||||||
|
|
||||||
### update_mods.py
|
### update_mods.py
|
||||||
|
|
||||||
Re-download mod files that have changed on the server without changing the modlist structure (same mods, updated file contents/versions).
|
Re-download mod files that have changed on the server without changing the modlist structure (same mods, updated file versions).
|
||||||
|
|
||||||
Detection uses **file size comparison**: a file is considered stale if it is missing locally or its local size differs from the server-reported size.
|
Detection uses **file size comparison**: a file is re-downloaded if it is missing locally or its local size differs from the server-reported size. Use `--force` to re-download everything unconditionally.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python update_mods.py # check all groups and mods
|
python update_mods.py # check all groups and mods
|
||||||
python update_mods.py --group shared # check one group only
|
python update_mods.py --group shared # one group only
|
||||||
python update_mods.py --mod @ace # check one specific mod
|
python update_mods.py --mod @ace # one specific mod
|
||||||
python update_mods.py --force # re-download all files regardless of size
|
python update_mods.py --force # re-download all files
|
||||||
python update_mods.py --force --group shared
|
python update_mods.py --force --group shared
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -391,14 +388,81 @@ Building server index... 87 mods indexed
|
|||||||
Mode: size-check
|
Mode: size-check
|
||||||
Checking 28 mod folder(s)...
|
Checking 28 mod folder(s)...
|
||||||
|
|
||||||
[=] @cba_a3 shared 4 files up-to-date
|
[=] @cba_a3 shared 4 files up-to-date
|
||||||
[+] @ace shared 42 files 3 updated (8.2 MB)
|
[+] @ace shared 42 files 3 updated (8.2 MB)
|
||||||
[=] @rhsusaf 150th_MW 88 files up-to-date
|
[=] @rhsusaf 150th_MW 88 files up-to-date
|
||||||
|
|
||||||
Total: 134 files checked, 3 updated, 8.2 MB downloaded
|
Total: 134 files checked, 3 updated, 8.2 MB downloaded
|
||||||
```
|
```
|
||||||
|
|
||||||
> **No re-linking needed.** Junctions/symlinks already point at the `downloads/` folders, so updated files are immediately visible to the Arma 3 Server.
|
> **No re-linking needed.** Junctions already point at the `downloads/` folders, so updated files are immediately visible to the Arma 3 Server.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### check_names.py
|
||||||
|
|
||||||
|
Diagnostic tool that compares mod folder names in `downloads/` against the server's canonical names, and optionally fixes mismatches.
|
||||||
|
|
||||||
|
**Status codes:**
|
||||||
|
|
||||||
|
| Status | Meaning |
|
||||||
|
|--------|---------|
|
||||||
|
| `OK` | Disk folder name matches server name exactly |
|
||||||
|
| `MISMATCH` | Disk name differs from server canonical name (rename needed) |
|
||||||
|
| `ID_COLLISION` | Local `meta.cpp` has a wrong `publishedid` that belongs to a different mod |
|
||||||
|
| `NOT_ON_SERVER` | No matching folder found on server |
|
||||||
|
|
||||||
|
#### Report only
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python check_names.py
|
||||||
|
python check_names.py --group shared # limit to one group
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
Disk name Group Status / Server name
|
||||||
|
-------------------------------------------- ------------------------ ---------------------------------------------------
|
||||||
|
@ace shared OK (@ace)
|
||||||
|
@CBA_A3 shared MISMATCH -> @cba_a3
|
||||||
|
@NIArms All in One- ACE Compatibility 150th_MW_2026_v1.0 ID_COLLISION @Realistic Ragdoll Physics (local id: 1234567)
|
||||||
|
@150th Languard Zeus Tools 150th_WW2_2026_V1.0 NOT_ON_SERVER
|
||||||
|
|
||||||
|
80 OK, 1 mismatch, 1 id_collision, 1 not on server
|
||||||
|
|
||||||
|
Run with --fix to rename mismatched folders and --fix-ids to correct wrong steam IDs in meta.cpp.
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Fix mismatched folder names
|
||||||
|
|
||||||
|
Renames `MISMATCH` folders on disk to the server's canonical name and updates the `arma_dir` junction to match.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python check_names.py --fix
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
[+] @CBA_A3 -> @cba_a3
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Fix wrong steam IDs
|
||||||
|
|
||||||
|
Corrects the `publishedid` in local `meta.cpp` files for `ID_COLLISION` entries. Uses `comparison.json` as the authoritative source of steam IDs (which came from the Steam Workshop URLs in your HTML presets).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python check_names.py --fix-ids
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
[+] @NIArms All in One- ACE Compatibility meta.cpp: 1234567 -> 9876543
|
||||||
|
```
|
||||||
|
|
||||||
|
**Both fixes at once:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python check_names.py --fix --fix-ids
|
||||||
|
```
|
||||||
|
|
||||||
|
**Requires:** `modlist_json/comparison.json` for `--fix-ids` (run `run.py --skip-fetch --skip-link` first).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -408,6 +472,39 @@ Orchestrator that chains all four pipeline steps. Described in [Quick Start](#qu
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Migrating Existing Mods
|
||||||
|
|
||||||
|
If the Arma 3 Server already has mods installed and you want to bring them under this toolchain without re-downloading:
|
||||||
|
|
||||||
|
**Step 1 — Generate comparison.json:**
|
||||||
|
```bash
|
||||||
|
python run.py --skip-fetch --skip-link
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 2 — Check for name mismatches before linking:**
|
||||||
|
```bash
|
||||||
|
python check_names.py
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 3 — Fix any issues:**
|
||||||
|
```bash
|
||||||
|
python check_names.py --fix # rename mismatched folders
|
||||||
|
python check_names.py --fix-ids # fix wrong steam IDs in meta.cpp
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 4 — Create links:**
|
||||||
|
```bash
|
||||||
|
python run.py --skip-parse --skip-compare --skip-fetch
|
||||||
|
```
|
||||||
|
|
||||||
|
> Instead of downloading, you can create junctions from `downloads/{group}/@ModName` pointing to wherever the mods already live on disk:
|
||||||
|
> ```cmd
|
||||||
|
> mklink /J downloads\shared\@ace "C:\existing\path\@ace"
|
||||||
|
> ```
|
||||||
|
> Then run the link step normally.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Folder Structure
|
## Folder Structure
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -452,6 +549,7 @@ arma-modlist-tools/
|
|||||||
|- report_missing.py # Missing mod report
|
|- report_missing.py # Missing mod report
|
||||||
|- sync_missing.py # Sync newly available missing mods
|
|- sync_missing.py # Sync newly available missing mods
|
||||||
|- update_mods.py # Re-download updated mod files
|
|- update_mods.py # Re-download updated mod files
|
||||||
|
|- check_names.py # Diagnose and fix folder name / steam_id issues
|
||||||
|- check_deps.py # Dependency checker
|
|- check_deps.py # Dependency checker
|
||||||
|- test_suite.py # Test suite
|
|- test_suite.py # Test suite
|
||||||
```
|
```
|
||||||
@@ -460,7 +558,7 @@ arma-modlist-tools/
|
|||||||
|
|
||||||
## Moving to a New Device
|
## Moving to a New Device
|
||||||
|
|
||||||
1. **Clone the repo** on the new device:
|
1. **Clone the repo:**
|
||||||
```bash
|
```bash
|
||||||
git clone https://git.revoluxiant.io.vn/revernomad17/arma-modlist-tools.git
|
git clone https://git.revoluxiant.io.vn/revernomad17/arma-modlist-tools.git
|
||||||
cd arma-modlist-tools
|
cd arma-modlist-tools
|
||||||
@@ -480,19 +578,19 @@ arma-modlist-tools/
|
|||||||
4. **Add your preset exports:**
|
4. **Add your preset exports:**
|
||||||
Copy your `.html` files from the Arma 3 Launcher into `modlist_html/`.
|
Copy your `.html` files from the Arma 3 Launcher into `modlist_html/`.
|
||||||
|
|
||||||
5. **Run the full pipeline:**
|
5. **Verify and run:**
|
||||||
```bash
|
```bash
|
||||||
python check_deps.py # verify everything is ready
|
python check_deps.py
|
||||||
python run.py # parse → compare → fetch → link
|
python run.py
|
||||||
```
|
```
|
||||||
|
|
||||||
> The `downloads/` folder can be large (several GB of mod files). On a second device you can either let `run.py` re-download everything, or copy the `downloads/` folder manually and run `python run.py --skip-fetch` to skip the download step and just create links.
|
> The `downloads/` folder can be several GB. On a second device you can either let `run.py` re-download everything, or copy the `downloads/` folder manually and run `python run.py --skip-fetch` to skip downloading and just create links.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Running Tests
|
## Running Tests
|
||||||
|
|
||||||
The test suite covers all modules with 71 tests. No network connection required.
|
The test suite covers all modules with 85 tests. No network connection required.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python test_suite.py
|
python test_suite.py
|
||||||
@@ -500,15 +598,16 @@ python test_suite.py
|
|||||||
|
|
||||||
```
|
```
|
||||||
------------------------------------------------------------
|
------------------------------------------------------------
|
||||||
compat 6 tests
|
compat 6 tests
|
||||||
config 5 tests
|
config 5 tests
|
||||||
parser 9 tests
|
parser 9 tests
|
||||||
compare 8 tests
|
compare 8 tests
|
||||||
fetcher 19 tests (pure functions, no network)
|
fetcher 19 tests (pure functions, no network)
|
||||||
reporter 8 tests
|
reporter 8 tests
|
||||||
linker 12 tests (uses temp dirs)
|
linker 12 tests (uses temp dirs)
|
||||||
__init__ 2 tests
|
__init__ 2 tests
|
||||||
integration 2 tests
|
check_names 16 tests
|
||||||
|
integration 2 tests
|
||||||
------------------------------------------------------------
|
------------------------------------------------------------
|
||||||
Results: 71 passed, 0 failed, 0 skipped (71 total)
|
Results: 85 passed, 0 failed, 0 skipped (85 total)
|
||||||
```
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user