From de46cafb0a86eabfd9ef7b88016a5c6adfba245c Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Tue, 5 Jul 2022 15:54:17 -0700 Subject: [PATCH] Add `Directory.Exists()` check to `SetInitialWorkingDirectoryAsync()` There was an edge case where, after setting and un-setting the `powershell.cwd` property in the VS Code client, instead of being `null` the setting would be the empty string `""`. The client did not care about this, and so left the server to silently crash on startup. We previously assumed that by the time the server started, the directory would be validated by the client, but this was wrong. So now we check its existence first. --- .../Services/PowerShell/Host/PsesInternalHost.cs | 8 +++++--- .../Session/PsesInternalHostTests.cs | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs b/src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs index 97ee2edd7..1826d4ce7 100644 --- a/src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs +++ b/src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs @@ -475,9 +475,11 @@ internal Task LoadHostProfilesAsync(CancellationToken cancellationToken) public Task SetInitialWorkingDirectoryAsync(string path, CancellationToken cancellationToken) { - return ExecutePSCommandAsync( - new PSCommand().AddCommand("Set-Location").AddParameter("LiteralPath", path), - cancellationToken); + return Directory.Exists(path) + ? ExecutePSCommandAsync( + new PSCommand().AddCommand("Set-Location").AddParameter("LiteralPath", path), + cancellationToken) + : Task.CompletedTask; } private void Run() diff --git a/test/PowerShellEditorServices.Test/Session/PsesInternalHostTests.cs b/test/PowerShellEditorServices.Test/Session/PsesInternalHostTests.cs index 7412ac59d..f0d82c0d9 100644 --- a/test/PowerShellEditorServices.Test/Session/PsesInternalHostTests.cs +++ b/test/PowerShellEditorServices.Test/Session/PsesInternalHostTests.cs @@ -186,5 +186,20 @@ await psesHost.ExecutePSCommandAsync( new PSCommand().AddScript("\"protocol=https`nhost=myhost.com`nusername=john`npassword=doe`n`n\" | git.exe credential approve; if ($LastExitCode) { throw }"), CancellationToken.None).ConfigureAwait(true); } + + [Theory] + [InlineData("")] // Regression test for "unset" path. + [InlineData("C:\\Some\\Bad\\Directory")] // Non-existent directory. + [InlineData("testhost.dll")] // Existent file. + public async Task CanHandleBadInitialWorkingDirectory(string path) + { + string cwd = Environment.CurrentDirectory; + await psesHost.SetInitialWorkingDirectoryAsync(path, CancellationToken.None).ConfigureAwait(true); + + IReadOnlyList getLocation = await psesHost.ExecutePSCommandAsync( + new PSCommand().AddCommand("Get-Location"), + CancellationToken.None).ConfigureAwait(true); + Assert.Collection(getLocation, (d) => Assert.Equal(cwd, d, ignoreCase: true)); + } } }