Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add origin metadata to database items #3066

Merged
merged 4 commits into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions extensions/ql-vscode/src/databases/config/db-config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Contains models and consts for the data we want to store in the database config.
// Changes to these models should be done carefully and account for backwards compatibility of data.

import { DatabaseOrigin } from "../local-databases/database-origin";

export const DB_CONFIG_VERSION = 1;

export interface DbConfig {
Expand Down Expand Up @@ -88,6 +90,7 @@ export interface LocalDatabase {
name: string;
dateAdded: number;
language: string;
origin: DatabaseOrigin;
storagePath: string;
}

Expand Down
35 changes: 34 additions & 1 deletion extensions/ql-vscode/src/databases/database-fetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { addDatabaseSourceToWorkspace, allowHttp } from "../config";
import { showAndLogInformationMessage } from "../common/logging";
import { AppOctokit } from "../common/octokit";
import { getLanguageDisplayName } from "../common/query-language";
import { DatabaseOrigin } from "./local-databases/database-origin";

/**
* Prompts a user to fetch a database from a remote location. Database is assumed to be an archive file.
Expand Down Expand Up @@ -62,6 +63,10 @@ export async function promptImportInternetDatabase(
databaseManager,
storagePath,
undefined,
{
type: "url",
url: databaseUrl,
},
progress,
cli,
);
Expand Down Expand Up @@ -199,7 +204,8 @@ export async function downloadGitHubDatabase(
return;
}

const { databaseUrl, name, owner } = result;
const { databaseUrl, name, owner, databaseId, databaseCreatedAt, commitOid } =
result;

/**
* The 'token' property of the token object returned by `octokit.auth()`.
Expand All @@ -221,6 +227,13 @@ export async function downloadGitHubDatabase(
databaseManager,
storagePath,
`${owner}/${name}`,
{
type: "github",
repository: nwo,
databaseId,
databaseCreatedAt,
commitOid,
},
progress,
cli,
makeSelected,
Expand Down Expand Up @@ -250,6 +263,10 @@ export async function importArchiveDatabase(
databaseManager,
storagePath,
undefined,
{
type: "archive",
path: databaseUrl,
},
progress,
cli,
);
Expand Down Expand Up @@ -282,6 +299,7 @@ export async function importArchiveDatabase(
* @param databaseManager the DatabaseManager
* @param storagePath where to store the unzipped database.
* @param nameOverride a name for the database that overrides the default
* @param origin the origin of the database
* @param progress callback to send progress messages to
* @param makeSelected make the new database selected in the databases panel (default: true)
* @param addSourceArchiveFolder whether to add a workspace folder containing the source archive to the workspace
Expand All @@ -292,6 +310,7 @@ async function databaseArchiveFetcher(
databaseManager: DatabaseManager,
storagePath: string,
nameOverride: string | undefined,
origin: DatabaseOrigin,
progress: ProgressCallback,
cli?: CodeQLCliServer,
makeSelected = true,
Expand Down Expand Up @@ -336,6 +355,7 @@ async function databaseArchiveFetcher(

const item = await databaseManager.openDatabase(
Uri.file(dbPath),
origin,
makeSelected,
nameOverride,
{
Expand Down Expand Up @@ -533,6 +553,9 @@ export async function convertGithubNwoToDatabaseUrl(
databaseUrl: string;
owner: string;
name: string;
databaseId: number;
databaseCreatedAt: string;
commitOid: string | null;
}
| undefined
> {
Expand All @@ -553,10 +576,20 @@ export async function convertGithubNwoToDatabaseUrl(
}
}

const databaseForLanguage = response.data.find(
(db: any) => db.language === language,
);
if (!databaseForLanguage) {
throw new Error(`No database found for language '${language}'`);
}

return {
databaseUrl: `https://api.github.com/repos/${owner}/${repo}/code-scanning/codeql/databases/${language}`,
owner,
name: repo,
databaseId: databaseForLanguage.id,
databaseCreatedAt: databaseForLanguage.created_at,
commitOid: databaseForLanguage.commit_oid,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's worth noting that this is the commit oid at the point of checking the database info and it might have changed by the point that we download the database contents. However the download should happen immediately and I'm not sure we can do better anyway since there isn't an API endpoint that returns both the metadata and the contents.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is something we are aware of. The chance of this race condition happening is unlikely, but if it does, it's also not problematic. The only reason the commit_oid will be used is for checking updates to the database. If we run into this race condition, it's probably pretty likely that it's an active repository and we would have new commits coming in shortly after anyways.

};
} catch (e) {
void extLogger.log(`Error: ${getErrorMessage(e)}`);
Expand Down
3 changes: 3 additions & 0 deletions extensions/ql-vscode/src/databases/db-item.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// This file contains models that are used to represent the databases.

import { DatabaseOrigin } from "./local-databases/database-origin";

export enum DbItemKind {
RootLocal = "RootLocal",
LocalList = "LocalList",
Expand Down Expand Up @@ -38,6 +40,7 @@ export interface LocalDatabaseDbItem {
databaseName: string;
dateAdded: number;
language: string;
origin: DatabaseOrigin;
storagePath: string;
parentListName?: string;
}
Expand Down
1 change: 1 addition & 0 deletions extensions/ql-vscode/src/databases/db-tree-creator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ function createLocalDb(
databaseName: db.name,
dateAdded: db.dateAdded,
language: db.language,
origin: db.origin,
storagePath: db.storagePath,
selected: !!selected,
parentListName: listName,
Expand Down
11 changes: 9 additions & 2 deletions extensions/ql-vscode/src/databases/local-databases-ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,9 @@ export class DatabaseUI extends DisposableObject {

await this.databaseManager.openDatabase(
uri,
{
type: "folder",
},
makeSelected,
nameOverride,
{
Expand Down Expand Up @@ -704,7 +707,9 @@ export class DatabaseUI extends DisposableObject {
this.queryServer?.cliServer,
);
} else {
await this.databaseManager.openDatabase(uri);
await this.databaseManager.openDatabase(uri, {
type: "folder",
});
}
} catch (e) {
// rethrow and let this be handled by default error handling.
Expand Down Expand Up @@ -819,7 +824,9 @@ export class DatabaseUI extends DisposableObject {
if (byFolder) {
const fixedUri = await this.fixDbUri(uri);
// we are selecting a database folder
return await this.databaseManager.openDatabase(fixedUri);
return await this.databaseManager.openDatabase(fixedUri, {
type: "folder",
});
} else {
// we are selecting a database archive. Must unzip into a workspace-controlled area
// before importing.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { isLikelyDatabaseRoot } from "./db-contents-heuristics";
import { stat } from "fs-extra";
import { containsPath, pathsEqual } from "../../common/files";
import { DatabaseContents } from "./database-contents";
import { DatabaseOrigin } from "./database-origin";

export class DatabaseItemImpl implements DatabaseItem {
// These are only public in the implementation, they are readonly in the interface
Expand Down Expand Up @@ -61,6 +62,10 @@ export class DatabaseItemImpl implements DatabaseItem {
return this.options.dateAdded;
}

public get origin(): DatabaseOrigin | undefined {
return this.options.origin;
}

public resolveSourceFile(uriStr: string | undefined): vscode.Uri {
const sourceArchive = this.sourceArchive;
const uri = uriStr ? vscode.Uri.parse(uriStr, true) : undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import vscode from "vscode";
import * as cli from "../../codeql-cli/cli";
import { DatabaseContents } from "./database-contents";
import { DatabaseOptions } from "./database-options";
import { DatabaseOrigin } from "./database-origin";

/** An item in the list of available databases */
export interface DatabaseItem {
Expand All @@ -25,6 +26,11 @@ export interface DatabaseItem {
*/
readonly dateAdded: number | undefined;

/**
* The origin this database item was retrieved from or undefined if unknown.
*/
readonly origin: DatabaseOrigin | undefined;

/** If the database is invalid, describes why. */
readonly error: Error | undefined;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { DatabaseChangedEvent, DatabaseEventKind } from "./database-events";
import { DatabaseResolver } from "./database-resolver";
import { telemetryListener } from "../../common/vscode/telemetry";
import { LanguageContextStore } from "../../language-context-store";
import { DatabaseOrigin } from "./database-origin";

/**
* The name of the key in the workspaceState dictionary in which we
Expand Down Expand Up @@ -132,14 +133,19 @@ export class DatabaseManager extends DisposableObject {
*/
public async openDatabase(
uri: vscode.Uri,
origin: DatabaseOrigin | undefined,
makeSelected = true,
displayName?: string,
{
isTutorialDatabase = false,
addSourceArchiveFolder = addDatabaseSourceToWorkspace(),
}: OpenDatabaseOptions = {},
): Promise<DatabaseItem> {
const databaseItem = await this.createDatabaseItem(uri, displayName);
const databaseItem = await this.createDatabaseItem(
uri,
origin,
displayName,
);

return await this.addExistingDatabaseItem(
databaseItem,
Expand Down Expand Up @@ -190,6 +196,7 @@ export class DatabaseManager extends DisposableObject {
*/
private async createDatabaseItem(
uri: vscode.Uri,
origin: DatabaseOrigin | undefined,
displayName: string | undefined,
): Promise<DatabaseItemImpl> {
const contents = await DatabaseResolver.resolveDatabaseContents(uri);
Expand All @@ -198,6 +205,7 @@ export class DatabaseManager extends DisposableObject {
displayName,
dateAdded: Date.now(),
language: await this.getPrimaryLanguage(uri.fsPath),
origin,
};
const databaseItem = new DatabaseItemImpl(uri, contents, fullOptions);

Expand All @@ -213,6 +221,7 @@ export class DatabaseManager extends DisposableObject {
*/
public async createOrOpenDatabaseItem(
uri: vscode.Uri,
origin: DatabaseOrigin | undefined,
): Promise<DatabaseItem> {
const existingItem = this.findDatabaseItem(uri);
if (existingItem !== undefined) {
Expand All @@ -221,7 +230,7 @@ export class DatabaseManager extends DisposableObject {
}

// We don't add this to the list automatically, but the user can add it later.
return this.createDatabaseItem(uri, undefined);
return this.createDatabaseItem(uri, origin, undefined);
}

public async createSkeletonPacks(databaseItem: DatabaseItem) {
Expand Down Expand Up @@ -356,6 +365,7 @@ export class DatabaseManager extends DisposableObject {
let displayName: string | undefined = undefined;
let dateAdded = undefined;
let language = undefined;
let origin = undefined;
if (state.options) {
if (typeof state.options.displayName === "string") {
displayName = state.options.displayName;
Expand All @@ -364,6 +374,7 @@ export class DatabaseManager extends DisposableObject {
dateAdded = state.options.dateAdded;
}
language = state.options.language;
origin = state.options.origin;
}

const dbBaseUri = vscode.Uri.parse(state.uri, true);
Expand All @@ -376,6 +387,7 @@ export class DatabaseManager extends DisposableObject {
displayName,
dateAdded,
language,
origin,
};
const item = new DatabaseItemImpl(dbBaseUri, undefined, fullOptions);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { DatabaseOrigin } from "./database-origin";

export interface DatabaseOptions {
displayName?: string;
dateAdded?: number | undefined;
language?: string;
origin?: DatabaseOrigin;
}

export interface FullDatabaseOptions extends DatabaseOptions {
dateAdded: number | undefined;
language: string | undefined;
origin: DatabaseOrigin | undefined;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
interface DatabaseOriginFolder {
type: "folder";
}

interface DatabaseOriginArchive {
type: "archive";
path: string;
}

interface DatabaseOriginGitHub {
type: "github";
repository: string;
databaseId: number;
databaseCreatedAt: string;
commitOid: string | null;
}

interface DatabaseOriginInternet {
type: "url";
url: string;
}

interface DatabaseOriginDebugger {
type: "debugger";
}

export type DatabaseOrigin =
| DatabaseOriginFolder
| DatabaseOriginArchive
| DatabaseOriginGitHub
| DatabaseOriginInternet
| DatabaseOriginDebugger;
4 changes: 3 additions & 1 deletion extensions/ql-vscode/src/debugger/debugger-ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,9 @@ class QLDebugAdapterTracker
body: CodeQLProtocol.EvaluationStartedEvent["body"],
): Promise<void> {
const dbUri = Uri.file(this.configuration.database);
const dbItem = await this.dbm.createOrOpenDatabaseItem(dbUri);
const dbItem = await this.dbm.createOrOpenDatabaseItem(dbUri, {
type: "debugger",
});

// When cancellation is requested from the query history view, we just stop the debug session.
const tokenSource = new CancellationTokenSource();
Expand Down
1 change: 1 addition & 0 deletions extensions/ql-vscode/src/query-testing/test-runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export class TestRunner extends DisposableObject {
try {
const reopenedDatabase = await this.databaseManager.openDatabase(
uri,
closedDatabase.origin,
false,
);
await this.databaseManager.renameDatabaseItem(
Expand Down
3 changes: 3 additions & 0 deletions extensions/ql-vscode/test/factories/databases/databases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ export function mockDbOptions(): FullDatabaseOptions {
return {
dateAdded: 123,
language: "",
origin: {
type: "folder",
},
};
}

Expand Down
Loading