From 8d69da902e3da6c8d555cb2cb9a96efca8ab2b76 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 23 Jun 2026 18:42:43 +0100 Subject: [PATCH] Improve whitespace handling --- lib/entry-points.js | 16 +++++++----- src/config/remote-file.test.ts | 48 ++++++++++++++++++++++++++++++++++ src/config/remote-file.ts | 18 ++++++++----- 3 files changed, 70 insertions(+), 12 deletions(-) diff --git a/lib/entry-points.js b/lib/entry-points.js index 05a52df4a..dff19f1be 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -151452,21 +151452,25 @@ function parseRemoteFileAddress(env, configFile) { "^((?[^/]+)/)?(?[^/@]+)(/(?[^@]+))?(@(?.*))?$" ); const pieces = format.exec(configFile.trim()); - if (!pieces?.groups?.repo || pieces.groups.repo.trim().length === 0) { + const repo = pieces?.groups?.repo?.trim(); + if (!pieces?.groups || !repo || repo.length === 0) { throw new ConfigurationError( getConfigFileRepoFormatInvalidMessage(configFile) ); } - if (pieces.groups.path?.startsWith("/")) { + const owner = pieces.groups.owner?.trim(); + const path29 = pieces.groups.path?.trim(); + const ref = pieces.groups.ref?.trim(); + if (path29?.startsWith("/")) { throw new ConfigurationError( `The path component of '${configFile}' cannot be an absolute path.` ); } return { - owner: pieces.groups.owner || getDefaultOwner(env), - repo: pieces.groups.repo.trim(), - path: pieces.groups.path || DEFAULT_CONFIG_FILE_NAME, - ref: pieces.groups.ref || DEFAULT_CONFIG_FILE_REF + owner: owner || getDefaultOwner(env), + repo, + path: path29 || DEFAULT_CONFIG_FILE_NAME, + ref: ref || DEFAULT_CONFIG_FILE_REF }; } diff --git a/src/config/remote-file.test.ts b/src/config/remote-file.test.ts index 1d4ed1f72..36b68fd55 100644 --- a/src/config/remote-file.test.ts +++ b/src/config/remote-file.test.ts @@ -22,6 +22,48 @@ test("parseRemoteFileAddress accepts full remote addresses", async (t) => { ref: "ref", } satisfies RemoteFileAddress); + t.deepEqual(parseRemoteFileAddress(env, "owner /repo/path@ref"), { + owner: "owner", + repo: "repo", + path: "path", + ref: "ref", + } satisfies RemoteFileAddress); + + t.deepEqual(parseRemoteFileAddress(env, "owner/ repo/path@ref"), { + owner: "owner", + repo: "repo", + path: "path", + ref: "ref", + } satisfies RemoteFileAddress); + + t.deepEqual(parseRemoteFileAddress(env, "owner/repo /path@ref"), { + owner: "owner", + repo: "repo", + path: "path", + ref: "ref", + } satisfies RemoteFileAddress); + + t.deepEqual(parseRemoteFileAddress(env, "owner/repo/ path@ref"), { + owner: "owner", + repo: "repo", + path: "path", + ref: "ref", + } satisfies RemoteFileAddress); + + t.deepEqual(parseRemoteFileAddress(env, "owner/repo/path @ref"), { + owner: "owner", + repo: "repo", + path: "path", + ref: "ref", + } satisfies RemoteFileAddress); + + t.deepEqual(parseRemoteFileAddress(env, "owner/repo/path@ ref"), { + owner: "owner", + repo: "repo", + path: "path", + ref: "ref", + } satisfies RemoteFileAddress); + t.deepEqual( parseRemoteFileAddress(env, "owner/repo/path/to/codeql.yml@ref/feature"), { @@ -129,4 +171,10 @@ test("parseRemoteFileAddress rejects invalid values", async (t) => { t.throws(() => parseRemoteFileAddress(env, "repo//absolute"), { instanceOf: ConfigurationError, }); + t.throws(() => parseRemoteFileAddress(env, "/repo@ref"), { + instanceOf: ConfigurationError, + }); + t.throws(() => parseRemoteFileAddress(env, " /repo@ref"), { + instanceOf: ConfigurationError, + }); }); diff --git a/src/config/remote-file.ts b/src/config/remote-file.ts index c2303417e..a4f8ea890 100644 --- a/src/config/remote-file.ts +++ b/src/config/remote-file.ts @@ -55,24 +55,30 @@ export function parseRemoteFileAddress( ); const pieces = format.exec(configFile.trim()); + const repo: string | undefined = pieces?.groups?.repo?.trim(); + // Check that the regular expression matched and that we have at least the repo name. - if (!pieces?.groups?.repo || pieces.groups.repo.trim().length === 0) { + if (!pieces?.groups || !repo || repo.length === 0) { throw new ConfigurationError( errorMessages.getConfigFileRepoFormatInvalidMessage(configFile), ); } + const owner: string | undefined = pieces.groups.owner?.trim(); + const path: string | undefined = pieces.groups.path?.trim(); + const ref: string | undefined = pieces.groups.ref?.trim(); + // Ensure that the path is a relative path. - if (pieces.groups.path?.startsWith("/")) { + if (path?.startsWith("/")) { throw new ConfigurationError( `The path component of '${configFile}' cannot be an absolute path.`, ); } return { - owner: pieces.groups.owner || getDefaultOwner(env), - repo: pieces.groups.repo.trim(), - path: pieces.groups.path || DEFAULT_CONFIG_FILE_NAME, - ref: pieces.groups.ref || DEFAULT_CONFIG_FILE_REF, + owner: owner || getDefaultOwner(env), + repo, + path: path || DEFAULT_CONFIG_FILE_NAME, + ref: ref || DEFAULT_CONFIG_FILE_REF, }; }