From 0462fc0d6d80a492ae2394dc2ebd408ec5968dfd Mon Sep 17 00:00:00 2001 From: alerickson <25858831+alerickson@users.noreply.github.com> Date: Tue, 11 Jul 2023 17:49:50 -0700 Subject: [PATCH 1/9] Check to see if version falls within version range --- src/code/FindHelper.cs | 44 ++++++++++++++++++++++++++++++++---- src/code/InstallHelper.cs | 17 ++++++++++++++ src/code/V2ServerAPICalls.cs | 9 +++++++- 3 files changed, 64 insertions(+), 6 deletions(-) diff --git a/src/code/FindHelper.cs b/src/code/FindHelper.cs index 043736822..ce12bba6c 100644 --- a/src/code/FindHelper.cs +++ b/src/code/FindHelper.cs @@ -637,11 +637,23 @@ private IEnumerable SearchByNames(ServerApiCall currentServer, R continue; } + // Check to see if version falls within version range PSResourceInfo foundPkg = currentResult.returnedObject; - parentPkgs.Add(foundPkg); - _pkgsLeftToFind.Remove(foundPkg.Name); - pkgsFound.Add(String.Format("{0}{1}", foundPkg.Name, foundPkg.Version.ToString())); - yield return foundPkg; + string versionStr = $"{foundPkg.Version}"; + if (foundPkg.IsPrerelease) + { + versionStr += $"-{foundPkg.Prerelease}"; + } + + if (NuGetVersion.TryParse(versionStr, out NuGetVersion version) + && _versionRange.Satisfies(version)) + { + parentPkgs.Add(foundPkg); + _pkgsLeftToFind.Remove(foundPkg.Name); + pkgsFound.Add(String.Format("{0}{1}", foundPkg.Name, foundPkg.Version.ToString())); + + yield return foundPkg; + } } } } @@ -768,9 +780,31 @@ internal IEnumerable FindDependencyPackages( continue; } - depPkg = currentResult.returnedObject; + // Check to see if version falls within version range + PSResourceInfo foundDep = currentResult.returnedObject; + string depVersionStr = $"{foundDep.Version}"; + if (foundDep.IsPrerelease) { + depVersionStr += $"-{foundDep.Prerelease}"; + } + + if (NuGetVersion.TryParse(depVersionStr, out NuGetVersion depVersion) + && dep.VersionRange.Satisfies(depVersion)) + { + depPkg = foundDep; + } } + if (depPkg == null) + { + _cmdletPassedIn.WriteError(new ErrorRecord( + new PackageNotFoundException($"Dependency package '{dep.Name}' with version range '{dep.VersionRange}' could not be found", currentResult.exception), + "DependencyPackageNotFound", + ErrorCategory.ObjectNotFound, + this)); + + yield return null; + } + string pkgHashKey = String.Format("{0}{1}", depPkg.Name, depPkg.Version.ToString()); if (!foundPkgs.Contains(pkgHashKey)) diff --git a/src/code/InstallHelper.cs b/src/code/InstallHelper.cs index 8ede5fd39..4e4a79d89 100644 --- a/src/code/InstallHelper.cs +++ b/src/code/InstallHelper.cs @@ -639,7 +639,24 @@ private Hashtable InstallPackage( return packagesHash; } + // Check to see if version falls within version range PSResourceInfo pkgToInstall = currentResult.returnedObject; + if (searchVersionType == VersionType.VersionRange) + { + string versionStr = $"{pkgToInstall.Version}"; + if (pkgToInstall.IsPrerelease) + { + versionStr += $"-{pkgToInstall.Prerelease}"; + } + + // Early out if version does + if (!NuGetVersion.TryParse(versionStr, out NuGetVersion version) + || !_versionRange.Satisfies(version)) + { + return packagesHash; + } + } + pkgToInstall.RepositorySourceLocation = repository.Uri.ToString(); pkgToInstall.AdditionalMetadata.TryGetValue("NormalizedVersion", out string pkgVersion); diff --git a/src/code/V2ServerAPICalls.cs b/src/code/V2ServerAPICalls.cs index f08d6d9ea..80fa29f81 100644 --- a/src/code/V2ServerAPICalls.cs +++ b/src/code/V2ServerAPICalls.cs @@ -797,7 +797,14 @@ private string FindVersionGlobbing(string packageName, VersionRange versionRange if (versionRange.MaxVersion != null) { string operation = versionRange.IsMaxInclusive ? "le" : "lt"; - maxPart = String.Format(format, operation, $"'{versionRange.MaxVersion.ToNormalizedString()}'"); + string maxString = $"{versionRange.MaxVersion.Major}.{versionRange.MaxVersion.Minor + 1}"; + if (NuGetVersion.TryParse(maxString, out NuGetVersion maxVersion)) + { + maxPart = String.Format(format, operation, $"'{maxVersion.ToNormalizedString()}'"); + } + else { + maxPart = String.Format(format, operation, $"'{versionRange.MaxVersion.ToNormalizedString()}'"); + } } string versionFilterParts = String.Empty; From 9e9442963313628d642a54b0a8d69b1b468dea77 Mon Sep 17 00:00:00 2001 From: alerickson <25858831+alerickson@users.noreply.github.com> Date: Tue, 11 Jul 2023 17:52:14 -0700 Subject: [PATCH 2/9] Clean up error message --- src/code/FindHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code/FindHelper.cs b/src/code/FindHelper.cs index ce12bba6c..5fffc4f5a 100644 --- a/src/code/FindHelper.cs +++ b/src/code/FindHelper.cs @@ -797,7 +797,7 @@ internal IEnumerable FindDependencyPackages( if (depPkg == null) { _cmdletPassedIn.WriteError(new ErrorRecord( - new PackageNotFoundException($"Dependency package '{dep.Name}' with version range '{dep.VersionRange}' could not be found", currentResult.exception), + new PackageNotFoundException($"Dependency package '{dep.Name}' with version range '{dep.VersionRange}' could not be found"), "DependencyPackageNotFound", ErrorCategory.ObjectNotFound, this)); From 375982b98152b2fe156483e93ea1864ff2e7b6f1 Mon Sep 17 00:00:00 2001 From: alerickson <25858831+alerickson@users.noreply.github.com> Date: Tue, 11 Jul 2023 18:03:24 -0700 Subject: [PATCH 3/9] add test --- test/FindPSResourceTests/FindPSResourceV2Server.Tests.ps1 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/FindPSResourceTests/FindPSResourceV2Server.Tests.ps1 b/test/FindPSResourceTests/FindPSResourceV2Server.Tests.ps1 index 456c70205..a64ba366f 100644 --- a/test/FindPSResourceTests/FindPSResourceV2Server.Tests.ps1 +++ b/test/FindPSResourceTests/FindPSResourceV2Server.Tests.ps1 @@ -372,6 +372,12 @@ Describe 'Test HTTP Find-PSResource for V2 Server Protocol' -tags 'CI' { $res.Count | Should -Be 1 $res.Repository | Should -Be $PSGalleryName } + + It "find all resources within a version range, including prereleases" { + $res = Find-PSResource -Name "PSReadLine" -Version "(2.0,2.1)" -Prerelease -Repository $PSGalleryName + $res | Should -Not -BeNullOrEmpty + $res.Count | Should -Be 7 + } } Describe 'Test HTTP Find-PSResource for V2 Server Protocol' -tags 'ManualValidationOnly' { From a5ce24d1b74998ec9a46521f7ed83b5eddeccfa6 Mon Sep 17 00:00:00 2001 From: alerickson <25858831+alerickson@users.noreply.github.com> Date: Wed, 12 Jul 2023 01:55:15 -0700 Subject: [PATCH 4/9] Fix some bugs with dependency version ranges --- src/code/FindHelper.cs | 2 +- src/code/InstallHelper.cs | 58 +++++++++++++++++++++--------------- src/code/V2ServerAPICalls.cs | 3 +- 3 files changed, 36 insertions(+), 27 deletions(-) diff --git a/src/code/FindHelper.cs b/src/code/FindHelper.cs index 5fffc4f5a..4418b5acd 100644 --- a/src/code/FindHelper.cs +++ b/src/code/FindHelper.cs @@ -711,7 +711,7 @@ internal IEnumerable FindDependencyPackages( { PSResourceInfo depPkg = null; - if (dep.VersionRange == VersionRange.All) + if (dep.VersionRange.Equals(VersionRange.All)) { FindResults responses = currentServer.FindName(dep.Name, _prerelease, _type, out ErrorRecord errRecord); if (errRecord != null) diff --git a/src/code/InstallHelper.cs b/src/code/InstallHelper.cs index 4e4a79d89..09bd6dbcd 100644 --- a/src/code/InstallHelper.cs +++ b/src/code/InstallHelper.cs @@ -626,37 +626,47 @@ private Hashtable InstallPackage( break; } - PSResourceResult currentResult = currentResponseUtil.ConvertToPSResourceResult(responseResults: responses).FirstOrDefault(); - - if (currentResult.exception != null && !currentResult.exception.Message.Equals(string.Empty)) - { - // V2Server API calls will return non-empty response when package is not found but fail at conversion time - _cmdletPassedIn.WriteError(new ErrorRecord( - new InvalidOrEmptyResponse($"Package '{pkgNameToInstall}' could not be installed", currentResult.exception), - "InstallPackageFailure", - ErrorCategory.InvalidData, - this)); - return packagesHash; - } - - // Check to see if version falls within version range - PSResourceInfo pkgToInstall = currentResult.returnedObject; - if (searchVersionType == VersionType.VersionRange) + PSResourceInfo pkgToInstall = null; + foreach (PSResourceResult currentResult in currentResponseUtil.ConvertToPSResourceResult(responses)) { - string versionStr = $"{pkgToInstall.Version}"; - if (pkgToInstall.IsPrerelease) + if (currentResult.exception != null && !currentResult.exception.Message.Equals(string.Empty)) { - versionStr += $"-{pkgToInstall.Prerelease}"; + // V2Server API calls will return non-empty response when package is not found but fail at conversion time + _cmdletPassedIn.WriteError(new ErrorRecord( + new InvalidOrEmptyResponse($"Package '{pkgNameToInstall}' could not be installed", currentResult.exception), + "InstallPackageFailure", + ErrorCategory.InvalidData, + this)); } - - // Early out if version does - if (!NuGetVersion.TryParse(versionStr, out NuGetVersion version) - || !_versionRange.Satisfies(version)) + else if (searchVersionType == VersionType.VersionRange) { - return packagesHash; + // Check to see if version falls within version range + PSResourceInfo foundPkg = currentResult.returnedObject; + string versionStr = $"{foundPkg.Version}"; + if (foundPkg.IsPrerelease) + { + versionStr += $"-{foundPkg.Prerelease}"; + } + + if (NuGetVersion.TryParse(versionStr, out NuGetVersion version) + && _versionRange.Satisfies(version)) + { + pkgToInstall = foundPkg; + + break; + } + } else { + pkgToInstall = currentResult.returnedObject; + + break; } } + if (pkgToInstall == null) + { + return packagesHash; + } + pkgToInstall.RepositorySourceLocation = repository.Uri.ToString(); pkgToInstall.AdditionalMetadata.TryGetValue("NormalizedVersion", out string pkgVersion); diff --git a/src/code/V2ServerAPICalls.cs b/src/code/V2ServerAPICalls.cs index 80fa29f81..e9cd6d1a6 100644 --- a/src/code/V2ServerAPICalls.cs +++ b/src/code/V2ServerAPICalls.cs @@ -840,8 +840,7 @@ private string FindVersionGlobbing(string packageName, VersionRange versionRange filterQuery += $"{andOperator}{versionFilterParts}"; } - string topParam = getOnlyLatest ? "$top=1" : "$top=100"; // only need 1 package if interested in latest - string paginationParam = $"$inlinecount=allpages&$skip={skip}&{topParam}"; + string paginationParam = $"$inlinecount=allpages&$skip={skip}"; filterQuery = filterQuery.EndsWith("=") ? string.Empty : filterQuery; var requestUrlV2 = $"{Repository.Uri}/FindPackagesById()?id='{packageName}'&$orderby=NormalizedVersion desc&{paginationParam}{filterQuery}"; From 46ea961445223af5861bc876e8eb2a6c6251d90d Mon Sep 17 00:00:00 2001 From: alerickson <25858831+alerickson@users.noreply.github.com> Date: Wed, 12 Jul 2023 13:08:26 -0700 Subject: [PATCH 5/9] test updates --- .../v17/.suo | Bin 0 -> 266752 bytes .../InstallPSResourceV2Server.Tests.ps1 | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 src/code/.vs/Microsoft.PowerShell.PSResourceGet/v17/.suo diff --git a/src/code/.vs/Microsoft.PowerShell.PSResourceGet/v17/.suo b/src/code/.vs/Microsoft.PowerShell.PSResourceGet/v17/.suo new file mode 100644 index 0000000000000000000000000000000000000000..05b0bcf91c690892d34c6ec7f22675839024ccd4 GIT binary patch literal 266752 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 Dz_FxB literal 0 HcmV?d00001 diff --git a/test/InstallPSResourceTests/InstallPSResourceV2Server.Tests.ps1 b/test/InstallPSResourceTests/InstallPSResourceV2Server.Tests.ps1 index 682662c33..5b9cbe229 100644 --- a/test/InstallPSResourceTests/InstallPSResourceV2Server.Tests.ps1 +++ b/test/InstallPSResourceTests/InstallPSResourceV2Server.Tests.ps1 @@ -141,7 +141,7 @@ Describe 'Test Install-PSResource for V2 Server scenarios' -tags 'CI' { It "Install a module with a dependency" { Uninstall-PSResource -Name "TestModuleWithDependency*" -Version "*" -SkipDependencyCheck -ErrorAction SilentlyContinue - Install-PSResource -Name "TestModuleWithDependencyC" -Version "1.0.0.0" -Repository $PSGalleryName -TrustRepository + Install-PSResource -Name "TestModuleWithDependencyC" -Version "5.0.0.0" -Repository $PSGalleryName -TrustRepository $pkg = Get-InstalledPSResource "TestModuleWithDependencyC" $pkg.Name | Should -Be "TestModuleWithDependencyC" From 32f0f8380d476d428499099eb6060566a7c33a32 Mon Sep 17 00:00:00 2001 From: alerickson <25858831+alerickson@users.noreply.github.com> Date: Wed, 12 Jul 2023 13:08:36 -0700 Subject: [PATCH 6/9] more test updates --- test/FindPSResourceTests/FindPSResourceV2Server.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/FindPSResourceTests/FindPSResourceV2Server.Tests.ps1 b/test/FindPSResourceTests/FindPSResourceV2Server.Tests.ps1 index a64ba366f..8c50efe3e 100644 --- a/test/FindPSResourceTests/FindPSResourceV2Server.Tests.ps1 +++ b/test/FindPSResourceTests/FindPSResourceV2Server.Tests.ps1 @@ -140,7 +140,7 @@ Describe 'Test HTTP Find-PSResource for V2 Server Protocol' -tags 'CI' { elseif ($pkg.Name -eq "TestModuleWithDependencyB") { $foundDepB = $true - $foundDepBCorrectVersion = [System.Version]$pkg.Version -ge [System.Version]"3.0" + $foundDepBCorrectVersion = [System.Version]$pkg.Version -ge [System.Version]"1.0" } elseif ($pkg.Name -eq "TestModuleWithDependencyD") { From b7dc0d0b2efa6cfd5c300f49220eead2a9bc1664 Mon Sep 17 00:00:00 2001 From: alerickson <25858831+alerickson@users.noreply.github.com> Date: Wed, 12 Jul 2023 13:25:38 -0700 Subject: [PATCH 7/9] update test again --- test/InstallPSResourceTests/InstallPSResourceV2Server.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/InstallPSResourceTests/InstallPSResourceV2Server.Tests.ps1 b/test/InstallPSResourceTests/InstallPSResourceV2Server.Tests.ps1 index 5b9cbe229..70e871976 100644 --- a/test/InstallPSResourceTests/InstallPSResourceV2Server.Tests.ps1 +++ b/test/InstallPSResourceTests/InstallPSResourceV2Server.Tests.ps1 @@ -145,7 +145,7 @@ Describe 'Test Install-PSResource for V2 Server scenarios' -tags 'CI' { $pkg = Get-InstalledPSResource "TestModuleWithDependencyC" $pkg.Name | Should -Be "TestModuleWithDependencyC" - $pkg.Version | Should -Be "1.0" + $pkg.Version | Should -Be "5.0" $pkg = Get-InstalledPSResource "TestModuleWithDependencyB" $pkg.Name | Should -Be "TestModuleWithDependencyB" From c6550071df7bda37772aaab31eb1b1c684060b96 Mon Sep 17 00:00:00 2001 From: alerickson <25858831+alerickson@users.noreply.github.com> Date: Wed, 12 Jul 2023 13:27:38 -0700 Subject: [PATCH 8/9] Update test --- test/InstallPSResourceTests/InstallPSResourceV2Server.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/InstallPSResourceTests/InstallPSResourceV2Server.Tests.ps1 b/test/InstallPSResourceTests/InstallPSResourceV2Server.Tests.ps1 index 70e871976..ad341c160 100644 --- a/test/InstallPSResourceTests/InstallPSResourceV2Server.Tests.ps1 +++ b/test/InstallPSResourceTests/InstallPSResourceV2Server.Tests.ps1 @@ -153,7 +153,7 @@ Describe 'Test Install-PSResource for V2 Server scenarios' -tags 'CI' { $pkg = Get-InstalledPSResource "TestModuleWithDependencyD" $pkg.Name | Should -Be "TestModuleWithDependencyD" - $pkg.Version | Should -Be "1.0" + $pkg.Version | Should -Be "2.0" } It "Install a module with a dependency and skip installing the dependency" { From ea3b104ad48f14a433c12bad790369d27c9147e6 Mon Sep 17 00:00:00 2001 From: alerickson <25858831+alerickson@users.noreply.github.com> Date: Fri, 14 Jul 2023 10:05:33 -0700 Subject: [PATCH 9/9] Add comment --- src/code/V2ServerAPICalls.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/code/V2ServerAPICalls.cs b/src/code/V2ServerAPICalls.cs index e9cd6d1a6..89d6990df 100644 --- a/src/code/V2ServerAPICalls.cs +++ b/src/code/V2ServerAPICalls.cs @@ -797,6 +797,8 @@ private string FindVersionGlobbing(string packageName, VersionRange versionRange if (versionRange.MaxVersion != null) { string operation = versionRange.IsMaxInclusive ? "le" : "lt"; + // Adding 1 because we want to retrieve all the prerelease versions for the max version and PSGallery views prerelease as higher than its stable + // eg 3.0.0-prerelease > 3.0.0 string maxString = $"{versionRange.MaxVersion.Major}.{versionRange.MaxVersion.Minor + 1}"; if (NuGetVersion.TryParse(maxString, out NuGetVersion maxVersion)) {