From fc8ca61b3dd2a561d7fe8fbc38fd779278ad7984 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Sat, 3 Oct 2020 09:20:24 -0700 Subject: [PATCH] Revert "Change `PSNativePSPathResolution` to not be Experimental" (#13734) * Revert "Change `PSNativePSPathResolution` to not be Experimental (#13522)" This reverts commit 74c743d279a91c9494ea7a7baa879cd1c31228ac. --- .../ExperimentalFeature.cs | 3 + .../engine/NativeCommandParameterBinder.cs | 83 +++++++++++-------- .../NativeCommandArguments.Tests.ps1 | 7 ++ 3 files changed, 57 insertions(+), 36 deletions(-) diff --git a/src/System.Management.Automation/engine/ExperimentalFeature/ExperimentalFeature.cs b/src/System.Management.Automation/engine/ExperimentalFeature/ExperimentalFeature.cs index ebb47e9be7..4fd79fe7d7 100644 --- a/src/System.Management.Automation/engine/ExperimentalFeature/ExperimentalFeature.cs +++ b/src/System.Management.Automation/engine/ExperimentalFeature/ExperimentalFeature.cs @@ -117,6 +117,9 @@ namespace System.Management.Automation new ExperimentalFeature( name: "PSCultureInvariantReplaceOperator", description: "Use culture invariant to-string convertor for lval in replace operator"), + new ExperimentalFeature( + name: "PSNativePSPathResolution", + description: "Convert PSPath to filesystem path, if possible, for native commands"), new ExperimentalFeature( name: "PSNotApplyErrorActionToStderr", description: "Don't have $ErrorActionPreference affect stderr output"), diff --git a/src/System.Management.Automation/engine/NativeCommandParameterBinder.cs b/src/System.Management.Automation/engine/NativeCommandParameterBinder.cs index 6d98733492..0091596a44 100644 --- a/src/System.Management.Automation/engine/NativeCommandParameterBinder.cs +++ b/src/System.Management.Automation/engine/NativeCommandParameterBinder.cs @@ -122,6 +122,14 @@ namespace System.Management.Automation break; } + // Prior to PSNativePSPathResolution experimental feature, a single quote worked the same as a double quote + // so if the feature is not enabled, we treat any quotes as double quotes. When this feature is no longer + // experimental, this code here needs to be removed. + if (!ExperimentalFeature.IsEnabled("PSNativePSPathResolution") && stringConstantType == StringConstantType.SingleQuoted) + { + stringConstantType = StringConstantType.DoubleQuoted; + } + AppendOneNativeArgument(Context, argValue, arrayLiteralAst, sawVerbatimArgumentMarker, stringConstantType); } } @@ -354,54 +362,57 @@ namespace System.Management.Automation /// Resolved PSPath if applicable otherwise the original path internal static string ResolvePath(string path, ExecutionContext context) { + if (ExperimentalFeature.IsEnabled("PSNativePSPathResolution")) + { #if !UNIX - // on Windows, we need to expand ~ to point to user's home path - if (string.Equals(path, "~", StringComparison.Ordinal) || path.StartsWith(TildeDirectorySeparator, StringComparison.Ordinal) || path.StartsWith(TildeAltDirectorySeparator, StringComparison.Ordinal)) - { - try + // on Windows, we need to expand ~ to point to user's home path + if (string.Equals(path, "~", StringComparison.Ordinal) || path.StartsWith(TildeDirectorySeparator, StringComparison.Ordinal) || path.StartsWith(TildeAltDirectorySeparator, StringComparison.Ordinal)) { - ProviderInfo fileSystemProvider = context.EngineSessionState.GetSingleProvider(FileSystemProvider.ProviderName); - return new StringBuilder(fileSystemProvider.Home) - .Append(path.Substring(1)) - .Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar) - .ToString(); - } - catch - { - return path; - } - } - - // check if the driveName is an actual disk drive on Windows, if so, no expansion - if (path.Length >= 2 && path[1] == ':') - { - foreach (var drive in DriveInfo.GetDrives()) - { - if (drive.Name.StartsWith(new string(path[0], 1), StringComparison.OrdinalIgnoreCase)) + try + { + ProviderInfo fileSystemProvider = context.EngineSessionState.GetSingleProvider(FileSystemProvider.ProviderName); + return new StringBuilder(fileSystemProvider.Home) + .Append(path.Substring(1)) + .Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar) + .ToString(); + } + catch { return path; } } - } -#endif - if (path.Contains(':')) - { - LocationGlobber globber = new LocationGlobber(context.SessionState); - try + // check if the driveName is an actual disk drive on Windows, if so, no expansion + if (path.Length >= 2 && path[1] == ':') { - ProviderInfo providerInfo; - - // replace the argument with resolved path if it's a filesystem path - string pspath = globber.GetProviderPath(path, out providerInfo); - if (string.Equals(providerInfo.Name, FileSystemProvider.ProviderName, StringComparison.OrdinalIgnoreCase)) + foreach (var drive in DriveInfo.GetDrives()) { - path = pspath; + if (drive.Name.StartsWith(new string(path[0], 1), StringComparison.OrdinalIgnoreCase)) + { + return path; + } } } - catch +#endif + + if (path.Contains(':')) { - // if it's not a provider path, do nothing + LocationGlobber globber = new LocationGlobber(context.SessionState); + try + { + ProviderInfo providerInfo; + + // replace the argument with resolved path if it's a filesystem path + string pspath = globber.GetProviderPath(path, out providerInfo); + if (string.Equals(providerInfo.Name, FileSystemProvider.ProviderName, StringComparison.OrdinalIgnoreCase)) + { + path = pspath; + } + } + catch + { + // if it's not a provider path, do nothing + } } } diff --git a/test/powershell/Language/Scripting/NativeExecution/NativeCommandArguments.Tests.ps1 b/test/powershell/Language/Scripting/NativeExecution/NativeCommandArguments.Tests.ps1 index 4848cd34b9..df71542a6b 100644 --- a/test/powershell/Language/Scripting/NativeExecution/NativeCommandArguments.Tests.ps1 +++ b/test/powershell/Language/Scripting/NativeExecution/NativeCommandArguments.Tests.ps1 @@ -67,6 +67,11 @@ Describe "Native Command Arguments" -tags "CI" { Describe 'PSPath to native commands' { BeforeAll { + $featureEnabled = $EnabledExperimentalFeatures.Contains('PSNativePSPathResolution') + $originalDefaultParameterValues = $PSDefaultParameterValues.Clone() + + $PSDefaultParameterValues["it:skip"] = (-not $featureEnabled) + if ($IsWindows) { $cmd = "cmd" $cmdArg1 = "/c" @@ -90,6 +95,8 @@ Describe 'PSPath to native commands' { } AfterAll { + $global:PSDefaultParameterValues = $originalDefaultParameterValues + Remove-Item -Path "env:/test var" Remove-Item -Path $filePath Remove-PSDrive -Name $complexDriveName