Repository navigation
Rework PSModulePath path building - #24568
Jordan Borean (jborean93) wants to merge 4 commits into
Conversation
11ffe1d to
231f0bd
Compare
|
Tests work locally on my macOS host so I need to figure out what the differences are in CI to cause it to fail. |
|
I've pushed a commit that removed the existing logic and reimplemented it in what I hope is a more sane manner. I'll have to sit down and write some more comprehensive tests for this API to test out edge cases like cases, inserting the system/shared path earlier and so on. I'll also need to look into things like trailing backslash and whitespace handling as I think before this was considered equal when compared. The only change that I can tell this makes is that the shared path |
|
As for tests, I'd consider xUnit tests for GetModulePath(). It saves a lot your time and makes design intentions explicit. |
2ee70e7 to
cbd1fd7
Compare
|
I've updated the PR title and summary to sum up the changes I've made here. The tests are passing except for the CodeFactor checks which is complaining about the lack of docs on the new unit tests added. No other tests have the docs so I'm just ignoring this failure. This is now ready for review. |
There was a problem hiding this comment.
It seems there is very optimized overload for two arguments so we can eliminate dirSeparatorChars.
There was a problem hiding this comment.
Fair point I’ll use the params overload which I think is the same one used but avoids the span allocation.
There was a problem hiding this comment.
Please see my comment about TrimEndingDirectorySeparator()
There was a problem hiding this comment.
Ah there reason why I did this is because the params overload is for a string, we are operating on a ReadOnlySpan and MemoryExtensions.TrimEnd doesn't have such an overload.
I've kept the current code because TrimEndingDirectorySeparator() doesn't handle trimming more than 1 trailing separator.
There was a problem hiding this comment.
I think it makes no sense for us to try to fix user errors. In fact, there may be a lot of user errors that we don't fix. I suggest following the same logic as you suggested for duplicated paths - just ignore it.
The main thing for us here is to correctly add the necessary paths and no more.
I suggest to use more simple code with TrimEndingDirectorySeparator() here. It is well tested (I see one issue in your code for Windows).
There was a problem hiding this comment.
I suggest to use more simple code with TrimEndingDirectorySeparator() here. It is well tested (I see one issue in your code for Windows)
What's the issue for Windows?
I'll wait until the WG weighs in to see whether they prefer the current code that trims all trailing dir path separators or whether to swap to TrimEndingDirectorySeparator which only trims the last.
There was a problem hiding this comment.
// On Windows we always want to trim '/' or '\'. Only exception
// is to keep one trailing char if the path is the drive root
// 'C:\+'.
entry = entry.Length > 1 && entry[1] == Path.VolumeSeparatorChar && trimmedEntry.Length == 2
? entry.Slice(0, 3)
: trimmedEntry;The code is not correct.
You will wait indefinitely.
I suggest making the code as simple as possible and accepting it now.
Since we are talking about an extreme case, you can create an issue for it and make changes to the code after additional discussion if it really turns out to be useful for many users.
There was a problem hiding this comment.
You will wait indefinitely.
I'm assuming I'm waiting indefinitely to get this reviewed by the WG anyway :) I appreciate you reviewing these PRs though and I'm not trying to be obstructionist it's just if they have to review this anyway I prefer to wait for the final verdict before changing things.
I have picked up the bug if it's C: then the Slice will go out of bounds and will fix up. Not sure if that's the incorrect part you are referring to though.
There was a problem hiding this comment.
Can we use [IO.Path.IsPathRooted](https://source.dot.net/#System.Private.CoreLib/src/libraries/System.Private.CoreLib/src/System/IO/Path.Unix.cs,132)?
And what about C:\ on Windows?
Also there is TrimEndingDirectorySeparator() - it checks for size and root.
There was a problem hiding this comment.
One downside of TrimEndingDirectorySeparator is that it seems like it only trims 1 char versus TrimEnd which trims them all if present. I don't think someone having C:\foo\\ would be common but it depends if we want to handle it or not (I think we should).
There was a problem hiding this comment.
I've updated the code to handle Windows absolute paths and their trailing chars and expanded the comments that explains what it does. I didn't use TrimEndingDirectorySeparator() because it will only trim 1 char at the end.
5554bb1 to
e46c27b
Compare
Fixes the parsing of the powershell.config.json PSModulePath entry when it contains the path separator char. Instead of crashing this is able to handle entries with those characters and treat them as multiple entries. This also rewrites the logic when building the process PSModulePath to simplify the way entries were added and deal with canonicalisation of the path entries.
e46c27b to
9019fe4
Compare
PR Summary
Fixes the parsing of the powershell.config.json PSModulePath entry when it contains the path separator char. Instead of crashing this is able to handle entries with those characters and treat them as multiple entries.
This also rewrites the logic when building the process PSModulePath to
simplify the way entries were added and deal with canonicalisation of
the path entries.
Fixes: #20706
PR Context
Using
powershell.config.jsonwith aPSModulePathentry that contains thePath.Separatorchar (;for Windows and:for *nix) crashes the process on startup. This is because the current logic adds the value provided as is to the path but then attempts to find the index for where it is located. This lookup splits the new path value by thePath.Separatorso the entry being added is never found (the raw value is never a split component of the new path).This new PR consolidates the various path addition logic and tries to make it more consistent in how it handles new values. It also attempts to remove as much string allocations by working on spans where possible to hopefully improve the memory allocation at startup.
Ultimately the behaviour of this logic when building the
PSModulePathis.config.jsonand falls back to the default user's modules dirC:\Program Files\PowerShell\Modules$PSHome/powershell.config.jsonentry and falls back to$PSHome/ModulesPSModulePathif presentPSModulePath(System32/Program Files\WindowsPowerShell)There are a few behavioural changes introduced by this PR which I think aren't breaking changes but are behaviour differences for the better.
/or\(on Windows) is removed/is converted to\PSModulePathPSModulePathis not set as a process env var (Linux mostly) and there is an explicitPSModulePathin the$PSHome/powershell.config.jsonthe shared module path is now includedPR Checklist
.h,.cpp,.cs,.ps1and.psm1files have the correct copyright headerWIP:or[ WIP ]to the beginning of the title (theWIPbot will keep its status check atPendingwhile the prefix is present) and remove the prefix when the PR is ready.- [ ] Issue filed:
(which runs in a different PS Host).