diff --git a/extensions/ql-vscode/media/dark/lgtm-plus.svg b/extensions/ql-vscode/media/dark/lgtm-plus.svg
deleted file mode 100644
index cfa1bb7a9..000000000
--- a/extensions/ql-vscode/media/dark/lgtm-plus.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-
diff --git a/extensions/ql-vscode/media/light/lgtm-plus.svg b/extensions/ql-vscode/media/light/lgtm-plus.svg
deleted file mode 100644
index 4ca2d548f..000000000
--- a/extensions/ql-vscode/media/light/lgtm-plus.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-
diff --git a/extensions/ql-vscode/package.json b/extensions/ql-vscode/package.json
index 6e24d078b..5cd9b16a6 100644
--- a/extensions/ql-vscode/package.json
+++ b/extensions/ql-vscode/package.json
@@ -48,7 +48,6 @@
"onCommand:codeQLDatabases.chooseDatabaseArchive",
"onCommand:codeQLDatabases.chooseDatabaseInternet",
"onCommand:codeQLDatabases.chooseDatabaseGithub",
- "onCommand:codeQLDatabases.chooseDatabaseLgtm",
"onCommand:codeQL.setCurrentDatabase",
"onCommand:codeQL.viewAst",
"onCommand:codeQL.viewCfg",
@@ -58,7 +57,6 @@
"onCommand:codeQL.chooseDatabaseArchive",
"onCommand:codeQL.chooseDatabaseInternet",
"onCommand:codeQL.chooseDatabaseGithub",
- "onCommand:codeQL.chooseDatabaseLgtm",
"onCommand:codeQLDatabases.chooseDatabase",
"onCommand:codeQLDatabases.setCurrentDatabase",
"onCommand:codeQLDatabasesExperimental.openConfigFile",
@@ -410,14 +408,6 @@
"dark": "media/dark/github.svg"
}
},
- {
- "command": "codeQLDatabases.chooseDatabaseLgtm",
- "title": "Download from LGTM",
- "icon": {
- "light": "media/light/lgtm-plus.svg",
- "dark": "media/dark/lgtm-plus.svg"
- }
- },
{
"command": "codeQL.setCurrentDatabase",
"title": "CodeQL: Set Current Database"
@@ -486,10 +476,6 @@
"command": "codeQL.chooseDatabaseGithub",
"title": "CodeQL: Download Database from GitHub"
},
- {
- "command": "codeQL.chooseDatabaseLgtm",
- "title": "CodeQL: Download Database from LGTM"
- },
{
"command": "codeQLDatabases.sortByName",
"title": "Sort by Name",
@@ -728,11 +714,6 @@
"when": "view == codeQLDatabases",
"group": "navigation"
},
- {
- "command": "codeQLDatabases.chooseDatabaseLgtm",
- "when": "config.codeQL.canary && view == codeQLDatabases",
- "group": "navigation"
- },
{
"command": "codeQLQueryHistory.openQuery",
"when": "view == codeQLQueryHistory",
@@ -997,10 +978,6 @@
"command": "codeQL.viewCfg",
"when": "resourceScheme == codeql-zip-archive && config.codeQL.canary"
},
- {
- "command": "codeQL.chooseDatabaseLgtm",
- "when": "config.codeQL.canary"
- },
{
"command": "codeQLDatabasesExperimental.openConfigFile",
"when": "false"
@@ -1061,10 +1038,6 @@
"command": "codeQLDatabases.chooseDatabaseGithub",
"when": "false"
},
- {
- "command": "codeQLDatabases.chooseDatabaseLgtm",
- "when": "false"
- },
{
"command": "codeQLDatabases.upgradeDatabase",
"when": "false"
diff --git a/extensions/ql-vscode/src/databaseFetcher.ts b/extensions/ql-vscode/src/databaseFetcher.ts
index 8c5b55425..f3d46e370 100644
--- a/extensions/ql-vscode/src/databaseFetcher.ts
+++ b/extensions/ql-vscode/src/databaseFetcher.ts
@@ -153,74 +153,6 @@ export async function promptImportGithubDatabase(
return;
}
-/**
- * Prompts a user to fetch a database from lgtm.
- * User enters a project url and then the user is asked which language
- * to download (if there is more than one)
- *
- * @param databaseManager the DatabaseManager
- * @param storagePath where to store the unzipped database.
- */
-export async function promptImportLgtmDatabase(
- databaseManager: DatabaseManager,
- storagePath: string,
- progress: ProgressCallback,
- token: CancellationToken,
- cli?: CodeQLCliServer,
-): Promise {
- progress({
- message: "Choose project",
- step: 1,
- maxStep: 2,
- });
- const lgtmUrl = await window.showInputBox({
- prompt:
- "Enter the project slug or URL on LGTM (e.g., g/github/codeql or https://lgtm.com/projects/g/github/codeql)",
- });
- if (!lgtmUrl) {
- return;
- }
-
- if (looksLikeLgtmUrl(lgtmUrl)) {
- const databaseUrl = await convertLgtmUrlToDatabaseUrl(lgtmUrl, progress);
- if (databaseUrl) {
- const item = await databaseArchiveFetcher(
- databaseUrl,
- {},
- databaseManager,
- storagePath,
- undefined,
- progress,
- token,
- cli,
- );
- if (item) {
- await commands.executeCommand("codeQLDatabases.focus");
- void showAndLogInformationMessage(
- "Database downloaded and imported successfully.",
- );
- }
- return item;
- }
- } else {
- throw new Error(`Invalid LGTM URL: ${lgtmUrl}`);
- }
- return;
-}
-
-export async function retrieveCanonicalRepoName(lgtmUrl: string) {
- const givenRepoName = extractProjectSlug(lgtmUrl);
- const response = await checkForFailingResponse(
- await fetch(`https://api.github.com/repos/${givenRepoName}`),
- "Failed to locate the repository on github",
- );
- const repo = await response.json();
- if (!repo || !repo.full_name) {
- return;
- }
- return repo.full_name;
-}
-
/**
* Imports a database from a local archive.
*
@@ -552,127 +484,6 @@ export async function convertGithubNwoToDatabaseUrl(
}
}
-/**
- * The URL pattern is https://lgtm.com/projects/{provider}/{org}/{name}/{irrelevant-subpages}.
- * There are several possibilities for the provider: in addition to GitHub.com (g),
- * LGTM currently hosts projects from Bitbucket (b), GitLab (gl) and plain git (git).
- *
- * This function accepts any url that matches the pattern above. It also accepts the
- * raw project slug, e.g., `g/myorg/myproject`
- *
- * After the `{provider}/{org}/{name}` path components, there may be the components
- * related to sub pages.
- *
- * @param lgtmUrl The URL to the lgtm project
- *
- * @return true if this looks like an LGTM project url
- */
-// exported for testing
-export function looksLikeLgtmUrl(
- lgtmUrl: string | undefined,
-): lgtmUrl is string {
- if (!lgtmUrl) {
- return false;
- }
-
- if (convertRawLgtmSlug(lgtmUrl)) {
- return true;
- }
-
- try {
- const uri = Uri.parse(lgtmUrl, true);
- if (uri.scheme !== "https") {
- return false;
- }
-
- if (uri.authority !== "lgtm.com" && uri.authority !== "www.lgtm.com") {
- return false;
- }
-
- const paths = uri.path.split("/").filter((segment: string) => segment);
- return paths.length >= 4 && paths[0] === "projects";
- } catch (e) {
- return false;
- }
-}
-
-function convertRawLgtmSlug(maybeSlug: string): string | undefined {
- if (!maybeSlug) {
- return;
- }
- const segments = maybeSlug.split("/");
- const providers = ["g", "gl", "b", "git"];
- if (segments.length === 3 && providers.includes(segments[0])) {
- return `https://lgtm.com/projects/${maybeSlug}`;
- }
- return;
-}
-
-function extractProjectSlug(lgtmUrl: string): string | undefined {
- // Only matches the '/g/' provider (github)
- const re = new RegExp("https://lgtm.com/projects/g/(.*[^/])");
- const match = lgtmUrl.match(re);
- if (!match) {
- return;
- }
- return match[1];
-}
-
-// exported for testing
-export async function convertLgtmUrlToDatabaseUrl(
- lgtmUrl: string,
- progress: ProgressCallback,
-) {
- try {
- lgtmUrl = convertRawLgtmSlug(lgtmUrl) || lgtmUrl;
- let projectJson = await downloadLgtmProjectMetadata(lgtmUrl);
-
- if (projectJson.code === 404) {
- // fallback check for github repositories with same name but different case
- // will fail for other providers
- let canonicalName = await retrieveCanonicalRepoName(lgtmUrl);
- if (!canonicalName) {
- throw new Error(`Project was not found at ${lgtmUrl}.`);
- }
- canonicalName = convertRawLgtmSlug(`g/${canonicalName}`);
- projectJson = await downloadLgtmProjectMetadata(canonicalName);
- if (projectJson.code === 404) {
- throw new Error("Failed to download project from LGTM.");
- }
- }
-
- const languages =
- projectJson?.languages?.map(
- (lang: { language: string }) => lang.language,
- ) || [];
-
- const language = await promptForLanguage(languages, progress);
- if (!language) {
- return;
- }
- return `https://lgtm.com/${[
- "api",
- "v1.0",
- "snapshots",
- projectJson.id,
- language,
- ].join("/")}`;
- } catch (e) {
- void extLogger.log(`Error: ${getErrorMessage(e)}`);
- throw new Error(`Invalid LGTM URL: ${lgtmUrl}`);
- }
-}
-
-async function downloadLgtmProjectMetadata(lgtmUrl: string): Promise {
- const uri = Uri.parse(lgtmUrl, true);
- const paths = ["api", "v1.0"]
- .concat(uri.path.split("/").filter((segment: string) => segment))
- .slice(0, 6);
- const projectUrl = `https://lgtm.com/${paths.join("/")}`;
- const projectResponse = await fetch(projectUrl);
- return projectResponse.json();
-}
-
async function promptForLanguage(
languages: string[],
progress: ProgressCallback,
diff --git a/extensions/ql-vscode/src/databases-ui.ts b/extensions/ql-vscode/src/databases-ui.ts
index 0f13731ab..80f7ac2de 100644
--- a/extensions/ql-vscode/src/databases-ui.ts
+++ b/extensions/ql-vscode/src/databases-ui.ts
@@ -33,7 +33,6 @@ import {
importArchiveDatabase,
promptImportGithubDatabase,
promptImportInternetDatabase,
- promptImportLgtmDatabase,
} from "./databaseFetcher";
import { asyncFilter, getErrorMessage } from "./pure/helpers-pure";
import { Credentials } from "./authentication";
@@ -308,15 +307,6 @@ export class DatabaseUI extends DisposableObject {
},
),
);
- this.push(
- commandRunnerWithProgress(
- "codeQLDatabases.chooseDatabaseLgtm",
- this.handleChooseDatabaseLgtm,
- {
- title: "Adding database from LGTM",
- },
- ),
- );
this.push(
commandRunner(
"codeQLDatabases.setCurrentDatabase",
@@ -491,19 +481,6 @@ export class DatabaseUI extends DisposableObject {
);
};
- handleChooseDatabaseLgtm = async (
- progress: ProgressCallback,
- token: CancellationToken,
- ): Promise => {
- return await promptImportLgtmDatabase(
- this.databaseManager,
- this.storagePath,
- progress,
- token,
- this.queryServer?.cliServer,
- );
- };
-
async tryUpgradeCurrentDatabase(
progress: ProgressCallback,
token: CancellationToken,
diff --git a/extensions/ql-vscode/src/extension.ts b/extensions/ql-vscode/src/extension.ts
index 66331dd16..abf49939b 100644
--- a/extensions/ql-vscode/src/extension.ts
+++ b/extensions/ql-vscode/src/extension.ts
@@ -1369,16 +1369,6 @@ async function activateWithInstalledDistribution(
},
),
);
- ctx.subscriptions.push(
- commandRunnerWithProgress(
- "codeQL.chooseDatabaseLgtm",
- (progress: ProgressCallback, token: CancellationToken) =>
- databaseUI.handleChooseDatabaseLgtm(progress, token),
- {
- title: "Adding database from LGTM",
- },
- ),
- );
ctx.subscriptions.push(
commandRunnerWithProgress(
"codeQL.chooseDatabaseInternet",
diff --git a/extensions/ql-vscode/src/vscode-tests/cli-integration/databases.test.ts b/extensions/ql-vscode/src/vscode-tests/cli-integration/databases.test.ts
index 2ecbb9a8c..15fd96e01 100644
--- a/extensions/ql-vscode/src/vscode-tests/cli-integration/databases.test.ts
+++ b/extensions/ql-vscode/src/vscode-tests/cli-integration/databases.test.ts
@@ -5,7 +5,6 @@ import { CodeQLExtensionInterface } from "../../extension";
import { CodeQLCliServer } from "../../cli";
import { DatabaseManager } from "../../databases";
import {
- promptImportLgtmDatabase,
importArchiveDatabase,
promptImportInternetDatabase,
} from "../../databaseFetcher";
@@ -17,9 +16,6 @@ jest.setTimeout(60_000);
* Run various integration tests for databases
*/
describe("Databases", () => {
- const LGTM_URL =
- "https://lgtm.com/projects/g/aeisenberg/angular-bind-notifier/";
-
let databaseManager: DatabaseManager;
let inputBoxStub: jest.SpiedFunction;
let cli: CodeQLCliServer;
@@ -71,27 +67,6 @@ describe("Databases", () => {
expect(dbItem.databaseUri.fsPath).toBe(join(storagePath, "db", "db"));
});
- it("should add a database from lgtm with only one language", async () => {
- inputBoxStub.mockResolvedValue(LGTM_URL);
- let dbItem = await promptImportLgtmDatabase(
- databaseManager,
- storagePath,
- progressCallback,
- {} as CancellationToken,
- cli,
- );
- expect(dbItem).toBeDefined();
- dbItem = dbItem!;
- expect(dbItem.name).toBe("aeisenberg_angular-bind-notifier_106179a");
- expect(dbItem.databaseUri.fsPath).toBe(
- join(
- storagePath,
- "javascript",
- "aeisenberg_angular-bind-notifier_106179a",
- ),
- );
- });
-
it("should add a database from a url", async () => {
inputBoxStub.mockResolvedValue(DB_URL);
diff --git a/extensions/ql-vscode/src/vscode-tests/no-workspace/databaseFetcher.test.ts b/extensions/ql-vscode/src/vscode-tests/no-workspace/databaseFetcher.test.ts
index 32c6455b1..15d7e4018 100644
--- a/extensions/ql-vscode/src/vscode-tests/no-workspace/databaseFetcher.test.ts
+++ b/extensions/ql-vscode/src/vscode-tests/no-workspace/databaseFetcher.test.ts
@@ -5,8 +5,6 @@ import { QuickPickItem, window } from "vscode";
import {
convertGithubNwoToDatabaseUrl,
- convertLgtmUrlToDatabaseUrl,
- looksLikeLgtmUrl,
findDirWithFile,
} from "../../databaseFetcher";
import * as Octokit from "@octokit/rest";
@@ -131,64 +129,6 @@ describe("databaseFetcher", () => {
});
});
- describe("convertLgtmUrlToDatabaseUrl", () => {
- let quickPickSpy: jest.SpiedFunction;
- const progressSpy = jest.fn();
-
- beforeEach(() => {
- quickPickSpy = jest
- .spyOn(window, "showQuickPick")
- .mockResolvedValue(undefined);
- });
-
- it("should convert a project url to a database url", async () => {
- quickPickSpy.mockResolvedValue("javascript" as unknown as QuickPickItem);
- const lgtmUrl = "https://lgtm.com/projects/g/github/codeql";
- const dbUrl = await convertLgtmUrlToDatabaseUrl(lgtmUrl, progressSpy);
-
- expect(dbUrl).toBe(
- "https://lgtm.com/api/v1.0/snapshots/1506465042581/javascript",
- );
- expect(quickPickSpy).toHaveBeenNthCalledWith(
- 1,
- expect.arrayContaining(["javascript", "python"]),
- expect.anything(),
- );
- });
-
- it("should convert a project url to a database url with extra path segments", async () => {
- quickPickSpy.mockResolvedValue("python" as unknown as QuickPickItem);
- const lgtmUrl =
- "https://lgtm.com/projects/g/github/codeql/subpage/subpage2?query=xxx";
- const dbUrl = await convertLgtmUrlToDatabaseUrl(lgtmUrl, progressSpy);
-
- expect(dbUrl).toBe(
- "https://lgtm.com/api/v1.0/snapshots/1506465042581/python",
- );
- expect(progressSpy).toBeCalledTimes(1);
- });
-
- it("should convert a raw slug to a database url with extra path segments", async () => {
- quickPickSpy.mockResolvedValue("python" as unknown as QuickPickItem);
- const lgtmUrl = "g/github/codeql";
- const dbUrl = await convertLgtmUrlToDatabaseUrl(lgtmUrl, progressSpy);
-
- expect(dbUrl).toBe(
- "https://lgtm.com/api/v1.0/snapshots/1506465042581/python",
- );
- expect(progressSpy).toBeCalledTimes(1);
- });
-
- it("should fail on a nonexistent project", async () => {
- quickPickSpy.mockResolvedValue("javascript" as unknown as QuickPickItem);
- const lgtmUrl = "https://lgtm.com/projects/g/github/hucairz";
- await expect(
- convertLgtmUrlToDatabaseUrl(lgtmUrl, progressSpy),
- ).rejects.toThrow(/Invalid LGTM URL/);
- expect(progressSpy).toBeCalledTimes(0);
- });
- });
-
describe("looksLikeGithubRepo", () => {
it("should handle invalid urls", () => {
expect(looksLikeGithubRepo("")).toBe(false);
@@ -208,42 +148,6 @@ describe("databaseFetcher", () => {
});
});
- describe("looksLikeLgtmUrl", () => {
- it("should handle invalid urls", () => {
- expect(looksLikeLgtmUrl("")).toBe(false);
- expect(looksLikeLgtmUrl("http://lgtm.com/projects/g/github/codeql")).toBe(
- false,
- );
- expect(
- looksLikeLgtmUrl("https://ww.lgtm.com/projects/g/github/codeql"),
- ).toBe(false);
- expect(looksLikeLgtmUrl("https://ww.lgtm.com/projects/g/github")).toBe(
- false,
- );
- expect(looksLikeLgtmUrl("g/github")).toBe(false);
- expect(looksLikeLgtmUrl("ggg/github/myproj")).toBe(false);
- });
-
- it("should handle valid urls", () => {
- expect(
- looksLikeLgtmUrl("https://lgtm.com/projects/g/github/codeql"),
- ).toBe(true);
- expect(
- looksLikeLgtmUrl("https://www.lgtm.com/projects/g/github/codeql"),
- ).toBe(true);
- expect(
- looksLikeLgtmUrl("https://lgtm.com/projects/g/github/codeql/sub/pages"),
- ).toBe(true);
- expect(
- looksLikeLgtmUrl(
- "https://lgtm.com/projects/g/github/codeql/sub/pages?query=string",
- ),
- ).toBe(true);
- expect(looksLikeLgtmUrl("g/github/myproj")).toBe(true);
- expect(looksLikeLgtmUrl("git/github/myproj")).toBe(true);
- });
- });
-
describe("findDirWithFile", () => {
let dir: tmp.DirResult;
beforeEach(() => {