Files
workinf_Blender_Wasm/tools/web/build-m12-git-snapshot.mjs
mes123456 c2c65d3a09
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled
Rebuild local Blender WASM environment and recovery evidence
2026-08-27 20:22:15 +08:00

108 lines
4.2 KiB
JavaScript

import assert from "node:assert/strict";
import crypto from "node:crypto";
import fs from "node:fs";
import path from "node:path";
import { execFileSync } from "node:child_process";
import { fileURLToPath } from "node:url";
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
const driftPath = path.join(root, "tests/golden/corrective/rehydration/M12-manifest-sha-drift.json");
const outputArgumentIndex = process.argv.indexOf("--out");
const outputRoot = path.resolve(root, outputArgumentIndex >= 0 ? process.argv[outputArgumentIndex + 1] : "tests/golden/corrective/rehydration/M12-git-history-snapshot");
const filesRoot = path.join(outputRoot, "files");
const drift = JSON.parse(fs.readFileSync(driftPath, "utf8"));
const sha256 = (bytes) => crypto.createHash("sha256").update(bytes).digest("hex");
const run = (args) => execFileSync("git", args, { cwd: root, encoding: "utf8", maxBuffer: 32 * 1024 * 1024 });
const uniqueEntries = new Map();
for (const entry of drift.entries) {
const key = `${entry.path}\0${entry.originalSha256}`;
if (!uniqueEntries.has(key)) uniqueEntries.set(key, entry);
}
function historicalBlob(pathname, expectedSha) {
let objectListing = "";
try {
objectListing = run(["rev-list", "--objects", "--all", "--", pathname]);
} catch {
return null;
}
const candidates = [...new Set(objectListing.split("\n").map((line) => line.split(" ")[0]).filter((id) => /^[0-9a-f]{40}$/u.test(id)))];
for (const blob of candidates) {
let type;
try {
type = run(["cat-file", "-t", blob]).trim();
} catch {
continue;
}
if (type !== "blob") continue;
const bytes = execFileSync("git", ["cat-file", "blob", blob], { cwd: root, maxBuffer: 64 * 1024 * 1024 });
if (sha256(bytes) !== expectedSha) continue;
let commits = [];
try {
commits = run(["log", "--all", "--format=%H", "--", pathname]).trim().split("\n").filter(Boolean);
} catch {
commits = [];
}
const commit = commits.find((candidate) => {
try {
return run(["rev-parse", `${candidate}:${pathname}`]).trim() === blob;
} catch {
return false;
}
}) ?? null;
return { blob, commit, bytes };
}
return null;
}
const matched = [];
const unresolved = [];
const pathPairCounts = new Map();
for (const entry of uniqueEntries.values()) pathPairCounts.set(entry.path, (pathPairCounts.get(entry.path) ?? 0) + 1);
for (const entry of uniqueEntries.values()) {
const pathname = entry.path;
const result = historicalBlob(pathname, entry.originalSha256);
if (!result) {
unresolved.push({ path: pathname, originalSha256: entry.originalSha256, reason: "exact SHA-256 content was not found in Git history" });
continue;
}
const suffix = (pathPairCounts.get(pathname) ?? 0) > 1 ? `.${entry.originalSha256.slice(0, 16)}` : "";
const snapshotPath = path.join("files", `${pathname}${suffix}`);
const destination = path.join(outputRoot, snapshotPath);
fs.mkdirSync(path.dirname(destination), { recursive: true });
fs.writeFileSync(destination, result.bytes);
matched.push({
path: pathname,
snapshotPath,
sha256: entry.originalSha256,
bytes: result.bytes.length,
gitBlob: result.blob,
gitCommit: result.commit,
});
}
const repository = run(["remote", "get-url", "origin"]).trim();
const head = run(["rev-parse", "HEAD"]).trim();
const manifest = {
schemaVersion: 1,
mode: "IMMUTABLE_REPOSITORY",
authorized: true,
source: {
kind: "GIT_HISTORY",
repository,
head,
selection: "exact original SHA-256 content match; current worktree is never read",
},
coverage: {
requestedPaths: new Set([...uniqueEntries.values()].map((entry) => entry.path)).size,
requestedPairs: uniqueEntries.size,
matchedPaths: matched.length,
unmatchedPaths: unresolved.length,
unresolved,
},
files: matched.sort((a, b) => a.path.localeCompare(b.path)),
};
fs.mkdirSync(outputRoot, { recursive: true });
fs.writeFileSync(path.join(outputRoot, "snapshot-manifest.json"), `${JSON.stringify(manifest, null, 2)}\n`, "utf8");
process.stdout.write(`m12-git-snapshot-ok requested=${uniqueEntries.size} matched=${matched.length} unmatched=${unresolved.length} output=${path.relative(root, outputRoot).replaceAll(path.sep, "/")}\n`);