diff --git a/src/code/GetHelper.cs b/src/code/GetHelper.cs index 18cd5ab29..39881b633 100644 --- a/src/code/GetHelper.cs +++ b/src/code/GetHelper.cs @@ -112,19 +112,18 @@ public IEnumerable FilterPkgPathsByVersion(VersionRange versionRange, Li foreach (string versionPath in versionsDirs) { _cmdletPassedIn.WriteVerbose(string.Format("Searching through package version path: '{0}'", versionPath)); - DirectoryInfo dirInfo = new DirectoryInfo(versionPath); - - // if the version is not valid, we'll just skip it and output a debug message - if (!NuGetVersion.TryParse(dirInfo.Name, out NuGetVersion dirAsNugetVersion)) + if(!Utils.GetVersionForInstallPath(installedPkgPath: versionPath, + isModule: true, + cmdletPassedIn: _cmdletPassedIn, + out NuGetVersion pkgNugetVersion)) { - _cmdletPassedIn.WriteVerbose(string.Format("Leaf directory in path '{0}' cannot be parsed into a version.", versionPath)); - // skip to next iteration of the loop continue; } - _cmdletPassedIn.WriteVerbose(string.Format("Directory parsed as NuGet version: '{0}'", dirAsNugetVersion)); - if (versionRange.Satisfies(dirAsNugetVersion)) + _cmdletPassedIn.WriteVerbose(string.Format("Package version parsed as NuGet version: '{0}'", pkgNugetVersion)); + + if (versionRange.Satisfies(pkgNugetVersion)) { // This will be one version or a version range. // yield results then continue with this iteration of the loop @@ -150,17 +149,17 @@ public IEnumerable FilterPkgPathsByVersion(VersionRange versionRange, Li // check to make sure it's within the version range. // script versions will be parsed from the script xml file PSResourceInfo scriptInfo = OutputPackageObject(pkgPath, _scriptDictionary); - if (scriptInfo == null) + if(!Utils.GetVersionForInstallPath(installedPkgPath: pkgPath, + isModule: false, + cmdletPassedIn: _cmdletPassedIn, + out NuGetVersion pkgNugetVersion)) { - // if script was not found skip to the next iteration of the loop - continue; + // skip to next iteration of the loop + yield return pkgPath; } - if (!NuGetVersion.TryParse(scriptInfo.Version.ToString(), out NuGetVersion scriptVersion)) - { - _cmdletPassedIn.WriteVerbose(string.Format("Version '{0}' could not be properly parsed from the script metadata file from the script installed at '{1}'", scriptInfo.Version.ToString(), scriptInfo.InstalledLocation)); - } - else if (versionRange.Satisfies(scriptVersion)) + _cmdletPassedIn.WriteVerbose(string.Format("Package version parsed as NuGet version: '{0}'", pkgNugetVersion)); + if (versionRange.Satisfies(pkgNugetVersion)) { _scriptDictionary.Add(pkgPath, scriptInfo); yield return pkgPath; diff --git a/src/code/UninstallPSResource.cs b/src/code/UninstallPSResource.cs index 36d16a1a0..7964c0deb 100644 --- a/src/code/UninstallPSResource.cs +++ b/src/code/UninstallPSResource.cs @@ -1,4 +1,3 @@ -using System.Text; // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. using System; @@ -110,7 +109,11 @@ protected override void ProcessRecord() break; case InputObjectParameterSet: - if (!Utils.TryParseVersionOrVersionRange(InputObject.Version.ToString(), out _versionRange)) + string inputObjectPrereleaseLabel = InputObject.PrereleaseLabel; + string inputObjectVersion = String.IsNullOrEmpty(inputObjectPrereleaseLabel) ? InputObject.Version.ToString() : Utils.GetNormalizedVersionString(versionString: InputObject.Version.ToString(), prerelease: inputObjectPrereleaseLabel); + if (!Utils.TryParseVersionOrVersionRange( + version: inputObjectVersion, + versionRange: out _versionRange)) { var exMessage = String.Format("Version '{0}' for resource '{1}' cannot be parsed.", InputObject.Version.ToString(), InputObject.Name); var ex = new ArgumentException(exMessage); diff --git a/src/code/Utils.cs b/src/code/Utils.cs index aaca16bbc..19e2ba077 100644 --- a/src/code/Utils.cs +++ b/src/code/Utils.cs @@ -180,6 +180,49 @@ public static bool TryParseVersionOrVersionRange( return VersionRange.TryParse(version, out versionRange); } + public static bool GetVersionForInstallPath( + string installedPkgPath, + bool isModule, + PSCmdlet cmdletPassedIn, + out NuGetVersion pkgNuGetVersion) + { + // this method returns false if the PSGetModuleInfo.xml or {pkgName}_InstalledScriptInfo.xml file + // could not be parsed properly, or the version from it could not be parsed into a NuGetVersion. + // In this case the caller method (i.e GetHelper.FilterPkgPathsByVersion()) should skip the current + // installed package path or reassign NuGetVersion variable passed in to a non-null value as it sees fit. + + // for Modules, installedPkgPath will look like this: + // ./PowerShell/Modules/test_module/3.0.0 + // for Scripts, installedPkgPath will look like this: + // ./PowerShell/Scripts/test_script.ps1 + string pkgName = isModule ? String.Empty : Utils.GetInstalledPackageName(installedPkgPath); + + string packageInfoXMLFilePath = isModule ? Path.Combine(installedPkgPath, "PSGetModuleInfo.xml") : Path.Combine((new DirectoryInfo(installedPkgPath).Parent).FullName, "InstalledScriptInfos", $"{pkgName}_InstalledScriptInfo.xml"); + if (!PSResourceInfo.TryRead(packageInfoXMLFilePath, out PSResourceInfo psGetInfo, out string errorMsg)) + { + cmdletPassedIn.WriteVerbose(String.Format( + "The {0} file found at location: {1} cannot be parsed due to {2}", + isModule ? "PSGetModuleInfo.xml" : $"{pkgName}_InstalledScriptInfo.xml", + packageInfoXMLFilePath, + errorMsg)); + pkgNuGetVersion = null; + return false; + } + + string version = psGetInfo.Version.ToString(); + string prereleaseLabel = psGetInfo.PrereleaseLabel; + + if (!NuGetVersion.TryParse( + value: String.IsNullOrEmpty(prereleaseLabel) ? version : GetNormalizedVersionString(version, prereleaseLabel), + version: out pkgNuGetVersion)) + { + cmdletPassedIn.WriteVerbose(String.Format("Leaf directory in path '{0}' cannot be parsed into a version.", installedPkgPath)); + return false; + } + + return true; + } + #endregion #region Url methods diff --git a/test/GetInstalledPSResource.Tests.ps1 b/test/GetInstalledPSResource.Tests.ps1 index 937ab4e72..95b51406d 100644 --- a/test/GetInstalledPSResource.Tests.ps1 +++ b/test/GetInstalledPSResource.Tests.ps1 @@ -7,6 +7,8 @@ Describe 'Test Get-InstalledPSResource for Module' { BeforeAll{ $TestGalleryName = Get-PoshTestGalleryName + $testModuleName = "test_module" + $testScriptName = "test_script" Get-NewPSResourceRepositoryFile Install-PSResource ContosoServer -Repository $TestGalleryName -TrustRepository @@ -106,4 +108,24 @@ $testCases = $pkgs = Get-InstalledPSResource -Name ContosoServer -Version "*" $pkgs.Count | Should -BeGreaterOrEqual 2 } + + It "Get prerelease version module when version with correct prerelease label is specified" { + Install-PSResource -Name $testModuleName -Version "5.2.5-alpha001" -Repository $TestGalleryName + $res = Get-InstalledPSResource -Name $testModuleName -Version "5.2.5" + $res | Should -BeNullOrEmpty + $res = Get-InstalledPSResource -Name $testModuleName -Version "5.2.5-alpha001" + $res.Name | Should -Be $testModuleName + $res.Version | Should -Be "5.2.5" + $res.PrereleaseLabel | Should -Be "alpha001" + } + + It "Get prerelease version script when version with correct prerelease label is specified" { + Install-PSResource -Name $testScriptName -Version "3.0.0-alpha001" -Repository $TestGalleryName + $res = Get-InstalledPSResource -Name $testScriptName -Version "3.0.0" + $res | Should -BeNullOrEmpty + $res = Get-InstalledPSResource -Name $testScriptName -Version "3.0.0-alpha001" + $res.Name | Should -Be $testScriptName + $res.Version | Should -Be "3.0.0" + $res.PrereleaseLabel | Should -Be "alpha001" + } } diff --git a/test/UninstallPSResource.Tests.ps1 b/test/UninstallPSResource.Tests.ps1 index 8f5f6a9f9..225623dcf 100644 --- a/test/UninstallPSResource.Tests.ps1 +++ b/test/UninstallPSResource.Tests.ps1 @@ -9,6 +9,7 @@ Describe 'Test Uninstall-PSResource for Modules' { $TestGalleryName = Get-PoshTestGalleryName $PSGalleryName = Get-PSGalleryName $testModuleName = "test_module" + $testScriptName = "test_script" Get-NewPSResourceRepositoryFile $res = Uninstall-PSResource -name ContosoServer -Version "*" } @@ -137,6 +138,36 @@ Describe 'Test Uninstall-PSResource for Modules' { $pkg.Version | Should -Be "2.5" } + It "Uninstall prerelease version module when prerelease version specified" { + Install-PSResource -Name $testModuleName -Version "5.2.5-alpha001" -Repository $TestGalleryName + Uninstall-PSResource -Name $testModuleName -Version "5.2.5-alpha001" + $res = Get-InstalledPSResource $testModuleName -Version "5.2.5-alpha001" + $res | Should -BeNullOrEmpty + } + + It "Not uninstall non-prerelease version module when similar prerelease version is specified" { + Install-PSResource -Name $testModuleName -Version "5.0.0.0" -Repository $TestGalleryName + Uninstall-PSResource -Name $testModuleName -Version "5.0.0-preview" + $res = Get-InstalledPSResource -Name $testModuleName -Version "5.0.0.0" + $res.Name | Should -Be $testModuleName + $res.Version | Should -Be "5.0.0.0" + } + + It "Uninstall prerelease version script when prerelease version specified" { + Install-PSResource -Name $testScriptName -Version "3.0.0-alpha001" -Repository $TestGalleryName + Uninstall-PSResource -Name $testScriptName -Version "3.0.0-alpha001" + $res = Get-InstalledPSResource -Name $testScriptName + $res | Should -BeNullOrEmpty + } + + It "Not uninstall non-prerelease version module when prerelease version specified" { + Install-PSResource -Name $testScriptName -Version "2.5.0.0" -Repository $TestGalleryName + Uninstall-PSResource -Name $testScriptName -Version "2.5.0-alpha001" + $res = Get-InstalledPSResource -Name $testScriptName -Version "2.5.0.0" + $res.Name | Should -Be $testScriptName + $res.Version | Should -Be "2.5.0.0" + } + It "Uninstall module using -WhatIf, should not uninstall the module" { $res = Uninstall-PSResource -Name "ContosoServer" -WhatIf @@ -173,11 +204,8 @@ Describe 'Test Uninstall-PSResource for Modules' { It "Uninstall PSResourceInfo object piped in for prerelease version object" { Install-PSResource -Name $testModuleName -Version "4.5.2-alpha001" -Repository $TestGalleryName - # Powershell cannot create install locations indicating a prerelease version (with prerelease label indicated in install location). - # To test we can uninstall prerelease versions, we must use the numeric part of the prerelease version only and it must be unique - # of all versions installed for that module. - Get-InstalledPSResource -Name $testModuleName -Version "4.5.2" | Uninstall-PSResource - $res = Get-InstalledPSResource -Name $testModuleName -Version "4.5.2" + Get-InstalledPSResource -Name $testModuleName -Version "4.5.2-alpha001" | Uninstall-PSResource + $res = Get-InstalledPSResource -Name $testModuleName -Version "4.5.2-alpha001" $res | Should -BeNullOrEmpty } }