Skip to content

Refactor how we import database archives #370

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

Merged
merged 1 commit into from
May 15, 2020
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
41 changes: 35 additions & 6 deletions extensions/ql-vscode/src/databaseFetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,23 @@ import { Uri, ProgressOptions, ProgressLocation, commands, window } from "vscode
import * as fs from "fs-extra";
import * as path from "path";
import { DatabaseManager, DatabaseItem } from "./databases";
import { ProgressCallback, showAndLogErrorMessage, withProgress } from "./helpers";
import { ProgressCallback, showAndLogErrorMessage, withProgress, showAndLogInformationMessage } from "./helpers";

/**
* Prompts a user to fetch a database from a remote location. Database is assumed to be an archive file.
*
* @param databasesManager the DatabaseManager
* @param storagePath where to store the unzipped database.
*/
export default async function promptFetchDatabase(databasesManager: DatabaseManager, storagePath: string): Promise<DatabaseItem | undefined> {
export async function promptImportInternetDatabase(databasesManager: DatabaseManager, storagePath: string): Promise<DatabaseItem | undefined> {
let item: DatabaseItem | undefined = undefined;

try {
const databaseUrl = await window.showInputBox({
prompt: 'Enter URL of zipfile of database to download'
});
if (databaseUrl) {
validateUrl(databaseUrl);
validateHttpsUrl(databaseUrl);

const progressOptions: ProgressOptions = {
location: ProgressLocation.Notification,
Expand All @@ -30,13 +30,41 @@ export default async function promptFetchDatabase(databasesManager: DatabaseMana
await withProgress(progressOptions, async progress => (item = await databaseArchiveFetcher(databaseUrl, databasesManager, storagePath, progress)));
commands.executeCommand('codeQLDatabases.focus');
}
showAndLogInformationMessage('Database downloaded and imported successfully.');
} catch (e) {
showAndLogErrorMessage(e.message);
}

return item;
}


/**
* Imports a database from a local archive.
*
* @param databaseUrl the file url of the archive to import
* @param databasesManager the DatabaseManager
* @param storagePath where to store the unzipped database.
*/
export async function importArchiveDatabase(databaseUrl: string, databasesManager: DatabaseManager, storagePath: string): Promise<DatabaseItem | undefined> {
let item: DatabaseItem | undefined = undefined;
try {
const progressOptions: ProgressOptions = {
location: ProgressLocation.Notification,
title: 'Importing database from archive',
cancellable: false,
};
await withProgress(progressOptions, async progress => (item = await databaseArchiveFetcher(databaseUrl, databasesManager, storagePath, progress)));
commands.executeCommand('codeQLDatabases.focus');

showAndLogInformationMessage('Database unzipped and imported successfully.');
} catch (e) {
showAndLogErrorMessage(e.message);
}
return item;
}


/**
* Fetches an archive database. The database might be on the internet
* or in the local filesystem.
Expand All @@ -46,15 +74,15 @@ export default async function promptFetchDatabase(databasesManager: DatabaseMana
* @param storagePath where to store the unzipped database.
* @param progressCallback optional callback to send progress messages to
*/
export async function databaseArchiveFetcher(
async function databaseArchiveFetcher(
databaseUrl: string,
databasesManager: DatabaseManager,
storagePath: string,
progressCallback?: ProgressCallback
): Promise<DatabaseItem> {
progressCallback?.({
maxStep: 3,
message: 'Downloading database',
message: 'Getting database',
step: 1
});
if (!storagePath) {
Expand All @@ -75,6 +103,7 @@ export async function databaseArchiveFetcher(
step: 3
});

// find the path to the database. The actual database might be in a sub-folder
const dbPath = await findDirWithFile(unzipPath, '.dbinfo', 'codeql-database.yml');
if (dbPath) {
const item = await databasesManager.openDatabase(Uri.parse(dbPath));
Expand Down Expand Up @@ -106,7 +135,7 @@ async function getStorageFolder(storagePath: string, urlStr: string) {
}


function validateUrl(databaseUrl: string) {
function validateHttpsUrl(databaseUrl: string) {
let uri;
try {
uri = Uri.parse(databaseUrl, true);
Expand Down
8 changes: 4 additions & 4 deletions extensions/ql-vscode/src/databases-ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { logger } from './logging';
import { clearCacheInDatabase, UserCancellationException } from './run-queries';
import * as qsClient from './queryserver-client';
import { upgradeDatabase } from './upgrades';
import promptFetchDatabase, { databaseArchiveFetcher } from './databaseFetcher';
import { importArchiveDatabase, promptImportInternetDatabase } from './databaseFetcher';

type ThemableIconPath = { light: string; dark: string } | string;

Expand Down Expand Up @@ -212,7 +212,7 @@ export class DatabaseUI extends DisposableObject {
}

private handleChooseDatabaseInternet = async (): Promise<DatabaseItem | undefined> => {
return await promptFetchDatabase(this.databaseManager, this.storagePath);
return await promptImportInternetDatabase(this.databaseManager, this.storagePath);
}

private handleSortByName = async () => {
Expand Down Expand Up @@ -292,7 +292,7 @@ export class DatabaseUI extends DisposableObject {
private handleSetCurrentDatabase = async (uri: Uri): Promise<DatabaseItem | undefined> => {
// Assume user has selected an archive if the file has a .zip extension
if (uri.path.endsWith('.zip')) {
return await databaseArchiveFetcher(uri.toString(), this.databaseManager, this.storagePath);
return await importArchiveDatabase(uri.toString(), this.databaseManager, this.storagePath);
}

return await this.setCurrentDatabase(uri);
Expand Down Expand Up @@ -366,7 +366,7 @@ export class DatabaseUI extends DisposableObject {
else {
// we are selecting a database archive. Must unzip into a workspace-controlled area
// before importing.
return await databaseArchiveFetcher(uri.toString(), this.databaseManager, this.storagePath);
return await importArchiveDatabase(uri.toString(), this.databaseManager, this.storagePath);
}
}
}
4 changes: 2 additions & 2 deletions extensions/ql-vscode/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { displayQuickQuery } from './quick-query';
import { compileAndRunQueryAgainstDatabase, tmpDirDisposal, UserCancellationException } from './run-queries';
import { QLTestAdapterFactory } from './test-adapter';
import { TestUIService } from './test-ui';
import promptFetchDatabase from './databaseFetcher';
import { promptImportInternetDatabase } from './databaseFetcher';

/**
* extension.ts
Expand Down Expand Up @@ -335,7 +335,7 @@ async function activateWithInstalledDistribution(ctx: ExtensionContext, distribu
await qs.restartQueryServer();
helpers.showAndLogInformationMessage('CodeQL Query Server restarted.', { outputLogger: queryServerLogger });
}));
ctx.subscriptions.push(commands.registerCommand('codeQL.downloadDatabase', () => promptFetchDatabase(dbm, getContextStoragePath(ctx))));
ctx.subscriptions.push(commands.registerCommand('codeQL.downloadDatabase', () => promptImportInternetDatabase(dbm, getContextStoragePath(ctx))));

ctx.subscriptions.push(client.start());

Expand Down