Skip to content

Commit 4ae2c81

Browse files
committed
Remember last workspace or directory
1 parent ae43e20 commit 4ae2c81

File tree

1 file changed

+94
-25
lines changed

1 file changed

+94
-25
lines changed

src/node/server.ts

Lines changed: 94 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,15 @@ export abstract class Server {
445445
}
446446
}
447447

448+
interface StartPath {
449+
path?: string[] | string;
450+
workspace?: boolean;
451+
}
452+
453+
interface Settings {
454+
lastVisited?: StartPath;
455+
}
456+
448457
export class MainServer extends Server {
449458
public readonly _onDidClientConnect = new Emitter<ClientConnectionEvent>();
450459
public readonly onDidClientConnect = this._onDidClientConnect.event;
@@ -461,6 +470,8 @@ export class MainServer extends Server {
461470
private _proxyServer?: Promise<net.Server>;
462471
private readonly proxyTimeout = 5000;
463472

473+
private settings: Settings = {};
474+
464475
public constructor(options: ServerOptions, args: ParsedArgs) {
465476
super(options);
466477
this.servicesPromise = this.initializeServices(args);
@@ -528,44 +539,37 @@ export class MainServer extends Server {
528539

529540
private async getRoot(request: http.IncomingMessage, parsedUrl: url.UrlWithParsedQuery): Promise<Response> {
530541
const filePath = path.join(this.rootPath, "out/vs/code/browser/workbench/workbench.html");
531-
let [content] = await Promise.all([
542+
let [content, startPath] = await Promise.all([
532543
util.promisify(fs.readFile)(filePath, "utf8"),
544+
this.getFirstValidPath([
545+
{ path: parsedUrl.query.workspace, workspace: true },
546+
{ path: parsedUrl.query.folder },
547+
(await this.readSettings()).lastVisited,
548+
{ path: this.options.folderUri }
549+
]),
533550
this.servicesPromise,
534551
]);
535552

553+
if (startPath) {
554+
this.writeSettings({
555+
lastVisited: {
556+
path: startPath.uri.fsPath,
557+
workspace: startPath.workspace
558+
},
559+
});
560+
}
561+
536562
const logger = this.services.get(ILogService) as ILogService;
537563
logger.info("request.url", `"${request.url}"`);
538564

539-
const cwd = process.env.VSCODE_CWD || process.cwd();
540-
541565
const remoteAuthority = request.headers.host as string;
542566
const transformer = getUriTransformer(remoteAuthority);
543-
const validatePath = async (filePath: string[] | string | undefined, isDirectory: boolean, unsetFallback?: string): Promise<UriComponents | undefined> => {
544-
if (!filePath || filePath.length === 0) {
545-
if (!unsetFallback) {
546-
return undefined;
547-
}
548-
filePath = unsetFallback;
549-
} else if (Array.isArray(filePath)) {
550-
filePath = filePath[0];
551-
}
552-
const uri = URI.file(sanitizeFilePath(filePath, cwd));
553-
try {
554-
const stat = await util.promisify(fs.stat)(uri.fsPath);
555-
if (isDirectory !== stat.isDirectory()) {
556-
return undefined;
557-
}
558-
} catch (error) {
559-
return undefined;
560-
}
561-
return transformer.transformOutgoing(uri);
562-
};
563567

564568
const environment = this.services.get(IEnvironmentService) as IEnvironmentService;
565569
const options: Options = {
566570
WORKBENCH_WEB_CONGIGURATION: {
567-
workspaceUri: await validatePath(parsedUrl.query.workspace, false),
568-
folderUri: !parsedUrl.query.workspace ? await validatePath(parsedUrl.query.folder, true, this.options.folderUri) : undefined,
571+
workspaceUri: startPath && startPath.workspace ? transformer.transformOutgoing(startPath.uri) : undefined,
572+
folderUri: startPath && !startPath.workspace ? transformer.transformOutgoing(startPath.uri) : undefined,
569573
remoteAuthority,
570574
productConfiguration: product,
571575
},
@@ -581,6 +585,34 @@ export class MainServer extends Server {
581585
return { content, filePath };
582586
}
583587

588+
/**
589+
* Choose the first valid path.
590+
*/
591+
private async getFirstValidPath(startPaths: Array<StartPath | undefined>): Promise<{ uri: URI, workspace?: boolean} | undefined> {
592+
const logger = this.services.get(ILogService) as ILogService;
593+
const cwd = process.env.VSCODE_CWD || process.cwd();
594+
for (let i = 0; i < startPaths.length; ++i) {
595+
const startPath = startPaths[i];
596+
if (!startPath) {
597+
continue;
598+
}
599+
const paths = typeof startPath.path === "string" ? [startPath.path] : (startPath.path || []);
600+
for (let j = 0; j < paths.length; ++j) {
601+
const uri = URI.file(sanitizeFilePath(paths[j], cwd));
602+
try {
603+
const stat = await util.promisify(fs.stat)(uri.fsPath);
604+
// Workspace must be a file.
605+
if (!!startPath.workspace !== stat.isDirectory()) {
606+
return { uri, workspace: startPath.workspace };
607+
}
608+
} catch (error) {
609+
logger.warn(error.message);
610+
}
611+
}
612+
}
613+
return undefined;
614+
}
615+
584616
private async connect(message: ConnectionTypeRequest, protocol: Protocol): Promise<void> {
585617
if (product.commit && message.commit !== product.commit) {
586618
throw new Error(`Version mismatch (${message.commit} instead of ${product.commit})`);
@@ -810,4 +842,41 @@ export class MainServer extends Server {
810842
}
811843
return path;
812844
}
845+
846+
/**
847+
* Return the file path for Coder settings.
848+
*/
849+
private get settingsPath(): string {
850+
const environment = this.services.get(IEnvironmentService) as IEnvironmentService;
851+
return path.join(environment.userDataPath, "coder.json");
852+
}
853+
854+
/**
855+
* Read settings from the file. On a failure return last known settings and
856+
* log a warning.
857+
*
858+
*/
859+
private async readSettings(): Promise<Settings> {
860+
try {
861+
const raw = (await util.promisify(fs.readFile)(this.settingsPath, "utf8")).trim();
862+
this.settings = raw ? JSON.parse(raw) : {};
863+
} catch (error) {
864+
if (error.code !== "ENOENT") {
865+
(this.services.get(ILogService) as ILogService).warn(error.message);
866+
}
867+
}
868+
return this.settings;
869+
}
870+
871+
/**
872+
* Write settings combined with current settings. On failure log a warning.
873+
*/
874+
private async writeSettings(newSettings: Partial<Settings>): Promise<void> {
875+
this.settings = { ...this.settings, ...newSettings };
876+
try {
877+
await util.promisify(fs.writeFile)(this.settingsPath, JSON.stringify(this.settings));
878+
} catch (error) {
879+
(this.services.get(ILogService) as ILogService).warn(error.message);
880+
}
881+
}
813882
}

0 commit comments

Comments
 (0)