Guard against no workspaces root.

Signed-off-by: Akos Kitta <kittaakos@typefox.io>
This commit is contained in:
Akos Kitta 2019-05-08 12:10:29 +02:00 committed by Christian Weichel
parent d8625ad9c3
commit bfb0edf50c
7 changed files with 98 additions and 17 deletions

View File

@ -1,4 +1,6 @@
import { inject, injectable } from 'inversify';
import URI from '@theia/core/lib/common/uri';
import { FileSystem } from '@theia/filesystem/lib/common';
import { WorkspaceService } from '@theia/workspace/lib/browser/workspace-service';
import { WorkspaceServiceExt } from './workspace-service-ext';
@ -8,6 +10,9 @@ import { WorkspaceServiceExt } from './workspace-service-ext';
@injectable()
export class WorkspaceServiceExtImpl implements WorkspaceServiceExt {
@inject(FileSystem)
protected readonly fileSystem: FileSystem;
@inject(WorkspaceService)
protected readonly delegate: WorkspaceService;
@ -16,4 +21,27 @@ export class WorkspaceServiceExtImpl implements WorkspaceServiceExt {
return stats.map(stat => stat.uri);
}
}
async defaultWorkspaceUri(): Promise<string> {
const home = await this.fileSystem.getCurrentUserHome();
if (home) {
return new URI(home.uri).resolve('Arduino-PoC').resolve('workspace').toString();
}
throw new Error(`Could not locate current user's home folder.`);
}
async defaultDownloadsDirUri(): Promise<string> {
const home = await this.fileSystem.getCurrentUserHome();
if (home) {
return new URI(home.uri).resolve('Arduino-PoC').resolve('downloads').toString();
}
throw new Error(`Could not locate current user's home folder.`);
}
async defaultDataDirUri(): Promise<string> {
const home = await this.fileSystem.getCurrentUserHome();
if (home) {
return new URI(home.uri).resolve('Arduino-PoC').resolve('data').toString();
}
throw new Error(`Could not locate current user's home folder.`);
}
}

View File

@ -2,4 +2,11 @@ export const WorkspaceServiceExtPath = '/services/workspace-service-ext';
export const WorkspaceServiceExt = Symbol('WorkspaceServiceExt');
export interface WorkspaceServiceExt {
roots(): Promise<string[]>;
/**
* By default it is under `~/Arduino-PoC/workspace`.
* It might not exist yet.
*/
defaultWorkspaceUri(): Promise<string>;
defaultDownloadsDirUri(): Promise<string>;
defaultDataDirUri(): Promise<string>;
}

View File

