Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,7 @@ export class ShellIntegrationAddon extends Disposable implements IShellIntegrati
}

private _updateCwd(value: string) {
this._logService.debug(`MYLOG ShellIntegrationAddon#_updateCwd: updating cwd to "${value}"`);
value = sanitizeCwd(value);
this._createOrGetCwdDetection().updateCwd(value);
const commandDetection = this.capabilities.get(TerminalCapability.CommandDetection);
Expand Down Expand Up @@ -739,10 +740,12 @@ export class ShellIntegrationAddon extends Disposable implements IShellIntegrati
if (!this._terminal) {
throw new Error('Cannot restore commands before addon is activated');
}
this._logService.debug(`MYLOG ShellIntegrationAddon#deserialize: deserializing command detection capability`);
const commandDetection = this._createOrGetCommandDetection(this._terminal);
commandDetection.deserialize(serialized);
if (commandDetection.cwd) {
// Cwd gets set when the command is deserialized, so we need to update it here
this._logService.debug(`MYLOG ShellIntegrationAddon#deserialize: updating cwd from deserialized commandDetection.cwd="${commandDetection.cwd}"`);
this._updateCwd(commandDetection.cwd);
}
}
Expand Down
32 changes: 27 additions & 5 deletions src/vs/workbench/contrib/terminal/browser/terminalInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
switch (e.id) {
case TerminalCapability.CwdDetection: {
capabilityListeners.set(e.id, e.capability.onDidChangeCwd(e => {
this._logService.debug(`MYLOG TerminalInstance#onDidChangeCwd: cwd changed to "${e}", hasRemoteAuthority=${this.hasRemoteAuthority}, remoteAuthority=${this.remoteAuthority}`);
this._cwd = e;
this._setTitle(this.title, TitleEventSource.Config);
}));
Expand Down Expand Up @@ -556,6 +557,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {

// Re-establish the title after reconnect
if (this.shellLaunchConfig.attachPersistentProcess) {
this._logService.debug(`MYLOG TerminalInstance: Setting cwd from attachPersistentProcess.cwd="${this.shellLaunchConfig.attachPersistentProcess.cwd}", previous _cwd="${this._cwd}"`);
this._cwd = this.shellLaunchConfig.attachPersistentProcess.cwd;
this._setTitle(this.shellLaunchConfig.attachPersistentProcess.title, this.shellLaunchConfig.attachPersistentProcess.titleSource);
this.setShellType(this.shellType);
Expand Down Expand Up @@ -876,7 +878,11 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
}
xterm.raw.options.windowsPty = processTraits.windowsPty;
}));
this._register(this._processManager.onRestoreCommands(e => this.xterm?.shellIntegration.deserialize(e)));
this._register(this._processManager.onRestoreCommands(e => {
this._logService.debug(`MYLOG TerminalInstance#onRestoreCommands: Restoring commands, current _cwd="${this._cwd}", hasRemoteAuthority=${this.hasRemoteAuthority}`);
this.xterm?.shellIntegration.deserialize(e);
this._logService.debug(`MYLOG TerminalInstance#onRestoreCommands: After deserialize, _cwd="${this._cwd}"`);
}));

