Skip to content

Commit 6350ac7

Browse files
authored
Merge pull request #1888 from github/nora/refactor-githubnwoowner-helper
Extract github url identifier helper
2 parents 22ec4b0 + 7241e31 commit 6350ac7

5 files changed

Lines changed: 150 additions & 83 deletions

File tree

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { OWNER_REGEX, REPO_REGEX } from "../pure/helpers-pure";
2+
3+
/**
4+
* Checks if a string is a valid GitHub NWO.
5+
* @param identifier The GitHub NWO
6+
* @returns
7+
*/
8+
export function validGitHubNwo(identifier: string): boolean {
9+
return validGitHubNwoOrOwner(identifier, "nwo");
10+
}
11+
12+
/**
13+
* Checks if a string is a valid GitHub owner.
14+
* @param identifier The GitHub owner
15+
* @returns
16+
*/
17+
export function validGitHubOwner(identifier: string): boolean {
18+
return validGitHubNwoOrOwner(identifier, "owner");
19+
}
20+
21+
function validGitHubNwoOrOwner(
22+
identifier: string,
23+
kind: "owner" | "nwo",
24+
): boolean {
25+
return kind === "owner"
26+
? OWNER_REGEX.test(identifier)
27+
: REPO_REGEX.test(identifier);
28+
}
29+
30+
/**
31+
* Extracts an NOW from a GitHub URL.
32+
* @param githubUrl The GitHub repository URL
33+
* @return The corresponding NWO, or undefined if the URL is not valid
34+
*/
35+
export function getNwoFromGitHubUrl(githubUrl: string): string | undefined {
36+
return getNwoOrOwnerFromGitHubUrl(githubUrl, "nwo");
37+
}
38+
39+
/**
40+
* Extracts an owner from a GitHub URL.
41+
* @param githubUrl The GitHub repository URL
42+
* @return The corresponding Owner, or undefined if the URL is not valid
43+
*/
44+
export function getOwnerFromGitHubUrl(githubUrl: string): string | undefined {
45+
return getNwoOrOwnerFromGitHubUrl(githubUrl, "owner");
46+
}
47+
48+
function getNwoOrOwnerFromGitHubUrl(
49+
githubUrl: string,
50+
kind: "owner" | "nwo",
51+
): string | undefined {
52+
try {
53+
const uri = new URL(githubUrl);
54+
if (uri.protocol !== "https:") {
55+
return;
56+
}
57+
if (uri.hostname !== "github.com" && uri.hostname !== "www.github.com") {
58+
return;
59+
}
60+
const paths = uri.pathname.split("/").filter((segment: string) => segment);
61+
const owner = `${paths[0]}`;
62+
if (kind === "owner") {
63+
return owner ? owner : undefined;
64+
}
65+
const nwo = `${paths[0]}/${paths[1]}`;
66+
return paths[1] ? nwo : undefined;
67+
} catch (e) {
68+
// Ignore the error here, since we catch failures at a higher level.
69+
return;
70+
}
71+
}

extensions/ql-vscode/src/databaseFetcher.ts

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ import { extLogger } from "./common";
2323
import { Credentials } from "./authentication";
2424
import { getErrorMessage } from "./pure/helpers-pure";
2525
import {
26-
convertGitHubUrlToNwo,
27-
looksLikeGithubRepo,
28-
} from "./databases/github-nwo";
26+
getNwoFromGitHubUrl,
27+
validGitHubNwo,
28+
} from "./common/github-url-identifier-helper";
2929

