openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
393 lines (392 loc) • 13.2 kB
JavaScript
import { r as isMissingPathError } from "./errno-FR4CRyya.mjs";
import "./errors-BvOkmQM5.mjs";
import { t as unquoteGitPath } from "./git-path-quote-DUm87W5B.mjs";
import fs from "node:fs";
import path from "node:path";
import { readFileDescriptorBoundedSync, readFileWindowFullySync } from "@openclaw/fs-safe/advanced";
import { safeStatSync } from "@openclaw/fs-safe/path";
import { isUtf8 } from "node:buffer";
//#region src/infra/git-root.ts
function walkUpFrom(startDir, opts, resolveAtDir) {
let current = path.resolve(startDir);
for (let i = 0; opts.maxDepth === void 0 || i < opts.maxDepth; i += 1) {
const resolved = resolveAtDir(current);
if (resolved !== null && resolved !== void 0) return resolved;
const parent = path.dirname(current);
if (parent === current) break;
current = parent;
}
return null;
}
function hasGitMarker(repoRoot) {
const stat = safeStatSync(path.join(repoRoot, ".git"));
return stat ? stat.isDirectory() || stat.isFile() : false;
}
function findGitRoot(startDir, opts = {}) {
return walkUpFrom(startDir, opts, (repoRoot) => hasGitMarker(repoRoot) ? repoRoot : null);
}
function readGitMetadataFile(filePath, limit = 1048576) {
const fd = fs.openSync(filePath, fs.constants.O_RDONLY | (fs.constants.O_NONBLOCK ?? 0));
try {
const stat = fs.fstatSync(fd);
if (!stat.isFile() || stat.size > limit) throw new Error("Git metadata is not a bounded regular file");
const bytes = readFileDescriptorBoundedSync(fd, Math.min(stat.size, limit));
if (bytes.length !== stat.size) throw new Error("Git metadata changed during its read");
return bytes;
} finally {
fs.closeSync(fd);
}
}
function readGitDirectoryPointerTarget(filePath, prefix = "") {
const bytes = readGitMetadataFile(filePath);
const raw = bytes.toString("utf8").replace(/[\r\n]+$/u, "");
if (!isUtf8(bytes) || !raw.startsWith(prefix) || raw.length === prefix.length || raw.includes("\0")) throw new Error("Git directory pointer is incomplete or malformed");
const target = raw.slice(prefix.length);
return path.isAbsolute(target) ? target : `${path.dirname(filePath)}${path.sep}${target}`;
}
function readGitDirectoryPointer(filePath, prefix = "") {
return fs.realpathSync.native(readGitDirectoryPointerTarget(filePath, prefix));
}
/** A lookup needs its aliases too: unlinking a traversed symlink can strand an outside target. */
function resolveGitStoragePath(target, paths, assertBudget) {
assertBudget();
const raw = path.isAbsolute(target) ? target : `${process.cwd()}${path.sep}${target}`;
paths.add(raw);
let canonical;
try {
canonical = fs.realpathSync.native(raw);
paths.add(canonical);
} catch {}
if (raw === canonical) return canonical;
const components = (value) => value.slice(path.parse(value).root.length).split(process.platform === "win32" ? /[\\/]/u : /\//u);
const pending = components(raw).toReversed();
let current = path.parse(raw).root;
let symlinks = 0;
while (pending.length > 0) {
assertBudget();
const component = pending.pop();
if (!component || component === ".") continue;
if (component === "..") {
current = path.dirname(current);
continue;
}
const lookup = path.join(current, component);
paths.add(lookup);
try {
if (fs.lstatSync(lookup).isSymbolicLink()) {
if (++symlinks > 40) return;
const link = fs.readlinkSync(lookup);
if (path.isAbsolute(link)) current = path.parse(link).root;
pending.push(...components(link).toReversed());
} else current = fs.realpathSync.native(lookup);
} catch {
return;
}
}
return current === canonical ? canonical : void 0;
}
function resolveGitDirFromMarker(repoRoot) {
const gitPath = path.join(repoRoot, ".git");
try {
const stat = fs.statSync(gitPath);
if (stat.isDirectory()) return gitPath;
if (!stat.isFile()) return null;
return readGitDirectoryPointer(gitPath, "gitdir: ");
} catch {
return null;
}
}
/** Resolve storage at an exact root; fleet callers run this uncached census in a worker. */
function readGitMetadataDirectories(repoRoot, assertBudget = () => {}) {
const paths = /* @__PURE__ */ new Set();
const root = resolveGitStoragePath(repoRoot, paths, assertBudget);
if (!root) return;
const marker = path.join(root, ".git");
let markerStat;
let commonMarkerExists;
let directory;
try {
markerStat = fs.lstatSync(marker, { throwIfNoEntry: false });
} catch {
return;
}
if (markerStat) {
const physicalMarker = resolveGitStoragePath(marker, paths, assertBudget);
if (!physicalMarker) return;
try {
directory = fs.statSync(physicalMarker).isDirectory() ? physicalMarker : readGitDirectoryPointerTarget(marker, "gitdir: ");
} catch {
return;
}
} else {
if (!safeStatSync(path.join(root, "HEAD"))?.isFile() || !safeStatSync(path.join(root, "objects"))?.isDirectory() || !safeStatSync(path.join(root, "refs"))?.isDirectory()) return;
directory = root;
}
const gitDir = resolveGitStoragePath(directory, paths, assertBudget);
if (!gitDir || !safeStatSync(gitDir)?.isDirectory()) return;
const commonMarker = path.join(gitDir, "commondir");
try {
commonMarkerExists = fs.lstatSync(commonMarker, { throwIfNoEntry: false }) !== void 0;
} catch {
return;
}
let commonDir = gitDir;
if (commonMarkerExists) {
if (!resolveGitStoragePath(commonMarker, paths, assertBudget)) return;
let target;
try {
target = readGitDirectoryPointerTarget(commonMarker);
} catch {
return;
}
const resolved = resolveGitStoragePath(target, paths, assertBudget);
if (!resolved || !safeStatSync(resolved)?.isDirectory()) return;
commonDir = resolved;
}
return {
gitDir,
commonDir,
paths: [...paths]
};
}
function resolveRelativeWorktreePath(base, relative, assertBudget) {
let resolved = base;
const components = relative.split(process.platform === "win32" ? /[\\/]/u : /\//u);
for (const component of components) {
assertBudget();
if (!component || component === ".") continue;
if (component === "..") {
resolved = path.dirname(resolved);
continue;
}
const next = path.join(resolved, component);
try {
resolved = fs.realpathSync.native(next);
} catch (error) {
try {
if (!isMissingPathError(error) || fs.lstatSync(next, { throwIfNoEntry: false })) return;
} catch {
return;
}
resolved = next;
}
}
return resolved;
}
/** Native removal owns common/worktrees/<id>, independently of the checkout's .git marker. */
function readGitWorktreeAdministrations(commonDir, assertBudget) {
const entries = [];
const root = path.join(commonDir, "worktrees");
let complete = true;
let directory;
assertBudget();
try {
directory = fs.opendirSync(root);
} catch (error) {
return {
entries,
complete: isMissingPathError(error) && !fs.lstatSync(root, { throwIfNoEntry: false })
};
}
try {
for (;;) {
assertBudget();
let entry;
try {
entry = directory.readSync();
} catch {
complete = false;
break;
}
if (!entry) break;
const adminPath = path.join(root, entry.name);
let backlink;
let physicalAdminPath;
try {
const marker = path.join(adminPath, "gitdir");
if (!fs.lstatSync(marker, { throwIfNoEntry: false })) continue;
const bytes = readGitMetadataFile(marker);
backlink = bytes.toString("utf8").replace(/[\t-\r ]+$/u, "").replace(/\/\.git$/u, "");
if (!backlink || !isUtf8(bytes) || backlink.includes("\0")) {
complete = false;
continue;
}
physicalAdminPath = fs.realpathSync.native(adminPath);
} catch {
complete = false;
continue;
}
const checkoutPath = path.isAbsolute(backlink) ? backlink : resolveRelativeWorktreePath(physicalAdminPath, backlink, assertBudget);
if (!checkoutPath) {
complete = false;
continue;
}
entries.push({
checkoutPath,
adminPath,
physicalAdminPath
});
}
} finally {
directory.closeSync();
}
assertBudget();
return {
entries,
complete
};
}
/** Git's object graph follows only info/alternates; each deletion census reads it anew. */
function readGitObjectStorageDependencies(commonDir, assertBudget) {
const paths = /* @__PURE__ */ new Set();
const visited = /* @__PURE__ */ new Set();
let complete = true;
const visit = (target, depth) => {
assertBudget();
const directory = resolveGitStoragePath(target, paths, assertBudget);
if (!directory) {
complete = false;
return;
}
let bytes;
const marker = path.join(directory, "info", "alternates");
try {
if (!fs.statSync(directory).isDirectory()) {
complete = false;
return;
}
const key = process.platform === "win32" ? directory.toLowerCase() : directory;
if (visited.has(key)) return;
visited.add(key);
if (!fs.lstatSync(marker, { throwIfNoEntry: false })) return;
} catch {
complete = false;
return;
}
const physicalMarker = resolveGitStoragePath(marker, paths, assertBudget);
if (!physicalMarker) {
complete = false;
return;
}
try {
bytes = readGitMetadataFile(physicalMarker);
} catch {
complete = false;
return;
}
assertBudget();
const nul = bytes.indexOf(0);
if (nul >= 0) {
complete = false;
bytes = bytes.subarray(0, nul);
}
if (depth >= 5) return;
for (let offset = 0; offset < bytes.length;) {
assertBudget();
const newline = bytes.indexOf(10, offset);
const lineEnd = newline < 0 ? bytes.length : newline;
const comment = bytes[offset] === 35;
const quoted = comment ? void 0 : unquoteGitPath(bytes, offset);
const entry = quoted?.bytes ?? bytes.subarray(offset, lineEnd);
const end = quoted?.end ?? lineEnd;
offset = end < bytes.length ? end + 1 : end;
if (comment || entry.length === 0) continue;
if (entry.includes(0) || !isUtf8(entry)) {
complete = false;
continue;
}
const pointer = entry.toString("utf8");
visit(path.isAbsolute(pointer) ? pointer : `${directory}${path.sep}${pointer}`, depth + 1);
}
};
visit(path.join(commonDir, "objects"), -1);
assertBudget();
return {
paths: [...paths],
complete
};
}
function resolveGitHeadPath(startDir, opts = {}) {
return walkUpFrom(startDir, opts, (repoRoot) => {
const gitDir = resolveGitDirFromMarker(repoRoot);
return gitDir ? path.join(gitDir, "HEAD") : null;
});
}
/** Read at most `limit` bytes from Git or build metadata. */
function readGitMetadataPrefix(filePath, limit = 256) {
const fd = fs.openSync(filePath, fs.constants.O_RDONLY | (fs.constants.O_NONBLOCK ?? 0));
try {
if (!fs.fstatSync(fd).isFile()) throw new Error("Git metadata is not a regular file");
const buf = Buffer.alloc(limit);
const bytesRead = readFileWindowFullySync(fd, buf, 0);
return buf.subarray(0, bytesRead).toString("utf-8");
} finally {
fs.closeSync(fd);
}
}
function readGitHead(startDir, opts = {}) {
const headPath = resolveGitHeadPath(startDir, opts);
if (!headPath) return;
const head = readGitMetadataFile(headPath).toString("utf8").trim();
if (!head.startsWith("ref:")) return {
headPath,
ref: null,
value: head || null
};
const ref = head.replace(/^ref:\s*/i, "").trim();
const refsBase = resolveGitRefsBase(headPath);
return {
headPath,
ref,
value: readGitRefs(refsBase, [ref]).get(ref) ?? null,
refsBase
};
}
function resolveGitRefsBase(headPath) {
const gitDir = path.dirname(headPath);
const marker = path.join(gitDir, "commondir");
try {
return readGitDirectoryPointer(marker);
} catch (error) {
if (!isMissingPathError(error) || fs.lstatSync(marker, { throwIfNoEntry: false })) throw error;
}
return gitDir;
}
/** Raw ref contents, sharing one packed inventory across the requested names. */
function readGitRefs(refsBase, refs) {
const values = new Map(refs.map((ref) => [ref, null]));
const missing = /* @__PURE__ */ new Set();
for (const ref of refs) {
const refPath = resolveRefPath(refsBase, ref);
if (!refPath) continue;
try {
values.set(ref, readGitMetadataPrefix(refPath).trim());
} catch (error) {
if (!isMissingPathError(error)) throw error;
missing.add(ref);
}
}
if (missing.size === 0) return values;
try {
const packedRefs = readGitMetadataFile(path.join(refsBase, "packed-refs"), Number.MAX_SAFE_INTEGER).toString("utf8");
for (const line of packedRefs.split("\n")) {
if (!line || line.startsWith("#") || line.startsWith("^")) continue;
const [value, packedRef] = line.trim().split(/\s+/, 2);
if (packedRef && missing.delete(packedRef)) values.set(packedRef, value ?? null);
}
} catch (error) {
if (!isMissingPathError(error)) throw error;
}
return values;
}
/** Safely resolve a Git ref path, rejecting traversal from a crafted HEAD file. */
function resolveRefPath(refsBase, ref) {
if (!ref.startsWith("refs/")) return null;
if (ref.split(/[/]/).includes("..")) return null;
const resolved = path.resolve(refsBase, ref);
const rel = path.relative(refsBase, resolved);
if (!rel || rel.startsWith("..") || path.isAbsolute(rel)) return null;
return resolved;
}
//#endregion
export { readGitMetadataPrefix as a, readGitWorktreeAdministrations as c, readGitMetadataFile as i, resolveGitRefsBase as l, readGitHead as n, readGitObjectStorageDependencies as o, readGitMetadataDirectories as r, readGitRefs as s, findGitRoot as t };