Initial release: full Arma 3 mod management toolchain

Pipeline: parse HTML presets, compare modlists, download from Caddy
file server, create junctions/symlinks to Arma 3 Server directory.
Includes update/sync flows, missing-mod reporting, OS compat layer,
shared config, dep checker, comprehensive test suite (71 tests).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
revernomad17
2026-04-07 16:04:36 +07:00
commit 91a38b269b
24 changed files with 4976 additions and 0 deletions

View File

@@ -0,0 +1,108 @@
"""
arma_modlist_tools.compat
~~~~~~~~~~~~~~~~~~~~~~~~~
OS detection and cross-platform utilities shared by all CLI scripts.
Supported platforms:
- Windows / Windows Server (sys.platform == "win32")
- Ubuntu / Ubuntu Server (sys.platform == "linux")
Typical usage::
from arma_modlist_tools.compat import is_windows, get_os_label, fix_console_encoding
fix_console_encoding() # call once at script start on Windows
print(get_os_label()) # "Windows Server", "Ubuntu", etc.
"""
from __future__ import annotations
import io
import platform
import sys
# ---------------------------------------------------------------------------
# Platform detection
# ---------------------------------------------------------------------------
def is_windows() -> bool:
"""Return ``True`` on Windows and Windows Server."""
return sys.platform == "win32"
def is_linux() -> bool:
"""Return ``True`` on Linux (Ubuntu, Ubuntu Server, and other distros)."""
return sys.platform == "linux"
def get_os_label() -> str:
"""
Return a human-readable OS label.
Possible values: ``"Windows"``, ``"Windows Server"``, ``"Ubuntu"``,
``"Ubuntu Server"``, ``"Linux"``, ``"Unknown"``.
"""
if is_windows():
ver = platform.version()
# Windows Server versions contain "Server" in the version string
# e.g. "10.0.17763 ... Windows Server 2019 ..."
if "Server" in platform.version() or "Server" in platform.uname().version:
return "Windows Server"
return "Windows"
if is_linux():
# Read /etc/os-release for distro name
os_release = _read_os_release()
name = os_release.get("NAME", "").lower()
if "ubuntu" in name:
# Distinguish desktop vs server: server images have no display server
if _is_headless():
return "Ubuntu Server"
return "Ubuntu"
return "Linux"
return "Unknown"
def _read_os_release() -> dict[str, str]:
"""Parse /etc/os-release into a dict (Linux only)."""
result: dict[str, str] = {}
try:
with open("/etc/os-release", encoding="utf-8") as f:
for line in f:
line = line.strip()
if "=" in line and not line.startswith("#"):
k, _, v = line.partition("=")
result[k] = v.strip('"')
except OSError:
pass
return result
def _is_headless() -> bool:
"""Return True if no graphical display server is detected (headless/server)."""
import os
# Check for common display environment variables
return not (os.environ.get("DISPLAY") or os.environ.get("WAYLAND_DISPLAY"))
# ---------------------------------------------------------------------------
# Console encoding
# ---------------------------------------------------------------------------
def fix_console_encoding() -> None:
"""
Force UTF-8 output on Windows terminals that default to cp1252.
Call once at the top of any CLI script that uses Unicode characters
(checkmarks, arrows, etc.). No-op on Linux.
"""
if not is_windows():
return
if sys.stdout.encoding and sys.stdout.encoding.lower() == "utf-8":
return
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8", errors="replace")
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding="utf-8", errors="replace")