summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node/src/meshbay_node/platform.py
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-03 16:20:23 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-03 16:20:28 +0200
commit753653b4df62723b82d32799825135822886eac7 (patch)
tree14829922bf343e6353093eaceaa84986fe5f84df /packages/meshbay-node/src/meshbay_node/platform.py
parent675beed6ff688733a9598f9d82d41578f48316be (diff)
downloadmeshbay-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.py70
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