this._register(this._viewDescriptorService.onDidChangeLocation(({ views }) => {
if (views.some(v => v.id === TERMINAL_VIEW_ID)) {
Expand Down Expand Up @@ -908,10 +914,13 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
}

if (this.xterm?.shellIntegration) {
this._logService.debug(`MYLOG TerminalInstance#_createXterm: Adding shell integration capabilities, hasRemoteAuthority=${this.hasRemoteAuthority}, current _cwd="${this._cwd}"`);
this.capabilities.add(this.xterm.shellIntegration.capabilities);
this._logService.debug(`MYLOG TerminalInstance#_createXterm: After adding shell integration capabilities, _cwd="${this._cwd}"`);
}

this._pathService.userHome().then(userHome => {
this._logService.debug(`MYLOG TerminalInstance#_createXterm: userHome resolved to "${userHome.fsPath}", current _cwd="${this._cwd}"`);
this._userHome = userHome.fsPath;
});

Expand Down Expand Up @@ -1530,24 +1539,35 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
if (this.isDisposed) {
return;
}
this._logService.debug(`MYLOG TerminalInstance#_createProcess: Starting process creation, _cwd="${this._cwd}", _userHome="${this._userHome}", hasRemoteAuthority=${this.hasRemoteAuthority}, remoteAuthority=${this.remoteAuthority}`);
const activeWorkspaceRootUri = this._historyService.getLastActiveWorkspaceRoot(Schemas.file);
this._logService.debug(`MYLOG TerminalInstance#_createProcess: activeWorkspaceRootUri=${activeWorkspaceRootUri?.toString()}`);
if (activeWorkspaceRootUri) {
const trusted = await this._trust();
if (!trusted) {
this._onProcessExit({ message: nls.localize('workspaceNotTrustedCreateTerminal', "Cannot launch a terminal process in an untrusted workspace") });
}
} else if (this._cwd && this._userHome && this._cwd !== this._userHome) {
// something strange is going on if cwd is not userHome in an empty workspace
this._onProcessExit({
message: nls.localize('workspaceNotTrustedCreateTerminalCwd', "Cannot launch a terminal process in an untrusted workspace with cwd {0} and userHome {1}", this._cwd, this._userHome)
});
const hasExplicitCwd = !!this._shellLaunchConfig.cwd;
this._logService.debug(`MYLOG TerminalInstance#_createProcess: Empty workspace cwd mismatch detected - cwd="${this._cwd}", userHome="${this._userHome}", hasRemoteAuthority=${this.hasRemoteAuthority}, hasExplicitCwd=${hasExplicitCwd}`);

// Skip trust check if:
// 1. This is a remote terminal (cwd and userHome are in different filesystem contexts)
// 2. The shellLaunchConfig explicitly specifies a cwd (legitimate task/terminal request)
if (!this.hasRemoteAuthority && !hasExplicitCwd) {
// something strange is going on if cwd is not userHome in an empty workspace
this._onProcessExit({
message: nls.localize('workspaceNotTrustedCreateTerminalCwd', "Cannot launch a terminal process in an untrusted workspace with cwd {0} and userHome {1}", this._cwd, this._userHome)
});
}
}
// Re-evaluate dimensions if the container has been set since the xterm instance was created
if (this._container && this._cols === 0 && this._rows === 0) {
this._initDimensions();
this.xterm?.resize(this._cols || Constants.DefaultCols, this._rows || Constants.DefaultRows);
}
const originalIcon = this.shellLaunchConfig.icon;
this._logService.debug(`MYLOG TerminalInstance#_createProcess: Creating process with shellLaunchConfig=${JSON.stringify(this._shellLaunchConfig)}, _cols=${this._cols}, _rows=${this._rows}`);
await this._processManager.createProcess(this._shellLaunchConfig, this._cols || Constants.DefaultCols, this._rows || Constants.DefaultRows).then(result => {
if (result) {
if (hasKey(result, { message: true })) {
Expand All @@ -1558,9 +1578,11 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
}
});
if (this.isDisposed) {
this._logService.debug(`MYLOG TerminalInstance#_createProcess: Disposed during process creation, skipping icon update`);
return;
}
if (originalIcon !== this.shellLaunchConfig.icon || this.shellLaunchConfig.color) {
this._logService.debug(`MYLOG TerminalInstance#_createProcess: Updating icon from originalIcon=${originalIcon} to icon=${this._shellLaunchConfig.attachPersistentProcess?.icon || this._shellLaunchConfig.icon}`);
this._icon = this._shellLaunchConfig.attachPersistentProcess?.icon || this._shellLaunchConfig.icon;
this._onIconChanged.fire({ instance: this, userInitiated: false });
}
Expand Down
Loading