Skip to content

Commit 45996c9

Browse files
authored
Wildcard processing (#432)
make wildcard support/error handling consistent across cmdlets
1 parent 1863cf0 commit 45996c9

10 files changed

+144
-62
lines changed

src/code/FindPSResource.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
33

4+
using System;
45
using System.Collections.Generic;
56
using Dbg = System.Diagnostics.Debug;
67
using System.Linq;
@@ -198,7 +199,8 @@ private void ProcessResourceNameParameterSet()
198199
this));
199200
}
200201

201-
Name = Utils.FilterOutWildcardNames(Name, out string[] errorMsgs);
202+
var namesToSearch = Utils.ProcessNameWildcards(Name, out string[] errorMsgs, out bool nameContainsWildcard);
203+
202204
foreach (string error in errorMsgs)
203205
{
204206
WriteError(new ErrorRecord(
@@ -208,8 +210,21 @@ private void ProcessResourceNameParameterSet()
208210
this));
209211
}
210212

211-
if (Name.Length == 0)
213+
// this catches the case where Name wasn't passed in as null or empty,
214+
// but after filtering out unsupported wildcard names there are no elements left in namesToSearch
215+
if (namesToSearch.Length == 0)
216+
{
217+
return;
218+
}
219+
220+
if (String.Equals(namesToSearch[0], "*", StringComparison.InvariantCultureIgnoreCase))
212221
{
222+
// WriteVerbose("Package names were detected to be (or contain an element equal to): '*', so all packages will be updated");
223+
WriteError(new ErrorRecord(
224+
new PSInvalidOperationException("-Name '*' is not supported for Find-PSResource so all Name entries will be discarded."),
225+
"NameEqualsWildcardIsNotSupported",
226+
ErrorCategory.InvalidArgument,
227+
this));
213228
return;
214229
}
215230

src/code/GetInstalledPSResource.cs

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -106,33 +106,31 @@ protected override void BeginProcessing()
106106
// retrieve all possible paths
107107
_pathsToSearch = Utils.GetAllResourcePaths(this);
108108
}
109-
110-
if (Name == null)
111-
{
112-
Name = new string[] { "*" };
113-
}
114-
// if '*' is passed in as an argument for -Name with other -Name arguments,
115-
// ignore all arguments except for '*' since it is the most inclusive
116-
// eg: -Name ["TestModule, Test*, *"] will become -Name ["*"]
117-
if (Name != null && Name.Length > 1)
118-
{
119-
foreach (var pkgName in Name)
120-
{
121-
if (pkgName.Trim().Equals("*"))
122-
{
123-
Name = new string[] { "*" };
124-
break;
125-
}
126-
}
127-
}
128109
}
129110

