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:
revernomad17
2026-04-07 17:29:50 +07:00
parent 9dea44fa3d
commit ef2f6329f6

191
README.md
View File

@@ -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)
``` ```