Compare commits
2 Commits
85fdfebd74
...
80ecd3a919
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
80ecd3a919 | ||
|
|
6197659568 |
@@ -101,6 +101,11 @@ Pass 2 builds `ok_disk_names` — the set of disk names that already match the s
|
|||||||
- `logs.py` — real-time log viewer fed from the stdout/stderr queue
|
- `logs.py` — real-time log viewer fed from the stdout/stderr queue
|
||||||
- `settings.py` — in-app editor for `config.json` (server URL, paths, credentials)
|
- `settings.py` — in-app editor for `config.json` (server URL, paths, credentials)
|
||||||
|
|
||||||
|
**`_find_folder` (mods.py) — three-level name matching:** The mods view resolves a mod's local folder by mod name from `comparison.json`, which may differ from the server-canonical folder name used by the fetcher. Lookup order:
|
||||||
|
1. Exact: `@{mod_name}`
|
||||||
|
2. Case-insensitive: `@CBA_A3` matches `CBA_A3`
|
||||||
|
3. Normalized (`_normalize_name`): strips all non-alphanumeric — handles punctuation/spacing differences, e.g. `@US GEAr- Units (IFA3)` matches `US GEAr: Units (IFA3)` (both → `usgearunitsifa3`)
|
||||||
|
|
||||||
**`selection.json`** — GUI selection state file, tracked in git. Persists which mods/groups are selected between GUI sessions. Written by the GUI; safe to delete (GUI recreates it on next save).
|
**`selection.json`** — GUI selection state file, tracked in git. Persists which mods/groups are selected between GUI sessions. Written by the GUI; safe to delete (GUI recreates it on next save).
|
||||||
|
|
||||||
## Python Version Compatibility
|
## Python Version Compatibility
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ from typing import TYPE_CHECKING, Optional
|
|||||||
|
|
||||||
import customtkinter as ctk
|
import customtkinter as ctk
|
||||||
|
|
||||||
|
from arma_modlist_tools.fetcher import _normalize_name
|
||||||
from gui._constants import COLOR_OK, COLOR_ERROR, COLOR_WARN, COLOR_RUNNING
|
from gui._constants import COLOR_OK, COLOR_ERROR, COLOR_WARN, COLOR_RUNNING
|
||||||
from gui.views.base import BaseView
|
from gui.views.base import BaseView
|
||||||
|
|
||||||
@@ -15,15 +16,26 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
|
|
||||||
def _find_folder(group_dir: Path, mod_name: str) -> Optional[Path]:
|
def _find_folder(group_dir: Path, mod_name: str) -> Optional[Path]:
|
||||||
"""Return the local mod folder path, or None if not downloaded."""
|
"""Return the local mod folder path, or None if not downloaded.
|
||||||
|
|
||||||
|
Matches in priority order:
|
||||||
|
1. Exact folder name ``@{mod_name}``
|
||||||
|
2. Case-insensitive name (handles ``@CBA_A3`` vs ``CBA_A3``)
|
||||||
|
3. Normalized name — strips non-alphanumeric (handles ``@cba_a3`` vs ``CBA A3``)
|
||||||
|
"""
|
||||||
if not group_dir.is_dir():
|
if not group_dir.is_dir():
|
||||||
return None
|
return None
|
||||||
candidate = group_dir / f"@{mod_name}"
|
candidate = group_dir / f"@{mod_name}"
|
||||||
if candidate.is_dir():
|
if candidate.is_dir():
|
||||||
return candidate
|
return candidate
|
||||||
target = mod_name.lower()
|
target_lower = mod_name.lower()
|
||||||
|
target_norm = _normalize_name(mod_name)
|
||||||
for p in group_dir.iterdir():
|
for p in group_dir.iterdir():
|
||||||
if p.is_dir() and p.name.lstrip("@").lower() == target:
|
if not p.is_dir():
|
||||||
|
continue
|
||||||
|
if p.name.lstrip("@").lower() == target_lower:
|
||||||
|
return p
|
||||||
|
if _normalize_name(p.name) == target_norm:
|
||||||
return p
|
return p
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user