130111
protected override void ProcessRecord()
131112
{
132113
WriteDebug("Entering GetInstalledPSResource");
133114

115+
var namesToSearch = Utils.ProcessNameWildcards(Name, out string[] errorMsgs, out bool _);
116+
foreach (string error in errorMsgs)
117+
{
118+
WriteError(new ErrorRecord(
119+
new PSInvalidOperationException(error),
120+
"ErrorFilteringNamesForUnsupportedWildcards",
121+
ErrorCategory.InvalidArgument,
122+
this));
123+
}
124+
125+
// this catches the case where Name wasn't passed in as null or empty,
126+
// but after filtering out unsupported wildcard names in BeginProcessing() there are no elements left in Name
127+
if (namesToSearch.Length == 0)
128+
{
129+
return;
130+
}
131+
134132
GetHelper getHelper = new GetHelper(this);
135-
foreach (PSResourceInfo pkg in getHelper.FilterPkgPaths(Name, _versionRange, _pathsToSearch))
133+
foreach (PSResourceInfo pkg in getHelper.FilterPkgPaths(namesToSearch, _versionRange, _pathsToSearch))
136134
{
137135
WriteObject(pkg);
138136
}

src/code/InstallPSResource.cs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,35 @@ protected override void ProcessRecord()
136136
switch (ParameterSetName)
137137
{
138138
case NameParameterSet:
139+
var namesToInstall = Utils.ProcessNameWildcards(Name, out string[] errorMsgs, out bool nameContainsWildcard);
140+
if (nameContainsWildcard)
141+
{
142+
WriteError(new ErrorRecord(
143+
new PSInvalidOperationException("Name with wildcards is not supported for Install-PSResource cmdlet"),
144+
"NameContainsWildcard",
145+
ErrorCategory.InvalidArgument,
146+
this));
147+
return;
148+
}
149+
150+
foreach (string error in errorMsgs)
151+
{
152+
WriteError(new ErrorRecord(
153+
new PSInvalidOperationException(error),
154+
"ErrorFilteringNamesForUnsupportedWildcards",
155+
ErrorCategory.InvalidArgument,
156+
this));
157+
}
158+
159+
// this catches the case where Name wasn't passed in as null or empty,
160+
// but after filtering out unsupported wildcard names there are no elements left in namesToInstall
161+
if (namesToInstall.Length == 0)
162+
{
163+
return;
164+
}
165+
139166
installHelper.InstallPackages(
140-
names: Name,
167+
names: namesToInstall,
141168
versionRange: _versionRange,
142169
prerelease: Prerelease,
143170
repository: Repository,

src/code/SavePSResource.cs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,35 @@ protected override void ProcessRecord()
151151
switch (ParameterSetName)
152152
{
153153
case NameParameterSet:
154+
var namesToSave = Utils.ProcessNameWildcards(Name, out string[] errorMsgs, out bool nameContainsWildcard);
155+
if (nameContainsWildcard)
156+
{
157+
WriteError(new ErrorRecord(
158+
new PSInvalidOperationException("Name with wildcards is not supported for Save-PSResource cmdlet"),
159+
"NameContainsWildcard",
160+
ErrorCategory.InvalidArgument,
161+
this));
162+
return;
163+
}
164+
165+
foreach (string error in errorMsgs)
166+
{
167+
WriteError(new ErrorRecord(
168+
new PSInvalidOperationException(error),
169+
"ErrorFilteringNamesForUnsupportedWildcards",
170+
ErrorCategory.InvalidArgument,
171+
this));
172+
}
173+
174+
// this catches the case where Name wasn't passed in as null or empty,
175+
// but after filtering out unsupported wildcard names there are no elements left in namesToSave
176+
if (namesToSave.Length == 0)
177+
{
178+
return;
179+
}
180+
154181
installHelper.InstallPackages(
155-
names: Name,
182+
names: namesToSave,
156183
versionRange: _versionRange,
157184
prerelease: Prerelease,
158185
repository: Repository,

src/code/UninstallPSResource.cs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Text;
12
// Copyright (c) Microsoft Corporation. All rights reserved.
23
// Licensed under the MIT License.
34
using System;
@@ -16,7 +17,7 @@ namespace Microsoft.PowerShell.PowerShellGet.Cmdlets
1617
/// <summary>
1718
/// Uninstall-PSResource uninstalls a package found in a module or script installation path.
1819
/// </summary>
19-
[Cmdlet(VerbsLifecycle.Uninstall, "PSResource", DefaultParameterSetName = NameParameterSet, SupportsShouldProcess = true, HelpUri = "<add>")]
20+
[Cmdlet(VerbsLifecycle.Uninstall, "PSResource", DefaultParameterSetName = NameParameterSet, SupportsShouldProcess = true)]
2021
public sealed class UninstallPSResource : PSCmdlet
2122
{
2223
#region Parameters
@@ -83,6 +84,24 @@ protected override void ProcessRecord()
8384
switch (ParameterSetName)
8485
{
8586
case NameParameterSet:
87+
Name = Utils.ProcessNameWildcards(Name, out string[] errorMsgs, out bool _);
88+
89+
foreach (string error in errorMsgs)
90+
{
91+
WriteError(new ErrorRecord(
92+
new PSInvalidOperationException(error),
93+
"ErrorFilteringNamesForUnsupportedWildcards",
94+
ErrorCategory.InvalidArgument,
95+
this));
96+
}
97+
98+
// this catches the case where Name wasn't passed in as null or empty,
99+
// but after filtering out unsupported wildcard names there are no elements left in Name
100+
if (Name.Length == 0)
101+
{
102+
return;
103+
}
104+
86105
if (!UninstallPkgHelper())
87106
{
88107
// any errors should be caught lower in the stack, this debug statement will let us know if there was an unusual failure

src/code/Utils.cs

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -111,42 +111,6 @@ public static string[] ProcessNameWildcards(
111111
errorMsgs = errorMsgsList.ToArray();
112112
return namesWithSupportedWildcards.ToArray();
113113
}
114-
115-
public static string[] FilterOutWildcardNames(
116-
string[] pkgNames,
117-
out string[] errorMsgs)
118-
{
119-
List<string> errorFreeNames = new List<string>();
120-
List<string> errorMsgList = new List<string>();
121-
122-
foreach (string n in pkgNames)
123-
{
124-
bool isNameErrorProne = false;
125-
if (WildcardPattern.ContainsWildcardCharacters(n))
126-
{
127-
if (String.Equals(n, "*", StringComparison.InvariantCultureIgnoreCase))
128-
{
129-
errorMsgList = new List<string>(); // clear prior error messages
130-
errorMsgList.Add("-Name '*' is not supported for Find-PSResource so all Name entries will be discarded.");
131-
errorFreeNames = new List<string>();
132-
break;
133-
}
134-
else if (n.Contains("?") || n.Contains("["))
135-
{
136-
errorMsgList.Add(String.Format("-Name with wildcards '?' and '[' are not supported for Find-PSResource so Name entry: {0} will be discarded.", n));
137-
isNameErrorProne = true;
138-
}
139-
}
140-
141-
if (!isNameErrorProne)
142-
{
143-
errorFreeNames.Add(n);
144-
}
145-
}
146-
147-
errorMsgs = errorMsgList.ToArray();
148-
return errorFreeNames.ToArray();
149-
}
150114

151115
#endregion
152116

test/FindPSResource.Tests.ps1

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ Describe 'Test Find-PSResource for Module' {
4848
$foundScript | Should -BeTrue
4949
}
5050

51+
It "should not find resources given Name that equals wildcard, '*'" {
52+
Find-PSResource -Name "*" -ErrorVariable err -ErrorAction SilentlyContinue
53+
$err.Count | Should -Not -Be 0
54+
$err[0].FullyQualifiedErrorId | Should -BeExactly "NameEqualsWildcardIsNotSupported,Microsoft.PowerShell.PowerShellGet.Cmdlets.FindPSResource"
55+
}
56+
5157
It "find resource given Name from V3 endpoint repository (NuGetGallery)" {
5258
$res = Find-PSResource -Name "Serilog" -Repository $NuGetGalleryName
5359
$res.Count | Should -Be 1

test/InstallPSResource.Tests.ps1

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,17 @@ Describe 'Test Install-PSResource for Module' {
2222
Get-RevertPSResourceRepositoryFile
2323
}
2424

25+
$testCases = @{Name="*"; ErrorId="NameContainsWildcard"},
26+
@{Name="TestModule*"; ErrorId="NameContainsWildcard"},
27+
@{Name="Test?Module","Test[Module"; ErrorId="ErrorFilteringNamesForUnsupportedWildcards"}
28+
29+
It "Should not install resource with wildcard in name" -TestCases $testCases {
30+
param($Name, $ErrorId)
31+
Install-PSResource -Name $Name -ErrorVariable err -ErrorAction SilentlyContinue
32+
$err.Count | Should -Not -Be 0
33+
$err[0].FullyQualifiedErrorId | Should -BeExactly "$ErrorId,Microsoft.PowerShell.PowerShellGet.Cmdlets.InstallPSResource"
34+
}
35+
2536
It "Install specific module resource by name" {
2637
Install-PSResource -Name "TestModule" -Repository $TestGalleryName
2738
$pkg = Get-Module "TestModule" -ListAvailable
@@ -43,7 +54,6 @@ Describe 'Test Install-PSResource for Module' {
4354
$pkg.Name | Should -Be $pkgNames
4455
}
4556

46-
4757
It "Should not install resource given nonexistant name" {
4858
Install-PSResource -Name NonExistantModule -Repository $TestGalleryName
4959
$pkg = Get-Module "NonExistantModule" -ListAvailable

test/SavePSResource.Tests.ps1

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ Describe 'Test Save-PSResource for PSResources' {
5454
$pkgDir.Name | Should -BeNullOrEmpty
5555
}
5656

57+
It "Not Save module with Name containing wildcard" {
58+
Save-PSResource -Name "TestModule*" -Repository $TestGalleryName -Path $SaveDir -ErrorVariable err -ErrorAction SilentlyContinue
59+
$err.Count | Should -Not -Be 0
60+
$err[0].FullyQualifiedErrorId | Should -BeExactly "NameContainsWildcard,Microsoft.PowerShell.PowerShellGet.Cmdlets.SavePSResource"
61+
}
62+
5763
# Do some version testing, but Find-PSResource should be doing thorough testing
5864
It "Should save resource given name and exact version" {
5965
Save-PSResource -Name "TestModule" -Version "1.2.0" -Repository $TestGalleryName -Path $SaveDir

test/UninstallPSResource.Tests.ps1

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@ Describe 'Test Uninstall-PSResource for Modules' {
2323
Get-Module ContosoServer -ListAvailable | Should -Be $null
2424
}
2525

26+
$testCases = @{Name="Test?Module"; ErrorId="ErrorFilteringNamesForUnsupportedWildcards"},
27+
@{Name="Test[Module"; ErrorId="ErrorFilteringNamesForUnsupportedWildcards"}
28+
29+
It "not uninstall module given Name with invalid wildcard characters" -TestCases $testCases {
30+
param($Name, $ErrorId)
31+
Uninstall-PSResource -Name $Name -ErrorVariable err -ErrorAction SilentlyContinue
32+
$err.Count | Should -Not -Be 0
33+
$err[0].FullyQualifiedErrorId | Should -BeExactly "$ErrorId,Microsoft.PowerShell.PowerShellGet.Cmdlets.UninstallPSResource"
34+
}
35+
2636
It "Uninstall a list of modules by name" {
2737
$null = Install-PSResource BaseTestPackage -Repository $TestGalleryName -TrustRepository -WarningAction SilentlyContinue
2838

0 commit comments

Comments
 (0)