mirror of
https://github.com/dtzp555-max/ocp.git
synced 2026-07-19 09:44:07 +00:00
Implements the upgrade dispatcher (noop / dry-run / light delegation / full path) and the snapshot writer/reader/list module. Full path snapshots plist + db + admin-key + openclaw.json before mutating, runs the 6 phases (pre-flight, snapshot, fetch+install, reconfigure, restart, post-flight), and emits a heads-up before launchctl bootout per notify_before_prod_service_restart.md policy. mockExec/mockDoctor injection points let tests verify the phase ordering without touching the real shell. fresh_install + rollback paths are deferred to Bundle 3. No cli.js citation needed: this is OCP-internal upgrade tooling with no corresponding cli.js operation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
51 lines
2.0 KiB
JavaScript
51 lines
2.0 KiB
JavaScript
import { mkdirSync, writeFileSync, readFileSync, copyFileSync, existsSync, readdirSync, statSync } from "node:fs";
|
|
import { join } from "node:path";
|
|
|
|
export function writeSnapshot({ homeDir, fromCommit, fromVersion, toVersion, extraFiles = [] }) {
|
|
const ts = new Date().toISOString().replace(/\.\d+Z$/, "Z");
|
|
const root = join(homeDir, ".ocp", `upgrade-snapshot-${ts}`);
|
|
mkdirSync(root, { recursive: true });
|
|
|
|
// Standard manifest files
|
|
writeFileSync(join(root, "from-commit.txt"), fromCommit + "\n");
|
|
writeFileSync(join(root, "from-version.txt"), fromVersion + "\n");
|
|
writeFileSync(join(root, "to-version.txt"), toVersion + "\n");
|
|
|
|
// Optional captures (best-effort, never fatal)
|
|
const tryCopy = (src, dst) => {
|
|
try {
|
|
if (existsSync(src)) copyFileSync(src, dst);
|
|
} catch { /* swallow */ }
|
|
};
|
|
tryCopy(join(homeDir, "Library", "LaunchAgents", "dev.ocp.proxy.plist"), join(root, "plist"));
|
|
tryCopy(join(homeDir, ".config", "systemd", "user", "ocp-proxy.service"), join(root, "service"));
|
|
tryCopy(join(homeDir, ".ocp", "ocp.db"), join(root, "db.bak"));
|
|
tryCopy(join(homeDir, ".ocp", "admin-key"), join(root, "admin-key"));
|
|
tryCopy(join(homeDir, ".openclaw", "openclaw.json"), join(root, "openclaw.json"));
|
|
|
|
for (const { src, name } of extraFiles) tryCopy(src, join(root, name));
|
|
|
|
return root;
|
|
}
|
|
|
|
export function readSnapshot(snapshotPath) {
|
|
const read = (n) => {
|
|
try { return readFileSync(join(snapshotPath, n), "utf8").trim(); } catch { return null; }
|
|
};
|
|
return {
|
|
path: snapshotPath,
|
|
fromCommit: read("from-commit.txt"),
|
|
fromVersion: read("from-version.txt"),
|
|
toVersion: read("to-version.txt")
|
|
};
|
|
}
|
|
|
|
export function listSnapshots(homeDir) {
|
|
const root = join(homeDir, ".ocp");
|
|
if (!existsSync(root)) return [];
|
|
return readdirSync(root)
|
|
.filter(name => name.startsWith("upgrade-snapshot-"))
|
|
.map(name => ({ name, path: join(root, name), mtime: statSync(join(root, name)).mtimeMs }))
|
|
.sort((a, b) => a.name.localeCompare(b.name));
|
|
}
|