Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added capability to remove existing conflicting module versions to PSGalleryModule #108

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
235 changes: 118 additions & 117 deletions PSDepend/PSDependScripts/PSGalleryModule.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
Install: Install the dependency
Import: Import the dependency

.PARAMETER Clean
Deletes existing versions of the module before installing/saving desired version

.EXAMPLE
@{
BuildHelpers = 'latest'
Expand Down Expand Up @@ -86,44 +89,52 @@ param(
[switch]$Import,

[ValidateSet('Test', 'Install', 'Import')]
[string[]]$PSDependAction = @('Install')
[string[]]$PSDependAction = @('Install'),

[switch]$Clean
)

# Extract data from Dependency
$DependencyName = $Dependency.DependencyName
$Name = $Dependency.Name
if(-not $Name)
{
$Name = $DependencyName
}

$Version = $Dependency.Version
if(-not $Version)
{
$Version = 'latest'
}
$Name = $Dependency.Name
if(-not $Name)
{
$Name = $Dependency.DependencyName
}

# We use target as a proxy for Scope
if(-not $Dependency.Target)
{
$Scope = 'AllUsers'
}
else
{
$Scope = $Dependency.Target
}
$findModuleSplat = @{
Name = $Name
}

$Credential = $Dependency.Credential
$moduleSplat = @{
Name = $Name
Verbose = $VerbosePreference
Force = $True
}

if('AllUsers', 'CurrentUser' -notcontains $Scope)
# We use target as a proxy for Scope
$install = $True
if($Dependency.Target -and 'AllUsers', 'CurrentUser' -notcontains $Dependency.Target)
{
$install = $false
$moduleFullname = Join-Path -Path $Dependency.Target -ChildPath $Name
}
else
{
if ($Dependency.Target)
{
$command = 'save'
$scope = $Dependency.Target
}
else
{
$command = 'install'
$scope = 'AllUsers'
}

$moduleFullname = $Name
$moduleSplat['AllowClobber'] = $AllowClobber
$moduleSplat['SkipPublisherCheck'] = $SkipPublisherCheck
$moduleSplat['Scope'] = $scope
}

if(-not (Get-PackageProvider -Name Nuget))
{
# Grab nuget bits.
Expand All @@ -134,140 +145,130 @@ Write-Verbose -Message "Getting dependency [$name] from PowerShell repository [$

# Validate that $target has been setup as a valid PowerShell repository,
# but allow to rely on all PS repos registered.
if($Repository) {
$validRepo = Get-PSRepository -Name $Repository -Verbose:$false -ErrorAction SilentlyContinue
if (-not $validRepo) {
Write-Error "[$Repository] has not been setup as a valid PowerShell repository."
return
}
}

$params = @{
Name = $Name
SkipPublisherCheck = $SkipPublisherCheck
AllowClobber = $AllowClobber
Verbose = $VerbosePreference
Force = $True
}

if($Repository) {
$params.Add('Repository',$Repository)
if($Repository)
{
if (-not (Get-PSRepository -Name $Repository -Verbose:$false -ErrorAction SilentlyContinue))
{
Write-Error "[$Repository] has not been setup as a valid PowerShell repository."
return
}
}

if( $Version -and $Version -ne 'latest')
if ($Repository)
{
$Params.add('RequiredVersion',$Version)
$findModuleSplat.Add('Repository',$Repository)
$moduleSplat.Add('Repository',$Repository)
}

if($Credential)
if ($Dependency.Credential)
{
$Params.add('Credential', $Credential)
$findModuleSplat.Add('Credential', $Dependency.Credential)
$moduleSplat.add('Credential', $Dependency.Credential)
}

# This code works for both install and save scenarios.
if($command -eq 'Save')
if ($Dependency.Version -and $Dependency.Version -ne 'latest')
{
$ModuleName = Join-Path $Scope $Name
$Params.Remove('AllowClobber')
$Params.Remove('SkipPublisherCheck')
$Version = $Dependency.Version
$moduleSplat.add('RequiredVersion',$Version)
}
elseif ($Command -eq 'Install')
else
{
$ModuleName = $Name
$Version = (Find-Module @findModuleSplat).Version.ToString()
}

Write-Verbose "Targetting module '$Name' Version: $Version"

# Only use "SkipPublisherCheck" (and other) parameter if "Install-Module" supports it
$availableParameters = (Get-Command "Install-Module").Parameters
$tempParams = $Params.Clone()
foreach($thisParameter in $Params.Keys)
$tempmoduleSplat = $moduleSplat.Clone()
foreach($thisParameter in $moduleSplat.Keys)
{
if(-Not ($availableParameters.ContainsKey($thisParameter)))
{
Write-Verbose -Message "Removing parameter [$thisParameter] from [Install-Module] as it is not available"
$tempParams.Remove($thisParameter)
$tempmoduleSplat.Remove($thisParameter)
}
}
$Params = $tempParams.Clone()

$moduleSplat = $tempmoduleSplat.Clone()
Add-ToPsModulePathIfRequired -Dependency $Dependency -Action $PSDependAction

$Existing = $null
$Existing = Get-Module -ListAvailable -Name $ModuleName -ErrorAction SilentlyContinue

if($Existing)
$existingModules = $null
$existingModules = Get-Module -ListAvailable -Name $Name -ErrorAction SilentlyContinue
if ($PSDependAction -contains 'Install')
{
Write-Verbose "Found existing module [$Name]"
# Thanks to Brandon Padgett!
$ExistingVersion = $Existing | Measure-Object -Property Version -Maximum | Select-Object -ExpandProperty Maximum
$FindModuleParams = @{Name = $Name}
if($Repository) {
$FindModuleParams.Add('Repository',$Repository)
}
if($Credential)
{
$FindModuleParams.Add('Credential', $Credential)
}

$GetGalleryVersion = { Find-Module @FindModuleParams | Measure-Object -Property Version -Maximum | Select-Object -ExpandProperty Maximum }

# Version string, and equal to current
if( $Version -and $Version -ne 'latest' -and $Version -eq $ExistingVersion)
# If Clean is set to $true, cleanup any existing versions of the module
if ($PSDependAction -notcontains 'Test' -and $Clean -and $existingModules)
{
Write-Verbose "You have the requested version [$Version] of [$Name]"
# Conditional import
Import-PSDependModule -Name $ModuleName -Action $PSDependAction -Version $ExistingVersion

if($PSDependAction -contains 'Test')
Write-Verbose "Parameter 'Clean' set to 'true', removing existing versions..."
foreach ($existingModule in $existingModules)
{
return $True
$existingVersion = $existingModule.Version.ToString()
Write-Verbose "Found existing module: '$Name' Version: $existingVersion"
if ($existingModule.ModuleBase)
{
$differentModulePath = (Get-Item -Path $existingModule.ModuleBase).Parent.FullName -ne $moduleFullname
}

if (($existingVersion -ne $Version -and $Dependency.Target -and $differentModulePath) -or $existingVersion -ne $Version)
{
# Remove module from session just in case
Write-Verbose "Removing existing module: '$($existingModule.Name)' Version: $existingVersion"
Remove-Module -Name $existingModule.Name -Force -ErrorAction SilentlyContinue -Verbose:$false

# Pause to give the module a chance to be fully removed from session
Start-Sleep -Seconds 1
Remove-Item -Path $existingModule.ModuleBase -Force -Recurse
}
}
return $null
}

# latest, and we have latest
if( $Version -and
($Version -eq 'latest' -or $Version -like '') -and
[System.Version]($GalleryVersion = (& $GetGalleryVersion)) -le [System.Version]$ExistingVersion
)

if (($existingModules -and ($existingModules | Foreach-Object {$_.Version.ToString()}) -notcontains $Version) -or -not $existingModules)
{
Write-Verbose "You have the latest version of [$Name], with installed version [$ExistingVersion] and PSGallery version [$GalleryVersion]"
# Conditional import
Import-PSDependModule -Name $ModuleName -Action $PSDependAction -Version $ExistingVersion
if (-not $install)
{
if (-not (Test-Path -Path $moduleFullname -ErrorAction SilentlyContinue))
{
Write-Verbose "Creating directory path to '$moduleFullname'"
$null = New-Item -ItemType Directory -Path $moduleFullname -Force -ErrorAction SilentlyContinue
}

if($PSDependAction -contains 'Test')
$modulePath = Join-Path -Path $moduleFullname -ChildPath $Version
if(-not (Test-Path -Path $modulePath -ErrorAction SilentlyContinue))
{
Write-Verbose "Saving '$Name' with path '$moduleFullname'"
Save-Module @moduleSplat -Path (Split-Path -Path $moduleFullname -Parent)
}
}
else
{
return $True
Write-Verbose "Installing [$Name] with scope [$Scope]"
Install-Module @moduleSplat
}
return $null
}
Write-Verbose "Continuing to install [$Name]: Requested version [$version], existing version [$ExistingVersion]"
}

#No dependency found, return false if we're testing alone...
if( $PSDependAction -contains 'Test' -and $PSDependAction.count -eq 1)
if ($PSDependAction -contains 'Import')
{
return $False
Write-Verbose "You have the requested version [$Version] of [$Name]"
# Conditional import
Import-PSDependModule -Name $moduleFullname -Action $PSDependAction -Version $Version

if($PSDependAction -contains 'Test')
{
return $True
}
}

if($PSDependAction -contains 'Install')
if ($PSDependAction -contains 'Test' -and $PSDependAction.count -eq 1)
{
if('AllUsers', 'CurrentUser' -contains $Scope)
if ($existingModules)
{
Write-Verbose "Installing [$Name] with scope [$Scope]"
Install-Module @params -Scope $Scope
return ($existingModules | Foreach-Object {$_.Version.ToString()}) -contains $Version
}
else
{
Write-Verbose "Saving [$Name] with path [$Scope]"
Write-Verbose "Creating directory path to [$Scope]"
if(-not (Test-Path $Scope -ErrorAction SilentlyContinue))
{
$Null = New-Item -ItemType Directory -Path $Scope -Force -ErrorAction SilentlyContinue
}
Save-Module @params -Path $Scope
return $false
}
}

# Conditional import
$importVs = $params['RequiredVersion']
Import-PSDependModule -Name $ModuleName -Action $PSDependAction -Version $importVs
7 changes: 7 additions & 0 deletions Tests/DependFiles/psgallerymodule.clean.depend.psd1
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@{
'Pester' = @{
Version = '4.1.0'
Target = 'TestDrive:/PSDependPesterTest'
Parameters = @{Clean = $true}
}
}
6 changes: 6 additions & 0 deletions Tests/DependFiles/psgallerymodule.cleannotarget.depend.psd1
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@{
'Pester' = @{
Version = '4.1.0'
Parameters = @{Clean = $true}
}
}
Loading