Default: /usr/local/gniza/workdir (root) or ~/.local/state/gniza/workdir (user). MySQL dumps and rclone temp configs now use WORK_DIR. Configurable via gniza.conf or TUI Settings screen. Created during install. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
101 lines
2.8 KiB
Python
101 lines
2.8 KiB
Python
import os
|
|
import re
|
|
from pathlib import Path
|
|
|
|
_KV_RE = re.compile(r'^([A-Z_][A-Z_0-9]*)=(.*)')
|
|
_QUOTED_RE = re.compile(r'^"(.*)"$|^\'(.*)\'$')
|
|
|
|
|
|
def _get_config_dir() -> Path:
|
|
if os.geteuid() == 0:
|
|
return Path("/etc/gniza")
|
|
xdg = os.environ.get("XDG_CONFIG_HOME", os.path.expanduser("~/.config"))
|
|
return Path(xdg) / "gniza"
|
|
|
|
|
|
def _get_log_dir() -> Path:
|
|
if os.geteuid() == 0:
|
|
return Path("/var/log/gniza")
|
|
xdg = os.environ.get("XDG_STATE_HOME", os.path.expanduser("~/.local/state"))
|
|
return Path(xdg) / "gniza" / "log"
|
|
|
|
|
|
def _get_work_dir() -> Path:
|
|
if os.geteuid() == 0:
|
|
return Path("/usr/local/gniza/workdir")
|
|
xdg = os.environ.get("XDG_STATE_HOME", os.path.expanduser("~/.local/state"))
|
|
return Path(xdg) / "gniza" / "workdir"
|
|
|
|
|
|
CONFIG_DIR = _get_config_dir()
|
|
LOG_DIR = _get_log_dir()
|
|
WORK_DIR = _get_work_dir()
|
|
|
|
|
|
def parse_conf(filepath: Path) -> dict[str, str]:
|
|
data = {}
|
|
if not filepath.is_file():
|
|
return data
|
|
for line in filepath.read_text().splitlines():
|
|
line = line.strip()
|
|
if not line or line.startswith("#"):
|
|
continue
|
|
m = _KV_RE.match(line)
|
|
if m:
|
|
key = m.group(1)
|
|
value = m.group(2)
|
|
qm = _QUOTED_RE.match(value)
|
|
if qm:
|
|
value = qm.group(1) if qm.group(1) is not None else qm.group(2)
|
|
data[key] = value
|
|
return data
|
|
|
|
|
|
def _sanitize_value(value: str) -> str:
|
|
return value.replace("\\", "\\\\").replace('"', '\\"').replace("\n", "")
|
|
|
|
|
|
def write_conf(filepath: Path, data: dict[str, str]) -> None:
|
|
filepath.parent.mkdir(parents=True, exist_ok=True)
|
|
lines = []
|
|
for key, value in data.items():
|
|
lines.append(f'{key}="{_sanitize_value(value)}"')
|
|
filepath.write_text("\n".join(lines) + "\n")
|
|
filepath.chmod(0o600)
|
|
|
|
|
|
def update_conf_key(filepath: Path, key: str, value: str) -> None:
|
|
value = _sanitize_value(value)
|
|
filepath.parent.mkdir(parents=True, exist_ok=True)
|
|
if not filepath.is_file():
|
|
filepath.write_text(f'{key}="{value}"\n')
|
|
filepath.chmod(0o600)
|
|
return
|
|
lines = filepath.read_text().splitlines()
|
|
found = False
|
|
for i, line in enumerate(lines):
|
|
m = _KV_RE.match(line.strip())
|
|
if m and m.group(1) == key:
|
|
lines[i] = f'{key}="{value}"'
|
|
found = True
|
|
break
|
|
if not found:
|
|
lines.append(f'{key}="{value}"')
|
|
filepath.write_text("\n".join(lines) + "\n")
|
|
filepath.chmod(0o600)
|
|
|
|
|
|
def list_conf_dir(subdir: str) -> list[str]:
|
|
d = CONFIG_DIR / subdir
|
|
if not d.is_dir():
|
|
return []
|
|
return sorted(p.stem for p in d.glob("*.conf") if p.is_file())
|
|
|
|
|
|
def has_targets() -> bool:
|
|
return len(list_conf_dir("targets.d")) > 0
|
|
|
|
|
|
def has_remotes() -> bool:
|
|
return len(list_conf_dir("remotes.d")) > 0
|