Public/Install-DFTool.ps1
|
#Requires -Version 7.0 function Install-DFTool { <# .SYNOPSIS Installs one or more known CLI tools via the first available package manager that has a package entry for each tool. .PARAMETER Name One or more tool names to install (must exist in the tool registry). .PARAMETER PackageManager Override the package manager for this call (scoop | winget | choco | psresource). .PARAMETER ToolsPath Override the tools directory (used in tests). .DESCRIPTION Looks up each tool in the JSON registry, determines which package managers are available, and installs via the first compatible one. Package manager preference order uses -PackageManager override, then $DFConfig['PackageManagerOrder'], then auto-detected order. Supports -WhatIf. .EXAMPLE Install-DFTool -Name ripgrep Installs ripgrep via scoop, winget, or choco — whichever is available first. .EXAMPLE Install-DFTool -Name ripgrep, bat, eza Installs multiple tools in one call. .EXAMPLE Install-DFTool -Name ripgrep -PackageManager winget Forces installation via winget regardless of preference order. .EXAMPLE Install-DFTool -Name ripgrep -WhatIf Shows what would be installed without executing. .OUTPUTS None #> [CmdletBinding(SupportsShouldProcess)] [OutputType([void])] param( [Parameter(Mandatory)][string[]]$Name, [string]$PackageManager, [string]$ToolsPath ) $dbArgs = if ($ToolsPath) { @{ ToolsPath = $ToolsPath } } else { @{} } $db = Import-DFToolDb @dbArgs $dfConfigVar = Get-Variable -Name DFConfig -Scope Global -ErrorAction Ignore $pmOrder = if ($PackageManager) { @($PackageManager) } elseif ($null -ne $dfConfigVar -and $dfConfigVar.Value['PackageManagerOrder']) { @($dfConfigVar.Value['PackageManagerOrder']) } else { Resolve-DFPackageManager } foreach ($toolName in $Name) { if (-not $db.ContainsKey($toolName)) { Write-Warning "DotForge: Unknown tool '$toolName'" continue } $tool = $db[$toolName] $packages = $tool.PSObject.Properties['packages']?.Value $installedVia = $null foreach ($pm in $pmOrder) { $pmAvailable = if ($pm -eq 'psresource') { Get-Command Install-PSResource -ErrorAction Ignore } else { Get-Command $pm -ErrorAction Ignore } if (-not $pmAvailable) { continue } $pkgProp = if ($null -ne $packages) { $packages.PSObject.Properties[$pm] } else { $null } $pkgId = if ($null -ne $pkgProp) { $pkgProp.Value } else { $null } if (-not $pkgId) { continue } if ($PSCmdlet.ShouldProcess("$toolName via $pm ($pkgId)", 'Install')) { Write-Host " Installing $toolName via $pm ($pkgId)…" ` -ForegroundColor DarkGray -NoNewline $null = switch ($pm) { 'scoop' { scoop install $pkgId 2>&1 } 'winget' { winget install --id $pkgId --silent ` --accept-source-agreements ` --accept-package-agreements 2>&1 } 'choco' { choco install $pkgId -y 2>&1 } 'psresource' { try { Install-PSResource -Name $pkgId -Scope CurrentUser -ErrorAction Stop | Out-Null $global:LASTEXITCODE = 0 } catch { $global:LASTEXITCODE = 1 } } } if ($LASTEXITCODE -eq 0) { Write-Host ' ✓' -ForegroundColor Green $installedVia = $pm break } else { Write-Host ' failed' -ForegroundColor Red } } else { $installedVia = $pm break } } if (-not $installedVia) { Write-Warning "DotForge: Could not install '$toolName'. No compatible package manager from: $($pmOrder -join ', ')" } } } |