PROP OUT: keep Location Assets mounted on the ProP Mac; SHARE NOT MOUNTED; hold remounts

- remote-access/mac-keep-mounted.sh: a user LaunchAgent that keeps a share mounted (every minute and at
  login; Keychain login; unmount + remount only when the share hangs), installed on NA ProP for
  Chronicles' Location Assets
- PROP OUT says SHARE NOT MOUNTED instead of NOT IN <weekend> when the share is gone; its hold (and
  auto-fix) starts the agent and waits for the share

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-22 11:22:07 -04:00
co-authored by Claude Opus 5.5
parent 11ac8aa8e0
commit e2add3b27e
8 changed files with 110 additions and 6 deletions
+35 -2
View File
@@ -1655,8 +1655,12 @@ def eval_columns(rc, prop, found, get_page, comp):
BUNDLE_SCRIPT = r'''
import glob, json, os
P = json.loads(%r)
files = glob.glob(os.path.join(os.path.expanduser(P["folder"]), P["pattern"]))
print(json.dumps(sorted([[os.path.basename(f), os.path.getmtime(f)] for f in files], key=lambda x: -x[1])[:5]))
folder = os.path.expanduser(P["folder"])
files = glob.glob(os.path.join(folder, P["pattern"]))
parts = folder.split("/")
share = "/".join(parts[:3]) if folder.startswith("/Volumes/") and len(parts) > 2 else None # /Volumes/Location Assets
print(json.dumps({"files": sorted([[os.path.basename(f), os.path.getmtime(f)] for f in files], key=lambda x: -x[1])[:5],
"share": share, "mounted": os.path.ismount(share) if share else None}))
'''
@@ -1666,8 +1670,28 @@ def prop_bundle_folder(rc, plan):
return str(rc.get("prop_bundle_folder", "")).replace("{date}", datetime.fromtimestamp(plan["time"]).strftime("%y%m%d"))
MOUNT_SCRIPT = r"""
import json, os, subprocess, time
P = json.loads(%r)
uid = os.getuid()
r = subprocess.run(["/bin/launchctl", "kickstart", "-k", "gui/%%d/%%s" %% (uid, P["label"])], capture_output=True, text=True)
for _ in range(60):
if os.path.ismount(P["share"]):
break
time.sleep(0.5)
print(json.dumps({"mounted": os.path.ismount(P["share"]), "no_agent": r.returncode != 0 and not os.path.ismount(P["share"])}))
"""
def eval_prop_bundle(rc, files, since, folder=None):
line = Line()
if isinstance(files, dict):
if files.get("share") and files.get("mounted") is False:
# 2026-10-22: Location Assets dropped off NA ProP; the bundle was there all along
line.fault(ERR, "SHARE NOT MOUNTED", "%s is not mounted on %s: hold PROP OUT to mount it again" % (
files["share"], rc.get("prop_bundle_host")))
return line
files = files.get("files") or []
if "{date}" in str(rc.get("prop_bundle_folder", "")):
# This weekend's own folder: any bundle in it is this weekend's.
if not files:
@@ -1943,6 +1967,15 @@ def run_action(cfg, action, chk=None, sleep=time.sleep):
return "NO SET TO COPY"
log.info("FIX tracks copy started to %s", ", ".join(r["started"]) or "nowhere (all there)")
return True
if action == "mount_share":
# The computer's keep-mounted agent (remote-access/mac-keep-mounted.sh) mounts it again, now.
label = "org.waterschurch.keep-mounted." + rc.get("prop_bundle_share_agent", "location-assets")
share = "/".join(str(rc.get("prop_bundle_folder", "")).split("/")[:3])
r = run_remote(cfg, rc["prop_bundle_host"], MOUNT_SCRIPT % json.dumps({"label": label, "share": share}), timeout=60)
if r.get("mounted"):
log.info("FIX %s mounted on %s", share, rc["prop_bundle_host"])
return True
return "NO AGENT" if r.get("no_agent") else "STILL NOT MOUNTED"
if action == "light_timing":
return fix_light_timing(cfg, rc)
if action == "ableton_mix":