@join-pantheon/cli 0.32.1 → 0.33.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/accounts.js +1 -1
- package/dist/board.js +1417 -0
- package/dist/claude-config.js +189 -0
- package/dist/cli.js +351 -101
- package/dist/client.js +16 -0
- package/dist/command-state.js +2 -1
- package/dist/dbus.js +92 -13
- package/dist/doctor.js +36 -5
- package/dist/folder-guard.js +89 -0
- package/dist/git-safe.js +3 -3
- package/dist/host-env.js +47 -1
- package/dist/install.js +76 -10
- package/dist/installer.js +2 -1
- package/dist/ledger.js +2 -2
- package/dist/machine.js +174 -3
- package/dist/managed.js +27 -1
- package/dist/notice-linux.js +501 -0
- package/dist/notice-windows.js +323 -0
- package/dist/notifier.js +12 -3
- package/dist/quickstart.js +28 -11
- package/dist/relay.js +64 -9
- package/dist/service.js +455 -29
- package/dist/setup-guide.js +22 -5
- package/dist/store.js +18 -2
- package/dist/uninstall.js +1 -1
- package/dist/upgrade.js +249 -4
- package/dist/uri-handler.js +335 -0
- package/dist/win-host.js +993 -0
- package/dist/worker-policy.js +3 -0
- package/dist/worker.js +11 -11
- package/helper/macos/prebuilt/manifest.json +2 -2
- package/helper/macos/prebuilt/pantheon-hud +0 -0
- package/helper/windows/pantheon-host.cs +170 -0
- package/helper/windows/pantheon-notice.ps1 +127 -0
- package/helper/windows/pantheon-tray.ps1 +731 -0
- package/helper/windows/pantheon.ico +0 -0
- package/installer/install.ps1 +238 -19
- package/installer/install.sh +36 -1
- package/package.json +2 -2
package/dist/store.js
CHANGED
|
@@ -8,13 +8,27 @@ export function ensurePrivateDir(dir) {
|
|
|
8
8
|
}
|
|
9
9
|
catch { }
|
|
10
10
|
}
|
|
11
|
+
let waitForDisk = true;
|
|
12
|
+
let slowestWaitMs = 0;
|
|
13
|
+
export function setWaitForDisk(on) { waitForDisk = on; }
|
|
14
|
+
export function waitsForDisk() { return waitForDisk; }
|
|
15
|
+
export function takeSlowestDiskWait() { const w = slowestWaitMs; slowestWaitMs = 0; return w; }
|
|
16
|
+
export function syncFd(fd) {
|
|
17
|
+
if (!waitForDisk)
|
|
18
|
+
return;
|
|
19
|
+
const t = Date.now();
|
|
20
|
+
fsyncSync(fd);
|
|
21
|
+
const took = Date.now() - t;
|
|
22
|
+
if (took > slowestWaitMs)
|
|
23
|
+
slowestWaitMs = took;
|
|
24
|
+
}
|
|
11
25
|
export function writeFileAtomic(file, data, mode = 0o600) {
|
|
12
26
|
mkdirSync(dirname(file), { recursive: true, mode: 0o700 });
|
|
13
27
|
const tmp = `${file}.tmp`;
|
|
14
28
|
const fd = openSync(tmp, "w", mode);
|
|
15
29
|
try {
|
|
16
30
|
writeSync(fd, typeof data === "string" ? Buffer.from(data) : data);
|
|
17
|
-
|
|
31
|
+
syncFd(fd);
|
|
18
32
|
}
|
|
19
33
|
finally {
|
|
20
34
|
closeSync(fd);
|
|
@@ -42,10 +56,12 @@ export function renameRetrying(from, to, o = {}) {
|
|
|
42
56
|
}
|
|
43
57
|
}
|
|
44
58
|
export function fsyncDir(dir) {
|
|
59
|
+
if (!waitForDisk)
|
|
60
|
+
return;
|
|
45
61
|
let fd = null;
|
|
46
62
|
try {
|
|
47
63
|
fd = openSync(dir, "r");
|
|
48
|
-
|
|
64
|
+
syncFd(fd);
|
|
49
65
|
}
|
|
50
66
|
catch { }
|
|
51
67
|
finally {
|
package/dist/uninstall.js
CHANGED
|
@@ -5,7 +5,7 @@ import { posix, win32 } from "node:path";
|
|
|
5
5
|
import { expectedLauncher } from "./managed.js";
|
|
6
6
|
export const BEGIN_MARK = "# >>> pantheon >>>";
|
|
7
7
|
export const END_MARK = "# <<< pantheon <<<";
|
|
8
|
-
export const PROFILES = [".profile", ".bash_profile", ".bashrc", ".zshrc", ".zprofile"];
|
|
8
|
+
export const PROFILES = [".profile", ".bash_profile", ".bash_login", ".bashrc", ".zshrc", ".zprofile"];
|
|
9
9
|
export const FISH_CONF = ".config/fish/conf.d/pantheon.fish";
|
|
10
10
|
export function withoutPathBlock(text) {
|
|
11
11
|
const lines = text.match(/[^\n]*\n|[^\n]+$/g) ?? [];
|
package/dist/upgrade.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { execFileSync } from "node:child_process";
|
|
2
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { dirname, join, posix, win32 } from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import { installForUser } from "./install.js";
|
|
@@ -7,7 +7,8 @@ import { npmSpawn } from "./which.js";
|
|
|
7
7
|
import { proxyEnvFor } from "./network.js";
|
|
8
8
|
import { relayProc, workerProc, notifierProc, menubarProc } from "./machine.js";
|
|
9
9
|
import { load } from "./config.js";
|
|
10
|
-
import {
|
|
10
|
+
import { compareVersions, INSTALLER_MIN_CLI, isVersion } from "./installer.js";
|
|
11
|
+
import { childNodeFlags, installerLineHere, launcherWithRepair, managedLayout, nodeSatisfies, nodeTooOldSentence, runtimeNodeVersion } from "./managed.js";
|
|
11
12
|
export function repoRoot() {
|
|
12
13
|
return join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
13
14
|
}
|
|
@@ -86,6 +87,7 @@ export function defaultDeps() {
|
|
|
86
87
|
return up;
|
|
87
88
|
},
|
|
88
89
|
npmUpgrade: (version) => npm(npmInstallArgs(version), { stdio: ["ignore", "pipe", "pipe"] }),
|
|
90
|
+
stagedUpgrade: (m, spec) => { stagedManagedUpgrade(m, spec); },
|
|
89
91
|
npmLatest: () => {
|
|
90
92
|
try {
|
|
91
93
|
return npm(["view", `${PKG_NAME}`, "version"], { stdio: ["ignore", "pipe", "ignore"], timeout: 4000 }).trim() || null;
|
|
@@ -113,13 +115,16 @@ export function defaultDeps() {
|
|
|
113
115
|
};
|
|
114
116
|
}
|
|
115
117
|
export function upgrade(deps = defaultDeps(), opts = {}) {
|
|
116
|
-
const spec = opts.version &&
|
|
118
|
+
const spec = opts.version && isVersion(opts.version) ? opts.version : "latest";
|
|
117
119
|
const { root } = deps;
|
|
118
120
|
const from = deps.version(root);
|
|
119
121
|
const steps = [];
|
|
120
122
|
const stop = (name, detail) => ({ root, from, to: from, steps: [...steps, { name, ok: false, detail }], ok: false, alreadyCurrent: false, restart: [] });
|
|
121
123
|
if (!deps.isGit(root)) {
|
|
122
124
|
const managed = deps.managed === undefined ? managedLayout() : deps.managed;
|
|
125
|
+
if (managed && spec !== "latest" && compareVersions(spec, INSTALLER_MIN_CLI) < 0) {
|
|
126
|
+
return stop("check", `${spec} is older than this install supports (${INSTALLER_MIN_CLI} or newer): it could not upgrade itself again. Nothing was changed.`);
|
|
127
|
+
}
|
|
123
128
|
if (managed && deps.engines) {
|
|
124
129
|
const range = deps.engines(spec);
|
|
125
130
|
const node = deps.runtimeNode ? deps.runtimeNode() : runtimeNodeVersion(managed);
|
|
@@ -129,10 +134,16 @@ export function upgrade(deps = defaultDeps(), opts = {}) {
|
|
|
129
134
|
}
|
|
130
135
|
}
|
|
131
136
|
try {
|
|
132
|
-
|
|
137
|
+
if (managed && deps.stagedUpgrade)
|
|
138
|
+
deps.stagedUpgrade(managed, spec);
|
|
139
|
+
else
|
|
140
|
+
deps.npmUpgrade(spec === "latest" ? undefined : spec);
|
|
133
141
|
steps.push({ name: "npm", ok: true, detail: `installed ${PKG_NAME}@${spec}` });
|
|
134
142
|
}
|
|
135
143
|
catch (e) {
|
|
144
|
+
if (e instanceof UpgradeBusy) {
|
|
145
|
+
return { root, from, to: from, steps: [...steps, { name: "npm", ok: true, detail: e.message }], ok: true, alreadyCurrent: true, restart: [] };
|
|
146
|
+
}
|
|
136
147
|
if (spec !== "latest" && /ETARGET|No matching version|notarget/i.test(String(e.stderr ?? "") + e.message)) {
|
|
137
148
|
return { root, from, to: from, steps: [...steps, { name: "npm", ok: true, detail: `${PKG_NAME}@${spec} is not on npm yet` }], ok: true, alreadyCurrent: true, restart: [] };
|
|
138
149
|
}
|
|
@@ -154,6 +165,9 @@ export function upgrade(deps = defaultDeps(), opts = {}) {
|
|
|
154
165
|
const restart = [...deps.running(), "your agent session"];
|
|
155
166
|
return { root, from, to, steps, ok: true, alreadyCurrent: false, restart };
|
|
156
167
|
}
|
|
168
|
+
if (opts.exact) {
|
|
169
|
+
return stop("check", `this is a git checkout, which upgrades by pulling commits, not to a version. Check out the release you want (git checkout v${spec}), or run \`pantheon upgrade\` for the latest commit.`);
|
|
170
|
+
}
|
|
157
171
|
const dirty = deps.dirty(root);
|
|
158
172
|
if (dirty.length) {
|
|
159
173
|
return stop("check", `the checkout has uncommitted changes (${dirty.slice(0, 4).join(", ")}${dirty.length > 4 ? ", …" : ""}). Commit or \`git stash\` them first — upgrade will not overwrite your work.`);
|
|
@@ -194,4 +208,235 @@ export function upgrade(deps = defaultDeps(), opts = {}) {
|
|
|
194
208
|
const restart = [...deps.running(), "your agent session"];
|
|
195
209
|
return { root, from, to, steps, ok: true, alreadyCurrent: false, restart };
|
|
196
210
|
}
|
|
211
|
+
const pidAlive = (pid) => {
|
|
212
|
+
if (!(pid > 0))
|
|
213
|
+
return false;
|
|
214
|
+
try {
|
|
215
|
+
process.kill(pid, 0);
|
|
216
|
+
return true;
|
|
217
|
+
}
|
|
218
|
+
catch (e) {
|
|
219
|
+
return e.code === "EPERM";
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
const realSwapIo = (m) => ({
|
|
223
|
+
npm: (args) => {
|
|
224
|
+
const sp = npmSpawn(args, undefined, undefined, proxyEnvFor(), m);
|
|
225
|
+
execFileSync(sp.command, sp.args, { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], timeout: 600_000, ...sp.options });
|
|
226
|
+
},
|
|
227
|
+
run: (cmd, args) => {
|
|
228
|
+
try {
|
|
229
|
+
return { status: 0, out: execFileSync(cmd, args, { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], timeout: 60_000 }) };
|
|
230
|
+
}
|
|
231
|
+
catch (e) {
|
|
232
|
+
const x = e;
|
|
233
|
+
return { status: x.status ?? null, out: `${x.stdout ?? ""}${x.stderr ?? ""}` || x.message };
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
exists: (p) => existsSync(p),
|
|
237
|
+
rename: (a, b) => renameSync(a, b),
|
|
238
|
+
remove: (p) => rmSync(p, { recursive: true, force: true }),
|
|
239
|
+
read: (p) => readFileSync(p, "utf8"),
|
|
240
|
+
write: (p, text) => { const tmp = `${p}.new-${process.pid}`; writeFileSync(tmp, text, { mode: 0o755 }); renameSync(tmp, p); },
|
|
241
|
+
list: (dir) => { try {
|
|
242
|
+
return readdirSync(dir);
|
|
243
|
+
}
|
|
244
|
+
catch {
|
|
245
|
+
return [];
|
|
246
|
+
} },
|
|
247
|
+
unlock: (dir) => {
|
|
248
|
+
try {
|
|
249
|
+
if (Number(readFileSync(join(dir, "pid"), "utf8").trim()) === process.pid)
|
|
250
|
+
rmSync(dir, { recursive: true, force: true });
|
|
251
|
+
}
|
|
252
|
+
catch { }
|
|
253
|
+
},
|
|
254
|
+
alive: (pid) => pidAlive(pid),
|
|
255
|
+
holdSignals: () => {
|
|
256
|
+
const hold = () => { };
|
|
257
|
+
const sigs = ["SIGINT", "SIGTERM", "SIGHUP", "SIGBREAK"].filter((x) => x !== "SIGBREAK" || process.platform === "win32");
|
|
258
|
+
for (const x of sigs)
|
|
259
|
+
process.on(x, hold);
|
|
260
|
+
return () => { for (const x of sigs)
|
|
261
|
+
process.off(x, hold); };
|
|
262
|
+
},
|
|
263
|
+
sleep: (ms) => { Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms); },
|
|
264
|
+
lock: (dir) => {
|
|
265
|
+
for (let i = 0; i < 3; i++) {
|
|
266
|
+
try {
|
|
267
|
+
mkdirSync(dir);
|
|
268
|
+
writeFileSync(join(dir, "pid"), String(process.pid));
|
|
269
|
+
return true;
|
|
270
|
+
}
|
|
271
|
+
catch (e) {
|
|
272
|
+
if (e.code !== "EEXIST")
|
|
273
|
+
throw e;
|
|
274
|
+
let pid = 0, age = 0;
|
|
275
|
+
try {
|
|
276
|
+
pid = Number(readFileSync(join(dir, "pid"), "utf8").trim());
|
|
277
|
+
}
|
|
278
|
+
catch { }
|
|
279
|
+
try {
|
|
280
|
+
age = Date.now() - statSync(dir).mtimeMs;
|
|
281
|
+
}
|
|
282
|
+
catch {
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
if (pidAlive(pid) ? age < 20 * 60_000 : !pid && age < 10_000)
|
|
286
|
+
return false;
|
|
287
|
+
const gone = `${dir}.stale-${process.pid}`;
|
|
288
|
+
try {
|
|
289
|
+
renameSync(dir, gone);
|
|
290
|
+
}
|
|
291
|
+
catch {
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
rmSync(gone, { recursive: true, force: true });
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return false;
|
|
298
|
+
},
|
|
299
|
+
});
|
|
300
|
+
export const realSwapIoForTest = realSwapIo;
|
|
301
|
+
export class UpgradeBusy extends Error {
|
|
302
|
+
constructor() { super("another pantheon upgrade is running on this machine; nothing was changed, and the next check tries again"); }
|
|
303
|
+
}
|
|
304
|
+
export function stagedManagedUpgrade(m, spec, io = realSwapIo(m)) {
|
|
305
|
+
const win = /\.exe$/i.test(m.node);
|
|
306
|
+
const P = win ? win32 : posix;
|
|
307
|
+
const runtime = P.dirname(m.nodeDir);
|
|
308
|
+
const staging = P.join(runtime, `.upgrade-${process.pid}`);
|
|
309
|
+
const stagedPkg = win ? P.join(staging, "node_modules", "@join-pantheon", "cli") : P.join(staging, "lib", "node_modules", "@join-pantheon", "cli");
|
|
310
|
+
const prev = m.prevDir;
|
|
311
|
+
const failed = P.join(runtime, "cli.failed");
|
|
312
|
+
const startsAs = (entry) => {
|
|
313
|
+
const r = io.run(m.node, ["--use-system-ca", entry, "--version"]);
|
|
314
|
+
const line = r.out.replace(/\u001b\[[0-9;]*m/g, "").trim().split(/\r?\n/).pop()?.trim() ?? "";
|
|
315
|
+
return r.status === 0 && /^\d+\.\d+\.\d+/.test(line) ? line.replace(/^pantheon\s+/, "") : null;
|
|
316
|
+
};
|
|
317
|
+
const rename = (a, b, waitMs = 1000) => {
|
|
318
|
+
for (let i = 0; i < 6; i++) {
|
|
319
|
+
try {
|
|
320
|
+
io.rename(a, b);
|
|
321
|
+
return true;
|
|
322
|
+
}
|
|
323
|
+
catch {
|
|
324
|
+
if (i < 5)
|
|
325
|
+
io.sleep(waitMs);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
return false;
|
|
329
|
+
};
|
|
330
|
+
const ready = `${staging}-ready`;
|
|
331
|
+
const whole = (d) => ["package.json", P.join("bin", "pantheon.js"), P.join("dist", "cli.js")].every((f) => io.exists(P.join(d, f)));
|
|
332
|
+
const inPlace = () => whole(m.pkgDir);
|
|
333
|
+
const tidy = (p) => { try {
|
|
334
|
+
io.remove(p);
|
|
335
|
+
}
|
|
336
|
+
catch { } };
|
|
337
|
+
const held = (fn) => { const release = io.holdSignals(); try {
|
|
338
|
+
return fn();
|
|
339
|
+
}
|
|
340
|
+
finally {
|
|
341
|
+
release();
|
|
342
|
+
} };
|
|
343
|
+
const repairHint = () => io.exists(P.join(prev, "bin", "pantheon.js")) ? `The pantheon command puts ${prev} back the next time it runs; or run the installer again` : "Run the installer again to repair it";
|
|
344
|
+
const unnest = (inside) => {
|
|
345
|
+
const nested = P.join(inside, "cli.prev");
|
|
346
|
+
if (!io.exists(nested))
|
|
347
|
+
return;
|
|
348
|
+
if (io.exists(prev))
|
|
349
|
+
tidy(nested);
|
|
350
|
+
else
|
|
351
|
+
rename(nested, prev, 200);
|
|
352
|
+
};
|
|
353
|
+
const lock = P.join(runtime, ".upgrade.lock");
|
|
354
|
+
if (!io.lock(lock))
|
|
355
|
+
throw new UpgradeBusy();
|
|
356
|
+
try {
|
|
357
|
+
if (!io.exists(m.pkgDir)) {
|
|
358
|
+
const from = [prev, ...io.list(runtime).filter((n) => /^\.upgrade-\d+-ready$/.test(n)).map((n) => P.join(runtime, n)), P.join(failed, "cli.prev")]
|
|
359
|
+
.find(whole);
|
|
360
|
+
if (from)
|
|
361
|
+
rename(from, m.pkgDir);
|
|
362
|
+
}
|
|
363
|
+
if (!inPlace()) {
|
|
364
|
+
throw new Error(`the pantheon in place (${m.pkgDir}) is missing and could not be put back yet (a file is in use); nothing was changed. ${repairHint()}`);
|
|
365
|
+
}
|
|
366
|
+
unnest(m.pkgDir);
|
|
367
|
+
unnest(failed);
|
|
368
|
+
if (whole(prev) && !startsAs(m.entry) && startsAs(P.join(prev, "bin", "pantheon.js"))) {
|
|
369
|
+
held(() => { if (rename(m.pkgDir, failed, 500))
|
|
370
|
+
rename(prev, m.pkgDir, 500); });
|
|
371
|
+
if (!inPlace())
|
|
372
|
+
throw new Error(`the pantheon in place did not start, and the previous version could not be put back yet (a file is in use); nothing else was changed. ${repairHint()}`);
|
|
373
|
+
}
|
|
374
|
+
for (const n of io.list(runtime)) {
|
|
375
|
+
const pid = /^\.upgrade-(\d+)(?:-ready)?$/.exec(n)?.[1];
|
|
376
|
+
if ((pid && (Number(pid) === process.pid || !io.alive(Number(pid)))) || (n === "cli.failed" && !io.exists(P.join(failed, "cli.prev"))))
|
|
377
|
+
tidy(P.join(runtime, n));
|
|
378
|
+
}
|
|
379
|
+
if (!win) {
|
|
380
|
+
try {
|
|
381
|
+
const healed = launcherWithRepair(io.read(m.launcher), m, "linux");
|
|
382
|
+
if (healed !== null)
|
|
383
|
+
io.write(m.launcher, healed);
|
|
384
|
+
}
|
|
385
|
+
catch { }
|
|
386
|
+
}
|
|
387
|
+
io.npm(["install", "-g", "--prefix", staging, "--cache", P.join(runtime, "npm-cache"), "--fetch-timeout=60000", "--fetch-retries=2",
|
|
388
|
+
`${PKG_NAME}@${spec}`, "--no-audit", "--no-fund", "--loglevel=error"]);
|
|
389
|
+
let version = "";
|
|
390
|
+
try {
|
|
391
|
+
version = JSON.parse(io.read(P.join(stagedPkg, "package.json"))).version ?? "";
|
|
392
|
+
}
|
|
393
|
+
catch { }
|
|
394
|
+
if (!version || (spec !== "latest" && version !== spec))
|
|
395
|
+
throw new Error(`npm installed ${version || "nothing readable"} into the staging folder, not ${spec}; nothing was changed`);
|
|
396
|
+
const staged = startsAs(P.join(stagedPkg, "bin", "pantheon.js"));
|
|
397
|
+
if (staged !== version)
|
|
398
|
+
throw new Error(`the new pantheon ${version} did not start (it answered ${staged ?? "nothing"}); the working version was kept`);
|
|
399
|
+
if (!rename(stagedPkg, ready))
|
|
400
|
+
throw new Error("the new pantheon's files are still held by another program (a virus scan); nothing was changed, and the next check tries again");
|
|
401
|
+
if (!inPlace())
|
|
402
|
+
throw new Error(`the pantheon in place (${m.pkgDir}) went missing during the upgrade; nothing was swapped. ${repairHint()}`);
|
|
403
|
+
tidy(prev);
|
|
404
|
+
if (io.exists(prev)) {
|
|
405
|
+
tidy(ready);
|
|
406
|
+
throw new Error(`the kept previous version (${prev}) could not be removed to make room (a file is in use); nothing was changed, and the next check tries again`);
|
|
407
|
+
}
|
|
408
|
+
held(() => {
|
|
409
|
+
if (io.exists(m.pkgDir) && !rename(m.pkgDir, prev, 500)) {
|
|
410
|
+
throw new Error(`could not move the working pantheon aside (a file in ${m.pkgDir} is in use); it was kept, and the next check tries again`);
|
|
411
|
+
}
|
|
412
|
+
if (!rename(ready, m.pkgDir, 500)) {
|
|
413
|
+
if (!io.exists(m.pkgDir) && io.exists(prev))
|
|
414
|
+
rename(prev, m.pkgDir, 500);
|
|
415
|
+
throw new Error(inPlace()
|
|
416
|
+
? `could not put the new pantheon in place (a file is in use); the working version was put back`
|
|
417
|
+
: `could not put the new pantheon in place, nor the working one back: ${m.pkgDir} is missing. The pantheon command puts ${prev} back the next time it runs; or run the installer again`);
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
unnest(m.pkgDir);
|
|
421
|
+
const placed = startsAs(m.entry);
|
|
422
|
+
if (placed !== version) {
|
|
423
|
+
const back = whole(prev) && held(() => rename(m.pkgDir, failed, 500) && (rename(prev, m.pkgDir, 500) || inPlace()));
|
|
424
|
+
if (back)
|
|
425
|
+
tidy(failed);
|
|
426
|
+
throw new Error(back
|
|
427
|
+
? `pantheon ${version} did not start once in place (it answered ${placed ?? "nothing"}); the previous version was put back`
|
|
428
|
+
: `pantheon ${version} did not start once in place, and the previous version could not be put back yet. ${inPlace() ? `It is kept at ${prev}; the next upgrade puts it back, or run the installer again` : repairHint()}`);
|
|
429
|
+
}
|
|
430
|
+
return { version };
|
|
431
|
+
}
|
|
432
|
+
finally {
|
|
433
|
+
tidy(staging);
|
|
434
|
+
if (inPlace())
|
|
435
|
+
tidy(ready);
|
|
436
|
+
try {
|
|
437
|
+
io.unlock(lock);
|
|
438
|
+
}
|
|
439
|
+
catch { }
|
|
440
|
+
}
|
|
441
|
+
}
|
|
197
442
|
//# sourceMappingURL=upgrade.js.map
|