The scope-normalization sweep only fixed the read paths (list_providers/get_provider/registry_generation) in most registries; the write paths (register/snapshot/restore) still stored under the raw scope string while reads resolved through hermes_home_key — so a scoped registration was written under one key and read under another (agent/terminal_env_registry.py test_scoped_registration_isolated failed on both Linux and Windows CI). - add hermes_constants.normalize_scope(scope): hermes_home_key for non-None, None preserved for the process-global layer — one named function instead of the expression repeated at ~20 call sites - apply it on both sides of all nine scoped registries (browser, terminal_env, image_gen, transcription, tts, video_gen, web_search, secret_sources, dashboard_auth, tools.registry) - agent/deadline: MAX_SAFE_TIMEOUT_S on win32 leaves 60s headroom under the DWORD-ms ceiling so margin-adding consumers (human-wait +60s) stay platform-safe; tools/approval fail-closed fallback mirrors it - tools/approval: strip shell escapes everywhere except inside drive-anchored paths (the Windows shell is bash, so r\m still spells rm; only C:\... backslashes must survive deobfuscation) - consolidate the duplicated _rmtree_force into hermes_cli/fs_utils and repoint both callers - hermes_cli/kanban + disk-cleanup: shlex.split(posix=False) keeps wrapping quotes in tokens; strip them before dispatch/matching - test gating: SIGKILL durability conformance cells are linux_only (TerminateProcess is not SIGKILL), macOS TCC anchor symlink-tree classes are linux_only, Linux chromium profile tests resolve the fixture home via expanduser patch + posix-joined expecteds so they run identically on every host
24 lines
665 B
Python
24 lines
665 B
Python
"""Filesystem helpers shared across Hermes CLI subsystems."""
|
|
|
|
import os
|
|
import shutil
|
|
import stat
|
|
from pathlib import Path
|
|
|
|
|
|
def rmtree_force(path: Path) -> None:
|
|
"""``shutil.rmtree`` that clears read-only bits before deleting.
|
|
|
|
Windows refuses to delete a tree containing read-only files — git clones
|
|
store objects read-only — raising ``PermissionError`` where POSIX unlinks
|
|
them fine. The ``onerror`` hook chmods the file writable and retries.
|
|
"""
|
|
def _onerror(func, p, _exc_info):
|
|
try:
|
|
os.chmod(p, stat.S_IWRITE)
|
|
except OSError:
|
|
pass
|
|
func(p)
|
|
|
|
shutil.rmtree(path, onerror=_onerror)
|