mirror of
https://github.com/morluto/rea
synced 2026-10-25 22:08:11 -04:00
fix(reference): keep unresolved root and Git directory reads as failures
This commit is contained in:
@@ -41,20 +41,20 @@ export const locateReferenceSourceGitDirectory = async (
|
||||
// Derived joins and the Git library normalize paths lexically. Admit the
|
||||
// physical directory first, while the source pointer stays in its file.
|
||||
const gitDirectory = await realpath(selectedGitDirectory);
|
||||
let commonDirectory = gitDirectory;
|
||||
let common: string | undefined;
|
||||
try {
|
||||
const common = (await readText(join(gitDirectory, "commondir"))).replace(
|
||||
common = (await readText(join(gitDirectory, "commondir"))).replace(
|
||||
/\r?\n$/u,
|
||||
"",
|
||||
);
|
||||
if (common.length === 0)
|
||||
throw new Error("Invalid Git common-directory pointer");
|
||||
commonDirectory = await realpath(
|
||||
absoluteCallerPath(common, { cwd: gitDirectory }),
|
||||
);
|
||||
} catch (cause: unknown) {
|
||||
if (!hasCode(cause, "ENOENT")) throw cause;
|
||||
}
|
||||
if (common === "") throw new Error("Invalid Git common-directory pointer");
|
||||
const commonDirectory =
|
||||
common === undefined
|
||||
? gitDirectory
|
||||
: await realpath(absoluteCallerPath(common, { cwd: gitDirectory }));
|
||||
return { repository, gitDirectory, commonDirectory };
|
||||
}
|
||||
};
|
||||
|
||||
@@ -91,6 +91,13 @@ const readSource = async (
|
||||
bytesRead: state.bytesRead,
|
||||
limitations: [PATH_RACE_LIMITATION],
|
||||
};
|
||||
if (traversal.ok && state.rootFailure?.code === "io")
|
||||
return err({
|
||||
tag: "reference-source-reader",
|
||||
code: "io",
|
||||
message: state.rootFailure.message,
|
||||
partial: read,
|
||||
});
|
||||
return traversal.ok ? ok(read) : err({ ...traversal.error, partial: read });
|
||||
};
|
||||
|
||||
|
||||
@@ -155,3 +155,20 @@ it.skipIf(process.platform === "win32")(
|
||||
expect(graph.vcs).toMatchObject({ kind: "git", head: intendedHead });
|
||||
},
|
||||
);
|
||||
|
||||
it("keeps a present but unresolved Git common-directory pointer from selecting private decoy configuration", async () => {
|
||||
const root = await createTestTempDirectory("rea-reference-common-missing-");
|
||||
await mkdir(join(root, ".git"));
|
||||
await writeFile(join(root, ".git", "HEAD"), `${"1".repeat(40)}\n`);
|
||||
await writeFile(join(root, ".git", "config"), "[core]\nignorecase = true\n");
|
||||
await writeFile(join(root, ".git", "commondir"), "../missing-common\n");
|
||||
const result = await importReferenceSource({
|
||||
root,
|
||||
caller: "ignore-policy-test",
|
||||
policy: { secretPatterns: [] },
|
||||
});
|
||||
expect(result).toMatchObject({
|
||||
ok: false,
|
||||
error: { code: "io", message: expect.stringContaining("missing-common") },
|
||||
});
|
||||
});
|
||||
|
||||
@@ -20,6 +20,33 @@ const permissionChecksUnavailable =
|
||||
process.platform === "win32" || process.getuid?.() === 0;
|
||||
|
||||
describe("reference source native unreadable directories", () => {
|
||||
it.skipIf(permissionChecksUnavailable)(
|
||||
"retains a root enumeration IO failure as an error and recovers after permission repair",
|
||||
async () => {
|
||||
const root = await createTestTempDirectory("rea-source-unreadable-root-");
|
||||
await writeFile(join(root, "main.txt"), "root bytes");
|
||||
await chmod(root, 0o100);
|
||||
try {
|
||||
const result = await importTree(root);
|
||||
expect(result).toMatchObject({
|
||||
ok: false,
|
||||
error: {
|
||||
code: "io",
|
||||
message: expect.stringContaining("EACCES"),
|
||||
partial: { rootFailure: { code: "io" } },
|
||||
},
|
||||
});
|
||||
if (!result.ok) expect(result.error.message).toContain(root);
|
||||
} finally {
|
||||
await chmod(root, 0o700);
|
||||
}
|
||||
const recovered = await importTree(root);
|
||||
expect(recovered.ok && recovered.value.entries).toContainEqual(
|
||||
expect.objectContaining({ path: "main.txt", content_state: "hashed" }),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
it.skipIf(permissionChecksUnavailable).each(["blocked", "src/blocked"])(
|
||||
"preserves a partial graph when %s cannot be enumerated",
|
||||
async (blocked) => {
|
||||
|
||||
Reference in New Issue
Block a user