Remember last workspace or directory

This commit is contained in:
Asher 2019-10-11 14:26:20 -05:00
parent ae43e2016f
commit 4ae2c81157
No known key found for this signature in database
GPG Key ID: D63C1EF81242354A

View File

@ -445,6 +445,15 @@ export abstract class Server {
} }
} }
interface StartPath {
path?: string[] | string;
workspace?: boolean;
}
interface Settings {
lastVisited?: StartPath;
}
export class MainServer extends Server { export class MainServer extends Server {
public readonly _onDidClientConnect = new Emitter<ClientConnectionEvent>(); public readonly _onDidClientConnect = new Emitter<ClientConnectionEvent>();
public readonly onDidClientConnect = this._onDidClientConnect.event; public readonly onDidClientConnect = this._onDidClientConnect.event;
@ -461,6 +470,8 @@ export class MainServer extends Server {
private _proxyServer?: Promise<net.Server>; private _proxyServer?: Promise<net.Server>;
private readonly proxyTimeout = 5000; private readonly proxyTimeout = 5000;
private settings: Settings = {};
public constructor(options: ServerOptions, args: ParsedArgs) { public constructor(options: ServerOptions, args: ParsedArgs) {
super(options); super(options);
this.servicesPromise = this.initializeServices(args); this.servicesPromise = this.initializeServices(args);
@ -528,44 +539,37 @@ export class MainServer extends Server {
private async getRoot(request: http.IncomingMessage, parsedUrl: url.UrlWithParsedQuery): Promise<Response> { private async getRoot(request: http.IncomingMessage, parsedUrl: url.UrlWithParsedQuery): Promise<Response> {
const filePath = path.join(this.rootPath, "out/vs/code/browser/workbench/workbench.html"); const filePath = path.join(this.rootPath, "out/vs/code/browser/workbench/workbench.html");
let [content] = await Promise.all([ let [content, startPath] = await Promise.all([
util.promisify(fs.readFile)(filePath, "utf8"), util.promisify(fs.readFile)(filePath, "utf8"),
this.getFirstValidPath([
{ path: parsedUrl.query.workspace, workspace: true },
{ path: parsedUrl.query.folder },
(await this.readSettings()).lastVisited,
{ path: this.options.folderUri }
]),
this.servicesPromise, this.servicesPromise,
]); ]);
if (startPath) {
this.writeSettings({
lastVisited: {
path: startPath.uri.fsPath,
workspace: startPath.workspace
},
});
}
const logger = this.services.get(ILogService) as ILogService; const logger = this.services.get(ILogService) as ILogService;
logger.info("request.url", `"${request.url}"`); logger.info("request.url", `"${request.url}"`);
const cwd = process.env.VSCODE_CWD || process.cwd();
const remoteAuthority = request.headers.host as string; const remoteAuthority = request.headers.host as string;
const transformer = getUriTransformer(remoteAuthority); const transformer = getUriTransformer(remoteAuthority);
const validatePath = async (filePath: string[] | string | undefined, isDirectory: boolean, unsetFallback?: string): Promise<UriComponents | undefined> => {
if (!filePath || filePath.length === 0) {
if (!unsetFallback) {
return undefined;
}
filePath = unsetFallback;
} else if (Array.isArray(filePath)) {
filePath = filePath[0];
}
const uri = URI.file(sanitizeFilePath(filePath, cwd));
try {
const stat = await util.promisify(fs.stat)(uri.fsPath);
if (isDirectory !== stat.isDirectory()) {
return undefined;
}
} catch (error) {
return undefined;
}
return transformer.transformOutgoing(uri);
};
const environment = this.services.get(IEnvironmentService) as IEnvironmentService; const environment = this.services.get(IEnvironmentService) as IEnvironmentService;
const options: Options = { const options: Options = {
WORKBENCH_WEB_CONGIGURATION: { WORKBENCH_WEB_CONGIGURATION: {
workspaceUri: await validatePath(parsedUrl.query.workspace, false), workspaceUri: startPath && startPath.workspace ? transformer.transformOutgoing(startPath.uri) : undefined,
folderUri: !parsedUrl.query.workspace ? await validatePath(parsedUrl.query.folder, true, this.options.folderUri) : undefined, folderUri: startPath && !startPath.workspace ? transformer.transformOutgoing(startPath.uri) : undefined,
remoteAuthority, remoteAuthority,
productConfiguration: product, productConfiguration: product,
}, },
@ -581,6 +585,34 @@ export class MainServer extends Server {
return { content, filePath }; return { content, filePath };
} }
/**
* Choose the first valid path.
*/
private async getFirstValidPath(startPaths: Array<StartPath | undefined>): Promise<{ uri: URI, workspace?: boolean} | undefined> {
const logger = this.services.get(ILogService) as ILogService;
const cwd = process.env.VSCODE_CWD || process.cwd();
for (let i = 0; i < startPaths.length; ++i) {
const startPath = startPaths[i];
if (!startPath) {
continue;
}
const paths = typeof startPath.path === "string" ? [startPath.path] : (startPath.path || []);
for (let j = 0; j < paths.length; ++j) {
const uri = URI.file(sanitizeFilePath(paths[j], cwd));
try {
const stat = await util.promisify(fs.stat)(uri.fsPath);
// Workspace must be a file.
if (!!startPath.workspace !== stat.isDirectory()) {
return { uri, workspace: startPath.workspace };
}
} catch (error) {
logger.warn(error.message);
}
}
}
return undefined;
}
private async connect(message: ConnectionTypeRequest, protocol: Protocol): Promise<void> { private async connect(message: ConnectionTypeRequest, protocol: Protocol): Promise<void> {
if (product.commit && message.commit !== product.commit) { if (product.commit && message.commit !== product.commit) {
throw new Error(`Version mismatch (${message.commit} instead of ${product.commit})`); throw new Error(`Version mismatch (${message.commit} instead of ${product.commit})`);
@ -810,4 +842,41 @@ export class MainServer extends Server {
} }
return path; return path;
} }
/**
* Return the file path for Coder settings.
*/
private get settingsPath(): string {
const environment = this.services.get(IEnvironmentService) as IEnvironmentService;
return path.join(environment.userDataPath, "coder.json");
}
/**
* Read settings from the file. On a failure return last known settings and
* log a warning.
*
*/
private async readSettings(): Promise<Settings> {
try {
const raw = (await util.promisify(fs.readFile)(this.settingsPath, "utf8")).trim();
this.settings = raw ? JSON.parse(raw) : {};
} catch (error) {
if (error.code !== "ENOENT") {
(this.services.get(ILogService) as ILogService).warn(error.message);
}
}
return this.settings;
}
/**
* Write settings combined with current settings. On failure log a warning.
*/
private async writeSettings(newSettings: Partial<Settings>): Promise<void> {
this.settings = { ...this.settings, ...newSettings };
try {
await util.promisify(fs.writeFile)(this.settingsPath, JSON.stringify(this.settings));
} catch (error) {
(this.services.get(ILogService) as ILogService).warn(error.message);
}
}
} }