fix check_names false positives from server steam_id collisions

When a server folder's meta.cpp publishedid appears in a local folder
that has a completely different name, the steam_id lookup was returning
a wrong MISMATCH. Added a two-pass classification: any proposed rename
target that is already an exact OK match for another folder is
reclassified as NOT_ON_SERVER (steam_id collision) instead of MISMATCH.

_resolve_status moved to module level and takes ok_disk_names as a
parameter so it can be unit-tested independently.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
revernomad17
2026-04-07 17:15:30 +07:00
parent e706e71f29
commit 2ab6d87532
2 changed files with 83 additions and 18 deletions

View File

@@ -97,6 +97,30 @@ def _collect_mod_folders(cfg, group_filter: str | None) -> list[tuple[str, Path]
return result
# ---------------------------------------------------------------------------
# Classification helpers
# ---------------------------------------------------------------------------
def _resolve_status(
disk_name: str,
server_name: str | None,
ok_disk_names: set[str],
) -> tuple[str, str]:
"""
Return (status, display_col) for one mod, after false-positive filtering.
A MISMATCH is downgraded to NOT_ON_SERVER when the proposed server name is
already the exact disk name of another folder (steam_id collision on server).
"""
if server_name is None:
return "NOT_ON_SERVER", "---"
if server_name == disk_name:
return "OK", server_name
if server_name in ok_disk_names:
return "NOT_ON_SERVER", "--- (steam_id collision)"
return "MISMATCH", server_name
# ---------------------------------------------------------------------------
# Fix: rename folder + update junction
# ---------------------------------------------------------------------------
@@ -174,32 +198,43 @@ def main() -> None:
print("No @Mod folders found in downloads/.\n")
sys.exit(0)
# ---- Classify each mod ----
# ---- Pass 1: raw lookup for every mod ----
# result row: (group, mod_dir, server_name | None)
raw: list[tuple[str, Path, str | None]] = []
for group, mod_dir in mods:
raw.append((group, mod_dir, _lookup_server_name(mod_dir.name, mod_dir, index)))
# ---- Pass 2: discard false positives caused by steam_id collisions ----
# If a server name is already an exact disk name (i.e. an OK match exists),
# any other folder whose steam_id lookup points to that same server name is a
# false positive — the server has a bad/shared publishedid in meta.cpp.
# Reclassify those entries as NOT_ON_SERVER.
ok_disk_names: set[str] = {
mod_dir.name
for _, mod_dir, server_name in raw
if server_name == mod_dir.name # exact match = genuinely OK
}
def _classify(disk_name: str, server_name: str | None) -> tuple[str, str]:
return _resolve_status(disk_name, server_name, ok_disk_names)
# ---- Print table ----
ok_count = mismatch_count = unknown_count = 0
mismatches: list[tuple[str, Path, str]] = [] # (group, mod_dir, server_name)
mismatches: list[tuple[str, Path, str]] = []
print(f" {'Disk name':<{W_DISK}} {'Group':<{W_GROUP}} {'Server name':<{W_SERVER}} Status")
print(f" {'-'*W_DISK} {'-'*W_GROUP} {'-'*W_SERVER} ------")
for group, mod_dir in mods:
disk_name = mod_dir.name
server_name = _lookup_server_name(disk_name, mod_dir, index)
if server_name is None:
status = "NOT_ON_SERVER"
unknown_count += 1
server_col = "---"
elif server_name == disk_name:
status = "OK"
for group, mod_dir, server_name in raw:
status, server_col = _classify(mod_dir.name, server_name)
if status == "OK":
ok_count += 1
server_col = server_name
else:
status = "MISMATCH"
elif status == "MISMATCH":
mismatch_count += 1
server_col = server_name
mismatches.append((group, mod_dir, server_name))
else:
unknown_count += 1
print(f" {disk_name:<{W_DISK}} {group:<{W_GROUP}} {server_col:<{W_SERVER}} {status}")
print(f" {mod_dir.name:<{W_DISK}} {group:<{W_GROUP}} {server_col:<{W_SERVER}} {status}")
print(f"\n {ok_count} OK, {mismatch_count} mismatch, {unknown_count} not on server\n")