From 3a6f95c6c69ec45b2143506b32787d981bd4e6b7 Mon Sep 17 00:00:00 2001 From: Charis Kyriakou Date: Tue, 6 Dec 2022 08:55:31 +0000 Subject: [PATCH 1/4] Add functionality to set the selected db item --- .../src/databases/config/db-config-store.ts | 28 ++++++-- .../src/databases/db-item-selection.ts | 47 ++++++++++++++ .../ql-vscode/src/databases/db-manager.ts | 12 +++- .../databases/config/db-config-store.test.ts | 65 ++++++++++++++++++- 4 files changed, 146 insertions(+), 6 deletions(-) diff --git a/extensions/ql-vscode/src/databases/config/db-config-store.ts b/extensions/ql-vscode/src/databases/config/db-config-store.ts index d146997cb49..4e79d86b5ef 100644 --- a/extensions/ql-vscode/src/databases/config/db-config-store.ts +++ b/extensions/ql-vscode/src/databases/config/db-config-store.ts @@ -1,6 +1,6 @@ import { pathExists, writeJSON, readJSON, readJSONSync } from "fs-extra"; import { join } from "path"; -import { cloneDbConfig, DbConfig } from "./db-config"; +import { cloneDbConfig, DbConfig, SelectedDbItem } from "./db-config"; import * as chokidar from "chokidar"; import { DisposableObject, DisposeHandler } from "../../pure/disposable-object"; import { DbConfigValidator } from "./db-config-validator"; @@ -56,11 +56,31 @@ export class DbConfigStore extends DisposableObject { return this.configPath; } + public async setSelectedDbItem(dbItem: SelectedDbItem): Promise { + if (!this.config) { + // If the app is trying to set the selected item without a config + // being set it means that there is a bug in our code. sp we thow + // an error instead of just returning an error result. + throw Error("Cannot select database item if config is not loaded"); + } + + const config: DbConfig = { + ...this.config, + selected: dbItem, + }; + + await this.writeConfig(config); + } + + private async writeConfig(config: DbConfig): Promise { + await writeJSON(this.configPath, config, { + spaces: 2, + }); + } + private async loadConfig(): Promise { if (!(await pathExists(this.configPath))) { - await writeJSON(this.configPath, this.createEmptyConfig(), { - spaces: 2, - }); + await this.writeConfig(this.createEmptyConfig()); } await this.readConfig(); diff --git a/extensions/ql-vscode/src/databases/db-item-selection.ts b/extensions/ql-vscode/src/databases/db-item-selection.ts index 9ddc9bdc8ac..d0dc051036c 100644 --- a/extensions/ql-vscode/src/databases/db-item-selection.ts +++ b/extensions/ql-vscode/src/databases/db-item-selection.ts @@ -1,4 +1,5 @@ import { DbItem, DbItemKind, LocalDbItem, RemoteDbItem } from "./db-item"; +import { SelectedDbItem, SelectedDbItemKind } from "./config/db-config"; export function getSelectedDbItem(dbItems: DbItem[]): DbItem | undefined { for (const dbItem of dbItems) { @@ -42,3 +43,49 @@ function extractSelected( } return undefined; } + +export function mapDbItemToSelectedDbItem( + dbItem: DbItem, +): SelectedDbItem | undefined { + switch (dbItem.kind) { + case DbItemKind.RootLocal: + case DbItemKind.RootRemote: + // Root items are not selectable. + return undefined; + + case DbItemKind.LocalList: + return { + kind: SelectedDbItemKind.LocalUserDefinedList, + listName: dbItem.listName, + }; + case DbItemKind.RemoteUserDefinedList: + return { + kind: SelectedDbItemKind.RemoteUserDefinedList, + listName: dbItem.listName, + }; + case DbItemKind.RemoteSystemDefinedList: + return { + kind: SelectedDbItemKind.RemoteSystemDefinedList, + listName: dbItem.listName, + }; + case DbItemKind.RemoteOwner: + return { + kind: SelectedDbItemKind.RemoteOwner, + ownerName: dbItem.ownerName, + }; + + case DbItemKind.LocalDatabase: + return { + kind: SelectedDbItemKind.LocalDatabase, + listName: dbItem?.parentListName, + databaseName: dbItem.databaseName, + }; + + case DbItemKind.RemoteRepo: + return { + kind: SelectedDbItemKind.RemoteRepository, + listName: dbItem?.parentListName, + repositoryName: dbItem.repoFullName, + }; + } +} diff --git a/extensions/ql-vscode/src/databases/db-manager.ts b/extensions/ql-vscode/src/databases/db-manager.ts index a4d499a82fc..3e715f6303a 100644 --- a/extensions/ql-vscode/src/databases/db-manager.ts +++ b/extensions/ql-vscode/src/databases/db-manager.ts @@ -3,7 +3,10 @@ import { AppEvent, AppEventEmitter } from "../common/events"; import { ValueResult } from "../common/value-result"; import { DbConfigStore } from "./config/db-config-store"; import { DbItem } from "./db-item"; -import { getSelectedDbItem } from "./db-item-selection"; +import { + getSelectedDbItem, + mapDbItemToSelectedDbItem, +} from "./db-item-selection"; import { createLocalTree, createRemoteTree } from "./db-tree-creator"; export class DbManager { @@ -44,4 +47,11 @@ export class DbManager { public getConfigPath(): string { return this.dbConfigStore.getConfigPath(); } + + public async setSelectedDbItem(dbItem: DbItem): Promise { + const selectedDbItem = mapDbItemToSelectedDbItem(dbItem); + if (selectedDbItem) { + await this.dbConfigStore.setSelectedDbItem(selectedDbItem); + } + } } diff --git a/extensions/ql-vscode/test/pure-tests/databases/config/db-config-store.test.ts b/extensions/ql-vscode/test/pure-tests/databases/config/db-config-store.test.ts index 8f3c3c8b5be..c2a294661fa 100644 --- a/extensions/ql-vscode/test/pure-tests/databases/config/db-config-store.test.ts +++ b/extensions/ql-vscode/test/pure-tests/databases/config/db-config-store.test.ts @@ -1,6 +1,12 @@ -import { ensureDir, remove, pathExists } from "fs-extra"; +import { ensureDir, remove, pathExists, writeJSON } from "fs-extra"; import { join } from "path"; +import { + DbConfig, + SelectedDbItemKind, + SelectedRemoteUserDefinedList, +} from "../../../../src/databases/config/db-config"; import { DbConfigStore } from "../../../../src/databases/config/db-config-store"; +import { sleep } from "../../../../src/pure/time"; import { createMockApp } from "../../../__mocks__/appMock"; describe("db config store", () => { @@ -128,4 +134,61 @@ describe("db config store", () => { configStore.dispose(); }); + + it("should allow updating the selected item", async () => { + const app = createMockApp({ + extensionPath, + workspaceStoragePath: tempWorkspaceStoragePath, + }); + const configStore = new DbConfigStore(app); + await configStore.initialize(); + + const initialConfig: DbConfig = { + databases: { + remote: { + repositoryLists: [ + { + name: "repoList1", + repositories: ["owner1/repo1", "owner1/repo2"], + }, + { + name: "repoList2", + repositories: ["owner2/repo1", "owner2/repo2"], + }, + ], + + owners: [], + repositories: [], + }, + local: { + lists: [], + databases: [], + }, + }, + }; + + await writeJSON(configStore.getConfigPath(), initialConfig, { + spaces: 2, + }); + + let config = configStore.getConfig().value; + expect(config.selected).toBeUndefined(); + + const selectedDbItem: SelectedRemoteUserDefinedList = { + kind: SelectedDbItemKind.RemoteUserDefinedList, + listName: "repoList2", + }; + + // Give the config file watcher enough time to read the file + await configStore.setSelectedDbItem(selectedDbItem); + await sleep(2000); + config = configStore.getConfig().value; + + expect(config.selected).toEqual({ + kind: "remoteUserDefinedList", + listName: "repoList2", + }); + + configStore.dispose(); + }); }); From d0fc42ca8646ca5f2500f5451f9812cc295ad0d8 Mon Sep 17 00:00:00 2001 From: Charis Kyriakou Date: Tue, 6 Dec 2022 11:40:00 +0000 Subject: [PATCH 2/4] Delete test since it's unreliable on CI --- .../databases/config/db-config-store.test.ts | 65 +------------------ 1 file changed, 1 insertion(+), 64 deletions(-) diff --git a/extensions/ql-vscode/test/pure-tests/databases/config/db-config-store.test.ts b/extensions/ql-vscode/test/pure-tests/databases/config/db-config-store.test.ts index c2a294661fa..8f3c3c8b5be 100644 --- a/extensions/ql-vscode/test/pure-tests/databases/config/db-config-store.test.ts +++ b/extensions/ql-vscode/test/pure-tests/databases/config/db-config-store.test.ts @@ -1,12 +1,6 @@ -import { ensureDir, remove, pathExists, writeJSON } from "fs-extra"; +import { ensureDir, remove, pathExists } from "fs-extra"; import { join } from "path"; -import { - DbConfig, - SelectedDbItemKind, - SelectedRemoteUserDefinedList, -} from "../../../../src/databases/config/db-config"; import { DbConfigStore } from "../../../../src/databases/config/db-config-store"; -import { sleep } from "../../../../src/pure/time"; import { createMockApp } from "../../../__mocks__/appMock"; describe("db config store", () => { @@ -134,61 +128,4 @@ describe("db config store", () => { configStore.dispose(); }); - - it("should allow updating the selected item", async () => { - const app = createMockApp({ - extensionPath, - workspaceStoragePath: tempWorkspaceStoragePath, - }); - const configStore = new DbConfigStore(app); - await configStore.initialize(); - - const initialConfig: DbConfig = { - databases: { - remote: { - repositoryLists: [ - { - name: "repoList1", - repositories: ["owner1/repo1", "owner1/repo2"], - }, - { - name: "repoList2", - repositories: ["owner2/repo1", "owner2/repo2"], - }, - ], - - owners: [], - repositories: [], - }, - local: { - lists: [], - databases: [], - }, - }, - }; - - await writeJSON(configStore.getConfigPath(), initialConfig, { - spaces: 2, - }); - - let config = configStore.getConfig().value; - expect(config.selected).toBeUndefined(); - - const selectedDbItem: SelectedRemoteUserDefinedList = { - kind: SelectedDbItemKind.RemoteUserDefinedList, - listName: "repoList2", - }; - - // Give the config file watcher enough time to read the file - await configStore.setSelectedDbItem(selectedDbItem); - await sleep(2000); - config = configStore.getConfig().value; - - expect(config.selected).toEqual({ - kind: "remoteUserDefinedList", - listName: "repoList2", - }); - - configStore.dispose(); - }); }); From db6e5a8ba53ecc841a7e0be7eb77aa72c5b29494 Mon Sep 17 00:00:00 2001 From: Charis Kyriakou Date: Tue, 6 Dec 2022 15:00:27 +0000 Subject: [PATCH 3/4] Apply suggestions from code review Co-authored-by: Shati Patel <42641846+shati-patel@users.noreply.github.com> --- extensions/ql-vscode/src/databases/config/db-config-store.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/ql-vscode/src/databases/config/db-config-store.ts b/extensions/ql-vscode/src/databases/config/db-config-store.ts index 4e79d86b5ef..fdac16945a4 100644 --- a/extensions/ql-vscode/src/databases/config/db-config-store.ts +++ b/extensions/ql-vscode/src/databases/config/db-config-store.ts @@ -59,7 +59,7 @@ export class DbConfigStore extends DisposableObject { public async setSelectedDbItem(dbItem: SelectedDbItem): Promise { if (!this.config) { // If the app is trying to set the selected item without a config - // being set it means that there is a bug in our code. sp we thow + // being set it means that there is a bug in our code, so we throw // an error instead of just returning an error result. throw Error("Cannot select database item if config is not loaded"); } From 615188298d6d4a31b4c7ff5178a63e1fd6bb4822 Mon Sep 17 00:00:00 2001 From: Charis Kyriakou Date: Tue, 6 Dec 2022 15:02:16 +0000 Subject: [PATCH 4/4] Add some empty lines between switch cases --- extensions/ql-vscode/src/databases/db-item-selection.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/extensions/ql-vscode/src/databases/db-item-selection.ts b/extensions/ql-vscode/src/databases/db-item-selection.ts index d0dc051036c..d4960ad37fa 100644 --- a/extensions/ql-vscode/src/databases/db-item-selection.ts +++ b/extensions/ql-vscode/src/databases/db-item-selection.ts @@ -58,16 +58,19 @@ export function mapDbItemToSelectedDbItem( kind: SelectedDbItemKind.LocalUserDefinedList, listName: dbItem.listName, }; + case DbItemKind.RemoteUserDefinedList: return { kind: SelectedDbItemKind.RemoteUserDefinedList, listName: dbItem.listName, }; + case DbItemKind.RemoteSystemDefinedList: return { kind: SelectedDbItemKind.RemoteSystemDefinedList, listName: dbItem.listName, }; + case DbItemKind.RemoteOwner: return { kind: SelectedDbItemKind.RemoteOwner,