Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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 @@ -98,7 +98,75 @@ public FileSystemProvider()
/// </returns>
private static string NormalizePath(string path)
{
return path.Replace(StringLiterals.AlternatePathSeparator, StringLiterals.DefaultPathSeparator);
return GetCorrectCasedPath(path.Replace(StringLiterals.AlternatePathSeparator, StringLiterals.DefaultPathSeparator));
}

/// <summary>
/// Get the correct casing for a path. This method assumes it's being called by NormalizePath()
/// so that the path is already normalized.
/// </summary>
/// <param name="path">
/// The path to retrieve.
/// </param>
/// <returns>
/// The path with accurate casing if item exists, otherwise it returns path that was passed in.
/// </returns>
private static string GetCorrectCasedPath(string path)
{
// Only apply to directories where there are issues with some tools if the casing
// doesn't match the source like git
if (Directory.Exists(path))
{
string exactPath = string.Empty;
int itemsToSkip = 0;
if (Utils.PathIsUnc(path))
{
// With the Split method, a UNC path like \\server\share, we need to skip
// trying to enumerate the server and share, so skip the first two empty
// strings, then server, and finally share name.
itemsToSkip = 4;
}

foreach (string item in path.Split(StringLiterals.DefaultPathSeparator))
{
if (itemsToSkip-- > 0)
{
// This handles the UNC server and share and 8.3 short path syntax
exactPath += item + StringLiterals.DefaultPathSeparator;
continue;
}
else if (string.IsNullOrEmpty(exactPath))
{
// This handles the drive letter or / root path start
exactPath = item + StringLiterals.DefaultPathSeparator;
}
else if (string.IsNullOrEmpty(item))
{
// This handles the trailing slash case
continue;
}
else if (item.Contains('~'))
{
// This handles short path names
exactPath += StringLiterals.DefaultPathSeparator + item;
}
else
{
exactPath = Directory.GetFileSystemEntries(exactPath, item).First();
}
}

if (path.EndsWith(StringLiterals.DefaultPathSeparator))
{
return exactPath + StringLiterals.DefaultPathSeparator;
}

return exactPath;
}
else
{
return path;
}
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,24 @@ Describe "Set-Location" -Tags "CI" {
Should -Throw -ErrorId "PathNotFound,Microsoft.PowerShell.Commands.SetLocationCommand"
}

It "Should use actual casing of folder on case-insensitive filesystem" -Skip:($IsLinux) {
$testPath = New-Item -ItemType Directory -Path testdrive:/teST
Set-Location $testPath.FullName.ToUpper()
$(Get-Location).Path | Should -BeExactly $testPath.FullName
}

It "Should use actual casing of folder on case-sensitive filesystem: <dir>" -Skip:(!$IsLinux)
{
$dir = "teST"
$testPathLower = New-Item -ItemType Directory -Path (Join-Path $TestDrive $dir.ToLower())
$testPathUpper = New-Item -ItemType Directory -Path (Join-Path $TestDrive $dir.ToUpper())
Set-Location $testPathLower.FullName
$(Get-Location).Path | Should -BeExactly $testPathLower.FullName
Set-Location $testPathUpper.FullName
$(Get-Location).Path | Should -BeExactly $testPathUpper.FullName
{ Set-Locaiton (Join-Path $TestDrive $dir) } | Should -Throw -ErrorId "PathNotFound,Microsoft.PowerShell.Commands.SetLocationCommand"
}

Context 'Set-Location with no arguments' {

It 'Should go to $env:HOME when Set-Location run with no arguments from FileSystem provider' {
Expand Down