mirror of
https://github.com/dtzp555-max/ocp.git
synced 2026-07-21 21:15:09 +00:00
5 issues raised by code-quality reviewer on c12013a:
A. exec() wrapper now captures stderr from execSync failures and
re-throws with `phase X failed: <stderr>` instead of the terse
"Command failed: ..." default. Operators see the actual git/npm
error.
B. runFullUpgrade body wrapped in try/catch; any error after phase 2
(snapshot written) carries snapshotPath + phases + hint pointing
at `ocp update --rollback`. Aligns with the post-flight failure
pattern.
C. CLI entrypoint now prints snapshotPath + hint on error.
Plus minor:
- snapshot.mjs tryCopy logs a [snapshot] warn line instead of silently
swallowing copy errors (e.g. permission-denied admin-key)
- heads-up window 1s → 3s, more operable per the policy intent
- opts.yes intent comment added (Bundle 3 will use)
One regression test added.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
53 lines
2.1 KiB
JavaScript
53 lines
2.1 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 (err) {
|
|
console.error(`[snapshot] warn: could not copy ${src} (${err.code || err.message})`);
|
|
}
|
|
};
|
|
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));
|
|
}
|