Skip to content

Commit a5239fb

Browse files
Merge pull request #3458 from github/robertbrignull/database-prompting
Refactor database-fetcher.ts into a class and simplify
2 parents 6f7b7cf + 7d259a9 commit a5239fb

File tree

20 files changed

+724
-883
lines changed

20 files changed

+724
-883
lines changed

extensions/ql-vscode/src/databases/database-fetcher.ts

Lines changed: 507 additions & 571 deletions
Large diffs are not rendered by default.

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

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ import { window } from "vscode";
22
import type { Octokit } from "@octokit/rest";
33
import { showNeverAskAgainDialog } from "../../common/vscode/dialog";
44
import { getLanguageDisplayName } from "../../common/query-language";
5-
import { downloadGitHubDatabaseFromUrl } from "../database-fetcher";
5+
import type { DatabaseFetcher } from "../database-fetcher";
66
import { withProgress } from "../../common/vscode/progress";
7-
import type { DatabaseManager } from "../local-databases";
8-
import type { CodeQLCliServer } from "../../codeql-cli/cli";
97
import type { AppCommandManager } from "../../common/commands";
108
import type { GitHubDatabaseConfig } from "../../config";
119
import type { CodeqlDatabase } from "./api";
@@ -58,9 +56,7 @@ export async function downloadDatabaseFromGitHub(
5856
owner: string,
5957
repo: string,
6058
databases: CodeqlDatabase[],
61-
databaseManager: DatabaseManager,
62-
storagePath: string,
63-
cliServer: CodeQLCliServer,
59+
databaseFetcher: DatabaseFetcher,
6460
commandManager: AppCommandManager,
6561
): Promise<void> {
6662
const selectedDatabases = await promptForDatabases(databases);
@@ -72,7 +68,7 @@ export async function downloadDatabaseFromGitHub(
7268
selectedDatabases.map((database) =>
7369
withProgress(
7470
async (progress) => {
75-
await downloadGitHubDatabaseFromUrl(
71+
await databaseFetcher.downloadGitHubDatabaseFromUrl(
7672
database.url,
7773
database.id,
7874
database.created_at,
@@ -81,9 +77,6 @@ export async function downloadDatabaseFromGitHub(
8177
repo,
8278
octokit,
8379
progress,
84-
databaseManager,
85-
storagePath,
86-
cliServer,
8780
true,
8881
false,
8982
);

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

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import {
1414
} from "./download";
1515
import type { GitHubDatabaseConfig } from "../../config";
1616
import type { DatabaseManager } from "../local-databases";
17-
import type { CodeQLCliServer } from "../../codeql-cli/cli";
1817
import type { CodeqlDatabase, ListDatabasesResult } from "./api";
1918
import { listDatabases } from "./api";
2019
import type { DatabaseUpdate } from "./updates";
@@ -24,6 +23,7 @@ import {
2423
isNewerDatabaseAvailable,
2524
} from "./updates";
2625
import type { Octokit } from "@octokit/rest";
26+
import type { DatabaseFetcher } from "../database-fetcher";
2727

2828
export class GitHubDatabasesModule extends DisposableObject {
2929
/**
@@ -33,8 +33,7 @@ export class GitHubDatabasesModule extends DisposableObject {
3333
constructor(
3434
private readonly app: App,
3535
private readonly databaseManager: DatabaseManager,
36-
private readonly databaseStoragePath: string,
37-
private readonly cliServer: CodeQLCliServer,
36+
private readonly databaseFetcher: DatabaseFetcher,
3837
private readonly config: GitHubDatabaseConfig,
3938
) {
4039
super();
@@ -43,15 +42,13 @@ export class GitHubDatabasesModule extends DisposableObject {
4342
public static async initialize(
4443
app: App,
4544
databaseManager: DatabaseManager,
46-
databaseStoragePath: string,
47-
cliServer: CodeQLCliServer,
45+
databaseFetcher: DatabaseFetcher,
4846
config: GitHubDatabaseConfig,
4947
): Promise<GitHubDatabasesModule> {
5048
const githubDatabasesModule = new GitHubDatabasesModule(
5149
app,
5250
databaseManager,
53-
databaseStoragePath,
54-
cliServer,
51+
databaseFetcher,
5552
config,
5653
);
5754
app.subscriptions.push(githubDatabasesModule);
@@ -185,9 +182,7 @@ export class GitHubDatabasesModule extends DisposableObject {
185182
owner,
186183
repo,
187184
databases,
188-
this.databaseManager,
189-
this.databaseStoragePath,
190-
this.cliServer,
185+
this.databaseFetcher,
191186
this.app.commands,
192187
);
193188
}
@@ -212,8 +207,7 @@ export class GitHubDatabasesModule extends DisposableObject {
212207
repo,
213208
databaseUpdates,
214209
this.databaseManager,
215-
this.databaseStoragePath,
216-
this.cliServer,
210+
this.databaseFetcher,
217211
this.app.commands,
218212
);
219213
}

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

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import type { CodeqlDatabase } from "./api";
22
import type { DatabaseItem, DatabaseManager } from "../local-databases";
33
import type { Octokit } from "@octokit/rest";
4-
import type { CodeQLCliServer } from "../../codeql-cli/cli";
54
import type { AppCommandManager } from "../../common/commands";
65
import { getLanguageDisplayName } from "../../common/query-language";
76
import { showNeverAskAgainDialog } from "../../common/vscode/dialog";
8-
import { downloadGitHubDatabaseFromUrl } from "../database-fetcher";
7+
import type { DatabaseFetcher } from "../database-fetcher";
98
import { withProgress } from "../../common/vscode/progress";
109
import { window } from "vscode";
1110
import type { GitHubDatabaseConfig } from "../../config";
@@ -156,8 +155,7 @@ export async function downloadDatabaseUpdateFromGitHub(
156155
repo: string,
157156
updates: DatabaseUpdate[],
158157
databaseManager: DatabaseManager,
159-
storagePath: string,
160-
cliServer: CodeQLCliServer,
158+
databaseFetcher: DatabaseFetcher,
161159
commandManager: AppCommandManager,
162160
): Promise<void> {
163161
const selectedDatabases = await promptForDatabases(
@@ -179,21 +177,19 @@ export async function downloadDatabaseUpdateFromGitHub(
179177

180178
return withProgress(
181179
async (progress) => {
182-
const newDatabase = await downloadGitHubDatabaseFromUrl(
183-
database.url,
184-
database.id,
185-
database.created_at,
186-
database.commit_oid ?? null,
187-
owner,
188-
repo,
189-
octokit,
190-
progress,
191-
databaseManager,
192-
storagePath,
193-
cliServer,
194-
databaseManager.currentDatabaseItem === update.databaseItem,
195-
update.databaseItem.hasSourceArchiveInExplorer(),
196-
);
180+
const newDatabase =
181+
await databaseFetcher.downloadGitHubDatabaseFromUrl(
182+
database.url,
183+
database.id,
184+
database.created_at,
185+
database.commit_oid ?? null,
186+
owner,
187+
repo,
188+
octokit,
189+
progress,
190+
databaseManager.currentDatabaseItem === update.databaseItem,
191+
update.databaseItem.hasSourceArchiveInExplorer(),
192+
);
197193
if (newDatabase === undefined) {
198194
return;
199195
}

extensions/ql-vscode/src/databases/local-databases-ui.ts

Lines changed: 7 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,7 @@ import {
3737
showAndLogExceptionWithTelemetry,
3838
showAndLogErrorMessage,
3939
} from "../common/logging";
40-
import {
41-
importLocalDatabase,
42-
promptImportGithubDatabase,
43-
promptImportInternetDatabase,
44-
} from "./database-fetcher";
40+
import type { DatabaseFetcher } from "./database-fetcher";
4541
import { asError, asyncFilter, getErrorMessage } from "../common/helpers-pure";
4642
import type { QueryRunner } from "../query-server";
4743
import type { App } from "../common/app";
@@ -248,6 +244,7 @@ export class DatabaseUI extends DisposableObject {
248244
public constructor(
249245
private app: App,
250246
private databaseManager: DatabaseManager,
247+
private readonly databaseFetcher: DatabaseFetcher,
251248
languageContext: LanguageContextStore,
252249
private readonly queryServer: QueryRunner,
253250
private readonly storagePath: string,
@@ -535,13 +532,7 @@ export class DatabaseUI extends DisposableObject {
535532
private async handleChooseDatabaseInternet(): Promise<void> {
536533
return withProgress(
537534
async (progress) => {
538-
await promptImportInternetDatabase(
539-
this.app.commands,
540-
this.databaseManager,
541-
this.storagePath,
542-
progress,
543-
this.queryServer.cliServer,
544-
);
535+
await this.databaseFetcher.promptImportInternetDatabase(progress);
545536
},
546537
{
547538
title: "Adding database from URL",
@@ -552,13 +543,7 @@ export class DatabaseUI extends DisposableObject {
552543
private async handleChooseDatabaseGithub(): Promise<void> {
553544
return withProgress(
554545
async (progress) => {
555-
await promptImportGithubDatabase(
556-
this.app,
557-
this.databaseManager,
558-
this.storagePath,
559-
progress,
560-
this.queryServer.cliServer,
561-
);
546+
await this.databaseFetcher.promptImportGithubDatabase(progress);
562547
},
563548
{
564549
title: "Adding database from GitHub",
@@ -707,13 +692,9 @@ export class DatabaseUI extends DisposableObject {
707692
try {
708693
// Assume user has selected an archive if the file has a .zip extension
709694
if (uri.path.endsWith(".zip")) {
710-
await importLocalDatabase(
711-
this.app.commands,
695+
await this.databaseFetcher.importLocalDatabase(
712696
uri.toString(true),
713-
this.databaseManager,
714-
this.storagePath,
715697
progress,
716-
this.queryServer.cliServer,
717698
);
718699
} else {
719700
await this.databaseManager.openDatabase(uri, {
@@ -758,13 +739,9 @@ export class DatabaseUI extends DisposableObject {
758739
await this.databaseManager.removeDatabaseItem(existingItem);
759740
}
760741

761-
await importLocalDatabase(
762-
this.app.commands,
742+
await this.databaseFetcher.importLocalDatabase(
763743
uri.toString(true),
764-
this.databaseManager,
765-
this.storagePath,
766744
progress,
767-
this.queryServer.cliServer,
768745
);
769746

770747
if (existingItem !== undefined) {
@@ -1005,13 +982,9 @@ export class DatabaseUI extends DisposableObject {
1005982
// we are selecting a database archive or a testproj.
1006983
// Unzip archives (if an archive) and copy into a workspace-controlled area
1007984
// before importing.
1008-
return await importLocalDatabase(
1009-
this.app.commands,
985+
return await this.databaseFetcher.importLocalDatabase(
1010986
uri.toString(true),
1011-
this.databaseManager,
1012-
this.storagePath,
1013987
progress,
1014-
this.queryServer.cliServer,
1015988
);
1016989
}
1017990
}

extensions/ql-vscode/src/databases/local-databases/database-contents.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
import { pathExists, remove } from "fs-extra";
2+
import { join } from "path";
13
import type { Uri } from "vscode";
4+
import { zip } from "zip-a-folder";
25

36
/**
47
* The layout of the database.
@@ -28,3 +31,26 @@ export interface DatabaseContents {
2831
export interface DatabaseContentsWithDbScheme extends DatabaseContents {
2932
dbSchemeUri: Uri; // Always present
3033
}
34+
35+
/**
36+
* Databases created by the old odasa tool will not have a zipped
37+
* source location. However, this extension works better if sources
38+
* are zipped.
39+
*
40+
* This function ensures that the source location is zipped. If the
41+
* `src` folder exists and the `src.zip` file does not, the `src`
42+
* folder will be zipped and then deleted.
43+
*
44+
* @param databasePath The full path to the unzipped database
45+
*/
46+
export async function ensureZippedSourceLocation(
47+
databasePath: string,
48+
): Promise<void> {
49+
const srcFolderPath = join(databasePath, "src");
50+
const srcZipPath = `${srcFolderPath}.zip`;
51+
52+
if ((await pathExists(srcFolderPath)) && !(await pathExists(srcZipPath))) {
53+
await zip(srcFolderPath, srcZipPath);
54+
await remove(srcFolderPath);
55+
}
56+
}

extensions/ql-vscode/src/databases/local-databases/database-manager.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ import { DatabaseResolver } from "./database-resolver";
4343
import { telemetryListener } from "../../common/vscode/telemetry";
4444
import type { LanguageContextStore } from "../../language-context-store";
4545
import type { DatabaseOrigin } from "./database-origin";
46-
import { ensureZippedSourceLocation } from "../database-fetcher";
46+
import { ensureZippedSourceLocation } from "./database-contents";
4747

4848
/**
4949
* The name of the key in the workspaceState dictionary in which we

extensions/ql-vscode/src/extension.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ import { OpenReferencedFileCodeLensProvider } from "./local-queries/open-referen
133133
import { LanguageContextStore } from "./language-context-store";
134134
import { LanguageSelectionPanel } from "./language-selection-panel/language-selection-panel";
135135
import { GitHubDatabasesModule } from "./databases/github-databases";
136+
import { DatabaseFetcher } from "./databases/database-fetcher";
136137

137138
/**
138139
* extension.ts
@@ -799,12 +800,20 @@ async function activateWithInstalledDistribution(
799800
// Let this run async.
800801
void dbm.loadPersistedState();
801802

803+
const databaseFetcher = new DatabaseFetcher(
804+
app,
805+
dbm,
806+
getContextStoragePath(ctx),
807+
cliServer,
808+
);
809+
802810
ctx.subscriptions.push(dbm);
803811

804812
void extLogger.log("Initializing database panel.");
805813
const databaseUI = new DatabaseUI(
806814
app,
807815
dbm,
816+
databaseFetcher,
808817
languageContext,
809818
qs,
810819
getContextStoragePath(ctx),
@@ -881,8 +890,7 @@ async function activateWithInstalledDistribution(
881890
await GitHubDatabasesModule.initialize(
882891
app,
883892
dbm,
884-
getContextStoragePath(ctx),
885-
cliServer,
893+
databaseFetcher,
886894
githubDatabaseConfigListener,
887895
);
888896

@@ -953,6 +961,7 @@ async function activateWithInstalledDistribution(
953961
qs,
954962
qhm,
955963
dbm,
964+
databaseFetcher,
956965
cliServer,
957966
databaseUI,
958967
localQueryResultsView,
@@ -977,6 +986,7 @@ async function activateWithInstalledDistribution(
977986
const modelEditorModule = await ModelEditorModule.initialize(
978987
app,
979988
dbm,
989+
databaseFetcher,
980990
variantAnalysisManager,
981991
cliServer,
982992
qs,

extensions/ql-vscode/src/local-queries/local-queries.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ import type { QueryTreeViewItem } from "../queries-panel/query-tree-view-item";
5454
import { tryGetQueryLanguage } from "../common/query-language";
5555
import type { LanguageContextStore } from "../language-context-store";
5656
import type { ExtensionApp } from "../common/vscode/vscode-app";
57+
import type { DatabaseFetcher } from "../databases/database-fetcher";
5758

5859
export enum QuickEvalType {
5960
None,
@@ -69,6 +70,7 @@ export class LocalQueries extends DisposableObject {
6970
private readonly queryRunner: QueryRunner,
7071
private readonly queryHistoryManager: QueryHistoryManager,
7172
private readonly databaseManager: DatabaseManager,
73+
private readonly databaseFetcher: DatabaseFetcher,
7274
private readonly cliServer: CodeQLCliServer,
7375
private readonly databaseUI: DatabaseUI,
7476
private readonly localQueryResultsView: ResultsView,
@@ -319,15 +321,13 @@ export class LocalQueries extends DisposableObject {
319321
private async createSkeletonQuery(): Promise<void> {
320322
await withProgress(
321323
async (progress: ProgressCallback) => {
322-
const contextStoragePath =
323-
this.app.workspaceStoragePath || this.app.globalStoragePath;
324324
const language = this.languageContextStore.selectedLanguage;
325325
const skeletonQueryWizard = new SkeletonQueryWizard(
326326
this.cliServer,
327327
progress,
328328
this.app,
329329
this.databaseManager,
330-
contextStoragePath,
330+
this.databaseFetcher,
331331
this.selectedQueryTreeViewItems,
332332
language,
333333
);

0 commit comments

Comments
 (0)