runpane 2.4.183 → 2.4.185
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/README.md +64 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +5 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands.d.ts +3 -0
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +28 -0
- package/dist/commands.js.map +1 -1
- package/dist/docs-index.json +1 -1
- package/dist/generated/contract.d.ts +25 -13
- package/dist/generated/contract.d.ts.map +1 -1
- package/dist/generated/contract.js +44 -23
- package/dist/generated/contract.js.map +1 -1
- package/dist/update.d.ts +9 -0
- package/dist/update.d.ts.map +1 -0
- package/dist/update.js +312 -0
- package/dist/update.js.map +1 -0
- package/dist/updateArtifacts.d.ts +12 -0
- package/dist/updateArtifacts.d.ts.map +1 -0
- package/dist/updateArtifacts.js +112 -0
- package/dist/updateArtifacts.js.map +1 -0
- package/dist/updateCapacity.d.ts +5 -0
- package/dist/updateCapacity.d.ts.map +1 -0
- package/dist/updateCapacity.js +72 -0
- package/dist/updateCapacity.js.map +1 -0
- package/dist/updateOperation.d.ts +48 -0
- package/dist/updateOperation.d.ts.map +1 -0
- package/dist/updateOperation.js +208 -0
- package/dist/updateOperation.js.map +1 -0
- package/dist/updatePackage.d.ts +14 -0
- package/dist/updatePackage.d.ts.map +1 -0
- package/dist/updatePackage.js +103 -0
- package/dist/updatePackage.js.map +1 -0
- package/dist/updatePreflight.d.ts +46 -0
- package/dist/updatePreflight.d.ts.map +1 -0
- package/dist/updatePreflight.js +134 -0
- package/dist/updatePreflight.js.map +1 -0
- package/dist/updatePython.d.ts +16 -0
- package/dist/updatePython.d.ts.map +1 -0
- package/dist/updatePython.js +46 -0
- package/dist/updatePython.js.map +1 -0
- package/dist/updateRuntime.d.ts +3 -0
- package/dist/updateRuntime.d.ts.map +1 -0
- package/dist/updateRuntime.js +61 -0
- package/dist/updateRuntime.js.map +1 -0
- package/dist/updateSupervisor.d.ts +13 -0
- package/dist/updateSupervisor.d.ts.map +1 -0
- package/dist/updateSupervisor.js +103 -0
- package/dist/updateSupervisor.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
declare const UPDATE_STEPS: readonly ["stage", "checkpoint", "stop", "snapshot", "install", "launch", "health", "restore"];
|
|
2
|
+
type UpdateStep = typeof UPDATE_STEPS[number];
|
|
3
|
+
declare const journalSchema: import("./boundaryDecoder").BoundarySchema<{
|
|
4
|
+
readonly id: string;
|
|
5
|
+
readonly host: string;
|
|
6
|
+
readonly scope: "pane" | "both" | "cli";
|
|
7
|
+
readonly version: string;
|
|
8
|
+
readonly phase: "install" | "failed" | "launch" | "stage" | "checkpoint" | "stop" | "snapshot" | "health" | "restore" | "accepted" | "complete" | "needs-attention";
|
|
9
|
+
readonly completed: ("install" | "launch" | "stage" | "checkpoint" | "stop" | "snapshot" | "health" | "restore")[];
|
|
10
|
+
readonly helperPid: number | undefined;
|
|
11
|
+
readonly setupPid: number | undefined;
|
|
12
|
+
readonly setupExpiresAt: number | undefined;
|
|
13
|
+
readonly updatedAt: string;
|
|
14
|
+
readonly appUpdated: boolean;
|
|
15
|
+
readonly cliUpdated: boolean;
|
|
16
|
+
readonly hostReachable: boolean;
|
|
17
|
+
readonly restored: {
|
|
18
|
+
readonly panelId: string;
|
|
19
|
+
readonly outcome: string;
|
|
20
|
+
readonly reason: string;
|
|
21
|
+
}[];
|
|
22
|
+
readonly error: string | undefined;
|
|
23
|
+
}>;
|
|
24
|
+
export type UpdateJournal = ReturnType<typeof journalSchema.decode>;
|
|
25
|
+
/** Commit one complete journal image; a crash leaves either the old or new image. */
|
|
26
|
+
export declare function writeUpdateJson<T extends object>(file: string, value: T): void;
|
|
27
|
+
export declare function readUpdateJournal(file: string): UpdateJournal;
|
|
28
|
+
export interface UpdateSteps {
|
|
29
|
+
/** Each step reconciles its recorded effect before repeating after a crash. */
|
|
30
|
+
run(step: UpdateStep, journal: UpdateJournal): Promise<Partial<UpdateJournal>>;
|
|
31
|
+
}
|
|
32
|
+
export declare function executeUpdate(file: string, steps: UpdateSteps): Promise<UpdateJournal>;
|
|
33
|
+
/** Publish a fully durable owner directory atomically; never expose an empty lock. */
|
|
34
|
+
export declare function claimUpdateLock(directory: string, id: string, statusFile: string): {
|
|
35
|
+
id: string;
|
|
36
|
+
statusFile: string;
|
|
37
|
+
acquired: boolean;
|
|
38
|
+
};
|
|
39
|
+
/** Elect one releaser. A terminal journal plus a dead recorded releaser repairs a crashed cleanup. */
|
|
40
|
+
export declare function releaseUpdateLock(directory: string, id: string): void;
|
|
41
|
+
/** Process disappearance is not proof of a clean shutdown. */
|
|
42
|
+
export declare function assertUpdateQuiescence(directory: string, expected: {
|
|
43
|
+
id: string;
|
|
44
|
+
bootId: string;
|
|
45
|
+
pid: number;
|
|
46
|
+
}): void;
|
|
47
|
+
export {};
|
|
48
|
+
//# sourceMappingURL=updateOperation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"updateOperation.d.ts","sourceRoot":"","sources":["../src/updateOperation.ts"],"names":[],"mappings":"AAMA,QAAA,MAAM,YAAY,gGAAiG,CAAC;AACpH,KAAK,UAAU,GAAG,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC;AAE9C,QAAA,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;EAgBjB,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC;AAEpE,qFAAqF;AACrF,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAW9E;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAE7D;AAED,MAAM,WAAW,WAAW;IAC1B,+EAA+E;IAC/E,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC;CAChF;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CA6B5F;AAED,sFAAsF;AACtF,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;;;;EAgChF;AAED,sGAAsG;AACtG,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CA+BrE;AAED,8DAA8D;AAC9D,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAKrH"}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.writeUpdateJson = writeUpdateJson;
|
|
7
|
+
exports.readUpdateJournal = readUpdateJournal;
|
|
8
|
+
exports.executeUpdate = executeUpdate;
|
|
9
|
+
exports.claimUpdateLock = claimUpdateLock;
|
|
10
|
+
exports.releaseUpdateLock = releaseUpdateLock;
|
|
11
|
+
exports.assertUpdateQuiescence = assertUpdateQuiescence;
|
|
12
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
13
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
14
|
+
const node_crypto_1 = require("node:crypto");
|
|
15
|
+
const boundaryDecoder_1 = require("./boundaryDecoder");
|
|
16
|
+
const errors_1 = require("./errors");
|
|
17
|
+
const UPDATE_STEPS = ['stage', 'checkpoint', 'stop', 'snapshot', 'install', 'launch', 'health', 'restore'];
|
|
18
|
+
const phaseSchema = boundaryDecoder_1.boundary.enumeration('accepted', ...UPDATE_STEPS, 'complete', 'needs-attention', 'failed');
|
|
19
|
+
const journalSchema = boundaryDecoder_1.boundary.object({
|
|
20
|
+
id: boundaryDecoder_1.boundary.nonEmptyString,
|
|
21
|
+
host: boundaryDecoder_1.boundary.nonEmptyString,
|
|
22
|
+
scope: boundaryDecoder_1.boundary.enumeration('both', 'pane', 'cli'),
|
|
23
|
+
version: boundaryDecoder_1.boundary.nonEmptyString,
|
|
24
|
+
phase: phaseSchema,
|
|
25
|
+
completed: boundaryDecoder_1.boundary.array(boundaryDecoder_1.boundary.enumeration(...UPDATE_STEPS)),
|
|
26
|
+
helperPid: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.number),
|
|
27
|
+
setupPid: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.number),
|
|
28
|
+
setupExpiresAt: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.number),
|
|
29
|
+
updatedAt: boundaryDecoder_1.boundary.nonEmptyString,
|
|
30
|
+
appUpdated: boundaryDecoder_1.boundary.boolean,
|
|
31
|
+
cliUpdated: boundaryDecoder_1.boundary.boolean,
|
|
32
|
+
hostReachable: boundaryDecoder_1.boundary.boolean,
|
|
33
|
+
restored: boundaryDecoder_1.boundary.array(boundaryDecoder_1.boundary.object({ panelId: boundaryDecoder_1.boundary.string, outcome: boundaryDecoder_1.boundary.string, reason: boundaryDecoder_1.boundary.string })),
|
|
34
|
+
error: boundaryDecoder_1.boundary.optional(boundaryDecoder_1.boundary.string),
|
|
35
|
+
});
|
|
36
|
+
/** Commit one complete journal image; a crash leaves either the old or new image. */
|
|
37
|
+
function writeUpdateJson(file, value) {
|
|
38
|
+
node_fs_1.default.mkdirSync(node_path_1.default.dirname(file), { recursive: true, mode: 0o700 });
|
|
39
|
+
const temporary = `${file}.${process.pid}.tmp`;
|
|
40
|
+
const fd = node_fs_1.default.openSync(temporary, 'w', 0o600);
|
|
41
|
+
try {
|
|
42
|
+
node_fs_1.default.writeFileSync(fd, JSON.stringify(value, null, 2));
|
|
43
|
+
node_fs_1.default.fsyncSync(fd);
|
|
44
|
+
}
|
|
45
|
+
finally {
|
|
46
|
+
node_fs_1.default.closeSync(fd);
|
|
47
|
+
}
|
|
48
|
+
node_fs_1.default.renameSync(temporary, file);
|
|
49
|
+
if (process.platform !== 'win32') {
|
|
50
|
+
const directory = node_fs_1.default.openSync(node_path_1.default.dirname(file), 'r');
|
|
51
|
+
try {
|
|
52
|
+
node_fs_1.default.fsyncSync(directory);
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
node_fs_1.default.closeSync(directory);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function readUpdateJournal(file) {
|
|
60
|
+
return (0, boundaryDecoder_1.decodeBoundary)(JSON.parse(node_fs_1.default.readFileSync(file, 'utf8')), journalSchema);
|
|
61
|
+
}
|
|
62
|
+
async function executeUpdate(file, steps) {
|
|
63
|
+
let journal = readUpdateJournal(file);
|
|
64
|
+
if (['complete', 'needs-attention', 'failed'].includes(journal.phase))
|
|
65
|
+
return journal;
|
|
66
|
+
const canceled = () => node_fs_1.default.existsSync(node_path_1.default.join(node_path_1.default.dirname(file), 'canceled.json'));
|
|
67
|
+
if (canceled()) {
|
|
68
|
+
journal = { ...journal, phase: 'failed', error: 'Operation setup was canceled before shutdown.' };
|
|
69
|
+
writeUpdateJson(file, journal);
|
|
70
|
+
return journal;
|
|
71
|
+
}
|
|
72
|
+
journal = { ...journal, helperPid: process.pid, updatedAt: new Date().toISOString() };
|
|
73
|
+
writeUpdateJson(file, journal); // This helper's durable acknowledgement, not the supervisor launch result.
|
|
74
|
+
try {
|
|
75
|
+
for (const step of UPDATE_STEPS) {
|
|
76
|
+
if (canceled())
|
|
77
|
+
throw new Error('Operation canceled before this stage.');
|
|
78
|
+
const persisted = readUpdateJournal(file);
|
|
79
|
+
if (['complete', 'needs-attention', 'failed'].includes(persisted.phase))
|
|
80
|
+
return persisted;
|
|
81
|
+
if (journal.completed.includes(step))
|
|
82
|
+
continue;
|
|
83
|
+
journal = { ...journal, phase: step, updatedAt: new Date().toISOString() };
|
|
84
|
+
writeUpdateJson(file, journal);
|
|
85
|
+
const outcome = await steps.run(step, journal);
|
|
86
|
+
const after = readUpdateJournal(file);
|
|
87
|
+
if (['complete', 'needs-attention', 'failed'].includes(after.phase))
|
|
88
|
+
return after;
|
|
89
|
+
journal = { ...journal, ...outcome, completed: [...journal.completed, step], updatedAt: new Date().toISOString() };
|
|
90
|
+
writeUpdateJson(file, journal);
|
|
91
|
+
}
|
|
92
|
+
const attention = journal.restored.some(item => item.outcome === 'needs-attention');
|
|
93
|
+
journal = { ...journal, phase: attention ? 'needs-attention' : 'complete' };
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
journal = { ...journal, ...readUpdateJournal(file), phase: journal.phase === 'stop' || journal.completed.includes('stop') ? 'needs-attention' : 'failed',
|
|
97
|
+
error: error instanceof Error ? error.message : String(error) };
|
|
98
|
+
}
|
|
99
|
+
writeUpdateJson(file, journal);
|
|
100
|
+
return journal;
|
|
101
|
+
}
|
|
102
|
+
/** Publish a fully durable owner directory atomically; never expose an empty lock. */
|
|
103
|
+
function claimUpdateLock(directory, id, statusFile) {
|
|
104
|
+
const candidate = node_fs_1.default.mkdtempSync(`${directory}.${id}.`);
|
|
105
|
+
try {
|
|
106
|
+
writeUpdateJson(node_path_1.default.join(candidate, 'owner.json'), { id, statusFile });
|
|
107
|
+
try {
|
|
108
|
+
node_fs_1.default.renameSync(candidate, directory);
|
|
109
|
+
return { id, statusFile, acquired: true };
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
if (!node_fs_1.default.existsSync(directory))
|
|
113
|
+
throw error;
|
|
114
|
+
}
|
|
115
|
+
const file = node_path_1.default.join(directory, 'owner.json');
|
|
116
|
+
if (!node_fs_1.default.existsSync(file))
|
|
117
|
+
throw new errors_1.RunpaneError('ERR_UPDATE_LOCK_INVALID', `An incomplete update lock requires inspection: ${directory}. Nothing was changed.`, 'Verify no update supervisor owns this target, then move this orphan lock aside and retry.');
|
|
118
|
+
const owner = (0, boundaryDecoder_1.decodeBoundary)(JSON.parse(node_fs_1.default.readFileSync(file, 'utf8')), boundaryDecoder_1.boundary.object({ id: boundaryDecoder_1.boundary.nonEmptyString, statusFile: boundaryDecoder_1.boundary.nonEmptyString }));
|
|
119
|
+
// A terminal journal is durable proof that this owner cannot run more work.
|
|
120
|
+
// Reconcile cleanup interrupted after the journal committed.
|
|
121
|
+
let journal = readUpdateJournal(owner.statusFile);
|
|
122
|
+
if (journal.phase === 'accepted' && !journal.helperPid && journal.setupPid && journal.setupExpiresAt && Date.now() > journal.setupExpiresAt) {
|
|
123
|
+
let setupExited = false;
|
|
124
|
+
try {
|
|
125
|
+
process.kill(journal.setupPid, 0);
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
setupExited = (0, boundaryDecoder_1.decodeBoundary)(error, boundaryDecoder_1.boundary.object({ code: boundaryDecoder_1.boundary.string })).code === 'ESRCH';
|
|
129
|
+
}
|
|
130
|
+
if (setupExited) {
|
|
131
|
+
// Cancellation is separate from the mutable journal, so a late queued
|
|
132
|
+
// helper cannot overwrite it with an acknowledgment and then stop Pane.
|
|
133
|
+
writeUpdateJson(node_path_1.default.join(node_path_1.default.dirname(owner.statusFile), 'canceled.json'), { id: owner.id });
|
|
134
|
+
journal = { ...journal, phase: 'failed', error: 'The caller exited before publishing an independent helper acknowledgment.' };
|
|
135
|
+
writeUpdateJson(owner.statusFile, journal);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (journal.id === owner.id && ['complete', 'failed'].includes(journal.phase)) {
|
|
139
|
+
releaseUpdateLock(directory, owner.id);
|
|
140
|
+
if (!node_fs_1.default.existsSync(directory))
|
|
141
|
+
return claimUpdateLock(directory, id, statusFile);
|
|
142
|
+
const current = (0, boundaryDecoder_1.decodeBoundary)(JSON.parse(node_fs_1.default.readFileSync(file, 'utf8')), boundaryDecoder_1.boundary.object({ id: boundaryDecoder_1.boundary.string }));
|
|
143
|
+
if (current.id !== owner.id)
|
|
144
|
+
return claimUpdateLock(directory, id, statusFile);
|
|
145
|
+
throw new errors_1.RunpaneError('ERR_UPDATE_LOCK_RECOVERY', `Update ${owner.id} finished, but its lock cleanup requires inspection: ${directory}. No new update was started.`, 'Wait for any active cleanup to finish. If it remains blocked, verify that no operation helper or installer is running, then follow docs/UPDATE_RECOVERY.md before moving this exact owner’s lock aside.');
|
|
146
|
+
}
|
|
147
|
+
return { ...owner, acquired: false };
|
|
148
|
+
}
|
|
149
|
+
finally {
|
|
150
|
+
node_fs_1.default.rmSync(candidate, { recursive: true, force: true });
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/** Elect one releaser. A terminal journal plus a dead recorded releaser repairs a crashed cleanup. */
|
|
154
|
+
function releaseUpdateLock(directory, id) {
|
|
155
|
+
const marker = node_path_1.default.join(directory, 'releasing');
|
|
156
|
+
const candidate = node_path_1.default.join(directory, `.releasing-${(0, node_crypto_1.randomUUID)()}`);
|
|
157
|
+
try {
|
|
158
|
+
const owner = (0, boundaryDecoder_1.decodeBoundary)(JSON.parse(node_fs_1.default.readFileSync(node_path_1.default.join(directory, 'owner.json'), 'utf8')), boundaryDecoder_1.boundary.object({ id: boundaryDecoder_1.boundary.nonEmptyString, statusFile: boundaryDecoder_1.boundary.nonEmptyString }));
|
|
159
|
+
if (owner.id !== id)
|
|
160
|
+
return;
|
|
161
|
+
if (node_fs_1.default.existsSync(marker)) {
|
|
162
|
+
const journal = readUpdateJournal(owner.statusFile);
|
|
163
|
+
const releasing = (0, boundaryDecoder_1.decodeBoundary)(JSON.parse(node_fs_1.default.readFileSync(marker, 'utf8')), boundaryDecoder_1.boundary.object({ id: boundaryDecoder_1.boundary.string, pid: boundaryDecoder_1.boundary.number }));
|
|
164
|
+
if (journal.id !== id || !['complete', 'failed'].includes(journal.phase) || releasing.id !== id || releasing.pid <= 0)
|
|
165
|
+
return;
|
|
166
|
+
try {
|
|
167
|
+
process.kill(releasing.pid, 0);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
if ((0, boundaryDecoder_1.decodeBoundary)(error, boundaryDecoder_1.boundary.object({ code: boundaryDecoder_1.boundary.string })).code !== 'ESRCH')
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
// Keep this election outside the removable lock directory. Two callers
|
|
175
|
+
// can both observe the same dead releaser; only one may remove its marker.
|
|
176
|
+
// Never remove the claim: a delayed observer must not act on a newer lock.
|
|
177
|
+
// An interrupted recovery election remains a manual inspection boundary.
|
|
178
|
+
const recovery = (0, node_crypto_1.createHash)('sha256').update(node_fs_1.default.realpathSync(directory)).update(JSON.stringify(releasing)).digest('hex');
|
|
179
|
+
node_fs_1.default.mkdirSync(node_path_1.default.join(node_path_1.default.dirname(owner.statusFile), `lock-recovery-${recovery}`), { mode: 0o700 });
|
|
180
|
+
node_fs_1.default.unlinkSync(marker);
|
|
181
|
+
}
|
|
182
|
+
// Publish fully written contents exclusively, without a crash window that
|
|
183
|
+
// exposes an empty releasing marker to another caller.
|
|
184
|
+
writeUpdateJson(candidate, { id, pid: process.pid });
|
|
185
|
+
node_fs_1.default.linkSync(candidate, marker);
|
|
186
|
+
const current = (0, boundaryDecoder_1.decodeBoundary)(JSON.parse(node_fs_1.default.readFileSync(node_path_1.default.join(directory, 'owner.json'), 'utf8')), boundaryDecoder_1.boundary.object({ id: boundaryDecoder_1.boundary.nonEmptyString }));
|
|
187
|
+
if (current.id === id)
|
|
188
|
+
node_fs_1.default.rmSync(directory, { recursive: true });
|
|
189
|
+
else
|
|
190
|
+
node_fs_1.default.unlinkSync(marker);
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
// Ambiguous ownership remains inspectable; it is never permission to steal.
|
|
194
|
+
}
|
|
195
|
+
finally {
|
|
196
|
+
node_fs_1.default.rmSync(candidate, { force: true });
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/** Process disappearance is not proof of a clean shutdown. */
|
|
200
|
+
function assertUpdateQuiescence(directory, expected) {
|
|
201
|
+
const file = node_path_1.default.join(directory, 'quiesced.json');
|
|
202
|
+
if (!node_fs_1.default.existsSync(file))
|
|
203
|
+
throw new Error('Pane exited without acknowledging clean shutdown. No installer was started; inspect the shutdown log and recovery checkpoint.');
|
|
204
|
+
const stopped = (0, boundaryDecoder_1.decodeBoundary)(JSON.parse(node_fs_1.default.readFileSync(file, 'utf8')), boundaryDecoder_1.boundary.object({ id: boundaryDecoder_1.boundary.string, bootId: boundaryDecoder_1.boundary.string, pid: boundaryDecoder_1.boundary.number }));
|
|
205
|
+
if (stopped.id !== expected.id || stopped.bootId !== expected.bootId || stopped.pid !== expected.pid)
|
|
206
|
+
throw new Error('Shutdown acknowledgment belongs to another operation or host. No installer was started.');
|
|
207
|
+
}
|
|
208
|
+
//# sourceMappingURL=updateOperation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"updateOperation.js","sourceRoot":"","sources":["../src/updateOperation.ts"],"names":[],"mappings":";;;;;AA6BA,0CAWC;AAED,8CAEC;AAOD,sCA6BC;AAGD,0CAgCC;AAGD,8CA+BC;AAGD,wDAKC;AA7JD,sDAAyB;AACzB,0DAA6B;AAC7B,6CAAqD;AACrD,uDAA6D;AAC7D,qCAAwC;AAExC,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,CAAU,CAAC;AAEpH,MAAM,WAAW,GAAG,0BAAQ,CAAC,WAAW,CAAC,UAAU,EAAE,GAAG,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,QAAQ,CAAC,CAAC;AAC/G,MAAM,aAAa,GAAG,0BAAQ,CAAC,MAAM,CAAC;IACpC,EAAE,EAAE,0BAAQ,CAAC,cAAc;IAC3B,IAAI,EAAE,0BAAQ,CAAC,cAAc;IAC7B,KAAK,EAAE,0BAAQ,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC;IAClD,OAAO,EAAE,0BAAQ,CAAC,cAAc;IAChC,KAAK,EAAE,WAAW;IAClB,SAAS,EAAE,0BAAQ,CAAC,KAAK,CAAC,0BAAQ,CAAC,WAAW,CAAC,GAAG,YAAY,CAAC,CAAC;IAChE,SAAS,EAAE,0BAAQ,CAAC,QAAQ,CAAC,0BAAQ,CAAC,MAAM,CAAC;IAC7C,QAAQ,EAAE,0BAAQ,CAAC,QAAQ,CAAC,0BAAQ,CAAC,MAAM,CAAC;IAC5C,cAAc,EAAE,0BAAQ,CAAC,QAAQ,CAAC,0BAAQ,CAAC,MAAM,CAAC;IAClD,SAAS,EAAE,0BAAQ,CAAC,cAAc;IAClC,UAAU,EAAE,0BAAQ,CAAC,OAAO;IAC5B,UAAU,EAAE,0BAAQ,CAAC,OAAO;IAC5B,aAAa,EAAE,0BAAQ,CAAC,OAAO;IAC/B,QAAQ,EAAE,0BAAQ,CAAC,KAAK,CAAC,0BAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,0BAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,0BAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,0BAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1H,KAAK,EAAE,0BAAQ,CAAC,QAAQ,CAAC,0BAAQ,CAAC,MAAM,CAAC;CAC1C,CAAC,CAAC;AAGH,qFAAqF;AACrF,SAAgB,eAAe,CAAmB,IAAY,EAAE,KAAQ;IACtE,iBAAE,CAAC,SAAS,CAAC,mBAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACnE,MAAM,SAAS,GAAG,GAAG,IAAI,IAAI,OAAO,CAAC,GAAG,MAAM,CAAC;IAC/C,MAAM,EAAE,GAAG,iBAAE,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IAC9C,IAAI,CAAC;QAAC,iBAAE,CAAC,aAAa,CAAC,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAAC,iBAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IAAC,CAAC;YACvE,CAAC;QAAC,iBAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IAAC,CAAC;IAC7B,iBAAE,CAAC,UAAU,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAC/B,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,MAAM,SAAS,GAAG,iBAAE,CAAC,QAAQ,CAAC,mBAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;QACvD,IAAI,CAAC;YAAC,iBAAE,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QAAC,CAAC;gBAAS,CAAC;YAAC,iBAAE,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QAAC,CAAC;IACvE,CAAC;AACH,CAAC;AAED,SAAgB,iBAAiB,CAAC,IAAY;IAC5C,OAAO,IAAA,gCAAc,EAAC,IAAI,CAAC,KAAK,CAAC,iBAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;AAClF,CAAC;AAOM,KAAK,UAAU,aAAa,CAAC,IAAY,EAAE,KAAkB;IAClE,IAAI,OAAO,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,CAAC,UAAU,EAAE,iBAAiB,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC;IACtF,MAAM,QAAQ,GAAG,GAAG,EAAE,CAAC,iBAAE,CAAC,UAAU,CAAC,mBAAI,CAAC,IAAI,CAAC,mBAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC;IACrF,IAAI,QAAQ,EAAE,EAAE,CAAC;QAAC,OAAO,GAAG,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,+CAA+C,EAAE,CAAC;QAAC,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAAC,OAAO,OAAO,CAAC;IAAC,CAAC;IACtK,OAAO,GAAG,EAAE,GAAG,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;IACtF,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,2EAA2E;IAC3G,IAAI,CAAC;QACH,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;YAChC,IAAI,QAAQ,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;YACzE,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAC1C,IAAI,CAAC,UAAU,EAAE,iBAAiB,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC;gBAAE,OAAO,SAAS,CAAC;YAC1F,IAAI,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAAE,SAAS;YAC/C,OAAO,GAAG,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;YAC3E,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC/B,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC/C,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;YACtC,IAAI,CAAC,UAAU,EAAE,iBAAiB,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC;gBAAE,OAAO,KAAK,CAAC;YAClF,OAAO,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,OAAO,EAAE,SAAS,EAAE,CAAC,GAAG,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;YACnH,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACjC,CAAC;QACD,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,KAAK,iBAAiB,CAAC,CAAC;QACpF,OAAO,GAAG,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC;IAC9E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,iBAAiB,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,KAAK,MAAM,IAAI,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,QAAQ;YACtJ,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;IACpE,CAAC;IACD,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC/B,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,sFAAsF;AACtF,SAAgB,eAAe,CAAC,SAAiB,EAAE,EAAU,EAAE,UAAkB;IAC/E,MAAM,SAAS,GAAG,iBAAE,CAAC,WAAW,CAAC,GAAG,SAAS,IAAI,EAAE,GAAG,CAAC,CAAC;IACxD,IAAI,CAAC;QACH,eAAe,CAAC,mBAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;QACxE,IAAI,CAAC;YAAC,iBAAE,CAAC,UAAU,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;YAAC,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QAAC,CAAC;QACvF,OAAO,KAAK,EAAE,CAAC;YAAC,IAAI,CAAC,iBAAE,CAAC,UAAU,CAAC,SAAS,CAAC;gBAAE,MAAM,KAAK,CAAC;QAAC,CAAC;QAC7D,MAAM,IAAI,GAAG,mBAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QAChD,IAAI,CAAC,iBAAE,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,qBAAY,CAAC,yBAAyB,EAAE,kDAAkD,SAAS,wBAAwB,EAAE,2FAA2F,CAAC,CAAC;QAC9P,MAAM,KAAK,GAAG,IAAA,gCAAc,EAAC,IAAI,CAAC,KAAK,CAAC,iBAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,EAAE,0BAAQ,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,0BAAQ,CAAC,cAAc,EAAE,UAAU,EAAE,0BAAQ,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;QAC/J,4EAA4E;QAC5E,6DAA6D;QAC7D,IAAI,OAAO,GAAG,iBAAiB,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAClD,IAAI,OAAO,CAAC,KAAK,KAAK,UAAU,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,cAAc,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;YAC5I,IAAI,WAAW,GAAG,KAAK,CAAC;YACxB,IAAI,CAAC;gBAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;YAAC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAAC,WAAW,GAAG,IAAA,gCAAc,EAAC,KAAK,EAAE,0BAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,0BAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC;YAAC,CAAC;YAC9J,IAAI,WAAW,EAAE,CAAC;gBAChB,sEAAsE;gBACtE,wEAAwE;gBACxE,eAAe,CAAC,mBAAI,CAAC,IAAI,CAAC,mBAAI,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,eAAe,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC9F,OAAO,GAAG,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,2EAA2E,EAAE,CAAC;gBAC9H,eAAe,CAAC,KAAK,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC;QACD,IAAI,OAAO,CAAC,EAAE,KAAK,KAAK,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9E,iBAAiB,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;YACvC,IAAI,CAAC,iBAAE,CAAC,UAAU,CAAC,SAAS,CAAC;gBAAE,OAAO,eAAe,CAAC,SAAS,EAAE,EAAE,EAAE,UAAU,CAAC,CAAC;YACjF,MAAM,OAAO,GAAG,IAAA,gCAAc,EAAC,IAAI,CAAC,KAAK,CAAC,iBAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,EAAE,0BAAQ,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,0BAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YACpH,IAAI,OAAO,CAAC,EAAE,KAAK,KAAK,CAAC,EAAE;gBAAE,OAAO,eAAe,CAAC,SAAS,EAAE,EAAE,EAAE,UAAU,CAAC,CAAC;YAC/E,MAAM,IAAI,qBAAY,CAAC,0BAA0B,EAAE,UAAU,KAAK,CAAC,EAAE,wDAAwD,SAAS,8BAA8B,EAAE,yMAAyM,CAAC,CAAC;QACnX,CAAC;QACD,OAAO,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IACvC,CAAC;YAAS,CAAC;QAAC,iBAAE,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAAC,CAAC;AACvE,CAAC;AAED,sGAAsG;AACtG,SAAgB,iBAAiB,CAAC,SAAiB,EAAE,EAAU;IAC7D,MAAM,MAAM,GAAG,mBAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IACjD,MAAM,SAAS,GAAG,mBAAI,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,IAAA,wBAAU,GAAE,EAAE,CAAC,CAAC;IACrE,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAA,gCAAc,EAAC,IAAI,CAAC,KAAK,CAAC,iBAAE,CAAC,YAAY,CAAC,mBAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,0BAAQ,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,0BAAQ,CAAC,cAAc,EAAE,UAAU,EAAE,0BAAQ,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;QAC7L,IAAI,KAAK,CAAC,EAAE,KAAK,EAAE;YAAE,OAAO;QAC5B,IAAI,iBAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1B,MAAM,OAAO,GAAG,iBAAiB,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YACpD,MAAM,SAAS,GAAG,IAAA,gCAAc,EAAC,IAAI,CAAC,KAAK,CAAC,iBAAE,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,0BAAQ,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,0BAAQ,CAAC,MAAM,EAAE,GAAG,EAAE,0BAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAC9I,IAAI,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,SAAS,CAAC,EAAE,KAAK,EAAE,IAAI,SAAS,CAAC,GAAG,IAAI,CAAC;gBAAE,OAAO;YAC9H,IAAI,CAAC;gBAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;gBAAC,OAAO;YAAC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAC7D,IAAI,IAAA,gCAAc,EAAC,KAAK,EAAE,0BAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,0BAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO;oBAAE,OAAO;YACjG,CAAC;YACD,uEAAuE;YACvE,2EAA2E;YAC3E,2EAA2E;YAC3E,yEAAyE;YACzE,MAAM,QAAQ,GAAG,IAAA,wBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,iBAAE,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACzH,iBAAE,CAAC,SAAS,CAAC,mBAAI,CAAC,IAAI,CAAC,mBAAI,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,iBAAiB,QAAQ,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YACtG,iBAAE,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC;QACD,0EAA0E;QAC1E,uDAAuD;QACvD,eAAe,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QACrD,iBAAE,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAC/B,MAAM,OAAO,GAAG,IAAA,gCAAc,EAAC,IAAI,CAAC,KAAK,CAAC,iBAAE,CAAC,YAAY,CAAC,mBAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,0BAAQ,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,0BAAQ,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;QAC1J,IAAI,OAAO,CAAC,EAAE,KAAK,EAAE;YAAE,iBAAE,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;;YAC5D,iBAAE,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,4EAA4E;IAC9E,CAAC;YAAS,CAAC;QAAC,iBAAE,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAAC,CAAC;AACtD,CAAC;AAED,8DAA8D;AAC9D,SAAgB,sBAAsB,CAAC,SAAiB,EAAE,QAAqD;IAC7G,MAAM,IAAI,GAAG,mBAAI,CAAC,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;IACnD,IAAI,CAAC,iBAAE,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,+HAA+H,CAAC,CAAC;IAC3K,MAAM,OAAO,GAAG,IAAA,gCAAc,EAAC,IAAI,CAAC,KAAK,CAAC,iBAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,EAAE,0BAAQ,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,0BAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,0BAAQ,CAAC,MAAM,EAAE,GAAG,EAAE,0BAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACnK,IAAI,OAAO,CAAC,EAAE,KAAK,QAAQ,CAAC,EAAE,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,KAAK,QAAQ,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,yFAAyF,CAAC,CAAC;AACnN,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Resolve npm's JS entry point so a Windows .cmd never needs shell evaluation. */
|
|
2
|
+
export declare function findNpm(runtime: string): string;
|
|
3
|
+
export declare function runNpm(runtime: string, npm: string, args: string[], cwd?: string): string;
|
|
4
|
+
/** Copy all helper modules before either the app or the active CLI is replaced. */
|
|
5
|
+
export declare function stageUpdateCode(entrypoint: string, directory: string): string;
|
|
6
|
+
export interface StagedCli {
|
|
7
|
+
version: string;
|
|
8
|
+
archive: string;
|
|
9
|
+
packageRoot: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function stageCliPackage(runtime: string, npm: string, requested: string, directory: string): StagedCli;
|
|
12
|
+
/** Commit a managed version pin and rewrite the current shim immediately. */
|
|
13
|
+
export declare function activateManagedCli(paneDir: string, version: string, entrypoint: string, runtime: string): void;
|
|
14
|
+
//# sourceMappingURL=updatePackage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"updatePackage.d.ts","sourceRoot":"","sources":["../src/updatePackage.ts"],"names":[],"mappings":"AAOA,mFAAmF;AACnF,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAc/C;AAED,wBAAgB,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAIzF;AAED,mFAAmF;AACnF,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAgB7E;AAED,MAAM,WAAW,SAAS;IAAG,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE;AACpF,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,CAc7G;AAED,6EAA6E;AAC7E,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAqB9G"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.findNpm = findNpm;
|
|
7
|
+
exports.runNpm = runNpm;
|
|
8
|
+
exports.stageUpdateCode = stageUpdateCode;
|
|
9
|
+
exports.stageCliPackage = stageCliPackage;
|
|
10
|
+
exports.activateManagedCli = activateManagedCli;
|
|
11
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
12
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
13
|
+
const node_child_process_1 = require("node:child_process");
|
|
14
|
+
const boundaryDecoder_1 = require("./boundaryDecoder");
|
|
15
|
+
const errors_1 = require("./errors");
|
|
16
|
+
const updateOperation_1 = require("./updateOperation");
|
|
17
|
+
/** Resolve npm's JS entry point so a Windows .cmd never needs shell evaluation. */
|
|
18
|
+
function findNpm(runtime) {
|
|
19
|
+
const candidates = [
|
|
20
|
+
node_path_1.default.join(node_path_1.default.dirname(runtime), 'node_modules/npm/bin/npm-cli.js'),
|
|
21
|
+
node_path_1.default.resolve(node_path_1.default.dirname(runtime), '../lib/node_modules/npm/bin/npm-cli.js'),
|
|
22
|
+
...(process.env.PATH ?? '').split(node_path_1.default.delimiter).flatMap(directory => [
|
|
23
|
+
node_path_1.default.join(directory, 'npm'), node_path_1.default.join(directory, 'node_modules/npm/bin/npm-cli.js'),
|
|
24
|
+
]),
|
|
25
|
+
];
|
|
26
|
+
for (const candidate of candidates) {
|
|
27
|
+
if (!node_fs_1.default.existsSync(candidate))
|
|
28
|
+
continue;
|
|
29
|
+
const real = node_fs_1.default.realpathSync(candidate);
|
|
30
|
+
if (real.endsWith(`${node_path_1.default.sep}npm-cli.js`))
|
|
31
|
+
return real;
|
|
32
|
+
}
|
|
33
|
+
throw new errors_1.RunpaneError('ERR_UPDATE_PACKAGE_MANAGER', 'npm could not be located. Nothing was changed.', 'Install standalone Node with npm, then retry.');
|
|
34
|
+
}
|
|
35
|
+
function runNpm(runtime, npm, args, cwd) {
|
|
36
|
+
const env = { ...process.env };
|
|
37
|
+
delete env.ELECTRON_RUN_AS_NODE;
|
|
38
|
+
return (0, node_child_process_1.execFileSync)(runtime, [npm, ...args], { encoding: 'utf8', cwd, env, timeout: 180_000, maxBuffer: 10 * 1024 * 1024 });
|
|
39
|
+
}
|
|
40
|
+
/** Copy all helper modules before either the app or the active CLI is replaced. */
|
|
41
|
+
function stageUpdateCode(entrypoint, directory) {
|
|
42
|
+
const original = node_fs_1.default.realpathSync(entrypoint);
|
|
43
|
+
node_fs_1.default.mkdirSync(directory, { recursive: true, mode: 0o700 });
|
|
44
|
+
if (original.endsWith('.cjs')) {
|
|
45
|
+
const target = node_path_1.default.join(directory, 'runpane.cjs');
|
|
46
|
+
node_fs_1.default.copyFileSync(original, target, node_fs_1.default.constants.COPYFILE_EXCL);
|
|
47
|
+
return target;
|
|
48
|
+
}
|
|
49
|
+
const root = node_path_1.default.resolve(node_path_1.default.dirname(original), '..');
|
|
50
|
+
const metadata = (0, boundaryDecoder_1.decodeBoundary)(JSON.parse(node_fs_1.default.readFileSync(node_path_1.default.join(root, 'package.json'), 'utf8')), boundaryDecoder_1.boundary.object({ name: boundaryDecoder_1.boundary.string }));
|
|
51
|
+
if (metadata.name !== 'runpane' || node_path_1.default.basename(original) !== 'cli.js') {
|
|
52
|
+
throw new errors_1.RunpaneError('ERR_UPDATE_HELPER', 'The invoked helper is not a supported runpane package. Nothing was changed.', 'Use the installed runpane CLI.');
|
|
53
|
+
}
|
|
54
|
+
node_fs_1.default.cpSync(node_path_1.default.join(root, 'dist'), node_path_1.default.join(directory, 'dist'), { recursive: true, dereference: true, errorOnExist: true, force: false });
|
|
55
|
+
node_fs_1.default.copyFileSync(node_path_1.default.join(root, 'package.json'), node_path_1.default.join(directory, 'package.json'));
|
|
56
|
+
return node_path_1.default.join(directory, 'dist', 'cli.js');
|
|
57
|
+
}
|
|
58
|
+
function stageCliPackage(runtime, npm, requested, directory) {
|
|
59
|
+
node_fs_1.default.mkdirSync(directory, { recursive: true, mode: 0o700 });
|
|
60
|
+
const result = (0, boundaryDecoder_1.decodeBoundary)(JSON.parse(runNpm(runtime, npm, ['pack', `runpane@${requested.replace(/^v/, '')}`, '--ignore-scripts', '--json', '--pack-destination', directory], directory)), boundaryDecoder_1.boundary.array(boundaryDecoder_1.boundary.object({ filename: boundaryDecoder_1.boundary.nonEmptyString, version: boundaryDecoder_1.boundary.nonEmptyString, integrity: boundaryDecoder_1.boundary.nonEmptyString })));
|
|
61
|
+
if (result.length !== 1 || node_path_1.default.basename(result[0].filename) !== result[0].filename)
|
|
62
|
+
throw new Error('npm returned an invalid package archive.');
|
|
63
|
+
const archive = node_path_1.default.join(directory, result[0].filename);
|
|
64
|
+
const entries = (0, node_child_process_1.execFileSync)('tar', ['-tzf', archive], { encoding: 'utf8', timeout: 30_000 }).split(/\r?\n/).filter(Boolean);
|
|
65
|
+
if (entries.some(entry => !entry.startsWith('package/') || entry.split('/').includes('..') || entry.includes('\\')))
|
|
66
|
+
throw new Error('The CLI archive contains unsafe paths.');
|
|
67
|
+
(0, node_child_process_1.execFileSync)('tar', ['-xzf', archive, '-C', directory], { timeout: 30_000 });
|
|
68
|
+
const packageRoot = node_path_1.default.join(directory, 'package');
|
|
69
|
+
const metadata = (0, boundaryDecoder_1.decodeBoundary)(JSON.parse(node_fs_1.default.readFileSync(node_path_1.default.join(packageRoot, 'package.json'), 'utf8')), boundaryDecoder_1.boundary.object({ name: boundaryDecoder_1.boundary.string, version: boundaryDecoder_1.boundary.string }));
|
|
70
|
+
if (metadata.name !== 'runpane' || metadata.version !== result[0].version)
|
|
71
|
+
throw new Error('The staged CLI identity does not match npm metadata.');
|
|
72
|
+
const actual = (0, node_child_process_1.execFileSync)(runtime, [node_path_1.default.join(packageRoot, 'dist', 'cli.js'), '--version'], { encoding: 'utf8', timeout: 15_000 }).trim();
|
|
73
|
+
if (!actual.includes(metadata.version))
|
|
74
|
+
throw new Error('The staged CLI failed its version check.');
|
|
75
|
+
return { version: metadata.version, archive, packageRoot };
|
|
76
|
+
}
|
|
77
|
+
/** Commit a managed version pin and rewrite the current shim immediately. */
|
|
78
|
+
function activateManagedCli(paneDir, version, entrypoint, runtime) {
|
|
79
|
+
const bin = node_path_1.default.join(paneDir, 'bin');
|
|
80
|
+
const root = node_fs_1.default.realpathSync(node_path_1.default.join(bin, 'cli'));
|
|
81
|
+
for (const file of [entrypoint, runtime]) {
|
|
82
|
+
const relative = node_path_1.default.relative(root, node_fs_1.default.realpathSync(file));
|
|
83
|
+
if (relative.startsWith('..') || node_path_1.default.isAbsolute(relative))
|
|
84
|
+
throw new Error('Managed CLI files must be inside the owned CLI directory.');
|
|
85
|
+
}
|
|
86
|
+
const quote = (value) => `'${value.replace(/'/g, `'\\''`)}'`;
|
|
87
|
+
const marker = 'pane-managed-runpane-shim v1';
|
|
88
|
+
const files = [{ name: 'runpane', content: `#!/bin/sh\n# ${marker}\nif [ -z "\${PANE_DIR:-}" ]; then PANE_DIR=${quote(paneDir)}; export PANE_DIR; fi\nexec ${quote(runtime)} ${quote(entrypoint)} "$@"\n` }];
|
|
89
|
+
if (process.platform === 'win32')
|
|
90
|
+
files.push({ name: 'runpane.cmd', content: `@echo off\r\nrem ${marker}\r\nsetlocal\r\nif not defined PANE_DIR set "PANE_DIR=${paneDir}"\r\n"${runtime}" "${entrypoint}" %*\r\n` });
|
|
91
|
+
for (const file of files) {
|
|
92
|
+
const target = node_path_1.default.join(bin, file.name);
|
|
93
|
+
if (node_fs_1.default.lstatSync(target).isSymbolicLink() || !node_fs_1.default.readFileSync(target, 'utf8').includes(marker))
|
|
94
|
+
throw new Error(`The CLI shim is not owned by Pane: ${target}`);
|
|
95
|
+
}
|
|
96
|
+
(0, updateOperation_1.writeUpdateJson)(node_path_1.default.join(bin, 'runpane-override.json'), { version, entrypoint, runtime });
|
|
97
|
+
for (const file of files) {
|
|
98
|
+
const target = node_path_1.default.join(bin, file.name);
|
|
99
|
+
node_fs_1.default.writeFileSync(`${target}.update`, file.content, { mode: 0o755 });
|
|
100
|
+
node_fs_1.default.renameSync(`${target}.update`, target);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=updatePackage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"updatePackage.js","sourceRoot":"","sources":["../src/updatePackage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { ParsedArgs } from './commands';
|
|
2
|
+
export declare const updateHostSchema: import("./boundaryDecoder").BoundarySchema<{
|
|
3
|
+
readonly protocol: 1;
|
|
4
|
+
readonly machine: string;
|
|
5
|
+
readonly bootId: string;
|
|
6
|
+
readonly pid: number;
|
|
7
|
+
readonly executable: string;
|
|
8
|
+
readonly version: string;
|
|
9
|
+
readonly paneDir: string;
|
|
10
|
+
readonly userData: string;
|
|
11
|
+
readonly packaged: boolean;
|
|
12
|
+
readonly remoteEnabled: boolean;
|
|
13
|
+
readonly remoteHealthy: boolean;
|
|
14
|
+
readonly endpointFingerprint: string;
|
|
15
|
+
readonly active: number;
|
|
16
|
+
readonly idle: number;
|
|
17
|
+
readonly blocked: number;
|
|
18
|
+
}>;
|
|
19
|
+
export type UpdateHost = ReturnType<typeof updateHostSchema.decode>;
|
|
20
|
+
interface UpdateCliInstallation {
|
|
21
|
+
owner: 'managed' | 'npm' | 'pip';
|
|
22
|
+
pipUser?: boolean;
|
|
23
|
+
entrypoint: string;
|
|
24
|
+
version: string;
|
|
25
|
+
prefix: string;
|
|
26
|
+
packageManager?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface UpdatePreflight {
|
|
29
|
+
machine: string;
|
|
30
|
+
paneDir: string;
|
|
31
|
+
scope: 'both' | 'pane' | 'cli';
|
|
32
|
+
requestedVersion: string;
|
|
33
|
+
host: UpdateHost | null;
|
|
34
|
+
cli: UpdateCliInstallation | null;
|
|
35
|
+
runtimeSource: string;
|
|
36
|
+
npmSource?: string;
|
|
37
|
+
lockDirectory: string;
|
|
38
|
+
additionalLockDirectories: string[];
|
|
39
|
+
limitations: string[];
|
|
40
|
+
disableOsIntegration?: boolean;
|
|
41
|
+
}
|
|
42
|
+
/** Exercise directory ACLs too: fs.access(W_OK) does not check Windows ACLs. */
|
|
43
|
+
export declare function assertUpdateDirectoryWritable(directory: string): void;
|
|
44
|
+
export declare function preflightUpdate(parsed: ParsedArgs, scope: UpdatePreflight['scope']): Promise<UpdatePreflight>;
|
|
45
|
+
export {};
|
|
46
|
+
//# sourceMappingURL=updatePreflight.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"updatePreflight.d.ts","sourceRoot":"","sources":["../src/updatePreflight.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;EAgB3B,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC;AAEpE,UAAU,qBAAqB;IAC7B,KAAK,EAAE,SAAS,GAAG,KAAK,GAAG,KAAK,CAAC;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC;IACxB,GAAG,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAClC,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,yBAAyB,EAAE,MAAM,EAAE,CAAC;IACpC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAMD,gFAAgF;AAChF,wBAAgB,6BAA6B,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAcrE;AAgCD,wBAAsB,eAAe,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC,CAkCnH"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.updateHostSchema = void 0;
|
|
7
|
+
exports.assertUpdateDirectoryWritable = assertUpdateDirectoryWritable;
|
|
8
|
+
exports.preflightUpdate = preflightUpdate;
|
|
9
|
+
const updateCapacity_1 = require("./updateCapacity");
|
|
10
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
11
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
12
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
13
|
+
const boundaryDecoder_1 = require("./boundaryDecoder");
|
|
14
|
+
const daemonClient_1 = require("./daemonClient");
|
|
15
|
+
const errors_1 = require("./errors");
|
|
16
|
+
const version_1 = require("./version");
|
|
17
|
+
const updatePython_1 = require("./updatePython");
|
|
18
|
+
const updatePackage_1 = require("./updatePackage");
|
|
19
|
+
const updateSupervisor_1 = require("./updateSupervisor");
|
|
20
|
+
exports.updateHostSchema = boundaryDecoder_1.boundary.object({
|
|
21
|
+
protocol: boundaryDecoder_1.boundary.literal(1),
|
|
22
|
+
machine: boundaryDecoder_1.boundary.nonEmptyString,
|
|
23
|
+
bootId: boundaryDecoder_1.boundary.nonEmptyString,
|
|
24
|
+
pid: boundaryDecoder_1.boundary.number,
|
|
25
|
+
executable: boundaryDecoder_1.boundary.nonEmptyString,
|
|
26
|
+
version: boundaryDecoder_1.boundary.nonEmptyString,
|
|
27
|
+
paneDir: boundaryDecoder_1.boundary.nonEmptyString,
|
|
28
|
+
userData: boundaryDecoder_1.boundary.nonEmptyString,
|
|
29
|
+
packaged: boundaryDecoder_1.boundary.boolean,
|
|
30
|
+
remoteEnabled: boundaryDecoder_1.boundary.boolean,
|
|
31
|
+
remoteHealthy: boundaryDecoder_1.boundary.boolean,
|
|
32
|
+
endpointFingerprint: boundaryDecoder_1.boundary.nonEmptyString,
|
|
33
|
+
active: boundaryDecoder_1.boundary.number,
|
|
34
|
+
idle: boundaryDecoder_1.boundary.number,
|
|
35
|
+
blocked: boundaryDecoder_1.boundary.number,
|
|
36
|
+
});
|
|
37
|
+
function fail(message, next) {
|
|
38
|
+
throw new errors_1.RunpaneError('ERR_UPDATE_PREFLIGHT', `${message} Nothing was changed.`, next);
|
|
39
|
+
}
|
|
40
|
+
/** Exercise directory ACLs too: fs.access(W_OK) does not check Windows ACLs. */
|
|
41
|
+
function assertUpdateDirectoryWritable(directory) {
|
|
42
|
+
let probe;
|
|
43
|
+
try {
|
|
44
|
+
probe = node_fs_1.default.mkdtempSync(node_path_1.default.join(directory, '.pane-update-preflight-'));
|
|
45
|
+
const file = node_path_1.default.join(probe, 'write');
|
|
46
|
+
node_fs_1.default.writeFileSync(file, 'update preflight', { flag: 'wx', mode: 0o600 });
|
|
47
|
+
node_fs_1.default.renameSync(file, node_path_1.default.join(probe, 'renamed'));
|
|
48
|
+
node_fs_1.default.rmSync(probe, { recursive: true });
|
|
49
|
+
probe = undefined;
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
fail(`The update target is not writable with the current account: ${directory}.`, 'Use the installation’s owning account or package manager; Pane has not been stopped.');
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
if (probe)
|
|
56
|
+
node_fs_1.default.rmSync(probe, { recursive: true, force: true });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** Resolve the invoked CLI, not another runpane earlier/later on PATH. */
|
|
60
|
+
function identifyUpdateCli(paneDir, entrypoint = process.argv[1]) {
|
|
61
|
+
const real = node_fs_1.default.realpathSync(entrypoint);
|
|
62
|
+
const managed = node_fs_1.default.existsSync(node_path_1.default.join(paneDir, 'bin')) ? node_fs_1.default.realpathSync(node_path_1.default.join(paneDir, 'bin')) : node_path_1.default.join(paneDir, 'bin');
|
|
63
|
+
if (real === node_path_1.default.join(managed, 'runpane.cjs') || real.startsWith(`${node_path_1.default.join(managed, 'cli')}${node_path_1.default.sep}`)) {
|
|
64
|
+
const shim = node_path_1.default.join(managed, process.platform === 'win32' ? 'runpane.cmd' : 'runpane');
|
|
65
|
+
if (!node_fs_1.default.readFileSync(shim, 'utf8').includes('pane-managed-runpane-shim v1'))
|
|
66
|
+
fail('The active CLI is not a Pane-owned shim.', 'Use its owning package manager.');
|
|
67
|
+
node_fs_1.default.accessSync(managed, node_fs_1.default.constants.W_OK);
|
|
68
|
+
return { owner: 'managed', entrypoint: real, version: (0, version_1.getWrapperVersion)(), prefix: managed };
|
|
69
|
+
}
|
|
70
|
+
const root = node_path_1.default.resolve(node_path_1.default.dirname(real), '..');
|
|
71
|
+
const pkg = (0, boundaryDecoder_1.decodeBoundary)(JSON.parse(node_fs_1.default.readFileSync(node_path_1.default.join(root, 'package.json'), 'utf8')), boundaryDecoder_1.boundary.object({ name: boundaryDecoder_1.boundary.string, version: boundaryDecoder_1.boundary.string }));
|
|
72
|
+
if (pkg.name !== 'runpane')
|
|
73
|
+
fail('The active CLI package is not runpane.', 'Use the supported runpane installation.');
|
|
74
|
+
const npmRoot = (0, updatePackage_1.findNpm)(process.execPath);
|
|
75
|
+
const prefix = (0, updatePackage_1.runNpm)(process.execPath, npmRoot, ['prefix', '--global']).trim();
|
|
76
|
+
const expected = node_path_1.default.join(prefix, ...(process.platform === 'win32' ? [] : ['lib']), 'node_modules', 'runpane');
|
|
77
|
+
if (!node_fs_1.default.existsSync(expected) || node_fs_1.default.realpathSync(expected) !== root)
|
|
78
|
+
fail('The invoked CLI is a local, cached, or unsupported package installation.', 'Update that installation with its owning package manager, or invoke the supported global/Pane-managed CLI.');
|
|
79
|
+
node_fs_1.default.accessSync(root, node_fs_1.default.constants.W_OK);
|
|
80
|
+
node_fs_1.default.accessSync(node_path_1.default.dirname(root), node_fs_1.default.constants.W_OK);
|
|
81
|
+
return { owner: 'npm', entrypoint: real, version: pkg.version, prefix, packageManager: npmRoot };
|
|
82
|
+
}
|
|
83
|
+
function findUpdateRuntime() {
|
|
84
|
+
if (!process.versions.electron)
|
|
85
|
+
return process.execPath;
|
|
86
|
+
const candidates = (process.env.PATH ?? '').split(node_path_1.default.delimiter).map(directory => node_path_1.default.join(directory, process.platform === 'win32' ? 'node.exe' : 'node'));
|
|
87
|
+
const node = candidates.find(file => node_fs_1.default.existsSync(file) && node_fs_1.default.realpathSync(file) !== node_fs_1.default.realpathSync(process.execPath));
|
|
88
|
+
if (!node)
|
|
89
|
+
fail('No independent Node runtime is available; the managed CLI is running inside Electron.', 'Install standalone Node 22 or newer, then retry.');
|
|
90
|
+
return node;
|
|
91
|
+
}
|
|
92
|
+
async function preflightUpdate(parsed, scope) {
|
|
93
|
+
if (parsed.channel !== 'stable' || parsed.target !== 'client' || parsed.downloadDir || (parsed.format !== 'auto' && parsed.format !== (process.platform === 'darwin' ? 'zip' : process.platform === 'win32' ? 'exe' : 'appimage')))
|
|
94
|
+
fail('These installer options are not supported by independent updates.', 'Use the stable client release with automatic format and operation-owned staging, or use runpane install for other installer options.');
|
|
95
|
+
if (!/^(?:latest|v?\d+\.\d+\.\d+(?:-[a-zA-Z0-9.-]+)?)$/.test(parsed.paneVersion))
|
|
96
|
+
fail('The requested version is invalid.', 'Use --version latest or a released version such as 2.4.182.');
|
|
97
|
+
const paneDir = node_path_1.default.resolve((0, daemonClient_1.resolvePaneDirectory)(parsed.paneDir));
|
|
98
|
+
const cli = scope === 'pane' ? null : process.env.PANE_UPDATE_PYTHON && process.env.PANE_UPDATE_PYTHON_ENTRYPOINT
|
|
99
|
+
? (0, updatePython_1.identifyPythonCli)(process.env.PANE_UPDATE_PYTHON, process.env.PANE_UPDATE_PYTHON_ENTRYPOINT) : identifyUpdateCli(paneDir);
|
|
100
|
+
let host = null;
|
|
101
|
+
if (scope !== 'cli') {
|
|
102
|
+
host = await (0, daemonClient_1.invokeDaemon)('runpane:update:host', [], exports.updateHostSchema, { paneDir, timeoutMs: 10_000 });
|
|
103
|
+
if (node_path_1.default.resolve(host.paneDir) !== paneDir || host.machine !== node_os_1.default.hostname())
|
|
104
|
+
fail('The daemon identity does not match this command’s local target.', 'Run update on the owning machine with its explicit --pane-dir.');
|
|
105
|
+
if (!host.packaged)
|
|
106
|
+
fail('This Pane is a development build, not a supported installed application.', 'Use the packaged installation, or the isolated update test harness.');
|
|
107
|
+
if (parsed.panePath && node_fs_1.default.realpathSync(parsed.panePath) !== node_fs_1.default.realpathSync(host.executable))
|
|
108
|
+
fail('--pane-path does not identify the running Pane.', 'Use the executable shown by this host’s update preflight.');
|
|
109
|
+
node_fs_1.default.accessSync(host.executable, node_fs_1.default.constants.W_OK);
|
|
110
|
+
}
|
|
111
|
+
if (process.platform === 'linux' && host && !host.executable.toLowerCase().endsWith('.appimage'))
|
|
112
|
+
fail('This Linux installation is not an owned AppImage.', 'Update the system package using its owning package manager.');
|
|
113
|
+
(0, updateSupervisor_1.checkUpdateSupervisor)();
|
|
114
|
+
const install = host ? (process.platform === 'darwin' ? node_path_1.default.resolve(host.executable, '../../..') : process.platform === 'linux' ? host.executable : node_path_1.default.dirname(host.executable)) : cli.prefix;
|
|
115
|
+
node_fs_1.default.accessSync(host ? node_path_1.default.dirname(install) : install, node_fs_1.default.constants.W_OK);
|
|
116
|
+
node_fs_1.default.mkdirSync(node_path_1.default.join(paneDir, 'updates'), { recursive: true, mode: 0o700 });
|
|
117
|
+
const writableDirectories = new Set([
|
|
118
|
+
paneDir,
|
|
119
|
+
...(host ? [node_path_1.default.dirname(install), ...(process.platform === 'win32' ? [install] : [])] : []),
|
|
120
|
+
...(cli ? [cli.prefix, node_path_1.default.dirname(cli.entrypoint)] : []),
|
|
121
|
+
]);
|
|
122
|
+
for (const directory of writableDirectories)
|
|
123
|
+
assertUpdateDirectoryWritable(directory);
|
|
124
|
+
(0, updateCapacity_1.assertUpdateCapacity)(paneDir, host, install, cli?.prefix);
|
|
125
|
+
const runtimeSource = findUpdateRuntime();
|
|
126
|
+
return {
|
|
127
|
+
machine: node_os_1.default.hostname(), paneDir, scope, requestedVersion: parsed.paneVersion, host, cli,
|
|
128
|
+
runtimeSource, npmSource: cli && cli.owner !== 'pip' ? (0, updatePackage_1.findNpm)(runtimeSource) : undefined, lockDirectory: node_path_1.default.join(paneDir, 'updates', '.operation-lock'),
|
|
129
|
+
additionalLockDirectories: [...(host ? [node_path_1.default.join(node_path_1.default.dirname(install), `.${node_path_1.default.basename(install)}.update-lock`)] : []), ...(cli ? [node_path_1.default.join(cli.prefix, '.runpane-update-lock')] : [])],
|
|
130
|
+
disableOsIntegration: process.env.PANE_DISABLE_OS_INTEGRATION === '1',
|
|
131
|
+
limitations: ['Requires the current interactive login. Logout/reboot recovery must be inspected through the durable operation status.', 'Agent turns with uncertain delivery are never replayed.'],
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=updatePreflight.js.map
|