diff --git a/src/code/FindPSResource.cs b/src/code/FindPSResource.cs index 12b3f4cb7..ba3016de3 100644 --- a/src/code/FindPSResource.cs +++ b/src/code/FindPSResource.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System; using System.Collections.Generic; using Dbg = System.Diagnostics.Debug; using System.Linq; @@ -198,7 +199,8 @@ private void ProcessResourceNameParameterSet() this)); } - Name = Utils.FilterOutWildcardNames(Name, out string[] errorMsgs); + var namesToSearch = Utils.ProcessNameWildcards(Name, out string[] errorMsgs, out bool nameContainsWildcard); + foreach (string error in errorMsgs) { WriteError(new ErrorRecord( @@ -208,8 +210,21 @@ private void ProcessResourceNameParameterSet() this)); } - if (Name.Length == 0) + // this catches the case where Name wasn't passed in as null or empty, + // but after filtering out unsupported wildcard names there are no elements left in namesToSearch + if (namesToSearch.Length == 0) + { + return; + } + + if (String.Equals(namesToSearch[0], "*", StringComparison.InvariantCultureIgnoreCase)) { + // WriteVerbose("Package names were detected to be (or contain an element equal to): '*', so all packages will be updated"); + WriteError(new ErrorRecord( + new PSInvalidOperationException("-Name '*' is not supported for Find-PSResource so all Name entries will be discarded."), + "NameEqualsWildcardIsNotSupported", + ErrorCategory.InvalidArgument, + this)); return; } diff --git a/src/code/GetInstalledPSResource.cs b/src/code/GetInstalledPSResource.cs index db1974781..7928c6e4c 100644 --- a/src/code/GetInstalledPSResource.cs +++ b/src/code/GetInstalledPSResource.cs @@ -106,33 +106,31 @@ protected override void BeginProcessing() // retrieve all possible paths _pathsToSearch = Utils.GetAllResourcePaths(this); } - - if (Name == null) - { - Name = new string[] { "*" }; - } - // if '*' is passed in as an argument for -Name with other -Name arguments, - // ignore all arguments except for '*' since it is the most inclusive - // eg: -Name ["TestModule, Test*, *"] will become -Name ["*"] - if (Name != null && Name.Length > 1) - { - foreach (var pkgName in Name) - { - if (pkgName.Trim().Equals("*")) - { - Name = new string[] { "*" }; - break; - } - } - } } protected override void ProcessRecord() { WriteDebug("Entering GetInstalledPSResource"); + var namesToSearch = Utils.ProcessNameWildcards(Name, out string[] errorMsgs, out bool _); + foreach (string error in errorMsgs) + { + WriteError(new ErrorRecord( + new PSInvalidOperationException(error), + "ErrorFilteringNamesForUnsupportedWildcards", + ErrorCategory.InvalidArgument, + this)); + } + + // this catches the case where Name wasn't passed in as null or empty, + // but after filtering out unsupported wildcard names in BeginProcessing() there are no elements left in Name + if (namesToSearch.Length == 0) + { + return; + } + GetHelper getHelper = new GetHelper(this); - foreach (PSResourceInfo pkg in getHelper.FilterPkgPaths(Name, _versionRange, _pathsToSearch)) + foreach (PSResourceInfo pkg in getHelper.FilterPkgPaths(namesToSearch, _versionRange, _pathsToSearch)) { WriteObject(pkg); } diff --git a/src/code/InstallPSResource.cs b/src/code/InstallPSResource.cs index dee8e3e4e..d546e6b4a 100644 --- a/src/code/InstallPSResource.cs +++ b/src/code/InstallPSResource.cs @@ -136,8 +136,35 @@ protected override void ProcessRecord() switch (ParameterSetName) { case NameParameterSet: + var namesToInstall = Utils.ProcessNameWildcards(Name, out string[] errorMsgs, out bool nameContainsWildcard); + if (nameContainsWildcard) + { + WriteError(new ErrorRecord( + new PSInvalidOperationException("Name with wildcards is not supported for Install-PSResource cmdlet"), + "NameContainsWildcard", + ErrorCategory.InvalidArgument, + this)); + return; + } + + foreach (string error in errorMsgs) + { + WriteError(new ErrorRecord( + new PSInvalidOperationException(error), + "ErrorFilteringNamesForUnsupportedWildcards", + ErrorCategory.InvalidArgument, + this)); + } + + // this catches the case where Name wasn't passed in as null or empty, + // but after filtering out unsupported wildcard names there are no elements left in namesToInstall + if (namesToInstall.Length == 0) + { + return; + } + installHelper.InstallPackages( - names: Name, + names: namesToInstall, versionRange: _versionRange, prerelease: Prerelease, repository: Repository, diff --git a/src/code/SavePSResource.cs b/src/code/SavePSResource.cs index a68496dd6..ff4832ce0 100644 --- a/src/code/SavePSResource.cs +++ b/src/code/SavePSResource.cs @@ -151,8 +151,35 @@ protected override void ProcessRecord() switch (ParameterSetName) { case NameParameterSet: + var namesToSave = Utils.ProcessNameWildcards(Name, out string[] errorMsgs, out bool nameContainsWildcard); + if (nameContainsWildcard) + { + WriteError(new ErrorRecord( + new PSInvalidOperationException("Name with wildcards is not supported for Save-PSResource cmdlet"), + "NameContainsWildcard", + ErrorCategory.InvalidArgument, + this)); + return; + } + + foreach (string error in errorMsgs) + { + WriteError(new ErrorRecord( + new PSInvalidOperationException(error), + "ErrorFilteringNamesForUnsupportedWildcards", + ErrorCategory.InvalidArgument, + this)); + } + + // this catches the case where Name wasn't passed in as null or empty, + // but after filtering out unsupported wildcard names there are no elements left in namesToSave + if (namesToSave.Length == 0) + { + return; + } + installHelper.InstallPackages( - names: Name, + names: namesToSave, versionRange: _versionRange, prerelease: Prerelease, repository: Repository, diff --git a/src/code/UninstallPSResource.cs b/src/code/UninstallPSResource.cs index 0a69e4617..5081d039b 100644 --- a/src/code/UninstallPSResource.cs +++ b/src/code/UninstallPSResource.cs @@ -1,3 +1,4 @@ +using System.Text; // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. using System; @@ -16,7 +17,7 @@ namespace Microsoft.PowerShell.PowerShellGet.Cmdlets /// /// Uninstall-PSResource uninstalls a package found in a module or script installation path. /// - [Cmdlet(VerbsLifecycle.Uninstall, "PSResource", DefaultParameterSetName = NameParameterSet, SupportsShouldProcess = true, HelpUri = "")] + [Cmdlet(VerbsLifecycle.Uninstall, "PSResource", DefaultParameterSetName = NameParameterSet, SupportsShouldProcess = true)] public sealed class UninstallPSResource : PSCmdlet { #region Parameters @@ -83,6 +84,24 @@ protected override void ProcessRecord() switch (ParameterSetName) { case NameParameterSet: + Name = Utils.ProcessNameWildcards(Name, out string[] errorMsgs, out bool _); + + foreach (string error in errorMsgs) + { + WriteError(new ErrorRecord( + new PSInvalidOperationException(error), + "ErrorFilteringNamesForUnsupportedWildcards", + ErrorCategory.InvalidArgument, + this)); + } + + // this catches the case where Name wasn't passed in as null or empty, + // but after filtering out unsupported wildcard names there are no elements left in Name + if (Name.Length == 0) + { + return; + } + if (!UninstallPkgHelper()) { // any errors should be caught lower in the stack, this debug statement will let us know if there was an unusual failure diff --git a/src/code/Utils.cs b/src/code/Utils.cs index c5155ffc0..8b2fa3a29 100644 --- a/src/code/Utils.cs +++ b/src/code/Utils.cs @@ -111,42 +111,6 @@ public static string[] ProcessNameWildcards( errorMsgs = errorMsgsList.ToArray(); return namesWithSupportedWildcards.ToArray(); } - - public static string[] FilterOutWildcardNames( - string[] pkgNames, - out string[] errorMsgs) - { - List errorFreeNames = new List(); - List errorMsgList = new List(); - - foreach (string n in pkgNames) - { - bool isNameErrorProne = false; - if (WildcardPattern.ContainsWildcardCharacters(n)) - { - if (String.Equals(n, "*", StringComparison.InvariantCultureIgnoreCase)) - { - errorMsgList = new List(); // clear prior error messages - errorMsgList.Add("-Name '*' is not supported for Find-PSResource so all Name entries will be discarded."); - errorFreeNames = new List(); - break; - } - else if (n.Contains("?") || n.Contains("[")) - { - errorMsgList.Add(String.Format("-Name with wildcards '?' and '[' are not supported for Find-PSResource so Name entry: {0} will be discarded.", n)); - isNameErrorProne = true; - } - } - - if (!isNameErrorProne) - { - errorFreeNames.Add(n); - } - } - - errorMsgs = errorMsgList.ToArray(); - return errorFreeNames.ToArray(); - } #endregion diff --git a/test/FindPSResource.Tests.ps1 b/test/FindPSResource.Tests.ps1 index fd24878e3..d1e1666be 100644 --- a/test/FindPSResource.Tests.ps1 +++ b/test/FindPSResource.Tests.ps1 @@ -42,6 +42,12 @@ Describe 'Test Find-PSResource for Module' { $foundScript | Should -BeTrue } + It "should not find resources given Name that equals wildcard, '*'" { + Find-PSResource -Name "*" -ErrorVariable err -ErrorAction SilentlyContinue + $err.Count | Should -Not -Be 0 + $err[0].FullyQualifiedErrorId | Should -BeExactly "NameEqualsWildcardIsNotSupported,Microsoft.PowerShell.PowerShellGet.Cmdlets.FindPSResource" + } + It "find resource given Name from V3 endpoint repository (NuGetGallery)" { $res = Find-PSResource -Name "Serilog" -Repository $NuGetGalleryName $res.Count | Should -Be 1 diff --git a/test/InstallPSResource.Tests.ps1 b/test/InstallPSResource.Tests.ps1 index 503f17bb6..ef206fece 100644 --- a/test/InstallPSResource.Tests.ps1 +++ b/test/InstallPSResource.Tests.ps1 @@ -22,6 +22,17 @@ Describe 'Test Install-PSResource for Module' { Get-RevertPSResourceRepositoryFile } + $testCases = @{Name="*"; ErrorId="NameContainsWildcard"}, + @{Name="TestModule*"; ErrorId="NameContainsWildcard"}, + @{Name="Test?Module","Test[Module"; ErrorId="ErrorFilteringNamesForUnsupportedWildcards"} + + It "Should not install resource with wildcard in name" -TestCases $testCases { + param($Name, $ErrorId) + Install-PSResource -Name $Name -ErrorVariable err -ErrorAction SilentlyContinue + $err.Count | Should -Not -Be 0 + $err[0].FullyQualifiedErrorId | Should -BeExactly "$ErrorId,Microsoft.PowerShell.PowerShellGet.Cmdlets.InstallPSResource" + } + It "Install specific module resource by name" { Install-PSResource -Name "TestModule" -Repository $TestGalleryName $pkg = Get-Module "TestModule" -ListAvailable @@ -43,7 +54,6 @@ Describe 'Test Install-PSResource for Module' { $pkg.Name | Should -Be $pkgNames } - It "Should not install resource given nonexistant name" { Install-PSResource -Name NonExistantModule -Repository $TestGalleryName $pkg = Get-Module "NonExistantModule" -ListAvailable diff --git a/test/SavePSResource.Tests.ps1 b/test/SavePSResource.Tests.ps1 index 6a20641e3..7f107b21f 100644 --- a/test/SavePSResource.Tests.ps1 +++ b/test/SavePSResource.Tests.ps1 @@ -54,6 +54,12 @@ Describe 'Test Save-PSResource for PSResources' { $pkgDir.Name | Should -BeNullOrEmpty } + It "Not Save module with Name containing wildcard" { + Save-PSResource -Name "TestModule*" -Repository $TestGalleryName -Path $SaveDir -ErrorVariable err -ErrorAction SilentlyContinue + $err.Count | Should -Not -Be 0 + $err[0].FullyQualifiedErrorId | Should -BeExactly "NameContainsWildcard,Microsoft.PowerShell.PowerShellGet.Cmdlets.SavePSResource" + } + # Do some version testing, but Find-PSResource should be doing thorough testing It "Should save resource given name and exact version" { Save-PSResource -Name "TestModule" -Version "1.2.0" -Repository $TestGalleryName -Path $SaveDir diff --git a/test/UninstallPSResource.Tests.ps1 b/test/UninstallPSResource.Tests.ps1 index 511f43016..f20e967ae 100644 --- a/test/UninstallPSResource.Tests.ps1 +++ b/test/UninstallPSResource.Tests.ps1 @@ -23,6 +23,16 @@ Describe 'Test Uninstall-PSResource for Modules' { Get-Module ContosoServer -ListAvailable | Should -Be $null } + $testCases = @{Name="Test?Module"; ErrorId="ErrorFilteringNamesForUnsupportedWildcards"}, + @{Name="Test[Module"; ErrorId="ErrorFilteringNamesForUnsupportedWildcards"} + + It "not uninstall module given Name with invalid wildcard characters" -TestCases $testCases { + param($Name, $ErrorId) + Uninstall-PSResource -Name $Name -ErrorVariable err -ErrorAction SilentlyContinue + $err.Count | Should -Not -Be 0 + $err[0].FullyQualifiedErrorId | Should -BeExactly "$ErrorId,Microsoft.PowerShell.PowerShellGet.Cmdlets.UninstallPSResource" + } + It "Uninstall a list of modules by name" { $null = Install-PSResource BaseTestPackage -Repository $TestGalleryName -TrustRepository -WarningAction SilentlyContinue