NetscootShared/Common/Capability.ps1
|
function Test-GitAvailable { [CmdletBinding()] param() return [bool](Get-Command git -CommandType Application -ErrorAction SilentlyContinue) } function Test-DotnetAvailable { [CmdletBinding()] param() return [bool](Resolve-DotnetCommand) } function Get-ExternalTool { # Presence, version, path and source (Stored or Path) of an external command. [CmdletBinding()] param([Parameter(Mandatory)][string]$Name) $found = if ($Name -eq 'dotnet') { Resolve-DotnetCommand } else { $onPath = Get-Command $Name -CommandType Application -ErrorAction SilentlyContinue | Select-Object -First 1 if ($onPath) { [pscustomobject]@{ Path = $onPath.Source; Source = 'Path' } } } if (-not $found) { return [pscustomobject]@{ Present = $false; Version = $null; Path = $null; Source = $null } } $version = Get-ExternalToolVersion -Path $found.Path if (-not $version) { # A dotnet host with no SDK installed is present but cannot report a version. Write-Warning "$Name was found at $($found.Path), but it could not report its version." } return [pscustomobject]@{ Present = $true; Version = "$version"; Path = $found.Path; Source = $found.Source } } function Write-CapabilityGuidance { # Red, copy-pasteable remediation. We never auto-install; this is guidance only. [CmdletBinding()] param( [Parameter(Mandatory)][ValidateSet('git', 'dotnet')][string]$Tool, # The dotnet installs found on the machine, when the tool is dotnet. [object[]]$Installs = @() ) $lines = switch ($Tool) { 'git' { @('git was not found on PATH. netscoot can fall back to a plain move (PowerShell `Move-Item`), but file', 'history will not be preserved. To install git:', ' Windows : winget install Git.Git (or: choco install git / scoop install git)', ' macOS : brew install git', ' Linux : sudo apt install git (or your distro package manager)') } 'dotnet' { if (@($Installs).Count) { @('dotnet is not on PATH. netscoot found these installs:', '') + @($Installs | ForEach-Object { " .NET SDK $($_.Version) $($_.Path)" }) + @('', 'Store the one to use, then run the command again:', " Set-NetscootDotnetPath -Path '$(if (@($Installs).Count -eq 1) { $Installs[0].Path } else { '<path>' })'") } else { @('The .NET SDK was not found. Moving a .NET project needs it.', '', 'To install it:', ' Windows : winget install Microsoft.DotNet.SDK.10', ' macOS : brew install --cask dotnet-sdk', ' Linux : https://learn.microsoft.com/dotnet/core/install/linux', '', 'Already installed somewhere netscoot did not look?', " Set-NetscootDotnetPath -Path '<path to dotnet>'") } } } foreach ($l in $lines) { Write-Host $l -ForegroundColor Red } } function Resolve-GitUsage { # Returns 'Git' (use git mv), 'Fallback' (plain move, confirmed), or 'Abort'. # On missing git: emit red guidance, then ShouldContinue unless -Force. [CmdletBinding()] param( [Parameter(Mandatory)][System.Management.Automation.PSCmdlet]$Cmdlet, [switch]$Force ) if (Test-GitAvailable) { return 'Git' } Write-CapabilityGuidance -Tool git if ($Force -or $Cmdlet.ShouldContinue( 'Proceed with a plain move via Move-Item (file history will not be preserved)?', 'git not found on PATH')) { return 'Fallback' } return 'Abort' } function Assert-DotnetAvailable { # Required tool. When dotnet is missing, a person at a terminal is asked which install to store. # Otherwise this prints guidance and writes an error. Returns $true when dotnet can be run. [CmdletBinding()] param([Parameter(Mandatory)][System.Management.Automation.PSCmdlet]$Cmdlet) if (Test-DotnetAvailable) { return $true } $installs = @(Find-DotnetInstall) $bound = $Cmdlet.MyInvocation.BoundParameters $previewing = $bound.ContainsKey('WhatIf') -and [bool]$bound['WhatIf'] if ($installs.Count -and (-not $previewing) -and (Test-InteractiveSession)) { $chosen = Read-DotnetInstallChoice -Cmdlet $Cmdlet -Installs $installs if ($chosen) { Save-StoredDotnetPath -Path $chosen.Path Write-Host "netscoot will use $($chosen.Path) from now on." -ForegroundColor DarkGray return $true } } Write-CapabilityGuidance -Tool dotnet -Installs $installs $Cmdlet.WriteError([System.Management.Automation.ErrorRecord]::new( [System.InvalidOperationException]::new('The .NET SDK (dotnet) is required for this command, but it is not on PATH and no path to it is stored.'), 'DotnetMissing', [System.Management.Automation.ErrorCategory]::NotInstalled, $null)) return $false } |