diff --git a/src/code/LocalServerApiCalls.cs b/src/code/LocalServerApiCalls.cs index 484ed351b..b22b3efb6 100644 --- a/src/code/LocalServerApiCalls.cs +++ b/src/code/LocalServerApiCalls.cs @@ -255,32 +255,48 @@ private FindResults FindNameHelper(string packageName, string[] tags, bool inclu FindResults findResponse = new FindResults(); errRecord = null; - WildcardPattern pkgNamePattern = new WildcardPattern($"{packageName}.*", WildcardOptions.IgnoreCase); NuGetVersion latestVersion = new NuGetVersion("0.0.0.0"); String latestVersionPath = String.Empty; string actualPkgName = packageName; + // this regex pattern matches packageName followed by a version (4 digit or 3 with prerelease word) + string regexPattern = $"{packageName}" + @".\d+\.\d+\.\d+(?:-\w+|.\d)*.nupkg"; + Regex rx = new Regex(regexPattern, RegexOptions.Compiled | RegexOptions.IgnoreCase); + _cmdletPassedIn.WriteDebug($"package file name pattern to be searched for is: {regexPattern}"); + foreach (string path in Directory.GetFiles(Repository.Uri.LocalPath)) { string packageFullName = Path.GetFileName(path); + MatchCollection matches = rx.Matches(packageFullName); + if (matches.Count == 0) + { + continue; + } - if (!String.IsNullOrEmpty(packageFullName) && pkgNamePattern.IsMatch(packageFullName)) + Match match = matches[0]; + + GroupCollection groups = match.Groups; + if (groups.Count == 0) { - NuGetVersion nugetVersion = GetInfoFromFileName(packageFullName: packageFullName, packageName: packageName, actualName: out actualPkgName, out errRecord); - _cmdletPassedIn.WriteDebug($"Version parsed as '{nugetVersion}'"); + continue; + } - if (errRecord != null) - { - return findResponse; - } + Capture group = groups[0]; - if ((!nugetVersion.IsPrerelease || includePrerelease) && (nugetVersion > latestVersion)) + NuGetVersion nugetVersion = GetInfoFromFileName(packageFullName: packageFullName, packageName: packageName, actualName: out actualPkgName, out errRecord); + _cmdletPassedIn.WriteDebug($"Version parsed as '{nugetVersion}'"); + + if (errRecord != null) + { + return findResponse; + } + + if ((!nugetVersion.IsPrerelease || includePrerelease) && (nugetVersion > latestVersion)) + { + if (nugetVersion > latestVersion) { - if (nugetVersion > latestVersion) - { - latestVersion = nugetVersion; - latestVersionPath = path; - } + latestVersion = nugetVersion; + latestVersionPath = path; } } } @@ -371,29 +387,46 @@ private FindResults FindVersionHelper(string packageName, string version, string return findResponse; } - WildcardPattern pkgNamePattern = new WildcardPattern($"{packageName}.*", WildcardOptions.IgnoreCase); + // this regex pattern matches packageName followed by the requested version + string regexPattern = $"{packageName}.{requiredVersion.ToNormalizedString()}" + @".nupkg"; + Regex rx = new Regex(regexPattern, RegexOptions.Compiled | RegexOptions.IgnoreCase); + _cmdletPassedIn.WriteDebug($"pattern is: {regexPattern}"); string pkgPath = String.Empty; string actualPkgName = String.Empty; + foreach (string path in Directory.GetFiles(Repository.Uri.LocalPath)) { string packageFullName = Path.GetFileName(path); - if (!String.IsNullOrEmpty(packageFullName) && pkgNamePattern.IsMatch(packageFullName)) + MatchCollection matches = rx.Matches(packageFullName); + if (matches.Count == 0) { - NuGetVersion nugetVersion = GetInfoFromFileName(packageFullName: packageFullName, packageName: packageName, actualName: out actualPkgName, out errRecord); - _cmdletPassedIn.WriteDebug($"'{packageName}' version parsed as '{nugetVersion}'"); + continue; + } - if (errRecord != null) - { - return findResponse; - } + Match match = matches[0]; - if (nugetVersion == requiredVersion) - { - _cmdletPassedIn.WriteDebug("Found matching version"); - string pkgFullName = $"{actualPkgName}.{nugetVersion.ToString()}.nupkg"; - pkgPath = Path.Combine(Repository.Uri.LocalPath, pkgFullName); - break; - } + GroupCollection groups = match.Groups; + if (groups.Count == 0) + { + continue; + } + + Capture group = groups[0]; + + NuGetVersion nugetVersion = GetInfoFromFileName(packageFullName: packageFullName, packageName: packageName, actualName: out actualPkgName, out errRecord); + _cmdletPassedIn.WriteDebug($"Version parsed as '{nugetVersion}'"); + + if (errRecord != null) + { + return findResponse; + } + + if (nugetVersion == requiredVersion) + { + _cmdletPassedIn.WriteDebug("Found matching version"); + string pkgFullName = $"{actualPkgName}.{nugetVersion.ToString()}.nupkg"; + pkgPath = Path.Combine(Repository.Uri.LocalPath, pkgFullName); + break; } } diff --git a/test/FindPSResourceTests/FindPSResourceLocal.Tests.ps1 b/test/FindPSResourceTests/FindPSResourceLocal.Tests.ps1 index dda4ddf50..b6e43716a 100644 --- a/test/FindPSResourceTests/FindPSResourceLocal.Tests.ps1 +++ b/test/FindPSResourceTests/FindPSResourceLocal.Tests.ps1 @@ -14,6 +14,7 @@ Describe 'Test Find-PSResource for local repositories' -tags 'CI' { $localUNCRepo = 'psgettestlocal3' $testModuleName = "test_local_mod" $testModuleName2 = "test_local_mod2" + $similarTestModuleName = "test_local_mod.similar" $commandName = "cmd1" $dscResourceName = "dsc1" $prereleaseLabel = "" @@ -31,6 +32,9 @@ Describe 'Test Find-PSResource for local repositories' -tags 'CI' { New-TestModule -moduleName $testModuleName2 -repoName $localRepo -packageVersion "5.0.0" -prereleaseLabel "" -tags $tagsEscaped New-TestModule -moduleName $testModuleName2 -repoName $localRepo -packageVersion "5.2.5" -prereleaseLabel $prereleaseLabel -tags $tagsEscaped + + New-TestModule -moduleName $similarTestModuleName -repoName $localRepo -packageVersion "4.0.0" -prereleaseLabel "" -tags $tagsEscaped + New-TestModule -moduleName $similarTestModuleName -repoName $localRepo -packageVersion "5.0.0" -prereleaseLabel "" -tags $tagsEscaped } AfterAll { @@ -74,6 +78,7 @@ Describe 'Test Find-PSResource for local repositories' -tags 'CI' { } It "should not find resource given nonexistant Name" { + # FindName() $res = Find-PSResource -Name NonExistantModule -Repository $localRepo -ErrorVariable err -ErrorAction SilentlyContinue $res | Should -BeNullOrEmpty $err.Count | Should -Not -Be 0 @@ -81,6 +86,17 @@ Describe 'Test Find-PSResource for local repositories' -tags 'CI' { $res | Should -BeNullOrEmpty } + It "find resource given specific Name when another package with similar name (with period) exists" { + # FindName() + $res = Find-PSResource -Name $testModuleName -Repository $localRepo + $res.Name | Should -Be $testModuleName + $res.Version | Should -Be "5.0.0" + + $res = Find-PSResource -Name $similarTestModuleName -Repository $localRepo + $res.Name | Should -Be $similarTestModuleName + $res.Version | Should -Be "5.0.0" + } + It "find resource(s) given wildcard Name" { # FindNameGlobbing $res = Find-PSResource -Name "test_local_*" -Repository $localRepo @@ -129,6 +145,22 @@ Describe 'Test Find-PSResource for local repositories' -tags 'CI' { $resPrerelease.Prerelease | Should -Be "alpha001" } + It "find resource given specific Name when another package with similar name (with period) exists" { + # FindVersion() + # Package $testModuleName version 4.0.0 does not exist + # previously if Find-PSResource -Version against local repo did not find that package's version it kept looking at + # similar named packages and would fault. This test is to ensure only the specified package and its version is checked + $res = Find-PSResource -Name $testModuleName -Version "4.0.0" -Repository $localRepo -ErrorVariable err -ErrorAction SilentlyContinue + $res | Should -BeNullOrEmpty + $err.Count | Should -Not -Be 0 + $err[0].FullyQualifiedErrorId | Should -BeExactly "PackageNotFound,Microsoft.PowerShell.PSResourceGet.Cmdlets.FindPSResource" + $res | Should -BeNullOrEmpty + + $res = Find-PSResource -Name $similarTestModuleName -Version "4.0.0" -Repository $localRepo + $res.Name | Should -Be $similarTestModuleName + $res.Version | Should -Be "4.0.0" + } + It "find resources, including Prerelease version resources, when given Prerelease parameter" { # FindVersionGlobbing() $resWithoutPrerelease = Find-PSResource -Name $testModuleName -Version "*" -Repository $localRepo