diff --git a/Docs/UpdatePSResource.md b/Docs/UpdatePSResource.md index c22376c9d..dceff9cd7 100644 --- a/Docs/UpdatePSResource.md +++ b/Docs/UpdatePSResource.md @@ -9,16 +9,11 @@ Other parameters allow the returned results to be further filtered. ### NameParameterSet (Default) ``` PowerShell -[[-Name] ] [-Version ] [-Prerelease] [-Scope ] +[[-Name] ] [-Version ] [-Prerelease] [-Scope ] [-Repository ] [-TrustRepository] [-Credential ] [-Quiet] [-AcceptLicense] [-NoClobber] [-WhatIf] [-Confirm] [] ``` -### InputObjectParameterSet -``` PowerShell -[[-InputObject] [-WhatIf] [-Confirm] [] -``` - ## Parameters ### -Name @@ -74,8 +69,8 @@ Parameter Sets: NameParameterSet Specifies the scope of the resource to update. ```yml -Type: string -Parameter Sets: NameParameterSet, RequiredResourceFileParameterSet +Type: Microsoft.PowerShell.PowerShellGet.UtilClasses.ScopeType +Parameter Sets: NameParameterSet AllowedValues: 'CurrentUser','AllUsers' ``` @@ -85,7 +80,7 @@ Suppresses being prompted for untrusted sources. ```yml Type: SwitchParameter -Parameter Sets: NameParameterSet, RequiredResourceFileParameterSet +Parameter Sets: NameParameterSet ``` ### -Credential @@ -115,22 +110,11 @@ Type: SwitchParameter Parameter Sets: (All) ``` -### -NoClobber - -Prevents updating modules that have the same cmdlets as a differently named module already - -```yml -Type: SwitchParameter -Parameter Sets: NameParameterSet -``` - - ### Outputs No output. ## Notes -Input object still needs to be implemented. Should a -PassThru parameter be added? @@ -138,7 +122,7 @@ Should a -PassThru parameter be added? Most update tests can be performed on a local repository. -Some tests should be performed on remote repository (PSGallery) to verify remote operation, but can be limited. +Some tests should be performed on remote repository (PoshTestGallery) to verify remote operation, but can be limited. ### -Name param @@ -149,11 +133,6 @@ Some tests should be performed on remote repository (PSGallery) to verify remote - Errors: Not found (single name, wildcard, multiple name) - Errors: Repository: Invalid name, connection error, etc -### -Type InputObject - -- Validate pipeline input -- Errors: The object passed in is not the correct type - ### -Version param - Validate the resource is updated to the correct version @@ -193,11 +172,6 @@ Some tests should be performed on remote repository (PSGallery) to verify remote - Validate that modules which require license agreements are approved without a prompt -### -NoClobber - -- Validate that resources are not overwritten when flag is passed - - ## Work Items ### Create cmdlet and parameter sets diff --git a/help/Update-PSResource.md b/help/Update-PSResource.md index 70478254c..158815573 100644 --- a/help/Update-PSResource.md +++ b/help/Update-PSResource.md @@ -8,39 +8,45 @@ schema: 2.0.0 # Update-PSResource ## SYNOPSIS -{{ Fill in the Synopsis }} +Updates a package already installed on the user's machine. ## SYNTAX ### NameParameterSet (Default) ``` Update-PSResource [-Name] [-Version ] [-Prerelease] [-Repository ] - [-Scope ] [-TrustRepository] [-Credential ] [-Quiet] [-AcceptLicense] [-NoClobber] - [-WhatIf] [-Confirm] [] -``` - -### RequiredResourceFileParameterSet -``` -Update-PSResource [-Scope ] [-TrustRepository] [-Quiet] [-AcceptLicense] [-WhatIf] [-Confirm] - [] + [-Scope ] [-TrustRepository] [-Credential ] [-Quiet] [-AcceptLicense] [-WhatIf] [-Confirm] [] ``` ## DESCRIPTION -{{ Fill in the Description }} +The Update-PSResource cmdlet replaces the Update-Module and Update-Script cmdlets from V2. +It updates an already installed package based on the -Name parameter argument. +It does not return an object. Other parameters allow the package to be updated to be further filtered. ## EXAMPLES ### Example 1 ```powershell -PS C:\> {{ Add example code here }} +PS C:\> Get-InstalledPSResource -Name "TestModule" + Name Version Prerelease Description + ---- ------- ---------- ----------- + TestModule 1.2.0 test + + Update-PSResource -Name "TestModule" + Get-InstalledPSResource -Name "TestModule" + Name Version Prerelease Description + ---- ------- ---------- ----------- + TestModule 1.3.0 test + TestModule 1.2.0 test + ``` -{{ Add example description here }} +In this example, the user already has the TestModule package installed and they update the package. Update-PSResource will install the latest version of the package without deleting the older version installed. ## PARAMETERS ### -AcceptLicense -{{ Fill AcceptLicense Description }} +For resources that require a license, AcceptLicense automatically accepts the license agreement during the update. ```yaml Type: System.Management.Automation.SwitchParameter @@ -55,7 +61,7 @@ Accept wildcard characters: False ``` ### -Credential -{{ Fill Credential Description }} +Specifies optional credentials to be used when accessing a private repository. ```yaml Type: System.Management.Automation.PSCredential @@ -65,12 +71,12 @@ Aliases: Required: False Position: Named Default value: None -Accept pipeline input: True (ByPropertyName) +Accept pipeline input: False Accept wildcard characters: False ``` ### -Name -{{ Fill Name Description }} +Specifies name of a resource or resources to update. ```yaml Type: System.String[] @@ -79,28 +85,13 @@ Aliases: Required: True Position: 0 -Default value: None +Default value: "*" Accept pipeline input: True (ByPropertyName, ByValue) -Accept wildcard characters: False -``` - -### -NoClobber -{{ Fill NoClobber Description }} - -```yaml -Type: System.Management.Automation.SwitchParameter -Parameter Sets: NameParameterSet -Aliases: - -Required: False -Position: Named -Default value: None -Accept pipeline input: False -Accept wildcard characters: False +Accept wildcard characters: True ``` ### -Prerelease -{{ Fill Prerelease Description }} +When specified, allows updating to a prerelease version. ```yaml Type: System.Management.Automation.SwitchParameter @@ -115,7 +106,7 @@ Accept wildcard characters: False ``` ### -Quiet -{{ Fill Quiet Description }} +Supresses progress information. ```yaml Type: System.Management.Automation.SwitchParameter @@ -130,7 +121,8 @@ Accept wildcard characters: False ``` ### -Repository -{{ Fill Repository Description }} +Specifies one or more repository names to update packages from. +If not specified, search for packages to update will include all currently registered repositories in order of highest priority. ```yaml Type: System.String[] @@ -145,10 +137,10 @@ Accept wildcard characters: False ``` ### -Scope -{{ Fill Scope Description }} +Specifies the scope of the resource to update. ```yaml -Type: System.String +Type: Microsoft.PowerShell.PowerShellGet.UtilClasses.ScopeType Parameter Sets: (All) Aliases: Accepted values: CurrentUser, AllUsers @@ -161,7 +153,7 @@ Accept wildcard characters: False ``` ### -TrustRepository -{{ Fill TrustRepository Description }} +Specifies optional credentials to be used when accessing a private repository. ```yaml Type: System.Management.Automation.SwitchParameter @@ -176,7 +168,7 @@ Accept wildcard characters: False ``` ### -Version -{{ Fill Version Description }} +Specifies the version the resource is to be updated to. ```yaml Type: System.String @@ -228,15 +220,10 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable ### System.String[] -### System.Management.Automation.PSCredential - ## OUTPUTS -### System.Object - ## NOTES ## RELATED LINKS []() - diff --git a/src/PowerShellGet.psd1 b/src/PowerShellGet.psd1 index 57fa37ce3..1fa277441 100644 --- a/src/PowerShellGet.psd1 +++ b/src/PowerShellGet.psd1 @@ -20,8 +20,8 @@ 'Set-PSResourceRepository', 'Publish-PSResource', 'Uninstall-PSResource', - 'Unregister-PSResourceRepository') - # 'Update-PSResource') + 'Unregister-PSResourceRepository', + 'Update-PSResource') VariablesToExport = 'PSGetPath' AliasesToExport = @('inmo', 'fimo', 'upmo', 'pumo') diff --git a/src/code/UpdatePSResource.cs b/src/code/UpdatePSResource.cs new file mode 100644 index 000000000..de6bacac7 --- /dev/null +++ b/src/code/UpdatePSResource.cs @@ -0,0 +1,219 @@ +using System.Collections.Specialized; +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using Dbg = System.Diagnostics.Debug; +using System.Linq; +using System.Management.Automation; +using System.Text; +using System.Threading; +using Microsoft.PowerShell.PowerShellGet.UtilClasses; +using NuGet.Versioning; + +namespace Microsoft.PowerShell.PowerShellGet.Cmdlets +{ + /// + /// The Update-PSResource cmdlet replaces the Update-Module and Update-Script cmdlets from V2. + /// It updates an already installed package based on the -Name parameter argument. + /// It does not return an object. Other parameters allow the package to be updated to be further filtered. + /// + + [Cmdlet(VerbsData.Update, + "PSResource", + SupportsShouldProcess = true)] + public sealed class UpdatePSResource : PSCmdlet + { + #region Members + private List _pathsToInstallPkg; + + #endregion + + #region Parameters + + /// + /// Specifies name of a resource or resources to update. + /// Accepts wildcard characters. + /// + [Parameter(Position = 0, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true)] + [ValidateNotNullOrEmpty] + public string[] Name { get; set ; } = new string[] {"*"}; + + /// + /// Specifies the version the resource is to be updated to. + /// + [Parameter] + [ValidateNotNullOrEmpty] + public string Version { get; set; } + + /// + /// When specified, allows updating to a prerelease version. + /// + [Parameter] + public SwitchParameter Prerelease { get; set; } + + /// + /// Specifies one or more repository names to update packages from. + /// If not specified, search will include all currently registered repositories in order of highest priority. + /// + [Parameter] + [ArgumentCompleter(typeof(RepositoryNameCompleter))] + [ValidateNotNullOrEmpty] + public string[] Repository { get; set; } + + /// + /// Specifies the scope of the resource to update. + /// + [Parameter] + public ScopeType Scope { get; set; } + + /// + /// When specified, supresses being prompted for untrusted sources. + /// + [Parameter] + public SwitchParameter TrustRepository { get; set; } + + /// + /// Specifies optional credentials to be used when accessing a private repository. + /// + [Parameter] + public PSCredential Credential { get; set; } + + /// + /// Supresses progress information. + /// + [Parameter] + public SwitchParameter Quiet { get; set; } + + /// + /// For resources that require a license, AcceptLicense automatically accepts the license agreement during the update. + /// + [Parameter] + public SwitchParameter AcceptLicense { get; set; } + + /// + /// When specified, bypasses checks for TrustRepository and AcceptLicense and updates the package. + /// + [Parameter] + public SwitchParameter Force { get; set; } + + #endregion + + #region Override Methods + + protected override void BeginProcessing() + { + _pathsToInstallPkg = Utils.GetAllInstallationPaths(this, Scope); + } + + protected override void ProcessRecord() + { + VersionRange versionRange; + + // handle case where Version == null + if (Version == null) { + versionRange = VersionRange.All; + } + else if (!Utils.TryParseVersionOrVersionRange(Version, out versionRange)) + { + // Only returns false if the range was incorrectly formatted and couldn't be parsed. + WriteError(new ErrorRecord( + new PSInvalidOperationException("Cannot parse Version parameter provided into VersionRange"), + "ErrorParsingVersionParamIntoVersionRange", + ErrorCategory.InvalidArgument, + this)); + return; + } + + var namesToUpdate = ProcessPackageNameWildCards(Name, versionRange); + + if (namesToUpdate.Length == 0) + { + return; + } + + if (!ShouldProcess(string.Format("package to update: '{0}'", String.Join(", ", Name)))) + { + WriteVerbose(string.Format("Update is cancelled by user for: {0}", String.Join(", ", Name))); + return; + } + + InstallHelper installHelper = new InstallHelper( + updatePkg: true, + savePkg: false, + cmdletPassedIn: this); + + installHelper.InstallPackages( + names: namesToUpdate, + versionRange: versionRange, + prerelease: Prerelease, + repository: Repository, + acceptLicense: AcceptLicense, + quiet: Quiet, + reinstall: false, + force: Force, + trustRepository: TrustRepository, + noClobber: false, + credential: Credential, + requiredResourceFile: null, + requiredResourceJson: null, + requiredResourceHash: null, + specifiedPath: null, + asNupkg: false, + includeXML: true, + pathsToInstallPkg: _pathsToInstallPkg); + } + + #endregion + #region Private Methods + + /// + /// This method checks all provided package names for wild card characters and removes any name containing invalid characters. + /// If any name contains a single '*' wildcard character then it is returned alone, indicating all packages should be processed. + /// + private string[] ProcessPackageNameWildCards(string[] namesToProcess, VersionRange versionRange) + { + namesToProcess = Utils.ProcessNameWildcards(namesToProcess, out string[] errorMsgs, out bool nameContainsWildcard); + + foreach (string error in errorMsgs) + { + WriteError(new ErrorRecord( + new PSInvalidOperationException(error), + "ErrorFilteringNamesForUnsupportedWildcards", + ErrorCategory.InvalidArgument, + this)); + } + + // this catches the case where namesToProcess wasn't passed in as null or empty, + // but after filtering out unsupported wildcard names there are no elements left in namesToProcess + if (namesToProcess.Length == 0) + { + return namesToProcess; + } + + if (String.Equals(namesToProcess[0], "*", StringComparison.InvariantCultureIgnoreCase)) + { + WriteVerbose("Package names were detected to be (or contain an element equal to): '*', so all packages will be updated"); + } + + if (nameContainsWildcard) + { + // if any of the namesToProcess entries contains a supported wildcard + // then we need to use GetHelper (Get-InstalledPSResource logic) to find which packages are installed that match + // the wildcard pattern name for each package name with wildcard + + GetHelper getHelper = new GetHelper( + cmdletPassedIn: this); + + namesToProcess = getHelper.FilterPkgPaths( + name: namesToProcess, + versionRange: versionRange, + pathsToSearch: Utils.GetAllResourcePaths(this)).Select(p => p.Name).ToArray(); + } + + return namesToProcess; + } + #endregion + } +} \ No newline at end of file diff --git a/src/code/Utils.cs b/src/code/Utils.cs index 492d07025..c5155ffc0 100644 --- a/src/code/Utils.cs +++ b/src/code/Utils.cs @@ -66,6 +66,52 @@ public static string[] GetStringArray(ArrayList list) return strArray; } + public static string[] ProcessNameWildcards( + string[] pkgNames, + out string[] errorMsgs, + out bool isContainWildcard) + { + List namesWithSupportedWildcards = new List(); + List errorMsgsList = new List(); + + if (pkgNames == null) + { + isContainWildcard = true; + errorMsgs = errorMsgsList.ToArray(); + return new string[] {"*"}; + } + + isContainWildcard = false; + foreach (string name in pkgNames) + { + if (WildcardPattern.ContainsWildcardCharacters(name)) + { + if (String.Equals(name, "*", StringComparison.InvariantCultureIgnoreCase)) + { + isContainWildcard = true; + errorMsgs = new string[] {}; + return new string[] {"*"}; + } + + if (name.Contains("?") || name.Contains("[")) + { + errorMsgsList.Add(String.Format("-Name with wildcards '?' and '[' are not supported for this cmdlet so Name entry: {0} will be discarded.", name)); + continue; + } + + isContainWildcard = true; + namesWithSupportedWildcards.Add(name); + } + else + { + namesWithSupportedWildcards.Add(name); + } + } + + errorMsgs = errorMsgsList.ToArray(); + return namesWithSupportedWildcards.ToArray(); + } + public static string[] FilterOutWildcardNames( string[] pkgNames, out string[] errorMsgs) @@ -145,10 +191,8 @@ public static bool TryParseVersionOrVersionRange( out VersionRange versionRange) { versionRange = null; - if (version == null) { return false; } - if (version.Trim().Equals("*")) { versionRange = VersionRange.All; diff --git a/test/InstallPSResource.Tests.ps1 b/test/InstallPSResource.Tests.ps1 index 33bc966af..3ee94b389 100644 --- a/test/InstallPSResource.Tests.ps1 +++ b/test/InstallPSResource.Tests.ps1 @@ -189,7 +189,7 @@ Describe 'Test Install-PSResource for Module' { Install-PSResource -Name "testModuleWithlicense" -Repository $TestGalleryName -AcceptLicense $pkg = Get-InstalledPSResource "testModuleWithlicense" $pkg.Name | Should -Be "testModuleWithlicense" - $pkg.Version | Should -Be "0.0.1.0" + $pkg.Version | Should -Be "0.0.3.0" } It "Install resource should not prompt 'trust repository' if repository is not trusted but -TrustRepository is used" { diff --git a/test/UpdatePSResource.Tests.ps1 b/test/UpdatePSResource.Tests.ps1 new file mode 100644 index 000000000..12c84574c --- /dev/null +++ b/test/UpdatePSResource.Tests.ps1 @@ -0,0 +1,347 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +Import-Module "$psscriptroot\PSGetTestUtils.psm1" -Force + +Describe 'Test Update-PSResource' { + + + BeforeAll{ + $TestGalleryName = Get-PoshTestGalleryName + $NuGetGalleryName = Get-NuGetGalleryName + Get-NewPSResourceRepositoryFile + Get-PSResourceRepository + } + + AfterEach { + Uninstall-PSResource "TestModule", "TestModule99", "TestModuleWithLicense", "PSGetTestModule" + } + + AfterAll { + Get-RevertPSResourceRepositoryFile + } + + It "update resource installed given Name parameter" { + Install-PSResource -Name "TestModule" -Version "1.1.0.0" -Repository $TestGalleryName + + Update-PSResource -Name "TestModule" -Repository $TestGalleryName + $res = Get-InstalledPSResource -Name "TestModule" + + $isPkgUpdated = $false + foreach ($pkg in $res) + { + if ([System.Version]$pkg.Version -gt [System.Version]"1.1.0.0") + { + $isPkgUpdated = $true + } + } + + $isPkgUpdated | Should -Be $true + } + + It "update resources installed given Name (with wildcard) parameter" { + Install-PSResource -Name "TestModule" -Version "1.1.0.0" -Repository $TestGalleryName + Install-PSResource -Name "TestModule99" -Version "0.0.4.0" -Repository $TestGalleryName + + Update-PSResource -Name "TestModule*" -Repository $TestGalleryName + $res = Get-InstalledPSResource -Name "TestModule*" + + $inputHashtable = @{TestModule = "1.1.0.0"; TestModule99 = "0.0.4.0"} + $isTestModuleUpdated = $false + $isTestModule99Updated = $false + foreach ($item in $res) + { + if ([System.Version]$item.Version -gt [System.Version]$inputHashtable[$item.Name]) + { + if ($item.Name -like "TestModule") + { + $isTestModuleUpdated = $true + } + elseif ($item.Name -like "TestModule99") + { + $isTestModule99Updated = $true + } + } + } + + $isTestModuleUpdated | Should -BeTrue + $isTestModule99Updated | Should -BeTrue + } + + It "update resource installed given Name and Version (specific) parameters" { + Install-PSResource -Name "TestModule" -Version "1.1.0.0" -Repository $TestGalleryName + + Update-PSResource -Name "TestModule" -Version "1.2.0.0" -Repository $TestGalleryName + $res = Get-InstalledPSResource -Name "TestModule" + $isPkgUpdated = $false + foreach ($pkg in $res) + { + if ([System.Version]$pkg.Version -eq [System.Version]"1.2.0.0") + { + $isPkgUpdated = $true + } + } + + $isPkgUpdated | Should -BeTrue + } + + $testCases2 = @{Version="[1.3.0.0]"; ExpectedVersions=@("1.1.0.0", "1.3.0.0"); Reason="validate version, exact match"}, + @{Version="1.3.0.0"; ExpectedVersions=@("1.1.0.0", "1.3.0.0"); Reason="validate version, exact match without bracket syntax"}, + @{Version="[1.1.1.0, 1.3.0.0]"; ExpectedVersions=@("1.1.0.0", "1.3.0.0"); Reason="validate version, exact range inclusive"}, + @{Version="(1.1.1.0, 1.3.0.0)"; ExpectedVersions=@("1.1.0.0", "1.2.0.0"); Reason="validate version, exact range exclusive"}, + @{Version="(1.1.1.0,)"; ExpectedVersions=@("1.1.0.0", "1.3.0.0"); Reason="validate version, minimum version exclusive"}, + @{Version="[1.1.1.0,)"; ExpectedVersions=@("1.1.0.0", "1.3.0.0"); Reason="validate version, minimum version inclusive"}, + @{Version="(,1.3.0.0)"; ExpectedVersions=@("1.1.0.0", "1.2.0.0"); Reason="validate version, maximum version exclusive"}, + @{Version="(,1.3.0.0]"; ExpectedVersions=@("1.1.0.0", "1.3.0.0"); Reason="validate version, maximum version inclusive"}, + @{Version="[1.1.1.0, 1.3.0.0)"; ExpectedVersions=@("1.1.0.0", "1.2.0.0"); Reason="validate version, mixed inclusive minimum and exclusive maximum version"} + @{Version="(1.1.1.0, 1.3.0.0]"; ExpectedVersions=@("1.1.0.0", "1.2.0.0"); Reason="validate version, mixed exclusive minimum and inclusive maximum version"} + + It "update resource when given Name to " -TestCases $testCases2{ + param($Version, $ExpectedVersions) + + Install-PSResource -Name "TestModule" -Version "1.1.0.0" -Repository $TestGalleryName + Update-PSResource -Name "TestModule" -Version $Version -Repository $TestGalleryName + + $res = Get-InstalledPSResource -Name "TestModule" + + foreach ($item in $res) { + $item.Name | Should -Be "TestModule" + $ExpectedVersions | Should -Contain $item.Version + } + } + + $testCases = @( + @{Version='(1.2.0.0)'; Description="exclusive version (2.10.0.0)"}, + @{Version='[1-2-0-0]'; Description="version formatted with invalid delimiter [1-2-0-0]"} + ) + It "Should not update resource with incorrectly formatted version such as " -TestCases $testCases{ + param($Version, $Description) + + Install-PSResource -Name "TestModule" -Version "1.1.0.0" -Repository $TestGalleryName + Update-PSResource -Name "TestModule" -Version $Version -Repository $TestGalleryName + + $res = Get-InstalledPSResource -Name "TestModule" + $isPkgUpdated = $false + foreach ($pkg in $res) + { + if ([System.Version]$pkg.Version -gt [System.Version]"1.1.0.0") + { + $isPkgUpdated = $true + } + } + + $isPkgUpdated | Should -Be $false + } + + It "update resource with latest (including prerelease) version given Prerelease parameter" { + # PSGetTestModule resource's latest version is a prerelease version, before that it has a non-prerelease version + + Install-PSResource -Name "PSGetTestModule" -Version "1.0.2.0" -Repository $TestGalleryName + Update-PSResource -Name "PSGetTestModule" -Prerelease -Repository $TestGalleryName + $res = Get-InstalledPSResource -Name "PSGetTestModule" + + $isPkgUpdated = $false + foreach ($pkg in $res) + { + if ([System.Version]$pkg.Version -gt [System.Version]"1.0.2.0") + { + $pkg.PrereleaseLabel | Should -Be "alpha1" + $isPkgUpdated = $true + } + } + + $isPkgUpdated | Should -Be $true + } + + # Windows only + It "update resource under CurrentUser scope" -skip:(!$IsWindows) { + # TODO: perhaps also install TestModule with the highest version (the one above 1.2.0.0) to the AllUsers path too + Install-PSResource -Name "TestModule" -Version "1.1.0.0" -Repository $TestGalleryName -Scope AllUsers + Install-PSResource -Name "TestModule" -Version "1.1.0.0" -Repository $TestGalleryName -Scope CurrentUser + + Update-PSResource -Name "TestModule" -Version "1.2.0.0" -Repository $TestGalleryName -Scope CurrentUser + + $res = Get-InstalledPSResource -Name "TestModule" + + $isPkgUpdated = $false + foreach ($pkg in $res) + { + if ([System.Version]$pkg.Version -gt [System.Version]"1.1.0.0") + { + $pkg.InstalledLocation.Contains("Documents") | Should -Be $true + $isPkgUpdated = $true + } + } + + $isPkgUpdated | Should -Be $true + } + + # Windows only + It "update resource under AllUsers scope" -skip:(!$IsWindows) { + Install-PSResource -Name "TestModule" -Version "1.1.0.0" -Repository $TestGalleryName -Scope AllUsers + Install-PSResource -Name "TestModule" -Version "1.1.0.0" -Repository $TestGalleryName -Scope CurrentUser + + Update-PSResource -Name "TestModule" -Version "1.2.0.0" -Repository $TestGalleryName -Scope AllUsers + + $res = Get-InstalledPSResource -Name "TestModule" + $isPkgUpdated = $false + foreach ($pkg in $res) + { + if ([System.Version]$pkg.Version -gt [System.Version]"1.1.0.0") + { + $pkg.InstalledLocation.Contains("Program Files") | Should -Be $true + $isPkgUpdated = $true + } + } + + $isPkgUpdated | Should -Be $true + } + + # Windows only + It "update resource under no specified scope" -skip:(!$IsWindows) { + Install-PSResource -Name "TestModule" -Version "1.1.0.0" -Repository $TestGalleryName + Update-PSResource -Name "TestModule" -Version "1.2.0.0" -Repository $TestGalleryName + + $res = Get-InstalledPSResource -Name "TestModule" + + $isPkgUpdated = $false + foreach ($pkg in $res) + { + if ([System.Version]$pkg.Version -gt [System.Version]"1.1.0.0") + { + $pkg.InstalledLocation.Contains("Documents") | Should -Be $true + $isPkgUpdated = $true + } + } + + $isPkgUpdated | Should -Be $true + } + + # Unix only + # Expected path should be similar to: '/home/janelane/.local/share/powershell/Modules' + It "Update resource under CurrentUser scope - Unix only" -Skip:(Get-IsWindows) { + # this line is commented out because AllUsers scope requires sudo and that isn't supported in CI yet + # Install-PSResource -Name "TestModule" -Version "1.1.0.0" -Repository $TestGalleryName -Scope AllUsers + Install-PSResource -Name "TestModule" -Version "1.1.0.0" -Repository $TestGalleryName -Scope CurrentUser + + Update-PSResource -Name "TestModule" -Repository $TestGalleryName -Scope CurrentUser + + $res = Get-InstalledPSResource -Name "TestModule" + + $isPkgUpdated = $false + foreach ($pkg in $res) + { + if ([System.Version]$pkg.Version -gt [System.Version]"1.1.0.0") + { + $pkg.InstalledLocation.Contains("$env:HOME/.local") | Should -Be $true + $isPkgUpdated = $true + } + } + + $isPkgUpdated | Should -Be $true + } + + # Unix only + # Expected path should be similar to: '/usr/local/share/powershell/Modules' + # this test is skipped because it requires sudo to run and has yet to be resolved in CI + It "Update resource under AllUsers scope - Unix only" -Skip:($true) { + Install-PSResource -Name "TestModule" -Version "1.1.0.0" -Repository $TestGalleryName -Scope AllUsers + Install-PSResource -Name "TestModule" -Version "1.1.0.0" -Repository $TestGalleryName -Scope CurrentUser + + Update-PSResource -Name "TestModule" -Repository $TestGalleryName -Scope AllUsers + + $res = Get-InstalledPSResource -Name "TestModule" + + $isPkgUpdated = $false + foreach ($pkg in $res) + { + if ([System.Version]$pkg.Version -gt [System.Version]"1.1.0.0") + { + $pkg.InstalledLocation.Contains("usr") | Should -Be $true + $isPkgUpdated = $true + } + } + + $isPkgUpdated | Should -Be $true + } + + # Unix only + # Expected path should be similar to: '/home/janelane/.local/share/powershell/Modules' + It "Update resource under no specified scope - Unix only" -Skip:(Get-IsWindows) { + # this is commented out because it requires sudo to run with AllUsers scope and this hasn't been resolved in CI yet + # Install-PSResource -Name "TestModule" -Version "1.1.0.0" -Repository $TestGalleryName -Scope AllUsers + Install-PSResource -Name "TestModule" -Version "1.1.0.0" -Repository $TestGalleryName -Scope CurrentUser + + Update-PSResource -Name "TestModule" -Repository $TestGalleryName + + $res = Get-InstalledPSResource -Name "TestModule" + + $isPkgUpdated = $false + foreach ($pkg in $res) + { + if ([System.Version]$pkg.Version -gt [System.Version]"1.1.0.0") + { + $pkg.InstalledLocation.Contains("$env:HOME/.local") | Should -Be $true + $isPkgUpdated = $true + } + } + + $isPkgUpdated | Should -Be $true + } + + It "update resource that requires accept license with -AcceptLicense flag" { + Install-PSResource -Name "TestModuleWithLicense" -Version "0.0.1.0" -Repository $TestGalleryName -AcceptLicense + Update-PSResource -Name "TestModuleWithLicense" -Repository $TestGalleryName -AcceptLicense + $res = Get-InstalledPSResource "TestModuleWithLicense" + + $isPkgUpdated = $false + foreach ($pkg in $res) + { + if ([System.Version]$pkg.Version -gt [System.Version]"0.0.1.0") + { + $isPkgUpdated = $true + } + } + + $isPkgUpdated | Should -Be $true + } + + It "update resource should not prompt 'trust repository' if repository is not trusted but -TrustRepository is used" { + Install-PSResource -Name "TestModule" -Version "1.1.0.0" -Repository $TestGalleryName + + Set-PSResourceRepository PoshTestGallery -Trusted:$false + + Update-PSResource -Name "TestModule" -Version "1.2.0.0" -Repository $TestGalleryName -TrustRepository + $res = Get-InstalledPSResource -Name "TestModule" + + $isPkgUpdated = $false + foreach ($pkg in $res) + { + if ([System.Version]$pkg.Version -gt [System.Version]"1.1.0.0") + { + $isPkgUpdated = $true + } + } + + $isPkgUpdated | Should -BeTrue + Set-PSResourceRepository PoshTestGallery -Trusted + } + + It "Update module using -WhatIf, should not update the module" { + Install-PSResource -Name "TestModule" -Version "1.1.0.0" -Repository $TestGalleryName + Update-PSResource -Name "TestModule" -WhatIf + + $res = Get-InstalledPSResource -Name "TestModule" + + $isPkgUpdated = $false + foreach ($pkg in $res) + { + if ([System.Version]$pkg.Version -gt [System.Version]"1.1.0.0") + { + $isPkgUpdated = $true + } + } + + $isPkgUpdated | Should -Be $false + } +} \ No newline at end of file