summaryrefslogtreecommitdiff
path: root/link/pi-models.py
diff options
context:
space:
mode:
Diffstat (limited to 'link/pi-models.py')
-rw-r--r--link/pi-models.py66
1 files changed, 66 insertions, 0 deletions
diff --git a/link/pi-models.py b/link/pi-models.py
new file mode 100644
index 0000000..6188c94
--- /dev/null
+++ b/link/pi-models.py
@@ -0,0 +1,66 @@
+"""Generate ~/.pi/agent/models.json from the repo and its fragments.
+
+Run by link/pi.sh. It lives in a file rather than a heredoc inside $( ):
+macOS ships bash 3.2, which does not skip heredoc content when it scans
+for the end of a command substitution, so an odd number of apostrophes in
+here would stop the whole script parsing -- which it did, on 2026-09-25.
+"""
+
+import glob, json, os, sys
+
+base_path, frag_dir, target = sys.argv[1:4]
+
+
+def load(path):
+ with open(path) as f:
+ return json.load(f)
+
+
+# The repo's providers, then each fragment's. A fragment may add a provider or
+# replace one of the same name; any other top-level key takes the last file's
+# value. Which provider came from where is reported: a fragment quietly
+# shadowing a provider the repo ships would otherwise be invisible.
+desired = {}
+notes = []
+for path in [base_path] + sorted(glob.glob(os.path.join(frag_dir, "*.json"))):
+ try:
+ layer = load(path)
+ except (OSError, ValueError) as e:
+ print("error:cannot read %s: %s" % (path, e))
+ sys.exit(0)
+ for key, value in layer.items():
+ if key == "providers":
+ providers = desired.setdefault("providers", {})
+ if path != base_path:
+ for name in value:
+ notes.append("%s %s by %s" % (
+ name,
+ "replaced" if name in providers else "added",
+ os.path.basename(path),
+ ))
+ providers.update(value)
+ else:
+ desired[key] = value
+
+# A symlink is the pre-generation state: replace it, even with no fragments, so
+# the live file is never the tracked one.
+was_link = os.path.islink(target)
+try:
+ current = None if was_link else load(target)
+except (OSError, ValueError):
+ current = None
+
+for note in notes:
+ print("note:" + note)
+
+if current == desired:
+ print("unchanged:")
+elif os.environ.get("DRY_RUN"):
+ print("would-write:" + ("replacing the link" if was_link else "merged changes"))
+else:
+ tmp = target + ".dotfiles-tmp"
+ with open(tmp, "w") as f:
+ json.dump(desired, f, indent=2)
+ f.write("\n")
+ os.replace(tmp, target)
+ print("wrote:" + ("replaced the link" if was_link else "merged changes"))