helper script for personal provider account script for pi agent.
This commit is contained in:
parent
5393e4eab5
commit
5a18e93d93
182
helpers/fill-oc-go-providers.py
Executable file
182
helpers/fill-oc-go-providers.py
Executable file
@ -0,0 +1,182 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""ocd-fill.py -- create ocd account stubs from oc-go account names.
|
||||||
|
|
||||||
|
Reads the oc-go provider account map (a YAML file), takes the account names,
|
||||||
|
and appends [[account]] stubs to the ocd config for any name not already
|
||||||
|
present. cookie and default_workspace are left empty for you to fill in.
|
||||||
|
|
||||||
|
Inputs
|
||||||
|
source defaults to $OC_GO_YAML or
|
||||||
|
~/.pi/agent/oc-providers/accounts/oc-go.yaml
|
||||||
|
(fallback: ~/.pi/agent/oc-providers/oc-go.yaml)
|
||||||
|
config defaults to $OCD_CONFIG or
|
||||||
|
$XDG_CONFIG_HOME/ocd/config.toml (~/.config/ocd/config.toml)
|
||||||
|
|
||||||
|
Flags
|
||||||
|
--source PATH override the oc-go YAML path
|
||||||
|
--config PATH override the ocd config path
|
||||||
|
--dry-run print the plan, do not write
|
||||||
|
-h, --help print this help
|
||||||
|
|
||||||
|
Report: added N / present N / to fill N
|
||||||
|
added new stubs written this run
|
||||||
|
present source names already in the config
|
||||||
|
to fill config entries whose cookie or default_workspace is empty or
|
||||||
|
still a placeholder
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
try:
|
||||||
|
import tomllib # Python 3.11+
|
||||||
|
except ModuleNotFoundError: # pragma: no cover
|
||||||
|
sys.stderr.write("ocd-fill: python 3.11+ required for tomllib\n")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
HEADER = (
|
||||||
|
"# ocd config. Generated by ocd-fill; fill in cookie and\n"
|
||||||
|
"# default_workspace for each account. ${VAR} expands from env.\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def default_source() -> Path:
|
||||||
|
if env := os.environ.get("OC_GO_YAML"):
|
||||||
|
return Path(env)
|
||||||
|
home = Path.home()
|
||||||
|
primary = home / ".pi/agent/oc-providers/accounts/oc-go.yaml"
|
||||||
|
if primary.is_file():
|
||||||
|
return primary
|
||||||
|
return home / ".pi/agent/oc-providers/oc-go.yaml"
|
||||||
|
|
||||||
|
|
||||||
|
def default_config() -> Path:
|
||||||
|
if env := os.environ.get("OCD_CONFIG"):
|
||||||
|
return Path(env)
|
||||||
|
xdg = os.environ.get("XDG_CONFIG_HOME") or str(Path.home() / ".config")
|
||||||
|
return Path(xdg) / "ocd/config.toml"
|
||||||
|
|
||||||
|
|
||||||
|
def toml_basic_string(s: str) -> str:
|
||||||
|
"""Encode a TOML basic string (double-quoted, minimal escapes)."""
|
||||||
|
s = s.replace("\\", "\\\\").replace('"', '\\"')
|
||||||
|
return f'"{s}"'
|
||||||
|
|
||||||
|
|
||||||
|
def read_source_names(path: Path) -> list[str]:
|
||||||
|
with path.open(encoding="utf-8") as f:
|
||||||
|
data = yaml.safe_load(f) or {}
|
||||||
|
accs = data.get("accounts") or {}
|
||||||
|
if not isinstance(accs, dict):
|
||||||
|
sys.stderr.write(f"ocd-fill: `accounts:` is not a map in {path}\n")
|
||||||
|
sys.exit(1)
|
||||||
|
return list(accs.keys())
|
||||||
|
|
||||||
|
|
||||||
|
def read_config(path: Path) -> tuple[list[str], int]:
|
||||||
|
"""Return (existing account names, count of entries still to fill)."""
|
||||||
|
if not path.is_file():
|
||||||
|
return [], 0
|
||||||
|
try:
|
||||||
|
with path.open("rb") as f:
|
||||||
|
data = tomllib.load(f)
|
||||||
|
except tomllib.TOMLDecodeError as e:
|
||||||
|
sys.stderr.write(f"ocd-fill: config is not valid TOML: {e}\n")
|
||||||
|
sys.exit(1)
|
||||||
|
names: list[str] = []
|
||||||
|
to_fill = 0
|
||||||
|
for a in data.get("account", []):
|
||||||
|
n = a.get("name")
|
||||||
|
if n:
|
||||||
|
names.append(str(n))
|
||||||
|
cookie = str(a.get("cookie", "") or "")
|
||||||
|
ws = str(a.get("default_workspace", "") or "")
|
||||||
|
needs = (
|
||||||
|
not cookie.strip()
|
||||||
|
or not ws.strip()
|
||||||
|
or "REPLACE_ME" in cookie
|
||||||
|
or "REPLACE_ME" in ws
|
||||||
|
)
|
||||||
|
if needs:
|
||||||
|
to_fill += 1
|
||||||
|
return names, to_fill
|
||||||
|
|
||||||
|
|
||||||
|
def append_stubs(path: Path, names: list[str]) -> None:
|
||||||
|
path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
existing = path.read_text(encoding="utf-8") if path.is_file() else ""
|
||||||
|
stub_text = "\n\n".join(stub_block(n) for n in names) + "\n"
|
||||||
|
with path.open("a", encoding="utf-8") as f:
|
||||||
|
if existing.strip():
|
||||||
|
# Keep one blank line before the first new stub.
|
||||||
|
f.write(existing.rstrip("\n") + "\n\n")
|
||||||
|
else:
|
||||||
|
f.write(HEADER + "\n")
|
||||||
|
f.write(stub_text)
|
||||||
|
|
||||||
|
|
||||||
|
def stub_block(name: str) -> str:
|
||||||
|
return (
|
||||||
|
f"[[account]]\n"
|
||||||
|
f"name = {toml_basic_string(name)}\n"
|
||||||
|
f'cookie = ""\n'
|
||||||
|
f'default_workspace = ""'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def main(argv: list[str]) -> int:
|
||||||
|
p = argparse.ArgumentParser(
|
||||||
|
prog="ocd-fill",
|
||||||
|
description="Create ocd account stubs from oc-go account names.",
|
||||||
|
add_help=False,
|
||||||
|
)
|
||||||
|
p.add_argument("-h", "--help", action="help", help="print this help and exit")
|
||||||
|
p.add_argument("--source", type=Path, default=default_source(),
|
||||||
|
help="oc-go YAML path")
|
||||||
|
p.add_argument("--config", type=Path, default=default_config(),
|
||||||
|
help="ocd config path to write")
|
||||||
|
p.add_argument("--dry-run", action="store_true", help="print plan, do not write")
|
||||||
|
args = p.parse_args(argv)
|
||||||
|
|
||||||
|
if not args.source.is_file():
|
||||||
|
sys.stderr.write(f"ocd-fill: source file not found: {args.source}\n")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
src_names = read_source_names(args.source)
|
||||||
|
existing_names, to_fill = read_config(args.config)
|
||||||
|
existing_set = set(existing_names)
|
||||||
|
to_add = [n for n in src_names if n not in existing_set]
|
||||||
|
present = [n for n in src_names if n in existing_set]
|
||||||
|
|
||||||
|
n_added = len(to_add)
|
||||||
|
n_present = len(present)
|
||||||
|
|
||||||
|
print(f"ocd-fill: source={args.source}")
|
||||||
|
print(f"ocd-fill: config={args.config}")
|
||||||
|
if n_added == 0:
|
||||||
|
print("ocd-fill: added 0")
|
||||||
|
else:
|
||||||
|
print(f"ocd-fill: added {n_added}: {' '.join(to_add)}")
|
||||||
|
print(f"ocd-fill: present {n_present}")
|
||||||
|
print(f"ocd-fill: to fill {to_fill}")
|
||||||
|
|
||||||
|
if args.dry_run:
|
||||||
|
print("ocd-fill: dry run, no write")
|
||||||
|
return 0
|
||||||
|
if n_added == 0:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
append_stubs(args.config, to_add)
|
||||||
|
print(f"ocd-fill: wrote {n_added} stub(s) to {args.config}")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main(sys.argv[1:]))
|
||||||
Loading…
Reference in New Issue
Block a user