docs: update CLAUDE.md, README, and Vietnamese guide for migration step
- CLAUDE.md: document migrator.py algorithm and junction-removal rationale - README.md: pipeline now 5 steps, add --skip-migrate flag, add migrator.py to folder structure, update test count 142 -> 158 - docs/huong-dan-su-dung.md: 5-step pipeline table, new glossary entry, updated footer version note
This commit is contained in:
14
CLAUDE.md
14
CLAUDE.md
@@ -117,6 +117,20 @@ Pass 2 builds `ok_disk_names` — the set of disk names that already match the s
|
||||
|
||||
**`build_server_index` progress callback:** Accepts an optional `progress_fn(current, total, name)` callback. `step_fetch` in `run.py` uses this to print `Indexing N/M: @FolderName` every 25 folders so the log never goes silent during the server scan phase. The library itself never calls `print` — the caller owns the I/O.
|
||||
|
||||
### `migrator.py` — mod group migration
|
||||
|
||||
Before `step_fetch` runs, `step_migrate` moves locally-downloaded mod folders to match the group assignments in the new `comparison.json`. This avoids re-downloading mods that already exist on disk under a different group when presets are switched (e.g. `A` → `A_v1`).
|
||||
|
||||
**Algorithm:**
|
||||
|
||||
1. `_build_local_index(downloads)` — scans every `downloads/{group}/@Folder`, reads `meta.cpp` to extract `publishedid`, builds `{steam_id → (group, path)}` and `{norm_name → (group, path)}` maps.
|
||||
2. `_build_target_list(comparison)` — flattens `comparison.json` into `[(new_group, steam_id, mod_name)]`.
|
||||
3. For each target: locate mod on disk (steam_id first, normalised name fallback); skip if already in correct group or destination exists; remove stale junction from `arma_dir` if present; move folder with `shutil.move`.
|
||||
|
||||
**Junction removal is critical:** a stale junction (target moved away) still has the reparse point attribute, so `_is_junction()` returns `True` and `link_group` would skip it as `already_linked` without recreating it at the new path. Removing the junction before the move lets `step_link` recreate it correctly.
|
||||
|
||||
**CLI:** `python run.py --skip-migrate` bypasses the step if needed.
|
||||
|
||||
### `update_mods.py` — orphan file removal
|
||||
|
||||
After downloading updated files, `update_mods.py` compares every file in the local mod folder against the server's file list and **deletes any local files that no longer exist on the server**. This prevents stale `.pbo` or `.bisign` files from accumulating when a mod's content changes upstream. Each removed file is logged as `[-] orphan removed: <rel_path>` and the final summary line includes an orphan count. The orphan check runs even when no files need downloading (e.g. timestamps match but the local folder has extras).
|
||||
|
||||
38
README.md
38
README.md
@@ -12,7 +12,7 @@ cp config.template.json config.json # fill in server URL + credentials + arma_
|
||||
python check_deps.py # verify dependencies
|
||||
|
||||
# Day-to-day: full pipeline
|
||||
python run.py # parse → compare → download → link
|
||||
python run.py # parse → compare → migrate → download → link
|
||||
|
||||
# GUI (recommended)
|
||||
python gui.py
|
||||
@@ -24,7 +24,7 @@ python sync_missing.py # retry mods that were absent from server
|
||||
python check_names.py --fix # fix folder name mismatches
|
||||
|
||||
# Testing
|
||||
python test_suite.py # 142 tests (network tests auto-skip if offline)
|
||||
python test_suite.py # 158 tests (network tests auto-skip if offline)
|
||||
```
|
||||
|
||||
---
|
||||
@@ -133,29 +133,34 @@ Place your Arma 3 Launcher preset exports (`.html`) into the `modlist_html/` fol
|
||||
python run.py
|
||||
```
|
||||
|
||||
This runs all four steps in sequence:
|
||||
This runs all five steps in sequence:
|
||||
|
||||
```
|
||||
Step 1/4: Parse presets — modlist_html/*.html -> modlist_json/*.json
|
||||
Step 2/4: Compare presets — produces modlist_json/comparison.json
|
||||
Step 3/4: Fetch mods — downloads from server -> downloads/
|
||||
Step 4/4: Link mods — creates junctions/symlinks in Arma 3 Server dir
|
||||
Step 1/5: Parse presets — modlist_html/*.html -> modlist_json/*.json
|
||||
Step 2/5: Compare presets — produces modlist_json/comparison.json
|
||||
Step 3/5: Migrate mod groups — moves existing folders to match new group assignments
|
||||
Step 4/5: Fetch mods — downloads from server -> downloads/
|
||||
Step 5/5: Link mods — creates junctions/symlinks in Arma 3 Server dir
|
||||
```
|
||||
|
||||
The **migrate step** avoids re-downloading mods that already exist on disk when you switch preset versions (e.g. `A` → `A_v1`). It matches mods by steam ID (via `meta.cpp`) and moves the folder to the correct group, removing any stale junction first so the link step can re-create it at the new path.
|
||||
|
||||
### Skip flags
|
||||
|
||||
```bash
|
||||
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-fetch --skip-link # parse + compare + migrate only
|
||||
python run.py --skip-parse --skip-compare --skip-fetch # link only
|
||||
python run.py --skip-parse --skip-compare --skip-fetch --group shared
|
||||
python run.py --skip-migrate # skip auto-migration
|
||||
```
|
||||
|
||||
| Flag | Skips |
|
||||
|------|-------|
|
||||
| `--skip-parse` | Step 1 (HTML parsing) |
|
||||
| `--skip-compare` | Step 2 (preset comparison) |
|
||||
| `--skip-fetch` | Step 3 (downloading) |
|
||||
| `--skip-link` | Step 4 (linking) |
|
||||
| `--skip-migrate` | Step 3 (mod group migration) |
|
||||
| `--skip-fetch` | Step 4 (downloading) |
|
||||
| `--skip-link` | Step 5 (linking) |
|
||||
| `--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.
|
||||
@@ -526,7 +531,7 @@ The same functionality is available as the **Clean Orphans** tab in the GUI.
|
||||
|
||||
### run.py
|
||||
|
||||
Orchestrator that chains all four pipeline steps. Described in [Quick Start](#quick-start--full-pipeline) above.
|
||||
Orchestrator that chains all five pipeline steps. Described in [Quick Start](#quick-start--full-pipeline) above.
|
||||
|
||||
---
|
||||
|
||||
@@ -602,6 +607,7 @@ arma-modlist-tools/
|
||||
| |- linker.py # Junction/symlink manager
|
||||
| |- reporter.py # Missing-mod report builder
|
||||
| |- cleaner.py # Orphan folder detection
|
||||
| |- migrator.py # Mod group migration (move folders to match comparison.json)
|
||||
| |- config.py # config.json loader
|
||||
| |- compat.py # OS detection + encoding fix
|
||||
|
|
||||
@@ -652,7 +658,7 @@ arma-modlist-tools/
|
||||
|- check_names.py # Diagnose and fix folder name / steam_id issues
|
||||
|- clean_orphans.py # Find and delete orphaned mod folders
|
||||
|- check_deps.py # Dependency checker
|
||||
|- test_suite.py # Test suite (142 tests)
|
||||
|- test_suite.py # Test suite (158 tests)
|
||||
```
|
||||
|
||||
---
|
||||
@@ -691,7 +697,7 @@ arma-modlist-tools/
|
||||
|
||||
## Running Tests
|
||||
|
||||
The test suite covers all modules with 142 tests. Network tests (section 15) auto-skip when the server is unreachable.
|
||||
The test suite covers all modules with 158 tests. Network tests auto-skip when the server is unreachable.
|
||||
|
||||
```bash
|
||||
python test_suite.py
|
||||
@@ -713,7 +719,9 @@ python test_suite.py
|
||||
cleaner 8 tests
|
||||
e2e — clean_orphans 6 tests (subprocess CLI)
|
||||
coverage gaps 23 tests (mocked platform branches)
|
||||
gui.views.mods 8 tests (_find_folder matching)
|
||||
migrator 7 tests (group migration logic)
|
||||
live server 9 tests (skipped if server unreachable)
|
||||
------------------------------------------------------------
|
||||
Results: 142 passed, 0 failed, 0 skipped (142 total)
|
||||
Results: 158 passed, 0 failed, 0 skipped (158 total)
|
||||
```
|
||||
|
||||
@@ -37,7 +37,8 @@ Tài liệu này dành cho người dùng **chưa biết gì** về dự án. B
|
||||
Ứng dụng sẽ tự động:
|
||||
- Đọc danh sách mod từ các preset
|
||||
- So sánh, tìm mod dùng chung và mod riêng giữa các preset
|
||||
- Tải mod từ máy chủ về máy tính của bạn
|
||||
- **Di chuyển** các thư mục mod đã tải về sang đúng nhóm mới (tránh tải lại khi đổi phiên bản preset)
|
||||
- Tải mod từ máy chủ về máy tính của bạn (chỉ những mod thực sự chưa có)
|
||||
- Tạo liên kết (junction/symlink) để Arma 3 Server nhận ra các mod
|
||||
|
||||
---
|
||||
@@ -153,13 +154,14 @@ Giao diện gồm thanh điều hướng bên trái và khu vực nội dung bê
|
||||
|
||||
### 5.3 Trạng thái Pipeline
|
||||
|
||||
Cột bên phải hiển thị 4 bước của quy trình:
|
||||
Cột bên phải hiển thị 5 bước của quy trình:
|
||||
|
||||
| Bước | Mô tả | Dấu hiệu hoàn thành |
|
||||
|------|-------|-------------------|
|
||||
| Phân tích preset | Đọc danh sách mod từ tệp HTML | Có ≥ 2 preset được chọn |
|
||||
| So sánh preset | Tìm mod chung và riêng | Tệp `comparison.json` tồn tại |
|
||||
| Tải mod | Tải tệp mod từ máy chủ | Có thư mục mod trong `downloads/` |
|
||||
| Di chuyển nhóm mod | Chuyển thư mục mod sẵn có sang đúng nhóm mới | Tự động (không cần tải lại) |
|
||||
| Tải mod | Tải tệp mod thực sự còn thiếu từ máy chủ | Có thư mục mod trong `downloads/` |
|
||||
| Liên kết với Arma | Tạo junction tới thư mục Arma 3 | Thư mục Arma 3 Server tồn tại |
|
||||
|
||||
Biểu tượng `✓` (xanh) = đã xong, `○` (xám) = chưa xong.
|
||||
@@ -391,7 +393,7 @@ Hiển thị các đường dẫn đang dùng: URL máy chủ, thư mục Arma,
|
||||
| Thuật ngữ | Giải thích |
|
||||
|-----------|------------|
|
||||
| **Preset** | Tệp HTML xuất từ Arma 3 Launcher chứa danh sách mod |
|
||||
| **Pipeline** | Chuỗi 4 bước tự động: phân tích → so sánh → tải → liên kết |
|
||||
| **Pipeline** | Chuỗi 5 bước tự động: phân tích → so sánh → di chuyển nhóm → tải → liên kết |
|
||||
| **Junction / Symlink** | Liên kết thư mục ảo — Arma 3 thấy mod trong thư mục của mình nhưng tệp thực sự nằm ở `downloads/` |
|
||||
| **Shared mods** | Mod xuất hiện trong tất cả preset đã chọn |
|
||||
| **Unique mods** | Mod chỉ có trong một preset cụ thể |
|
||||
@@ -401,9 +403,10 @@ Hiển thị các đường dẫn đang dùng: URL máy chủ, thư mục Arma,
|
||||
| **comparison.json** | Tệp kết quả so sánh preset, lưu danh sách mod theo nhóm |
|
||||
| **missing_report.json** | Báo cáo mod có trong preset nhưng chưa có trên máy chủ |
|
||||
| **downloads/** | Thư mục chứa tệp mod đã tải về |
|
||||
| **Di chuyển nhóm mod** | Bước tự động chuyển thư mục mod từ nhóm cũ sang nhóm mới theo `comparison.json` — tránh tải lại khi đổi phiên bản preset |
|
||||
| **Mod thừa (Orphan)** | Thư mục mod còn trong `downloads/` nhưng không còn trong preset nào đang dùng |
|
||||
| **config.json** | Tệp cấu hình lưu thông tin máy chủ và đường dẫn |
|
||||
|
||||
---
|
||||
|
||||
*Phiên bản tài liệu: 2026-04 (cập nhật: thêm Clean Orphans). Nếu có vấn đề, liên hệ người quản trị máy chủ.*
|
||||
*Phiên bản tài liệu: 2026-04 (cập nhật: thêm bước Di chuyển nhóm mod, pipeline 5 bước). Nếu có vấn đề, liên hệ người quản trị máy chủ.*
|
||||
|
||||
Reference in New Issue
Block a user