Skip to content

Commit 4e3db1b

Browse files
Matthew Bobkedaxian-dbw
authored andcommitted
Fix 'Set-Location DriveName:' to restore current working directory in the drive (#6774)
1 parent aa0af5e commit 4e3db1b

4 files changed

Lines changed: 89 additions & 9 deletions

File tree

src/System.Management.Automation/engine/SessionStateLocationAPIs.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
using System.Collections.Generic;
77
using System.Collections.ObjectModel;
8+
using System.IO;
89
using System.Management.Automation.Provider;
910
using Dbg = System.Management.Automation;
1011

@@ -262,10 +263,18 @@ internal PathInfo SetLocation(string path, CmdletProviderContext context)
262263
// Since the path is an absolute path
263264
// we need to change the current working
264265
// drive
265-
266266
PSDriveInfo newWorkingDrive = GetDrive(driveName);
267267
CurrentDrive = newWorkingDrive;
268268

269+
// If the path is simply a colon-terminated drive,
270+
// not a slash-terminated path to the root of a drive,
271+
// set the path to the current working directory of that drive.
272+
string colonTerminatedVolume = CurrentDrive.Name + ':';
273+
if (CurrentDrive.VolumeSeparatedByColon && (path.Length == colonTerminatedVolume.Length))
274+
{
275+
path = Path.Combine((colonTerminatedVolume + Path.DirectorySeparatorChar), CurrentDrive.CurrentLocation);
276+
}
277+
269278
// Now that the current working drive is set,
270279
// process the rest of the path as a relative path.
271280
}

src/System.Management.Automation/namespaces/LocationGlobber.cs

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2013,6 +2013,9 @@ internal string GetDriveRootRelativePathFromPSPath(
20132013
// Check to see if the path is relative or absolute
20142014
bool isPathForCurrentDrive = false;
20152015

2016+
// Check to see if the path is to the root of a drive
2017+
bool isPathForRootOfDrive = false;
2018+
20162019
if (IsAbsolutePath(path, out driveName))
20172020
{
20182021
Dbg.Diagnostics.Assert(
@@ -2080,6 +2083,12 @@ internal string GetDriveRootRelativePathFromPSPath(
20802083
// this is the default behavior for all windows drives, and all non-filesystem
20812084
// drives on non-windows
20822085
path = path.Substring(driveName.Length + 1);
2086+
2087+
if (String.IsNullOrEmpty(path))
2088+
{
2089+
// path was to the root of a drive such as 'c:'
2090+
isPathForRootOfDrive = true;
2091+
}
20832092
}
20842093
}
20852094
}
@@ -2111,14 +2120,23 @@ internal string GetDriveRootRelativePathFromPSPath(
21112120
// have access to it.
21122121
context.Drive = workingDriveForPath;
21132122

2114-
string relativePath =
2115-
GenerateRelativePath(
2116-
workingDriveForPath,
2117-
path,
2118-
escapeCurrentLocation,
2119-
providerInstance,
2120-
context);
2123+
string relativePath = String.Empty;
21212124

2125+
if (isPathForRootOfDrive)
2126+
{
2127+
relativePath = context.Drive.Root;
2128+
}
2129+
else
2130+
{
2131+
relativePath =
2132+
GenerateRelativePath(
2133+
workingDriveForPath,
2134+
path,
2135+
escapeCurrentLocation,
2136+
providerInstance,
2137+
context);
2138+
}
2139+
21222140
return relativePath;
21232141
}
21242142
catch (PSNotSupportedException)

test/powershell/Modules/Microsoft.PowerShell.Management/New-Item.Tests.ps1

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,33 @@ Describe "New-Item" -Tags "CI" {
117117
$fileInfo.Target | Should -BeNullOrEmpty
118118
$fileInfo.LinkType | Should -BeExactly "HardLink"
119119
}
120+
121+
It "Should create a file at the root of the drive while the current working directory is not the root" {
122+
try {
123+
New-Item -Name $testfolder -Path "TestDrive:\" -ItemType directory > $null
124+
Push-Location -Path "TestDrive:\$testfolder"
125+
New-Item -Name $testfile -Path "TestDrive:\" -ItemType file > $null
126+
$FullyQualifiedFile | Should -Exist
127+
}
128+
finally {
129+
Pop-Location
130+
}
131+
}
132+
133+
It "Should create a folder at the root of the drive while the current working directory is not the root" {
134+
$testfolder2 = "newDirectory2"
135+
$FullyQualifiedFolder2 = Join-Path -Path $tmpDirectory -ChildPath $testfolder2
136+
137+
try {
138+
New-Item -Name $testfolder -Path "TestDrive:\" -ItemType directory > $null
139+
Push-Location -Path "TestDrive:\$testfolder"
140+
New-Item -Name $testfolder2 -Path "TestDrive:\" -ItemType directory > $null
141+
$FullyQualifiedFolder2 | Should -Exist
142+
}
143+
finally {
144+
Pop-Location
145+
}
146+
}
120147
}
121148

122149
# More precisely these tests require SeCreateSymbolicLinkPrivilege.
@@ -186,7 +213,7 @@ Describe "New-Item with links" -Tags @('CI', 'RequireAdminOnWindows') {
186213
}
187214

188215
It "New-Item -ItemType SymbolicLink should understand directory path ending with slash" {
189-
$folderName = [System.IO.Path]::GetRandomFileName()
216+
$folderName = [System.IO.Path]::GetRandomFileName()
190217
$symbolicLinkPath = New-Item -ItemType SymbolicLink -Path "$tmpDirectory/$folderName/" -Value "/bar/"
191218
$symbolicLinkPath | Should -Not -BeNullOrEmpty
192219
}

test/powershell/Modules/Microsoft.PowerShell.Management/Set-Location.Tests.ps1

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,30 @@ Describe "Set-Location" -Tags "CI" {
6767
(Get-Location).Path | Should -BeExactly (Get-PSProvider FileSystem).Home
6868
}
6969
}
70+
71+
It "Should set location to new drive's current working directory when path is the colon-terminated name of a different drive" {
72+
try
73+
{
74+
$oldLocation = Get-Location
75+
Set-Location 'TestDrive:\'
76+
New-Item -Path 'TestDrive:\' -Name 'Directory1' -ItemType Directory
77+
New-PSDrive -Name 'Z' -PSProvider FileSystem -Root 'TestDrive:\Directory1'
78+
New-Item -Path 'Z:\' -Name 'Directory2' -ItemType Directory
79+
80+
Set-Location 'TestDrive:\Directory1'
81+
$pathToTest1 = (Get-Location).Path
82+
Set-Location 'Z:\Directory2'
83+
$pathToTest2 = (Get-Location).Path
84+
85+
Set-Location 'TestDrive:'
86+
(Get-Location).Path | Should -BeExactly $pathToTest1
87+
Set-Location 'Z:'
88+
(Get-Location).Path | Should -BeExactly $pathToTest2
89+
}
90+
finally
91+
{
92+
Set-Location $oldLocation
93+
Remove-PSDrive -Name 'Z'
94+
}
95+
}
7096
}

0 commit comments

Comments
 (0)