@ -17,7 +17,11 @@ export class BoardsServiceImpl implements BoardsService {
protected selectedBoard: Board | undefined;
public async getAttachedBoards(): Promise<{ boards: Board[] }> {
const { client, instance } = await this.coreClientProvider.getClient();
const coreClient = await this.coreClientProvider.getClient();
if (!coreClient) {
return { boards: [] };
}
const { client, instance } = coreClient;
const req = new BoardListReq();
req.setInstance(instance);
@ -51,12 +55,16 @@ export class BoardsServiceImpl implements BoardsService {
}
async search(options: { query?: string }): Promise<{ items: BoardPackage[] }> {
const { client, instance } = await this.coreClientProvider.getClient();
const coreClient = await this.coreClientProvider.getClient();
if (!coreClient) {
return { items: [] };
}
const { client, instance } = coreClient;
const installedPlatformsReq = new PlatformListReq();
installedPlatformsReq.setInstance(instance);
const installedPlatformsResp = await new Promise<PlatformListResp>((resolve, reject) =>
client.platformList(installedPlatformsReq, (err, resp) => (!!err ? reject : resolve)(!!err ? err : resp))
client.platformList(installedPlatformsReq, (err, resp) => (!!err ? reject : resolve)(!!err ? err : resp))
);
const installedPlatforms = installedPlatformsResp.getInstalledPlatformList();
@ -90,7 +98,11 @@ export class BoardsServiceImpl implements BoardsService {
}
async install(pkg: BoardPackage): Promise<void> {
const { client, instance } = await this.coreClientProvider.getClient();
const coreClient = await this.coreClientProvider.getClient();
if (!coreClient) {
return;
}
const { client, instance } = coreClient;
const [ platform, boardName ] = pkg.id.split(":");

View File

@ -9,10 +9,12 @@ import { CoreClientProvider, Client } from './core-client-provider';
import * as PQueue from 'p-queue';
import { ToolOutputServiceServer } from '../common/protocol/tool-output-service';
import { Instance } from './cli-protocol/common_pb';
import * as fs from 'fs-extra';
@injectable()
export class CoreClientProviderImpl implements CoreClientProvider {
protected clients = new Map<string, Client>();
protected readonly clientRequestQueue = new PQueue({ autoStart: true, concurrency: 1 });
@inject(FileSystem)
@ -24,10 +26,8 @@ export class CoreClientProviderImpl implements CoreClientProvider {
@inject(ToolOutputServiceServer)
protected readonly toolOutputService: ToolOutputServiceServer;
protected clients = new Map<string, Client>();
async getClient(workspaceRootOrResourceUri?: string): Promise<Client> {
return this.clientRequestQueue.add(() => new Promise<Client>(async resolve => {
async getClient(workspaceRootOrResourceUri?: string): Promise<Client | undefined> {
return this.clientRequestQueue.add(() => new Promise<Client | undefined>(async resolve => {
const roots = await this.workspaceServiceExt.roots();
if (!workspaceRootOrResourceUri) {
resolve(this.getOrCreateClient(roots[0]));
@ -47,7 +47,10 @@ export class CoreClientProviderImpl implements CoreClientProvider {
}));
}
protected async getOrCreateClient(rootUri: string): Promise<Client> {
protected async getOrCreateClient(rootUri: string | undefined): Promise<Client | undefined> {
if (!rootUri) {
return undefined;
}
const existing = this.clients.get(rootUri);
if (existing) {
console.debug(`Reusing existing client for ${rootUri}.`);
@ -60,11 +63,30 @@ export class CoreClientProviderImpl implements CoreClientProvider {
const config = new Configuration();
const rootPath = await this.fileSystem.getFsPath(rootUri);
if (!rootPath) {
throw new Error(`Could not resolve file-system path of URI: ${rootUri}.`);
throw new Error(`Could not resolve filesystem path of URI: ${rootUri}.`);
}
const defaultDownloadsDirUri = await this.workspaceServiceExt.defaultDownloadsDirUri();
const defaultDownloadsDirPath = await this.fileSystem.getFsPath(defaultDownloadsDirUri);
if (!defaultDownloadsDirPath) {
throw new Error(`Could not resolve filesystem path of URI: ${defaultDownloadsDirUri}.`);
}
if (!fs.existsSync(defaultDownloadsDirPath)) {
fs.mkdirpSync(defaultDownloadsDirPath);
}
const defaultDataDirUri = await this.workspaceServiceExt.defaultDataDirUri();
const defaultDataDirPath = await this.fileSystem.getFsPath(defaultDataDirUri);
if (!defaultDataDirPath) {
throw new Error(`Could not resolve filesystem path of URI: ${defaultDataDirUri}.`);
}
if (!fs.existsSync(defaultDataDirPath)) {
fs.mkdirpSync(defaultDataDirPath);
}
config.setSketchbookdir(rootPath);
config.setDatadir(rootPath);
config.setDownloadsdir(rootPath);
config.setDatadir(defaultDataDirPath);
config.setDownloadsdir(defaultDownloadsDirPath);
const initReq = new InitReq();
initReq.setConfiguration(config);

View File

@ -4,7 +4,7 @@ import { ArduinoCoreClient } from './cli-protocol/commands_grpc_pb';
export const CoreClientProviderPath = '/services/core-client-provider';
export const CoreClientProvider = Symbol('CoreClientProvider');
export interface CoreClientProvider {
getClient(workspaceRootOrResourceUri?: string): Promise<Client>;
getClient(workspaceRootOrResourceUri?: string): Promise<Client | undefined>;
}
export interface Client {

View File

@ -32,7 +32,11 @@ export class CoreServiceImpl implements CoreService {
}
const sketchpath = path.dirname(sketchFilePath);
const { client, instance } = await this.coreClientProvider.getClient(uri);
const coreClient = await this.coreClientProvider.getClient(uri);
if (!coreClient) {
return;
}
const { client, instance } = coreClient;
const currentBoard = await this.boardsService.getSelectBoard();
if (!currentBoard) {
@ -86,7 +90,11 @@ export class CoreServiceImpl implements CoreService {
throw new Error(`selected board (${currentBoard.name}) has no FQBN`);
}
const { client, instance } = await this.coreClientProvider.getClient(uri);
const coreClient = await this.coreClientProvider.getClient(uri);
if (!coreClient) {
return;
}
const { client, instance } = coreClient;
const req = new UploadReq();
req.setInstance(instance);

View File

@ -15,7 +15,11 @@ export class LibraryServiceImpl implements LibraryService {
protected readonly toolOutputService: ToolOutputServiceServer;
async search(options: { query?: string; }): Promise<{ items: Library[] }> {
const { client, instance } = await this.coreClientProvider.getClient();
const coreClient = await this.coreClientProvider.getClient();
if (!coreClient) {
return { items: [] };
}
const { client, instance } = coreClient;
const listReq = new LibraryListReq();
listReq.setInstance(instance);