You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(dev): #99 review — the identity changes as one, and the launch waits for macOS to agree
Two findings, both on scripts/editor-identity.mjs, both right.
1. The two files could still end up half changed. Everything that could REFUSE
was asked before writing — but the writes themselves can fail, and
product.overrides.json was written before Info.plist. A bundle that could not
be written left the editor asking to be called back on a scheme the bundle
did not own: the half-state the function said it prevented. Reproduced on the
reviewed script with a read-only bundle.
The files are now replaced as one change (replaceTogether). Each new text is
staged in a temporary file beside its target, so a directory that cannot be
written or a full disk is met while both targets are untouched; then each is
renamed into place, which either happens or does not. The one way left to be
half done — a rename failing after an earlier one went through — is undone:
old contents back, a newly created file removed. If the undo fails too, the
error names the file left changed. A symlinked overrides file is replaced
where it really is, and a file keeps its mode.
A process killed between the two renames can still leave one file ahead. The
next run finishes it, and run-dev.sh does not launch without a finished run.
2. A registration that failed was logged and passed over, so run-dev.sh went on
to launch an editor macOS might not route levelcode-dev:// to. It is fatal
now: the script throws, exits 1, and `set -e` stops the launcher.
Checking lsregister's exit status turned out not to be enough. Run on a
bundle under a temporary folder, the reviewed script printed "registered" and
exited 0 — lsregister had exited 0 too — while macOS had no app for the
scheme at all: it registers such a bundle and never chooses it. So after
registering, the script asks macOS what it will do with the link
(NSWorkspace, through osascript: built in, ~120 ms) and fails unless the
answer is this bundle. No app, or another copy holding the scheme, are both
fatal, the second naming the copy and how to unregister it. If macOS cannot
be asked at all, a registration that succeeded stands and the log says it is
unconfirmed.
The two files stay as they are when registration fails: they agree with each
other, the next run registers again, and undoing them would hand the next
launch the installed app's scheme.
Found while doing it: the comparison of macOS's answer with the bundle's path
has to use the native realpath. macOS answers with the path as it is on disk;
the checkout's is as someone typed it into `cd`, and on a Mac's default volume
~/Code and ~/code are one place. The JS realpath keeps the case it is given and
would have called the bundle's own path "another copy".
Also: the dev bundle identifier is checked for shape before it is written into
XML; a product.json that is not JSON is a problem the release check reports
rather than a crash; and the suite now replaces the script's macOS object with
one that throws, so a test that forgets its stand-in fails instead of leaving a
temp-folder bundle in LaunchServices.
test/editorIdentity.test.js goes from 25 to 37 cases. The filesystem is handed
in with one step failing only where the failure cannot be provoked for real (a
second rename); the rest use real files. Seventeen mutations of the new code
each fail a case. Checked against macOS itself, on a clone of the dev bundle
under the home folder: success says "macOS opens levelcode-dev:// with this
bundle" and exits 0; the same clone under a temp folder exits 1. 49 suites pass
on macOS and in a Linux container.
@@ -360,6 +523,9 @@ async function signInUrl(uriScheme) {
360
523
awaittest('release check: an overrides file inside the app, a missing product.json, a missing Info.plist — each fails',()=>{
361
524
assert.deepStrictEqual(identity.releaseIdentityProblems(builtApp({overrides: true})),['product.overrides.json was packaged — it is for runs from source only']);
0 commit comments