Skip to content

Commit 1196902

Browse files
committed
Allow import all database subfolders by selecting a folder
1 parent 7b29015 commit 1196902

File tree

4 files changed

+81
-18
lines changed

4 files changed

+81
-18
lines changed

extensions/ql-vscode/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## [UNRELEASED]
44

5+
- Add a palette command that allow user to select a folder and import all database subfolders.
6+
57
## 1.16.1 - 6 November 2024
68

79
- Support result columns of type `QlBuiltins::BigInt` in quick evaluations. [#3647](https://github.com/github/vscode-codeql/pull/3647)

extensions/ql-vscode/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,10 @@
839839
"command": "codeQL.chooseDatabaseFolder",
840840
"title": "CodeQL: Choose Database from Folder"
841841
},
842+
{
843+
"command": "codeQL.chooseMultipleDatabaseFolder",
844+
"title": "CodeQL: Choose Folder contains all Database Folders to import"
845+
},
842846
{
843847
"command": "codeQL.chooseDatabaseArchive",
844848
"title": "CodeQL: Choose Database from Archive"

extensions/ql-vscode/src/common/commands.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ export type LanguageSelectionCommands = {
211211
export type LocalDatabasesCommands = {
212212
// Command palette commands
213213
"codeQL.chooseDatabaseFolder": () => Promise<void>;
214+
"codeQL.chooseMultipleDatabaseFolder": () => Promise<void>;
214215
"codeQL.chooseDatabaseArchive": () => Promise<void>;
215216
"codeQL.chooseDatabaseInternet": () => Promise<void>;
216217
"codeQL.chooseDatabaseGithub": () => Promise<void>;

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

Lines changed: 74 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
ThemeIcon,
1717
ThemeColor,
1818
workspace,
19+
FileType,
1920
} from "vscode";
2021
import { pathExists, stat, readdir, remove } from "fs-extra";
2122

@@ -36,6 +37,7 @@ import {
3637
import {
3738
showAndLogExceptionWithTelemetry,
3839
showAndLogErrorMessage,
40+
showAndLogInformationMessage,
3941
} from "../common/logging";
4042
import type { DatabaseFetcher } from "./database-fetcher";
4143
import { asError, asyncFilter, getErrorMessage } from "../common/helpers-pure";
@@ -267,6 +269,8 @@ export class DatabaseUI extends DisposableObject {
267269
"codeQL.getCurrentDatabase": this.handleGetCurrentDatabase.bind(this),
268270
"codeQL.chooseDatabaseFolder":
269271
this.handleChooseDatabaseFolderFromPalette.bind(this),
272+
"codeQL.chooseMultipleDatabaseFolder":
273+
this.handleChooseMultipleDatabaseFolderFromPalette.bind(this),
270274
"codeQL.chooseDatabaseArchive":
271275
this.handleChooseDatabaseArchiveFromPalette.bind(this),
272276
"codeQL.chooseDatabaseInternet":
@@ -322,10 +326,11 @@ export class DatabaseUI extends DisposableObject {
322326
}
323327

324328
private async chooseDatabaseFolder(
329+
subFolder: boolean,
325330
progress: ProgressCallback,
326331
): Promise<void> {
327332
try {
328-
await this.chooseAndSetDatabase(true, progress);
333+
await this.chooseAndSetDatabase(true, subFolder, progress);
329334
} catch (e) {
330335
void showAndLogExceptionWithTelemetry(
331336
this.app.logger,
@@ -340,7 +345,7 @@ export class DatabaseUI extends DisposableObject {
340345
private async handleChooseDatabaseFolder(): Promise<void> {
341346
return withProgress(
342347
async (progress) => {
343-
await this.chooseDatabaseFolder(progress);
348+
await this.chooseDatabaseFolder(false, progress);
344349
},
345350
{
346351
title: "Adding database from folder",
@@ -351,14 +356,25 @@ export class DatabaseUI extends DisposableObject {
351356
private async handleChooseDatabaseFolderFromPalette(): Promise<void> {
352357
return withProgress(
353358
async (progress) => {
354-
await this.chooseDatabaseFolder(progress);
359+
await this.chooseDatabaseFolder(false, progress);
355360
},
356361
{
357362
title: "Choose a Database from a Folder",
358363
},
359364
);
360365
}
361366

367+
private async handleChooseMultipleDatabaseFolderFromPalette(): Promise<void> {
368+
return withProgress(
369+
async (progress) => {
370+
await this.chooseDatabaseFolder(true, progress);
371+
},
372+
{
373+
title: "Choose a Folder contains all Database Folders",
374+
},
375+
);
376+
}
377+
362378
private async handleSetDefaultTourDatabase(): Promise<void> {
363379
return withProgress(
364380
async () => {
@@ -494,7 +510,7 @@ export class DatabaseUI extends DisposableObject {
494510
progress: ProgressCallback,
495511
): Promise<void> {
496512
try {
497-
await this.chooseAndSetDatabase(false, progress);
513+
await this.chooseAndSetDatabase(false, false, progress);
498514
} catch (e: unknown) {
499515
void showAndLogExceptionWithTelemetry(
500516
this.app.logger,
@@ -962,27 +978,67 @@ export class DatabaseUI extends DisposableObject {
962978
*/
963979
private async chooseAndSetDatabase(
964980
byFolder: boolean,
981+
subFolder: boolean,
965982
progress: ProgressCallback,
966-
): Promise<DatabaseItem | undefined> {
983+
): Promise<DatabaseItem[] | DatabaseItem | undefined> {
967984
const uri = await chooseDatabaseDir(byFolder);
968985
if (!uri) {
969986
return undefined;
970987
}
971988

972-
if (byFolder && !uri.fsPath.endsWith("testproj")) {
973-
const fixedUri = await this.fixDbUri(uri);
974-
// we are selecting a database folder
975-
return await this.databaseManager.openDatabase(fixedUri, {
976-
type: "folder",
977-
});
989+
if (subFolder) {
990+
if (!byFolder) {
991+
return undefined;
992+
}
993+
994+
const databases: DatabaseItem[] = [];
995+
const failures: string[] = [];
996+
const entries = await workspace.fs.readDirectory(uri);
997+
for (const entry of entries) {
998+
if (entry[1] === FileType.Directory) {
999+
try {
1000+
const fixedUri = await this.fixDbUri(Uri.joinPath(uri, entry[0]));
1001+
const database = await this.databaseManager.openDatabase(fixedUri, {
1002+
type: "folder",
1003+
});
1004+
databases.push(database);
1005+
} catch (e) {
1006+
failures.push(entry[0]);
1007+
}
1008+
}
1009+
}
1010+
1011+
if (failures.length) {
1012+
void showAndLogErrorMessage(
1013+
this.app.logger,
1014+
`Failed to import ${failures.length} database(s) (${failures.join(
1015+
", ",
1016+
)}), successfully imported ${databases.length} database(s).`,
1017+
);
1018+
} else {
1019+
void showAndLogInformationMessage(
1020+
this.app.logger,
1021+
`Successfully imported ${databases.length} database(s).`,
1022+
);
1023+
}
1024+
1025+
return databases;
9781026
} else {
979-
// we are selecting a database archive or a testproj.
980-
// Unzip archives (if an archive) and copy into a workspace-controlled area
981-
// before importing.
982-
return await this.databaseFetcher.importLocalDatabase(
983-
uri.toString(true),
984-
progress,
985-
);
1027+
if (byFolder && !uri.fsPath.endsWith("testproj")) {
1028+
const fixedUri = await this.fixDbUri(uri);
1029+
// we are selecting a database folder
1030+
return await this.databaseManager.openDatabase(fixedUri, {
1031+
type: "folder",
1032+
});
1033+
} else {
1034+
// we are selecting a database archive or a testproj.
1035+
// Unzip archives (if an archive) and copy into a workspace-controlled area
1036+
// before importing.
1037+
return await this.databaseFetcher.importLocalDatabase(
1038+
uri.toString(true),
1039+
progress,
1040+
);
1041+
}
9861042
}
9871043
}
9881044

0 commit comments

Comments
 (0)