Skip to content

Commit

Permalink
Add ability to install or update a subset of the modules listed in th…
Browse files Browse the repository at this point in the history
…e prism.json file.
  • Loading branch information
KhoiKy committed Aug 26, 2024
1 parent 26e9fb2 commit 40a8571
Show file tree
Hide file tree
Showing 5 changed files with 501 additions and 46 deletions.
25 changes: 17 additions & 8 deletions Prism/Functions/Install-PrivateModule.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ function Install-PrivateModule
[CmdletBinding()]
param(
[Parameter(Mandatory, ValueFromPipeline)]
[Object] $Configuration
[Object] $Configuration,

# A subset of the required modules to install or update.
[String[]] $Name
)

begin
Expand All @@ -18,7 +21,7 @@ function Install-PrivateModule

process
{
if( -not (Test-Path -Path $Configuration.LockPath) )
if (-not (Test-Path -Path $Configuration.LockPath))
{
$Configuration | Update-ModuleLock | Format-Table
}
Expand All @@ -37,14 +40,20 @@ function Install-PrivateModule
$privateModulePathWildcard = Join-Path -Path $config.PSModulesPath -ChildPath '*'
$locks = Get-Content -Path $Configuration.LockPath | ConvertFrom-Json
$locks | Add-Member -Name 'PSModules' -MemberType NoteProperty -Value @() -ErrorAction Ignore
foreach( $module in $locks.PSModules )

if ($Name)
{
$locks.PSModules = $locks.PSModules | Where-Object {$_.Name -in $Name}
}

foreach ($module in $locks.PSModules)
{
$installedModules =
Get-Module -Name $module.name -ListAvailable -ErrorAction Ignore |
Where-Object 'Path' -Like $privateModulePathWildcard |
Add-Member -Name 'SemVer' -MemberType ScriptProperty -PassThru -Value {
$prerelease = $this.PrivateData['PSData']['PreRelease']
if( $prerelease )
if ($prerelease)
{
$prerelease = "-$($prerelease)"
}
Expand All @@ -55,17 +64,17 @@ function Install-PrivateModule
Join-Path -Path $Configuration.File.DirectoryName -ChildPath $Configuration.PSModulesDirectoryName

$installedModule = $installedModules | Where-Object SemVer -EQ $module.version
if( -not $installedModule )
if (-not $installedModule)
{
$sourceUrl = $module.repositorySourceLocation
$repoName = $repoByLocation[$sourceUrl]
if( -not $repoName )
if (-not $repoName)
{
# Ignore slashes at the end of URLs.
$sourceUrl = $sourceUrl.TrimEnd('/')
}
$repoName = $repoByLocation[$sourceUrl]
if( -not $repoName )
if (-not $repoName)
{
$msg = "PowerShell repository at ""$($module.repositorySourceLocation)"" does not exist. Use " +
'"Get-PSRepository" to see the current list of repositories, "Register-PSRepository" ' +
Expand All @@ -74,7 +83,7 @@ function Install-PrivateModule
continue
}

if( -not (Test-Path -Path $savePath) )
if (-not (Test-Path -Path $savePath))
{
New-Item -Path $savePath -ItemType 'Directory' -Force | Out-Null
}
Expand Down
40 changes: 27 additions & 13 deletions Prism/Functions/Invoke-Prism.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,28 @@ function Invoke-Prism
Invoke-Prism 'install'
Demonstrates how to call this function to install required PSModules.
.EXAMPLE
Invoke-Prism 'install' -Name 'Module1', 'Module2'
Demonstrates how to install a subset of the required PSModules.
.EXAMPLE
Invoke-Prism 'update' -Name 'Module1', 'Module2'
Demonstrates how to update a subset of the required PSModules.
#>

[CmdletBinding()]
param(
[Parameter(Mandatory)]
[Parameter(Mandatory, Position=0)]
[ValidateSet('install', 'update')]
[String] $Command,

# A subset of the required modules to install or update.
[Parameter(Position=1)]
[String[]] $Name,

# The path to a prism.json file or a directory where Prism can find a prism.json file. If path is to a file,
# the "FileName" parameter is ignored, if given.
#
Expand Down Expand Up @@ -70,14 +84,14 @@ function Invoke-Prism
try
{
$startIn = '.'
if( $Path )
if ($Path)
{
if( (Test-Path -Path $Path -PathType Leaf) )
if ((Test-Path -Path $Path -PathType Leaf))
{
$FileName = $Path | Split-Path -Leaf
$startIn = $Path | Split-Path -Parent
}
elseif( (Test-Path -Path $Path -PathType Container) )
elseif ((Test-Path -Path $Path -PathType Container))
{
$startIn = $Path
}
Expand All @@ -90,18 +104,18 @@ function Invoke-Prism

$Force = $FileName.StartsWith('.')
$prismJsonFiles = Get-ChildItem -Path $startIn -Filter $FileName -Recurse:$Recurse -Force:$Force -ErrorAction Ignore
if( -not $prismJsonFiles )
if (-not $prismJsonFiles)
{
$msg = ''
$suffix = ''
if( $Recurse )
if ($Recurse)
{
$suffix = 's'
$msg = ' or any of its sub-directories'
}

$locationMsg = 'the current directory'
if( $startIn -ne '.' -and $startIn -ne (Get-Location).Path )
if ($startIn -ne '.' -and $startIn -ne (Get-Location).Path)
{
$locationMsg = """$($startIn | Resolve-Path -Relative)"""
}
Expand All @@ -111,11 +125,11 @@ function Invoke-Prism
return
}

foreach( $prismJsonFile in $prismJsonFiles )
foreach ($prismJsonFile in $prismJsonFiles)
{
$prismJsonPath = $prismJsonFile.FullName
$config = Get-Content -Path $prismJsonPath | ConvertFrom-Json
if( -not $config )
if (-not $config)
{
Write-Warning "File ""$($prismJsonPath | Resolve-Path -Relative) is empty."
continue
Expand All @@ -124,7 +138,7 @@ function Invoke-Prism
$lockBaseName = [IO.Path]::GetFileNameWithoutExtension($prismJsonPath)
$lockExtension = [IO.Path]::GetExtension($prismJsonPath)
# Hidden file with no extension, e.g. `.prism`
if( -not $lockBaseName -and $lockExtension )
if (-not $lockBaseName -and $lockExtension)
{
$lockBaseName = $lockExtension
$lockExtension = ''
Expand Down Expand Up @@ -173,15 +187,15 @@ function Invoke-Prism
$env:PSModulePath = $privateModulePath -join [IO.Path]::PathSeparator
Write-Debug -Message "env:PSModulePath $($env:PSModulePath)"

switch( $Command )
switch ($Command)
{
'install'
{
$config | Install-PrivateModule
$config | Install-PrivateModule -Name $Name
}
'update'
{
$config | Update-ModuleLock
$config | Update-ModuleLock -Name $Name
}
}
}
Expand Down
63 changes: 52 additions & 11 deletions Prism/Functions/Update-ModuleLock.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ function Update-ModuleLock
[CmdletBinding()]
param(
[Parameter(Mandatory, ValueFromPipeline)]
[Object] $Configuration
[Object] $Configuration,

# A subset of the required modules to install or update.
[String[]] $Name
)

begin
Expand All @@ -19,12 +22,28 @@ function Update-ModuleLock
{
$modulesNotFound = [Collections.ArrayList]::New()
$moduleNames = $Configuration.PSModules | Select-Object -ExpandProperty 'Name'
if( -not $moduleNames )
if (-not $moduleNames)
{
Write-Warning "There are no modules listed in ""$($Configuration.Path | Resolve-Path -Relative)""."
return
}

[Collections.Generic.List[String]]$nameCopy = $Name
foreach ($item in $Name)
{
if ($item -notin $moduleNames)
{
Write-Warning "The given module ""$item"" does not exist in the prism.json file."
$nameCopy.Remove($item)
}
}

if ($Name -and -not $nameCopy)
{
return
}
$Name = $nameCopy

$numFinds = $moduleNames | Measure-Object | Select-Object -ExpandProperty 'Count'
$numFinds = $numFinds + 2
Write-Debug " numSteps $($numFinds)"
Expand All @@ -48,6 +67,21 @@ function Update-ModuleLock
Join-Path -Path $Configuration.File.DirectoryName -ChildPath $Configuration.PSModulesDirectoryName
foreach( $pxModule in $Configuration.PSModules )
{
$currentLock = $null
if ($Name)
{
if ($Configuration.LockPath -and (Test-Path -Path $Configuration.LockPath))
{
$currentLock = Get-Content -Path $Configuration.LockPath | ConvertFrom-Json
}

# If current module is not in the given list of modules and doesn't already exist in the lock file, skip.
if ($currentLock -and ($pxModule.Name -notin $Name) -and ($pxModule.Name -notin $currentLock.PSModules.Name))
{
continue
}
}

$optionalParams = @{}

# Make sure these members are present and have default values.
Expand All @@ -56,13 +90,20 @@ function Update-ModuleLock
Add-Member -Name 'AllowPrerelease' -MemberType NoteProperty -Value $false -ErrorAction Ignore

$versionDesc = 'latest'
if( $pxModule.Version )
if ($pxModule.Version)
{
$versionDesc = $optionalParams['Version'] = $pxModule.Version

# If current module is not in the given list of modules, use it's version from lock file.
if ($Name -and $pxModule.Name -notin $Name)
{
$lockedModule = $currentLock.PSModules | Where-Object {$_.Name -eq $pxModule.Name}
$versionDesc = $optionalParams['Version'] = $lockedModule.Version
}
}

$allowPrerelease = $false
if( $pxModule.AllowPrerelease -or $pxModule.Version -match '-' )
if ($pxModule.AllowPrerelease -or $pxModule.Version -match '-')
{
$allowPrerelease = $optionalParams['AllowPrerelease'] = $true
}
Expand All @@ -72,15 +113,15 @@ function Update-ModuleLock
Write-Debug " curStep $($curStep)"
$moduleToInstall =
$modules | Select-Module -Name $pxModule.Name @optionalParams | Select-Object -First 1
if( -not $moduleToInstall )
if (-not $moduleToInstall)
{
$status = "Find-Module -Name '$($pxModule.Name)' -AllVersions"
if( $allowPrerelease )
if ($allowPrerelease)
{
$status = "$($status) -AllowPrerelease"
}

if( -not $findModuleCache.ContainsKey($status) )
if (-not $findModuleCache.ContainsKey($status))
{
Write-Progress @activity -Status $status -PercentComplete ($curStep/$numFinds * 100)
$findModuleCache[$status] = Find-Module -Name $pxModule.Name `
Expand All @@ -95,7 +136,7 @@ function Update-ModuleLock
Select-Object -First 1
}

if( -not $moduleToInstall )
if (-not $moduleToInstall)
{
[void]$modulesNotFound.Add($pxModule.Name)
continue
Expand All @@ -108,7 +149,7 @@ function Update-ModuleLock
}
[void]$locks.Add( $pin )

if( -not (Test-Path -Path $Configuration.LockPath) )
if (-not (Test-Path -Path $Configuration.LockPath))
{
New-Item -Path $Configuration.LockPath `
-ItemType 'File' `
Expand All @@ -133,10 +174,10 @@ function Update-ModuleLock
}
$prismLock | ConvertTo-Json -Depth 2 | Set-Content -Path $Configuration.LockPath -NoNewline

if( $modulesNotFound.Count )
if ($modulesNotFound.Count)
{
$suffix = ''
if( $modulesNotFound.Count -gt 1 )
if ($modulesNotFound.Count -gt 1)
{
$suffix = 's'
}
Expand Down
Loading

0 comments on commit 40a8571

Please sign in to comment.