From 84c07feb2f51ce5da5cf456eb531a51341438201 Mon Sep 17 00:00:00 2001 From: Jason Daming Date: Fri, 1 Nov 2024 14:48:03 -0500 Subject: [PATCH] Stops Conflicting Vendordeps and Installs Required Ones (#715) --- vscode-wpilib/media/main.js | 5 + vscode-wpilib/src/dependencyView.ts | 97 ++++++++++++++++--- .../src/shared/vendorlibrariesbase.ts | 15 +++ vscode-wpilib/src/vendorlibraries.ts | 29 +++--- 4 files changed, 121 insertions(+), 25 deletions(-) diff --git a/vscode-wpilib/media/main.js b/vscode-wpilib/media/main.js index 26ba7538..62370dbb 100644 --- a/vscode-wpilib/media/main.js +++ b/vscode-wpilib/media/main.js @@ -115,6 +115,11 @@ document.getElementById('refresh-action')?.addEventListener('click', () => { vscode.postMessage({ type: 'refresh' }) }); + + // Listen for focus events + window.addEventListener('blur', () => { + vscode.postMessage({ type: 'blur' }); + }); } function addDropdownListeners() { diff --git a/vscode-wpilib/src/dependencyView.ts b/vscode-wpilib/src/dependencyView.ts index 29938861..c3e3976d 100644 --- a/vscode-wpilib/src/dependencyView.ts +++ b/vscode-wpilib/src/dependencyView.ts @@ -36,6 +36,7 @@ export class DependencyViewProvider implements vscode.WebviewViewProvider { private externalApi: IExternalAPI; private ghURL = `https://raw.githubusercontent.com/wpilibsuite/vendor-json-repo/master/`; private wp: vscode.WorkspaceFolder | undefined; + private changed = 0; private _view?: vscode.WebviewView; @@ -80,7 +81,15 @@ export class DependencyViewProvider implements vscode.WebviewViewProvider { void this.refresh(this.wp); webviewView.onDidChangeVisibility(() => { if (this.wp) { - void this.refresh(this.wp); + // If the webview becomes visible refresh it, invisible then check for changes + if (webviewView.visible) { + void this.refresh(this.wp); + } else { + if (this.changed > this.vendorLibraries.getLastBuild()) { + this.externalApi.getBuildTestAPI().buildCode(this.wp, undefined); + this.changed = 0; + } + } } }); @@ -118,6 +127,16 @@ export class DependencyViewProvider implements vscode.WebviewViewProvider { } break; } + case 'blur': + { + if (this.wp) { + if (this.changed > this.vendorLibraries.getLastBuild()) { + this.externalApi.getBuildTestAPI().buildCode(this.wp, undefined); + this.changed = 0; + } + } + break; + } default: { break; @@ -175,35 +194,74 @@ export class DependencyViewProvider implements vscode.WebviewViewProvider { } private async uninstall(index: string) { + this.sortInstalledDeps(); const uninstall = [this.installedDeps[parseInt(index, 10)]]; if (this.wp) { - await this.vendorLibraries.uninstallVendorLibraries(uninstall, this.wp); + const success = await this.vendorLibraries.uninstallVendorLibraries(uninstall, this.wp); + if (success) { + this.changed = Date.now(); + } await this.refresh(this.wp); } } private async getURLInstallDep(avail: IJsonList | undefined) { + if (avail && this.wp) { + const dep = await this.listToDependency(avail); + + if (dep) { + let conflictdep = undefined; + if (dep.conflictsWith) { + // Check to see if it conflicts with currently installed deps + for (const conflict of dep.conflictsWith) { + if (this.installedDeps.find(installedDep => installedDep.uuid === conflict.uuid)) { + conflictdep = conflict; + break; + } + } + } + + // If no conflict is found install otherwise show dialog + if (!conflictdep) { + const success = await this.vendorLibraries.installDependency(dep, this.vendorLibraries.getWpVendorFolder(this.wp), true); + + if (success) { + this.changed = Date.now(); + + if (dep.requires) { + let reqDep = undefined; + // Check to see if there are required deps and install those too + for (const required of dep.requires) { + reqDep = this.availableDeps.find(requiredDep => requiredDep.uuid === required.uuid); + const newDep = await this.listToDependency(reqDep); + if (reqDep && newDep) { + await this.vendorLibraries.installDependency(newDep, this.vendorLibraries.getWpVendorFolder(this.wp), true); + } + } + } + } + } else { + vscode.window.showErrorMessage(i18n('message', '{0}', conflictdep.errorMessage), {modal: true}); + } + } + } + } + + private async listToDependency(avail: IJsonList | undefined) { + let dependency = undefined; if (avail && this.wp) { // Check to see if it is already a URL let url = avail.path; if (url.substring(0, 4) !== 'http') { url = this.ghURL + url; } - let dep; try { - dep = await this.vendorLibraries.getJsonDepURL(url); + dependency = await this.vendorLibraries.getJsonDepURL(url); } catch { - dep = this.homeDeps.find(homdep => homdep.uuid === avail.uuid && homdep.version === avail.version); - } - - if (dep) { - const success = await this.vendorLibraries.installDependency(dep, this.vendorLibraries.getWpVendorFolder(this.wp), true); - - if (success) { - this.vendorLibraries.offerBuild(this.wp); - } + dependency = this.homeDeps.find(homdep => homdep.uuid === avail.uuid && homdep.version === avail.version); } } + return dependency; } public addDependency() { @@ -305,6 +363,19 @@ export class DependencyViewProvider implements vscode.WebviewViewProvider { }); } + private sortInstalledDeps() { + this.installedDeps.sort((a, b) => { + if (a.name.toLowerCase() > b.name.toLowerCase()) { + return 1; + } + else if (a.name.toLowerCase() === b.name.toLowerCase()) { + return 0; + } else { + return -1; + } + }); + } + private sortAvailable() { this.availableDepsList.sort((a, b) => { if (a.name.toLowerCase() > b.name.toLowerCase()) { diff --git a/vscode-wpilib/src/shared/vendorlibrariesbase.ts b/vscode-wpilib/src/shared/vendorlibrariesbase.ts index 8ec4aad8..91b2c04b 100644 --- a/vscode-wpilib/src/shared/vendorlibrariesbase.ts +++ b/vscode-wpilib/src/shared/vendorlibrariesbase.ts @@ -12,6 +12,21 @@ export interface IJsonDependency { uuid: string; jsonUrl: string; fileName: string; + conflictsWith: IJsonConflicts[] | undefined; + requires: IJsonRequires[] | undefined; +} + +export interface IJsonRequires { + uuid: string; + errorMessage: string; + offlineFileName: string; + onlineUrl: string; +} + +export interface IJsonConflicts { + uuid: string; + errorMessage: string; + offlineFileName: string; } export function isJsonDependency(arg: unknown): arg is IJsonDependency { diff --git a/vscode-wpilib/src/vendorlibraries.ts b/vscode-wpilib/src/vendorlibraries.ts index abb00b34..899998d9 100644 --- a/vscode-wpilib/src/vendorlibraries.ts +++ b/vscode-wpilib/src/vendorlibraries.ts @@ -37,6 +37,7 @@ class LibraryQuickPick implements vscode.QuickPickItem { export class VendorLibraries extends VendorLibrariesBase { private disposables: vscode.Disposable[] = []; private externalApi: IExternalAPI; + private lastBuildTime = 1; constructor(externalApi: IExternalAPI) { super(externalApi.getUtilitiesAPI()); @@ -127,9 +128,9 @@ export class VendorLibraries extends VendorLibrariesBase { } } - public async uninstallVendorLibraries(toRemove: IJsonDependency[] | undefined, workspace: vscode.WorkspaceFolder) { + public async uninstallVendorLibraries(toRemove: IJsonDependency[] | undefined, workspace: vscode.WorkspaceFolder): Promise { + let anySucceeded = false; if (toRemove !== undefined) { - let anySucceeded = false; const url = this.getWpVendorFolder(workspace); const files = await readdirAsync(url); for (const file of files) { @@ -144,11 +145,8 @@ export class VendorLibraries extends VendorLibrariesBase { } } } - - if (anySucceeded) { - this.offerBuild(workspace); - } } + return anySucceeded; } private async offlineUpdates(workspace: vscode.WorkspaceFolder): Promise { @@ -185,7 +183,7 @@ export class VendorLibraries extends VendorLibrariesBase { } } if (anySucceeded) { - this.offerBuild(workspace); + this.offerBuild(workspace, true); } } } else { @@ -241,7 +239,7 @@ export class VendorLibraries extends VendorLibrariesBase { } } if (anySucceeded) { - this.offerBuild(workspace); + this.offerBuild(workspace, true); } } } else { @@ -287,7 +285,7 @@ export class VendorLibraries extends VendorLibrariesBase { } } if (anySucceeded) { - this.offerBuild(workspace); + this.offerBuild(workspace, true); } } } else { @@ -316,7 +314,7 @@ export class VendorLibraries extends VendorLibrariesBase { const success = await this.installDependency(file, this.getWpVendorFolder(workspace), true); if (success) { - this.offerBuild(workspace); + this.offerBuild(workspace, true); } else { vscode.window.showErrorMessage(i18n('message', 'Failed to install {0}', file.name)); } @@ -331,15 +329,22 @@ export class VendorLibraries extends VendorLibrariesBase { return this.getDependencies(this.getWpVendorFolder(workspace)); } - public async offerBuild(workspace: vscode.WorkspaceFolder) { + public async offerBuild(workspace: vscode.WorkspaceFolder, modal = false): Promise { const buildRes = await vscode.window.showInformationMessage(i18n('message', 'It is recommended to run a "Build" after a vendor update. ' + 'Would you like to do this now?'), { - modal: false, + modal: modal }, {title: i18n('ui', 'Yes')}, {title: i18n('ui', 'No'), isCloseAffordance: true}); if (buildRes?.title === i18n('ui', 'Yes')) { await this.externalApi.getBuildTestAPI().buildCode(workspace, undefined); + this.lastBuildTime = Date.now(); + return true; } + return false; + } + + public getLastBuild(): number { + return this.lastBuildTime; } }