-
Notifications
You must be signed in to change notification settings - Fork 8.1k
Reduce aggressive correcting casing of file system paths #14469
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -108,12 +108,11 @@ public FileSystemProvider() | |
| /// </returns> | ||
| private static string NormalizePath(string path) | ||
| { | ||
| return GetCorrectCasedPath(path.Replace(StringLiterals.AlternatePathSeparator, StringLiterals.DefaultPathSeparator)); | ||
| return 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. | ||
| /// Normalize and get the correct casing for a path. | ||
| /// </summary> | ||
| /// <param name="path"> | ||
| /// The path to retrieve. | ||
|
|
@@ -123,6 +122,13 @@ private static string NormalizePath(string path) | |
| /// </returns> | ||
| private static string GetCorrectCasedPath(string path) | ||
| { | ||
| path = NormalizePath(path); | ||
|
|
||
| if (Platform.IsLinux) | ||
| { | ||
| return 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)) | ||
|
|
@@ -167,13 +173,13 @@ private static string GetCorrectCasedPath(string path) | |
| } | ||
| else | ||
| { | ||
| // Use GetFileSystemEntries to get the correct casing of this element | ||
| // Use enumeration to get the correct casing of this element | ||
| try | ||
| { | ||
| var entries = Directory.GetFileSystemEntries(exactPath, item); | ||
| if (entries.Length > 0) | ||
| var entry = Directory.EnumerateFileSystemEntries(exactPath, item).FirstOrDefault(); | ||
| if (entry is not null) | ||
| { | ||
| exactPath = entries[0]; | ||
| exactPath = entry; | ||
| } | ||
| else | ||
| { | ||
|
|
@@ -1376,7 +1382,7 @@ protected override void GetItem(string path) | |
|
|
||
| private FileSystemInfo GetFileSystemItem(string path, ref bool isContainer, bool showHidden) | ||
| { | ||
| path = NormalizePath(path); | ||
| path = GetCorrectCasedPath(path); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see we've swapped a bunch of calls to use GetCorrectCasedPath -- are there cases where NormalizePath is still called on its own? Or is it only used in the GetCorrectCasedPath method now?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. After the PR:
The PR does mostly obvious changes. Later we could remove more GetCorrectCasedPath uses. |
||
| FileInfo result = new FileInfo(path); | ||
|
|
||
| // FileInfo.Exists is always false for a directory path, so we check the attribute for existence. | ||
|
|
@@ -1639,7 +1645,7 @@ private void GetPathItems( | |
| throw PSTraceSource.NewArgumentException(nameof(path)); | ||
| } | ||
|
|
||
| path = NormalizePath(path); | ||
| path = GetCorrectCasedPath(path); | ||
|
|
||
| var fsinfo = GetFileSystemInfo(path, out bool isDirectory); | ||
|
|
||
|
|
@@ -2125,7 +2131,7 @@ protected override void RenameItem( | |
| throw PSTraceSource.NewArgumentException(nameof(path)); | ||
| } | ||
|
|
||
| path = NormalizePath(path); | ||
| path = GetCorrectCasedPath(path); | ||
|
|
||
| if (string.IsNullOrEmpty(newName)) | ||
| { | ||
|
|
@@ -2271,7 +2277,7 @@ protected override void NewItem( | |
| type = "file"; | ||
| } | ||
|
|
||
| path = NormalizePath(path); | ||
| path = GetCorrectCasedPath(path); | ||
|
|
||
| if (Force) | ||
| { | ||
|
|
@@ -3616,8 +3622,8 @@ protected override void CopyItem( | |
| throw PSTraceSource.NewArgumentException(nameof(destinationPath)); | ||
| } | ||
|
|
||
| path = NormalizePath(path); | ||
| destinationPath = NormalizePath(destinationPath); | ||
| path = GetCorrectCasedPath(path); | ||
| destinationPath = GetCorrectCasedPath(destinationPath); | ||
|
|
||
| PSSession fromSession = null; | ||
| PSSession toSession = null; | ||
|
|
@@ -5083,13 +5089,13 @@ protected override string NormalizeRelativePath( | |
|
|
||
| do // false loop | ||
| { | ||
| path = NormalizePath(path); | ||
| path = GetCorrectCasedPath(path); | ||
| path = EnsureDriveIsRooted(path); | ||
|
|
||
| // If it's not fully normalized, normalize it. | ||
| path = NormalizeRelativePathHelper(path, basePath); | ||
|
|
||
| basePath = NormalizePath(basePath); | ||
| basePath = GetCorrectCasedPath(basePath); | ||
| basePath = EnsureDriveIsRooted(basePath); | ||
|
|
||
| result = path; | ||
|
|
@@ -5785,8 +5791,8 @@ protected override void MoveItem( | |
| throw PSTraceSource.NewArgumentException(nameof(destination)); | ||
| } | ||
|
|
||
| path = NormalizePath(path); | ||
| destination = NormalizePath(destination); | ||
| path = GetCorrectCasedPath(path); | ||
| destination = GetCorrectCasedPath(destination); | ||
|
|
||
| // Verify that the target doesn't represent a device name | ||
| if (PathIsReservedDeviceName(destination, "MoveError")) | ||
|
|
@@ -6170,7 +6176,7 @@ public void GetProperty(string path, Collection<string> providerSpecificPickList | |
| throw PSTraceSource.NewArgumentException(nameof(path)); | ||
| } | ||
|
|
||
| path = NormalizePath(path); | ||
| path = GetCorrectCasedPath(path); | ||
|
|
||
| PSObject result = null; | ||
|
|
||
|
|
@@ -6308,7 +6314,7 @@ public void SetProperty(string path, PSObject propertyToSet) | |
| throw PSTraceSource.NewArgumentNullException(nameof(propertyToSet)); | ||
| } | ||
|
|
||
| path = NormalizePath(path); | ||
| path = GetCorrectCasedPath(path); | ||
|
|
||
| PSObject results = new PSObject(); | ||
|
|
||
|
|
@@ -6474,7 +6480,7 @@ public void ClearProperty( | |
| throw PSTraceSource.NewArgumentException(nameof(path)); | ||
| } | ||
|
|
||
| path = NormalizePath(path); | ||
| path = GetCorrectCasedPath(path); | ||
|
|
||
| if (propertiesToClear == null || | ||
| propertiesToClear.Count == 0) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aren't MacOS paths also case sensitive? Is there another reason we'd have this behaviour for Linux but not MacOS?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By default MacOS uses a case-insensitive file system.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The primary scenario where we hit a problem is with git where the remote repo is on Linux and case-sensitive and someone adds a file with a directory that they manually typed and then you have two directories in git that only differ by case. I think that affects Windows and macOS clients even if their local filesystems are case insensitive.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If git is case-sensetive locally on all platforms then users should follow the application design why should PowerShell do expensive work for all paths and for other scenarios?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow! If repo/application is case-sensitive and user obviously know this shouldn't the user take care of compliance himself?
If different platforms have different behavior, this is a fundamental and unsolvable problem. We constantly get requests about slashes because they are different in local (Windows) and remote session (Linux). I haven't seen as many requests about case, but the root of the problem is the same.
It should be clearly written in the documentation that this is the user's concern: if a scenario is - scripts works on Windows client and remote sessions are on Linux-s (and vise-versa) a recommendation for users should be to prefer forward slashes (backslashs) and be careful about cases.