Skip to content

Commit 5bbc687

Browse files
authored
Bugfix - Correctly match package names from local repos (#1731)
* Fix pattern matching code to match specific pkgName.version.nupkg not packageName* to avoid unwanted wildcard clashes * remove unused code * remove unused code some more * use Regex instead of WildcardPattern for FindVersion() too * add tests * remove comment * add ErrorVariable reference * addres PR feedback about comments and debug message * add comment
1 parent b8a3013 commit 5bbc687

File tree

2 files changed

+94
-29
lines changed

2 files changed

+94
-29
lines changed

src/code/LocalServerApiCalls.cs

Lines changed: 62 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -255,32 +255,48 @@ private FindResults FindNameHelper(string packageName, string[] tags, bool inclu
255255
FindResults findResponse = new FindResults();
256256
errRecord = null;
257257

258-
WildcardPattern pkgNamePattern = new WildcardPattern($"{packageName}.*", WildcardOptions.IgnoreCase);
259258
NuGetVersion latestVersion = new NuGetVersion("0.0.0.0");
260259
String latestVersionPath = String.Empty;
261260
string actualPkgName = packageName;
262261

262+
// this regex pattern matches packageName followed by a version (4 digit or 3 with prerelease word)
263+
string regexPattern = $"{packageName}" + @".\d+\.\d+\.\d+(?:-\w+|.\d)*.nupkg";
264+
Regex rx = new Regex(regexPattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
265+
_cmdletPassedIn.WriteDebug($"package file name pattern to be searched for is: {regexPattern}");
266+
263267
foreach (string path in Directory.GetFiles(Repository.Uri.LocalPath))
264268
{
265269
string packageFullName = Path.GetFileName(path);
270+
MatchCollection matches = rx.Matches(packageFullName);
271+
if (matches.Count == 0)
272+
{
273+
continue;
274+
}
266275

267-
if (!String.IsNullOrEmpty(packageFullName) && pkgNamePattern.IsMatch(packageFullName))
276+
Match match = matches[0];
277+
278+
GroupCollection groups = match.Groups;
279+
if (groups.Count == 0)
268280
{
269-
NuGetVersion nugetVersion = GetInfoFromFileName(packageFullName: packageFullName, packageName: packageName, actualName: out actualPkgName, out errRecord);
270-
_cmdletPassedIn.WriteDebug($"Version parsed as '{nugetVersion}'");
281+
continue;
282+
}
271283

272-
if (errRecord != null)
273-
{
274-
return findResponse;
275-
}
284+
Capture group = groups[0];
276285

277-
if ((!nugetVersion.IsPrerelease || includePrerelease) && (nugetVersion > latestVersion))
286+
NuGetVersion nugetVersion = GetInfoFromFileName(packageFullName: packageFullName, packageName: packageName, actualName: out actualPkgName, out errRecord);
287+
_cmdletPassedIn.WriteDebug($"Version parsed as '{nugetVersion}'");
288+
289+
if (errRecord != null)
290+
{
291+
return findResponse;
292+
}
293+
294+
if ((!nugetVersion.IsPrerelease || includePrerelease) && (nugetVersion > latestVersion))
295+
{
296+
if (nugetVersion > latestVersion)
278297
{
279-
if (nugetVersion > latestVersion)
280-
{
281-
latestVersion = nugetVersion;
282-
latestVersionPath = path;
283-
}
298+
latestVersion = nugetVersion;
299+
latestVersionPath = path;
284300
}
285301
}
286302
}
@@ -371,29 +387,46 @@ private FindResults FindVersionHelper(string packageName, string version, string
371387
return findResponse;
372388
}
373389

374-
WildcardPattern pkgNamePattern = new WildcardPattern($"{packageName}.*", WildcardOptions.IgnoreCase);
390+
// this regex pattern matches packageName followed by the requested version
391+
string regexPattern = $"{packageName}.{requiredVersion.ToNormalizedString()}" + @".nupkg";
392+
Regex rx = new Regex(regexPattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
393+
_cmdletPassedIn.WriteDebug($"pattern is: {regexPattern}");
375394
string pkgPath = String.Empty;
376395
string actualPkgName = String.Empty;
396+
377397
foreach (string path in Directory.GetFiles(Repository.Uri.LocalPath))
378398
{
379399
string packageFullName = Path.GetFileName(path);
380-
if (!String.IsNullOrEmpty(packageFullName) && pkgNamePattern.IsMatch(packageFullName))
400+
MatchCollection matches = rx.Matches(packageFullName);
401+
if (matches.Count == 0)
381402
{
382-
NuGetVersion nugetVersion = GetInfoFromFileName(packageFullName: packageFullName, packageName: packageName, actualName: out actualPkgName, out errRecord);
383-
_cmdletPassedIn.WriteDebug($"'{packageName}' version parsed as '{nugetVersion}'");
403+
continue;
404+
}
384405

385-
if (errRecord != null)
386-
{
387-
return findResponse;
388-
}
406+
Match match = matches[0];
389407

390-
if (nugetVersion == requiredVersion)
391-
{
392-
_cmdletPassedIn.WriteDebug("Found matching version");
393-
string pkgFullName = $"{actualPkgName}.{nugetVersion.ToString()}.nupkg";
394-
pkgPath = Path.Combine(Repository.Uri.LocalPath, pkgFullName);
395-
break;
396-
}
408+
GroupCollection groups = match.Groups;
409+
if (groups.Count == 0)
410+
{
411+
continue;
412+
}
413+
414+
Capture group = groups[0];
415+
416+
NuGetVersion nugetVersion = GetInfoFromFileName(packageFullName: packageFullName, packageName: packageName, actualName: out actualPkgName, out errRecord);
417+
_cmdletPassedIn.WriteDebug($"Version parsed as '{nugetVersion}'");
418+
419+
if (errRecord != null)
420+
{
421+
return findResponse;
422+
}
423+
424+
if (nugetVersion == requiredVersion)
425+
{
426+
_cmdletPassedIn.WriteDebug("Found matching version");
427+
string pkgFullName = $"{actualPkgName}.{nugetVersion.ToString()}.nupkg";
428+
pkgPath = Path.Combine(Repository.Uri.LocalPath, pkgFullName);
429+
break;
397430
}
398431
}
399432

test/FindPSResourceTests/FindPSResourceLocal.Tests.ps1

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Describe 'Test Find-PSResource for local repositories' -tags 'CI' {
1414
$localUNCRepo = 'psgettestlocal3'
1515
$testModuleName = "test_local_mod"
1616
$testModuleName2 = "test_local_mod2"
17+
$similarTestModuleName = "test_local_mod.similar"
1718
$commandName = "cmd1"
1819
$dscResourceName = "dsc1"
1920
$prereleaseLabel = ""
@@ -31,6 +32,9 @@ Describe 'Test Find-PSResource for local repositories' -tags 'CI' {
3132

3233
New-TestModule -moduleName $testModuleName2 -repoName $localRepo -packageVersion "5.0.0" -prereleaseLabel "" -tags $tagsEscaped
3334
New-TestModule -moduleName $testModuleName2 -repoName $localRepo -packageVersion "5.2.5" -prereleaseLabel $prereleaseLabel -tags $tagsEscaped
35+
36+
New-TestModule -moduleName $similarTestModuleName -repoName $localRepo -packageVersion "4.0.0" -prereleaseLabel "" -tags $tagsEscaped
37+
New-TestModule -moduleName $similarTestModuleName -repoName $localRepo -packageVersion "5.0.0" -prereleaseLabel "" -tags $tagsEscaped
3438
}
3539

3640
AfterAll {
@@ -74,13 +78,25 @@ Describe 'Test Find-PSResource for local repositories' -tags 'CI' {
7478
}
7579

7680
It "should not find resource given nonexistant Name" {
81+
# FindName()
7782
$res = Find-PSResource -Name NonExistantModule -Repository $localRepo -ErrorVariable err -ErrorAction SilentlyContinue
7883
$res | Should -BeNullOrEmpty
7984
$err.Count | Should -Not -Be 0
8085
$err[0].FullyQualifiedErrorId | Should -BeExactly "PackageNotFound,Microsoft.PowerShell.PSResourceGet.Cmdlets.FindPSResource"
8186
$res | Should -BeNullOrEmpty
8287
}
8388

89+
It "find resource given specific Name when another package with similar name (with period) exists" {
90+
# FindName()
91+
$res = Find-PSResource -Name $testModuleName -Repository $localRepo
92+
$res.Name | Should -Be $testModuleName
93+
$res.Version | Should -Be "5.0.0"
94+
95+
$res = Find-PSResource -Name $similarTestModuleName -Repository $localRepo
96+
$res.Name | Should -Be $similarTestModuleName
97+
$res.Version | Should -Be "5.0.0"
98+
}
99+
84100
It "find resource(s) given wildcard Name" {
85101
# FindNameGlobbing
86102
$res = Find-PSResource -Name "test_local_*" -Repository $localRepo
@@ -129,6 +145,22 @@ Describe 'Test Find-PSResource for local repositories' -tags 'CI' {
129145
$resPrerelease.Prerelease | Should -Be "alpha001"
130146
}
131147

148+
It "find resource given specific Name when another package with similar name (with period) exists" {
149+
# FindVersion()
150+
# Package $testModuleName version 4.0.0 does not exist
151+
# previously if Find-PSResource -Version against local repo did not find that package's version it kept looking at
152+
# similar named packages and would fault. This test is to ensure only the specified package and its version is checked
153+
$res = Find-PSResource -Name $testModuleName -Version "4.0.0" -Repository $localRepo -ErrorVariable err -ErrorAction SilentlyContinue
154+
$res | Should -BeNullOrEmpty
155+
$err.Count | Should -Not -Be 0
156+
$err[0].FullyQualifiedErrorId | Should -BeExactly "PackageNotFound,Microsoft.PowerShell.PSResourceGet.Cmdlets.FindPSResource"
157+
$res | Should -BeNullOrEmpty
158+
159+
$res = Find-PSResource -Name $similarTestModuleName -Version "4.0.0" -Repository $localRepo
160+
$res.Name | Should -Be $similarTestModuleName
161+
$res.Version | Should -Be "4.0.0"
162+
}
163+
132164
It "find resources, including Prerelease version resources, when given Prerelease parameter" {
133165
# FindVersionGlobbing()
134166
$resWithoutPrerelease = Find-PSResource -Name $testModuleName -Version "*" -Repository $localRepo

0 commit comments

Comments
 (0)