Add support for SHA-256 Git object IDs

This commit is contained in:
Henry Mercer
2026-05-12 18:24:21 +01:00
parent b62aaa99a5
commit 6a4e35fad9
12 changed files with 101 additions and 18 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ See the [releases page](https://github.com/github/codeql-action/releases) for th
## [UNRELEASED]
No user facing changes.
- Add support for SHA-256 Git object IDs. [#3893](https://github.com/github/codeql-action/pull/3893)
## 4.35.4 - 07 May 2026
+1 -1
View File
@@ -127527,7 +127527,7 @@ var getFileOidsUnderPath = async function(basePath) {
"Cannot list Git OIDs of tracked files."
);
const fileOidMap = {};
const regex = /^[0-9]+ ([0-9a-f]{40}) [0-9]+\t(.+)$/;
const regex = /^[0-9]+ ([0-9a-f]{40}(?:[a-f0-9]{24})?) [0-9]+\t(.+)$/;
for (const line of stdout.split("\n")) {
if (line) {
const match = line.match(regex);
+2 -2
View File
@@ -89819,7 +89819,7 @@ var determineBaseBranchHeadCommitOid = async function(checkoutPathOverride) {
}
}
}
if (commitOid === mergeSha && headOid.length === 40 && baseOid.length === 40) {
if (commitOid === mergeSha && (headOid.length === 40 || headOid.length === 64) && (baseOid.length === 40 || baseOid.length === 64)) {
return baseOid;
}
return void 0;
@@ -89885,7 +89885,7 @@ var getFileOidsUnderPath = async function(basePath) {
"Cannot list Git OIDs of tracked files."
);
const fileOidMap = {};
const regex = /^[0-9]+ ([0-9a-f]{40}) [0-9]+\t(.+)$/;
const regex = /^[0-9]+ ([0-9a-f]{40}(?:[a-f0-9]{24})?) [0-9]+\t(.+)$/;
for (const line of stdout.split("\n")) {
if (line) {
const match = line.match(regex);
+1 -1
View File
@@ -86338,7 +86338,7 @@ var getFileOidsUnderPath = async function(basePath) {
"Cannot list Git OIDs of tracked files."
);
const fileOidMap = {};
const regex = /^[0-9]+ ([0-9a-f]{40}) [0-9]+\t(.+)$/;
const regex = /^[0-9]+ ([0-9a-f]{40}(?:[a-f0-9]{24})?) [0-9]+\t(.+)$/;
for (const line of stdout.split("\n")) {
if (line) {
const match = line.match(regex);
+2 -2
View File
@@ -130981,7 +130981,7 @@ var determineBaseBranchHeadCommitOid = async function(checkoutPathOverride) {
}
}
}
if (commitOid === mergeSha && headOid.length === 40 && baseOid.length === 40) {
if (commitOid === mergeSha && (headOid.length === 40 || headOid.length === 64) && (baseOid.length === 40 || baseOid.length === 64)) {
return baseOid;
}
return void 0;
@@ -131047,7 +131047,7 @@ var getFileOidsUnderPath = async function(basePath) {
"Cannot list Git OIDs of tracked files."
);
const fileOidMap = {};
const regex = /^[0-9]+ ([0-9a-f]{40}) [0-9]+\t(.+)$/;
const regex = /^[0-9]+ ([0-9a-f]{40}(?:[a-f0-9]{24})?) [0-9]+\t(.+)$/;
for (const line of stdout.split("\n")) {
if (line) {
const match = line.match(regex);
+1 -1
View File
@@ -87416,7 +87416,7 @@ var getFileOidsUnderPath = async function(basePath) {
"Cannot list Git OIDs of tracked files."
);
const fileOidMap = {};
const regex = /^[0-9]+ ([0-9a-f]{40}) [0-9]+\t(.+)$/;
const regex = /^[0-9]+ ([0-9a-f]{40}(?:[a-f0-9]{24})?) [0-9]+\t(.+)$/;
for (const line of stdout.split("\n")) {
if (line) {
const match = line.match(regex);
+1 -1
View File
@@ -86331,7 +86331,7 @@ var getFileOidsUnderPath = async function(basePath) {
"Cannot list Git OIDs of tracked files."
);
const fileOidMap = {};
const regex = /^[0-9]+ ([0-9a-f]{40}) [0-9]+\t(.+)$/;
const regex = /^[0-9]+ ([0-9a-f]{40}(?:[a-f0-9]{24})?) [0-9]+\t(.+)$/;
for (const line of stdout.split("\n")) {
if (line) {
const match = line.match(regex);
+1 -1
View File
@@ -86179,7 +86179,7 @@ var getFileOidsUnderPath = async function(basePath) {
"Cannot list Git OIDs of tracked files."
);
const fileOidMap = {};
const regex = /^[0-9]+ ([0-9a-f]{40}) [0-9]+\t(.+)$/;
const regex = /^[0-9]+ ([0-9a-f]{40}(?:[a-f0-9]{24})?) [0-9]+\t(.+)$/;
for (const line of stdout.split("\n")) {
if (line) {
const match = line.match(regex);
+2 -2
View File
@@ -89427,7 +89427,7 @@ var determineBaseBranchHeadCommitOid = async function(checkoutPathOverride) {
}
}
}
if (commitOid === mergeSha && headOid.length === 40 && baseOid.length === 40) {
if (commitOid === mergeSha && (headOid.length === 40 || headOid.length === 64) && (baseOid.length === 40 || baseOid.length === 64)) {
return baseOid;
}
return void 0;
@@ -89493,7 +89493,7 @@ var getFileOidsUnderPath = async function(basePath) {
"Cannot list Git OIDs of tracked files."
);
const fileOidMap = {};
const regex = /^[0-9]+ ([0-9a-f]{40}) [0-9]+\t(.+)$/;
const regex = /^[0-9]+ ([0-9a-f]{40}(?:[a-f0-9]{24})?) [0-9]+\t(.+)$/;
for (const line of stdout.split("\n")) {
if (line) {
const match = line.match(regex);
+2 -2
View File
@@ -89098,7 +89098,7 @@ var determineBaseBranchHeadCommitOid = async function(checkoutPathOverride) {
}
}
}
if (commitOid === mergeSha && headOid.length === 40 && baseOid.length === 40) {
if (commitOid === mergeSha && (headOid.length === 40 || headOid.length === 64) && (baseOid.length === 40 || baseOid.length === 64)) {
return baseOid;
}
return void 0;
@@ -89164,7 +89164,7 @@ var getFileOidsUnderPath = async function(basePath) {
"Cannot list Git OIDs of tracked files."
);
const fileOidMap = {};
const regex = /^[0-9]+ ([0-9a-f]{40}) [0-9]+\t(.+)$/;
const regex = /^[0-9]+ ([0-9a-f]{40}(?:[a-f0-9]{24})?) [0-9]+\t(.+)$/;
for (const line of stdout.split("\n")) {
if (line) {
const match = line.match(regex);
+81
View File
@@ -305,6 +305,29 @@ test.serial("determineBaseBranchHeadCommitOid other error", async (t) => {
infoStub.restore();
});
test.serial(
"determineBaseBranchHeadCommitOid accepts SHA-256 OIDs",
async (t) => {
const mergeSha = "a".repeat(64);
const baseOid = "b".repeat(64);
const headOid = "c".repeat(64);
process.env["GITHUB_EVENT_NAME"] = "pull_request";
process.env["GITHUB_SHA"] = mergeSha;
const runGitCommandStub = sinon
.stub(gitUtils as any, "runGitCommand")
.resolves(`commit ${mergeSha}\nparent ${baseOid}\nparent ${headOid}\n`);
try {
const result = await gitUtils.determineBaseBranchHeadCommitOid(__dirname);
t.deepEqual(result, baseOid);
} finally {
runGitCommandStub.restore();
}
},
);
test.serial("decodeGitFilePath unquoted strings", async (t) => {
t.deepEqual(gitUtils.decodeGitFilePath("foo"), "foo");
t.deepEqual(gitUtils.decodeGitFilePath("foo bar"), "foo bar");
@@ -436,6 +459,64 @@ test.serial("getFileOidsUnderPath handles quoted paths", async (t) => {
});
});
test.serial("getFileOidsUnderPath handles SHA-256 OIDs", async (t) => {
await withTmpDir(async (tmpDir) => {
const sha256OidA =
"9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2c0d4b7e8f9a1234567890ab";
const sha256OidB =
"aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899";
sinon
.stub(gitUtils as any, "runGitCommand")
.callsFake(async (_cwd: any, args: any) => {
if (args[0] === "rev-parse") {
return `${tmpDir}\n`;
}
return (
`100644 ${sha256OidA} 0\tlib/sha256-file-a.js\n` +
`100644 ${sha256OidB} 0\tsrc/sha256-file-b.ts`
);
});
const result = await gitUtils.getFileOidsUnderPath("/fake/path");
t.deepEqual(result, {
"lib/sha256-file-a.js": sha256OidA,
"src/sha256-file-b.ts": sha256OidB,
});
});
});
test.serial(
"getFileOidsUnderPath rejects OIDs of unsupported length",
async (t) => {
await withTmpDir(async (tmpDir) => {
// 50-char OID: not a valid SHA-1 (40) or SHA-256 (64) length. The regex
// must not accept this even though every character is a valid hex digit.
const invalidLine =
"100644 30d998ded095371488be3a729eb61d86ed721a1830d998ded0 0\tlib/bad.js";
sinon
.stub(gitUtils as any, "runGitCommand")
.callsFake(async (_cwd: any, args: any) => {
if (args[0] === "rev-parse") {
return `${tmpDir}\n`;
}
return invalidLine;
});
await t.throwsAsync(
async () => {
await gitUtils.getFileOidsUnderPath("/fake/path");
},
{
instanceOf: Error,
message: `Unexpected "git ls-files" output: ${invalidLine}`,
},
);
});
},
);
test.serial("getFileOidsUnderPath handles empty output", async (t) => {
await withTmpDir(async (tmpDir) => {
sinon
+6 -4
View File
@@ -163,11 +163,12 @@ export const determineBaseBranchHeadCommitOid = async function (
}
}
// Let's confirm our assumptions: We had a merge commit and the parsed parent data looks correct
// Let's confirm our assumptions: We had a merge commit and the parsed parent
// data looks correct. OIDs are either 40 (SHA-1) or 64 (SHA-256) hex characters.
if (
commitOid === mergeSha &&
headOid.length === 40 &&
baseOid.length === 40
(headOid.length === 40 || headOid.length === 64) &&
(baseOid.length === 40 || baseOid.length === 64)
) {
return baseOid;
}
@@ -296,7 +297,8 @@ export const getFileOidsUnderPath = async function (
// 100644 4c51bc1d9e86cd86e01b0f340cb8ce095c33b283 0\tsrc/git-utils.test.ts
// 100644 6b792ea543ce75d7a8a03df591e3c85311ecb64f 0\tsrc/git-utils.ts
// The fields are: <mode> <oid> <stage>\t<path>
const regex = /^[0-9]+ ([0-9a-f]{40}) [0-9]+\t(.+)$/;
// The OID is either 40 (SHA-1) or 64 (SHA-256) hex characters.
const regex = /^[0-9]+ ([0-9a-f]{40}(?:[a-f0-9]{24})?) [0-9]+\t(.+)$/;
for (const line of stdout.split("\n")) {
if (line) {
const match = line.match(regex);