diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-09-03 16:20:23 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-09-03 16:20:28 +0200 |
| commit | 753653b4df62723b82d32799825135822886eac7 (patch) | |
| tree | 14829922bf343e6353093eaceaa84986fe5f84df /packages/meshbay-node/src/meshbay_node/platform.py | |
| parent | 675beed6ff688733a9598f9d82d41578f48316be (diff) | |
| download | meshbay-753653b4df62723b82d32799825135822886eac7.tar.gz | |
refactor(node): platform abstraction for Windows portability (W1-W2-W5-W6-W7)
Platform directories, signal handling, chmod guards, ffmpeg discovery,
and platform-conditional CLI messages — all testable on Linux.
See docs/WINDOWS-PORT.md §5 for the plan these implement.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-node/src/meshbay_node/platform.py')
| -rw-r--r-- | packages/meshbay-node/src/meshbay_node/platform.py | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/packages/meshbay-node/src/meshbay_node/platform.py b/packages/meshbay-node/src/meshbay_node/platform.py new file mode 100644 index 0000000..bc48169 --- /dev/null +++ b/packages/meshbay-node/src/meshbay_node/platform.py @@ -0,0 +1,70 @@ +"""Platform-specific paths and tool resolution for meshbay-node.""" + +import os +import shutil +import sys +from pathlib import Path + +# ── Directories ────────────────────────────────────────────────────────────── + + +def config_dir() -> Path: + if sys.platform == "win32": + return Path(os.environ.get("LOCALAPPDATA") or Path.home()) / "meshbay" + return Path.home() / ".config" / "meshbay" + + +def data_dir() -> Path: + if sys.platform == "win32": + return Path(os.environ.get("LOCALAPPDATA") or Path.home()) / "meshbay" / "data" + return Path.home() / ".local" / "share" / "meshbay" + + +def state_dir() -> Path: + if sys.platform == "win32": + return Path(os.environ.get("LOCALAPPDATA") or Path.home()) / "meshbay" / "state" + return Path.home() / ".local" / "state" / "meshbay" + + +# ── File permissions ───────────────────────────────────────────────────────── + + +def chmod_private(path: Path, *, mode: int = 0o600) -> None: + """Set restrictive permissions on a file. No-op on Windows (NTFS ignores mode bits).""" + if sys.platform != "win32": + path.chmod(mode) + + +# ── Media tools ────────────────────────────────────────────────────────────── + +_ffmpeg_path: str = "ffmpeg" +_ffprobe_path: str = "ffprobe" + + +def check_media_tools( + ffmpeg: str = "ffmpeg", ffprobe: str = "ffprobe", +) -> None: + """Resolve ffmpeg/ffprobe at daemon startup. Raises RuntimeError if not found.""" + global _ffmpeg_path, _ffprobe_path + resolved = shutil.which(ffmpeg) + if not resolved: + raise RuntimeError( + f"{ffmpeg!r} not found in PATH. " + "Install ffmpeg or set [node] ffmpeg_path in node.toml." + ) + _ffmpeg_path = resolved + resolved = shutil.which(ffprobe) + if not resolved: + raise RuntimeError( + f"{ffprobe!r} not found in PATH. " + "Install ffmpeg or set [node] ffprobe_path in node.toml." + ) + _ffprobe_path = resolved + + +def ffmpeg_cmd() -> str: + return _ffmpeg_path + + +def ffprobe_cmd() -> str: + return _ffprobe_path |