mirror of
https://github.com/openclaw/openclaw.git
synced 2026-10-03 17:53:39 +00:00
* perf(ci): reduce Windows test setup and worker time * perf(anthropic): defer auth loading until hook execution * perf(test): narrow selected config startup work * fix(ci): bound compiler memory on constrained lint runners * test(ci): prepare media fixture input capabilities * perf(test): scope selected unit configuration discovery * fix(ci): release cancelled runs and route hybrid control jobs * fix(ci): resolve merge bases before Testbox preparation * fix(ci): align gateway recovery validation with runtime contracts * perf(ci): avoid rename blob fetches during docs classification * test(ci): consolidate Testbox base preparation coverage * perf(ci): account for tooling work and shared build prerequisites * fix(ci): declare serial plugin config worker ownership * perf(ci): overlap independent performance Git lifecycle fixtures * perf(ci): partition the complete plugin catch-all with native sharding * perf(ci): reuse compiled session workers * perf(test): compare complete SQLite snapshots natively * test(ci): reuse race-safe process cleanup in report fixtures * fix(ci): preserve the trusted PR helper closure * test(ci): derive PR fixtures from the trusted helper closure * perf(ci): reuse matching checkout for harness actions * fix(ci): replace retained harness files during index export * perf(ci): restore exact caches on hybrid runners * fix(ci): include pnpm metadata in dependency archives * test(ci): own direct compiler checkpoints in dist fixtures * perf(ci): balance Windows projects by selected test costs * perf(ci): seed UI transforms and scope tooling prerequisites Keep package timeout observations joined across PID discovery, and test planner measurements against stable fixtures while preserving actual runtime-build singleton costs. * docs(ci): drop the note for the already-landed Telegram type fix * perf(ci): reuse preflight checkout and route hybrid macOS * test(ci): wait for command readiness before timeout proof
111 lines
2.9 KiB
JavaScript
111 lines
2.9 KiB
JavaScript
// Resolves the diff base for merge commits when first-parent comparison is requested.
|
|
import { execFileSync } from "node:child_process";
|
|
import { pathToFileURL } from "node:url";
|
|
import { requireOptionArgument } from "./arg-utils.runtime.mjs";
|
|
|
|
const DEFAULT_GIT_OUTPUT_MAX_BUFFER = 16 * 1024 * 1024;
|
|
|
|
/**
|
|
* Resolve the git base ref to use when diffing a merge head.
|
|
* @param {{base: string, head?: string, cwd?: string, maxBuffer?: number, preferFirstParent?: boolean}} params
|
|
* @returns {string}
|
|
*/
|
|
export function resolveMergeHeadDiffBase({
|
|
base,
|
|
head = "HEAD",
|
|
cwd = process.cwd(),
|
|
maxBuffer = DEFAULT_GIT_OUTPUT_MAX_BUFFER,
|
|
preferFirstParent = false,
|
|
}) {
|
|
if (!base) {
|
|
return "";
|
|
}
|
|
if (!preferFirstParent) {
|
|
return base;
|
|
}
|
|
|
|
const parents = listCommitParents({ ref: head, cwd, maxBuffer });
|
|
if (parents.length < 2) {
|
|
return base;
|
|
}
|
|
|
|
// The merge parent is authoritative. Resolving a stale base in a partial
|
|
// clone can fetch unrelated history even when its result is discarded.
|
|
return resolveCommit({ ref: parents[0], cwd, maxBuffer }) || base;
|
|
}
|
|
|
|
/**
|
|
* @param {{ref: string, cwd: string, maxBuffer: number}} params
|
|
* @returns {string[]}
|
|
*/
|
|
function listCommitParents({ ref, cwd, maxBuffer }) {
|
|
try {
|
|
const output = execFileSync("git", ["rev-list", "--parents", "-n", "1", ref], {
|
|
cwd,
|
|
stdio: ["ignore", "pipe", "ignore"],
|
|
encoding: "utf8",
|
|
maxBuffer,
|
|
}).trim();
|
|
return output.split(/\s+/u).slice(1);
|
|
} catch {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {{ref: string, cwd: string, maxBuffer: number}} params
|
|
* @returns {string}
|
|
*/
|
|
function resolveCommit({ ref, cwd, maxBuffer }) {
|
|
try {
|
|
return execFileSync("git", ["rev-parse", "--verify", `${ref}^{commit}`], {
|
|
cwd,
|
|
stdio: ["ignore", "pipe", "ignore"],
|
|
encoding: "utf8",
|
|
maxBuffer,
|
|
}).trim();
|
|
} catch {
|
|
return "";
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @internal Directly tested script implementation detail.
|
|
* @param {readonly string[]} argv
|
|
* @returns {{base: string, head: string, preferFirstParent: boolean}}
|
|
*/
|
|
export function parseArgs(argv) {
|
|
const args = {
|
|
base: "",
|
|
head: "HEAD",
|
|
preferFirstParent: false,
|
|
};
|
|
for (let index = 0; index < argv.length; index += 1) {
|
|
const arg = argv[index];
|
|
if (arg === "--base") {
|
|
args.base = requireOptionArgument(argv, index, "--base");
|
|
index += 1;
|
|
continue;
|
|
}
|
|
if (arg === "--head") {
|
|
args.head = requireOptionArgument(argv, index, "--head");
|
|
index += 1;
|
|
continue;
|
|
}
|
|
if (arg === "--prefer-first-parent") {
|
|
args.preferFirstParent = true;
|
|
}
|
|
}
|
|
return args;
|
|
}
|
|
|
|
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
const args = parseArgs(process.argv.slice(2));
|
|
process.stdout.write(
|
|
`${resolveMergeHeadDiffBase({
|
|
base: args.base,
|
|
head: args.head,
|
|
preferFirstParent: args.preferFirstParent,
|
|
})}\n`,
|
|
);
|
|
}
|