Wait for profiles before creating first terminal

Fixes #123188
This commit is contained in:
Daniel Imms 2021-05-12 16:06:13 -07:00
parent 2e2dc15945
commit dd54e2b24a
7 changed files with 39 additions and 30 deletions

View file

@ -210,7 +210,6 @@ export class DefaultConfigurationModel extends ConfigurationModel {
});
}
}
console.log({ contents, keys, overrides });
super(contents, keys, overrides);
}
}

View file

@ -195,7 +195,6 @@ class ConfigurationRegistry implements IConfigurationRegistry {
}
public registerConfiguration(configuration: IConfigurationNode, validate: boolean = true): void {
console.trace('registerConfiguration', configuration);
this.registerConfigurations([configuration], validate);
}

View file

@ -218,8 +218,6 @@ export class PtyHostService extends Disposable implements IPtyService {
return this._proxy.getDefaultSystemShell(osOverride);
}
async getProfiles(includeDetectedProfiles: boolean = false): Promise<ITerminalProfile[]> {
const vars = this._resolveVariables([`Path: \${env:PATH}`, 'b']);
this._logService.info('vars', await vars);
// return detectAvailableProfiles(configuredProfilesOnly, safeConfigProvider, undefined, this._logService, await this._variableResolverPromise, this._lastActiveWorkspace);
// const variableResolver: IConfigurationResolverService {
// resolveAsync(folder: IWorkspaceFolder | undefined, value: string): Promise<string> {
@ -335,15 +333,11 @@ export class PtyHostService extends Disposable implements IPtyService {
private _buildSafeConfigProvider(): SafeConfigProvider {
return (key: string) => {
console.log('namespace', this._configurationService.getValue('terminal.integrated'));
const isWorkspaceConfigAllowed = this._configurationService.getValue('terminal.integrated.allowWorkspaceConfiguration');
console.log('isWorkspaceConfigAllowed?', isWorkspaceConfigAllowed);
if (isWorkspaceConfigAllowed) {
console.log('inspected 1', key, this._configurationService.getValue(key));
return this._configurationService.getValue(key) as any;
}
const inspected = this._configurationService.inspect(key);
console.log('inspected', key, inspected);
return inspected?.userValue || inspected?.defaultValue;
};
}

View file

@ -94,6 +94,7 @@ export interface ITerminalService {
isProcessSupportRegistered: boolean;
readonly connectionState: TerminalConnectionState;
readonly availableProfiles: ITerminalProfile[];
readonly profilesReady: Promise<void>;
initializeTerminals(): Promise<void>;
onActiveGroupChanged: Event<void>;

View file

@ -172,9 +172,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
}
detachFromProcess(): void {
if (this._process?.detach) {
this._process.detach();
}
this._process?.detach?.();
}
async createProcess(

View file

@ -149,12 +149,16 @@ export abstract class BaseTerminalProfileResolverService implements ITerminalPro
// If either shell or shellArgs are specified, they will take priority for now until we
// allow users to migrate, see https://github.com/microsoft/vscode/issues/123171
const shellSettingProfile = await this._getUnresolvedShellSettingDefaultProfile(options);
console.log('shellSettingProfile', shellSettingProfile);
if (shellSettingProfile) {
return shellSettingProfile;
}
// Return the real default profile if it exists and is valid
// Return the real default profile if it exists and is valid, wait for profiles to be ready
// if the window just opened
await this._terminalService.profilesReady;
const defaultProfile = this._getUnresolvedRealDefaultProfile(options.os);
console.log('defaultProfile', defaultProfile);
if (defaultProfile) {
return defaultProfile;
}
@ -166,7 +170,9 @@ export abstract class BaseTerminalProfileResolverService implements ITerminalPro
private _getUnresolvedRealDefaultProfile(os: OperatingSystem): ITerminalProfile | undefined {
const defaultProfileName = this.getSafeConfigValue('defaultProfile', os);
console.log('defaultProfileName', defaultProfileName);
if (defaultProfileName && typeof defaultProfileName === 'string') {
console.log('this._terminalService.availableProfiles', this._terminalService.availableProfiles);
return this._terminalService.availableProfiles.find(e => e.profileName === defaultProfileName);
}
return undefined;

View file

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { timeout } from 'vs/base/common/async';
import { AutoOpenBarrier, timeout } from 'vs/base/common/async';
import { debounce, throttle } from 'vs/base/common/decorators';
import { Emitter, Event } from 'vs/base/common/event';
import { IDisposable } from 'vs/base/common/lifecycle';
@ -60,6 +60,7 @@ export class TerminalService implements ITerminalService {
private _processSupportContextKey: IContextKey<boolean>;
private readonly _localTerminalService?: ILocalTerminalService;
private readonly _offProcessTerminalService?: IOffProcessTerminalService;
private _profilesReadyBarrier: AutoOpenBarrier;
private _availableProfiles: ITerminalProfile[] | undefined;
private _configHelper: TerminalConfigHelper;
private _terminalContainer: HTMLElement | undefined;
@ -71,6 +72,7 @@ export class TerminalService implements ITerminalService {
public get terminalGroups(): ITerminalGroup[] { return this._terminalGroups; }
public get isProcessSupportRegistered(): boolean { return !!this._processSupportContextKey.get(); }
get connectionState(): TerminalConnectionState { return this._connectionState; }
get profilesReady(): Promise<void> { return this._profilesReadyBarrier.wait().then(() => { }); }
get availableProfiles(): ITerminalProfile[] {
this._refreshAvailableProfiles();
return this._availableProfiles || [];
@ -188,23 +190,26 @@ export class TerminalService implements ITerminalService {
const enableTerminalReconnection = this.configHelper.config.enablePersistentSessions;
const conn = this._remoteAgentService.getConnection();
const remoteAuthority = conn ? conn.remoteAuthority : 'null';
this._whenExtHostReady(remoteAuthority).then(() => {
this._refreshAvailableProfiles();
});
// const conn = this._remoteAgentService.getConnection();
// const remoteAuthority = conn ? conn.remoteAuthority : 'null';
// this._whenExtHostReady(remoteAuthority).then(() => {
// });
// Connect to the extension host if it's there, set the connection state to connected when
// it's done. This should happen even when there is no extension host.
this._connectionState = TerminalConnectionState.Connecting;
const isPersistentRemote = !!this._environmentService.remoteAuthority && enableTerminalReconnection;
let initPromise: Promise<any> = isPersistentRemote ? this._remoteTerminalsInitPromise = this._reconnectToRemoteTerminals() :
enableTerminalReconnection ? this._localTerminalsInitPromise = this._reconnectToLocalTerminals() :
Promise.resolve();
this._offProcessTerminalService = isPersistentRemote ? this._remoteTerminalService :
enableTerminalReconnection ? this._localTerminalService : undefined;
let initPromise: Promise<any> = isPersistentRemote
? this._remoteTerminalsInitPromise = this._reconnectToRemoteTerminals()
: enableTerminalReconnection
? this._localTerminalsInitPromise = this._reconnectToLocalTerminals()
: Promise.resolve();
this._offProcessTerminalService = !!this._environmentService.remoteAuthority ? this._remoteTerminalService : this._localTerminalService;
initPromise.then(() => this._setConnected());
this._profilesReadyBarrier = new AutoOpenBarrier(5000);
this._refreshAvailableProfiles();
}
private _setConnected() {
@ -325,24 +330,28 @@ export class TerminalService implements ITerminalService {
@throttle(10000)
private async _refreshAvailableProfiles(): Promise<void> {
const result = await this._detectProfiles(true);
console.log('detectProfiles result', result);
if (!equals(result, this._availableProfiles)) {
this._availableProfiles = result;
this._onDidChangeAvailableProfiles.fire(this._availableProfiles);
this._profilesReadyBarrier.open();
}
}
// TODO: Invert arg
private async _detectProfiles(configuredProfilesOnly: boolean): Promise<ITerminalProfile[]> {
const offProcService = this._offProcessTerminalService;
console.log('offProcService?', offProcService);
if (!offProcService) {
return this._availableProfiles || [];
}
return offProcService?.getProfiles();
return offProcService?.getProfiles(!configuredProfilesOnly);
}
private async _whenExtHostReady(remoteAuthority: string): Promise<void> {
this._createExtHostReadyEntry(remoteAuthority);
return this._extHostsReady[remoteAuthority]!.promise;
}
// private async _whenExtHostReady(remoteAuthority: string): Promise<void> {
// this._createExtHostReadyEntry(remoteAuthority);
// return this._extHostsReady[remoteAuthority]!.promise;
// }
private _createExtHostReadyEntry(remoteAuthority: string): void {
if (this._extHostsReady[remoteAuthority]) {
@ -405,6 +414,9 @@ export class TerminalService implements ITerminalService {
@debounce(500)
private _saveState(): void {
if (!this.configHelper.config.enablePersistentSessions) {
return;
}
const state: ITerminalsLayoutInfoById = {
tabs: this.terminalGroups.map(g => g.getLayoutInfo(g === this.getActiveGroup()))
};
@ -413,7 +425,7 @@ export class TerminalService implements ITerminalService {
@debounce(500)
private _updateTitle(instance?: ITerminalInstance): void {
if (!instance || !instance.persistentProcessId || !instance.title) {
if (!this.configHelper.config.enablePersistentSessions || !instance || !instance.persistentProcessId || !instance.title) {
return;
}
this._offProcessTerminalService?.updateTitle(instance.persistentProcessId, instance.title);
@ -421,7 +433,7 @@ export class TerminalService implements ITerminalService {
@debounce(500)
private _updateIcon(instance?: ITerminalInstance): void {
if (!instance || !instance.persistentProcessId || !instance.icon) {
if (!this.configHelper.config.enablePersistentSessions || !instance || !instance.persistentProcessId || !instance.icon) {
return;
}
this._offProcessTerminalService?.updateIcon(instance.persistentProcessId, instance.icon.id);