3030
/**
3131
* Prompts a user to fetch a database from a remote location. Database is assumed to be an archive file.
@@ -100,19 +100,16 @@ export async function promptImportGithubDatabase(
100100
return;
101101
}
102102

103-
if (!looksLikeGithubRepo(githubRepo)) {
103+
const nwo = getNwoFromGitHubUrl(githubRepo) || githubRepo;
104+
if (!validGitHubNwo(nwo)) {
104105
throw new Error(`Invalid GitHub repository: ${githubRepo}`);
105106
}
106107

107108
const octokit = credentials
108109
? await credentials.getOctokit(true)
109110
: new Octokit.Octokit({ retry });
110111

111-
const result = await convertGithubNwoToDatabaseUrl(
112-
githubRepo,
113-
octokit,
114-
progress,
115-
);
112+
const result = await convertGithubNwoToDatabaseUrl(nwo, octokit, progress);
116113
if (!result) {
117114
return;
118115
}
@@ -446,7 +443,7 @@ export async function findDirWithFile(
446443
}
447444

448445
export async function convertGithubNwoToDatabaseUrl(
449-
githubRepo: string,
446+
nwo: string,
450447
octokit: Octokit.Octokit,
451448
progress: ProgressCallback,
452449
): Promise<
@@ -458,7 +455,6 @@ export async function convertGithubNwoToDatabaseUrl(
458455
| undefined
459456
> {
460457
try {
461-
const nwo = convertGitHubUrlToNwo(githubRepo) || githubRepo;
462458
const [owner, repo] = nwo.split("/");
463459

464460
const response = await octokit.request(
@@ -480,7 +476,7 @@ export async function convertGithubNwoToDatabaseUrl(
480476
};
481477
} catch (e) {
482478
void extLogger.log(`Error: ${getErrorMessage(e)}`);
483-
throw new Error(`Unable to get database for '${githubRepo}'`);
479+
throw new Error(`Unable to get database for '${nwo}'`);
484480
}
485481
}
486482

extensions/ql-vscode/src/databases/github-nwo.ts

Lines changed: 0 additions & 51 deletions
This file was deleted.

extensions/ql-vscode/src/vscode-tests/no-workspace/databaseFetcher.test.ts

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {
88
findDirWithFile,
99
} from "../../databaseFetcher";
1010
import * as Octokit from "@octokit/rest";
11-
import { looksLikeGithubRepo } from "../../databases/github-nwo";
1211

1312
// These tests make API calls and may need extra time to complete.
1413
jest.setTimeout(10000);
@@ -129,25 +128,6 @@ describe("databaseFetcher", () => {
129128
});
130129
});
131130

132-
describe("looksLikeGithubRepo", () => {
133-
it("should handle invalid urls", () => {
134-
expect(looksLikeGithubRepo("")).toBe(false);
135-
expect(looksLikeGithubRepo("http://github.com/foo/bar")).toBe(false);
136-
expect(looksLikeGithubRepo("https://ww.github.com/foo/bar")).toBe(false);
137-
expect(looksLikeGithubRepo("https://ww.github.com/foo")).toBe(false);
138-
expect(looksLikeGithubRepo("foo")).toBe(false);
139-
});
140-
141-
it("should handle valid urls", () => {
142-
expect(looksLikeGithubRepo("https://github.com/foo/bar")).toBe(true);
143-
expect(looksLikeGithubRepo("https://www.github.com/foo/bar")).toBe(true);
144-
expect(looksLikeGithubRepo("https://github.com/foo/bar/sub/pages")).toBe(
145-
true,
146-
);
147-
expect(looksLikeGithubRepo("foo/bar")).toBe(true);
148-
});
149-
});
150-
151131
describe("findDirWithFile", () => {
152132
let dir: tmp.DirResult;
153133
beforeEach(() => {
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import {
2+
getNwoFromGitHubUrl,
3+
getOwnerFromGitHubUrl,
4+
validGitHubNwo,
5+
validGitHubOwner,
6+
} from "../../../src/common/github-url-identifier-helper";
7+
8+
describe("github url identifier helper", () => {
9+
describe("valid GitHub Nwo Or Owner method", () => {
10+
it("should return true for valid owner", () => {
11+
expect(validGitHubOwner("github")).toBe(true);
12+
});
13+
it("should return true for valid NWO", () => {
14+
expect(validGitHubNwo("github/codeql")).toBe(true);
15+
});
16+
it("should return false for invalid owner", () => {
17+
expect(validGitHubOwner("github/codeql")).toBe(false);
18+
});
19+
it("should return false for invalid NWO", () => {
20+
expect(validGitHubNwo("githubl")).toBe(false);
21+
});
22+
});
23+
24+
describe("getNwoFromGitHubUrl method", () => {
25+
it("should handle invalid urls", () => {
26+
expect(getNwoFromGitHubUrl("")).toBe(undefined);
27+
expect(getNwoFromGitHubUrl("http://github.com/foo/bar")).toBe(undefined);
28+
expect(getNwoFromGitHubUrl("https://ww.github.com/foo/bar")).toBe(
29+
undefined,
30+
);
31+
expect(getNwoFromGitHubUrl("https://www.github.com/foo")).toBe(undefined);
32+
expect(getNwoFromGitHubUrl("foo")).toBe(undefined);
33+
expect(getNwoFromGitHubUrl("foo/bar")).toBe(undefined);
34+
});
35+
36+
it("should handle valid urls", () => {
37+
expect(getNwoFromGitHubUrl("https://github.com/foo/bar")).toBe("foo/bar");
38+
expect(getNwoFromGitHubUrl("https://www.github.com/foo/bar")).toBe(
39+
"foo/bar",
40+
);
41+
expect(getNwoFromGitHubUrl("https://github.com/foo/bar/sub/pages")).toBe(
42+
"foo/bar",
43+
);
44+
});
45+
});
46+
47+
describe("getOwnerFromGitHubUrl method", () => {
48+
it("should handle invalid urls", () => {
49+
expect(getOwnerFromGitHubUrl("")).toBe(undefined);
50+
expect(getOwnerFromGitHubUrl("http://github.com/foo/bar")).toBe(
51+
undefined,
52+
);
53+
expect(getOwnerFromGitHubUrl("https://ww.github.com/foo/bar")).toBe(
54+
undefined,
55+
);
56+
expect(getOwnerFromGitHubUrl("foo")).toBe(undefined);
57+
expect(getOwnerFromGitHubUrl("foo/bar")).toBe(undefined);
58+
});
59+
60+
it("should handle valid urls", () => {
61+
expect(getOwnerFromGitHubUrl("https://github.com/foo/bar")).toBe("foo");
62+
expect(getOwnerFromGitHubUrl("https://www.github.com/foo/bar")).toBe(
63+
"foo",
64+
);
65+
expect(
66+
getOwnerFromGitHubUrl("https://github.com/foo/bar/sub/pages"),
67+
).toBe("foo");
68+
expect(getOwnerFromGitHubUrl("https://www.github.com/foo")).toBe("foo");
69+
});
70+
});
71+
});

0 commit comments

Comments
 (0)