Skip to content

Commit 9122dbf

Browse files
devermanclaude
andauthored
Fail install-plugin.sh when an expected location is skipped (#200) (#210)
add_target dropped any directory that was not on disk at that instant and recorded nothing, so an iCloud plug-in folder that had not been materialised was skipped with no warning while the script still exited 0. The install looked completely successful and OmniFocus kept loading the stale copy from the folder that was missed -- observed on this machine, where the same script left iCloud stale in one run and updated both locations in the next with no code change between them. A location absent because the user does not use it is still skipped quietly. A location that is expected is now reported and fails the run: iCloud counts as expected whenever the OmniFocus iCloud container exists, which means plug-in sync is on, and an explicitly configured custom directory always counts. Partial installs exit 1 with guidance to open OmniFocus once so the folder materialises, and point at bridge-health-check, which reports every installed copy and warns when they disagree. Verified both paths: with the iCloud plug-in folder moved aside the script reports the skip and exits 1; with it present it exits 0 as before. Validation impact: package. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
1 parent 91c884b commit 9122dbf

1 file changed

Lines changed: 41 additions & 7 deletions

File tree

scripts/install-plugin.sh

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,10 @@ timeout_seconds = 5
3131
sandbox_dir = os.path.expanduser(
3232
"~/Library/Containers/com.omnigroup.OmniFocus4/Data/Library/Application Support/Plug-Ins"
3333
)
34-
icloud_dir = os.path.expanduser(
35-
"~/Library/Mobile Documents/iCloud~com~omnigroup~OmniFocus/Documents/Plug-Ins"
34+
icloud_container_dir = os.path.expanduser(
35+
"~/Library/Mobile Documents/iCloud~com~omnigroup~OmniFocus"
3636
)
37+
icloud_dir = os.path.join(icloud_container_dir, "Documents", "Plug-Ins")
3738
legacy_dir = os.path.expanduser("~/Library/Application Support/OmniFocus/Plug-Ins")
3839
3940
@@ -71,12 +72,24 @@ def read_custom_plugin_dirs():
7172
return dirs
7273
7374
74-
def add_target(targets, seen, path, reason, create_if_missing=False):
75+
def add_target(targets, seen, skipped, path, reason, create_if_missing=False, expected_when=None):
76+
"""Record a plugin directory as a target, or as a reportable skip.
77+
78+
A location that is absent because the user does not use it is fine to skip
79+
quietly. A location that is *expected* but not currently on disk -- an
80+
iCloud plug-in folder that has not been materialised, for example -- is a
81+
partial install waiting to happen: OmniFocus may still load the stale copy
82+
from there later. Those skips are reported and make the run fail.
83+
"""
7584
if not path or path in seen:
7685
return
7786
if create_if_missing or os.path.isdir(path):
7887
targets.append((path, reason))
7988
seen.add(path)
89+
return
90+
if expected_when and os.path.isdir(expected_when):
91+
skipped.append((path, reason))
92+
seen.add(path)
8093
8194
8295
def install_plugin(plugin_dir):
@@ -104,13 +117,18 @@ def sha256_file(path):
104117
105118
targets = []
106119
seen = set()
120+
skipped = []
107121
108122
for custom_dir in read_custom_plugin_dirs():
109-
add_target(targets, seen, custom_dir, "custom", create_if_missing=False)
123+
# A directory the user named explicitly is always expected.
124+
add_target(targets, seen, skipped, custom_dir, "custom", expected_when=custom_dir)
110125
111-
add_target(targets, seen, icloud_dir, "icloud", create_if_missing=False)
112-
add_target(targets, seen, sandbox_dir, "sandbox", create_if_missing=True)
113-
add_target(targets, seen, legacy_dir, "legacy", create_if_missing=False)
126+
# The iCloud plug-in folder is expected whenever the OmniFocus iCloud container
127+
# exists, which means the user has plug-in sync. OmniFocus prefers that copy, so
128+
# skipping it silently is how an install looks successful yet changes nothing.
129+
add_target(targets, seen, skipped, icloud_dir, "icloud", expected_when=icloud_container_dir)
130+
add_target(targets, seen, skipped, sandbox_dir, "sandbox", create_if_missing=True)
131+
add_target(targets, seen, skipped, legacy_dir, "legacy")
114132
115133
if not targets:
116134
print("❌ Failed to detect any OmniFocus plugin directory.", file=sys.stderr)
@@ -119,6 +137,11 @@ if not targets:
119137
print("Detected plugin directories:")
120138
for path, reason in targets:
121139
print(f" - {path} ({reason})")
140+
if skipped:
141+
print("")
142+
print("⚠️ Expected plugin directories that are not currently available:")
143+
for path, reason in skipped:
144+
print(f" - {path} ({reason})")
122145
123146
installed = []
124147
errors = []
@@ -154,6 +177,17 @@ if len(installed) > 1:
154177
print("")
155178
print("ℹ️ Multiple OmniFocus plugin directories were updated to keep duplicate bundles in sync.")
156179
180+
if skipped or errors:
181+
print("")
182+
print("❌ Partial install: at least one expected plugin location was not updated.", file=sys.stderr)
183+
print(" OmniFocus may keep loading an older plugin from a location that was", file=sys.stderr)
184+
print(" skipped. Check `focusrelay bridge-health-check` — it reports every", file=sys.stderr)
185+
print(" installed copy and warns when they disagree.", file=sys.stderr)
186+
if skipped:
187+
print(" For an iCloud location, open OmniFocus once so the plug-in folder", file=sys.stderr)
188+
print(" is materialised locally, then re-run this script.", file=sys.stderr)
189+
sys.exit(1)
190+
157191
print("")
158192
print("🔄 IMPORTANT: You MUST restart OmniFocus completely for changes to take effect.")
159193
print("")

0 commit comments

Comments
 (0)