From a392e8c97db7aeac9a3f1d1fc893a3fef3509726 Mon Sep 17 00:00:00 2001 From: Bjarke Sporring Date: Thu, 15 Jan 2026 10:09:11 +0100 Subject: [PATCH] feat: add a "what do you want" step --- install.ps1 | 440 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 345 insertions(+), 95 deletions(-) diff --git a/install.ps1 b/install.ps1 index 4dfa96b..191494a 100644 --- a/install.ps1 +++ b/install.ps1 @@ -246,6 +246,188 @@ function Get-UserConfirmation { #endregion +#region Prerequisites Check Function + +function Get-SystemPrerequisites { + <# + .SYNOPSIS + Checks which required tools are installed and their versions. + + .DESCRIPTION + Scans the system for PowerShell 7, Git 2.23+, and Visual Studio Code. + Returns a hashtable with installation status and version information. + #> + + $prereqs = @{ + PowerShell = @{ + Installed = $false + Version = $null + Command = "pwsh" + MinVersion = "7.0" + Name = "PowerShell 7" + } + Git = @{ + Installed = $false + Version = $null + Command = "git" + MinVersion = "2.23" + Name = "Git" + } + VSCode = @{ + Installed = $false + Version = $null + Command = "code" + MinVersion = $null + Name = "Visual Studio Code" + } + WindowsTerminal = @{ + Installed = $false + Version = $null + Command = "wt" + MinVersion = $null + Name = "Windows Terminal" + } + } + + Write-Host "Checking system for installed tools..." -ForegroundColor Cyan + Write-Host "" + + foreach ($key in $prereqs.Keys) { + $tool = $prereqs[$key] + + if (Test-CommandExists $tool.Command) { + $tool.Installed = $true + $tool.Version = Get-InstalledVersion $tool.Command + + if ($tool.MinVersion -and $tool.Version) { + # Extract semantic version for comparison + if ($tool.Version -match '(\d+)(?:\.(\d+))?(?:\.(\d+))?') { + $major = [int]$matches[1] + $minor = if ($matches[2]) { [int]$matches[2] } else { 0 } + $patch = if ($matches[3]) { [int]$matches[3] } else { 0 } + $installedVersion = "$major.$minor.$patch" + + $minParts = $tool.MinVersion.Split('.') + $minMajor = [int]$minParts[0] + $minMinor = if ($minParts[1]) { [int]$minParts[1] } else { 0 } + $minPatch = if ($minParts[2]) { [int]$minParts[2] } else { 0 } + $minVersion = "$minMajor.$minMinor.$minPatch" + + if ([version]$installedVersion -lt [version]$minVersion) { + Write-Host " ✓ $($tool.Name): $($tool.Version) (⚠ below required $($tool.MinVersion))" -ForegroundColor Yellow + $tool.Sufficient = $false + } else { + Write-Host " ✓ $($tool.Name): $($tool.Version)" -ForegroundColor Green + $tool.Sufficient = $true + } + } else { + Write-Host " ✓ $($tool.Name): $($tool.Version) (⚠ cannot parse version)" -ForegroundColor Yellow + $tool.Sufficient = $true # Assume sufficient if we can't parse + } + } else { + Write-Host " ✓ $($tool.Name): $($tool.Version)" -ForegroundColor Green + $tool.Sufficient = $true + } + } else { + Write-Host " ✗ $($tool.Name): Not installed" -ForegroundColor Red + $tool.Sufficient = $false + } + } + + return $prereqs +} + +function Show-PrerequisitesSummary { + param([hashtable]$Prereqs) + + Write-Host "" + Write-Step "Prerequisites Summary" + + $requiredTools = @("PowerShell", "Git", "VSCode") + $allRequiredInstalled = $true + $allRequiredSufficient = $true + + Write-Host "" + Write-Host "Required Tools:" -ForegroundColor White + + foreach ($toolName in $requiredTools) { + $tool = $Prereqs[$toolName] + if ($tool.Installed -and $tool.Sufficient) { + Write-Success " $($tool.Name): $($tool.Version)" + } elseif ($tool.Installed) { + Write-Warning " $($tool.Name): $($tool.Version) (needs upgrade)" + $allRequiredSufficient = $false + } else { + Write-Error " $($tool.Name): Not installed" + $allRequiredInstalled = $false + $allRequiredSufficient = $false + } + } + + Write-Host "" + Write-Host "Optional Tools:" -ForegroundColor White + + $wt = $Prereqs.WindowsTerminal + if ($wt.Installed) { + Write-Success " $($wt.Name): $($wt.Version)" + } else { + Write-Host " $($wt.Name): Not installed" -ForegroundColor Gray + } + + return @{ + AllRequiredInstalled = $allRequiredInstalled -and $allRequiredSufficient + AnyMissing = -not $allRequiredInstalled + AnyInsufficient = -not $allRequiredSufficient + } +} + +function Get-UserChoice { + param([hashtable]$PrereqStatus) + + Write-Host "" + Write-Step "Choose Your Action" + + if ($PrereqStatus.AllRequiredInstalled) { + Write-Host "All required tools are already installed!" -ForegroundColor Green + Write-Host "" + Write-Host "What would you like to do?" -ForegroundColor White + Write-Host " 1) Just clone the workshop repository" -ForegroundColor Cyan + Write-Host " 2) Install/update missing optional tools" -ForegroundColor Cyan + Write-Host " 3) Reinstall all tools (fresh installation)" -ForegroundColor Yellow + Write-Host "" + + while ($true) { + $choice = Read-Host "Enter your choice (1-3)" + switch ($choice.Trim()) { + "1" { return "CloneOnly" } + "2" { return "OptionalOnly" } + "3" { return "InstallAll" } + default { Write-Host "Please enter 1, 2, or 3" -ForegroundColor Yellow } + } + } + } else { + Write-Host "Some required tools are missing or need updates." -ForegroundColor Yellow + Write-Host "" + Write-Host "What would you like to do?" -ForegroundColor White + Write-Host " 1) Install missing/insufficient tools only" -ForegroundColor Green + Write-Host " 2) Install all required tools" -ForegroundColor Cyan + Write-Host " 3) Just clone the workshop repository (not recommended)" -ForegroundColor Yellow + Write-Host "" + + while ($true) { + $choice = Read-Host "Enter your choice (1-3)" + switch ($choice.Trim()) { + "1" { return "InstallMissing" } + "2" { return "InstallAll" } + "3" { return "CloneOnly" } + default { Write-Host "Please enter 1, 2, or 3" -ForegroundColor Yellow } + } + } + } +} + +#endregion + #region Main Script Write-Host @" @@ -258,18 +440,8 @@ Write-Host @" "@ -ForegroundColor Cyan -Write-Host "This script will install the required tools for the Git Workshop:" -ForegroundColor White -Write-Host " • PowerShell 7 (cross-platform PowerShell)" -ForegroundColor White -Write-Host " • Git 2.23+ (version control system)" -ForegroundColor White -Write-Host " • Visual Studio Code (code editor)" -ForegroundColor White -Write-Host "" -Write-Host "You will be prompted for optional tools:" -ForegroundColor White - -Write-Host " • Windows Terminal (modern terminal experience)" -ForegroundColor White -Write-Host "" - -# Check for winget -Write-Step "Checking Prerequisites" +# Check for winget first +Write-Step "Checking System Requirements" if (-not (Test-WingetAvailable)) { Write-Host "`nInstallation cannot continue without winget." -ForegroundColor Red @@ -278,11 +450,19 @@ if (-not (Test-WingetAvailable)) { Write-Success "winget is available" +# Check system prerequisites +$prereqs = Get-SystemPrerequisites +$prereqStatus = Show-PrerequisitesSummary $prereqs +$userChoice = Get-UserChoice $prereqStatus + +Write-Host "" +Write-Step "User Choice: $userChoice" + # Track installation results $results = @{ - PowerShell = $false - Git = $false - VSCode = $false + PowerShell = $prereqs.PowerShell.Installed -and $prereqs.PowerShell.Sufficient + Git = $prereqs.Git.Installed -and $prereqs.Git.Sufficient + VSCode = $prereqs.VSCode.Installed -and $prereqs.VSCode.Sufficient VSCodeExtensions = $false VSCodePowerShellIntegration = $null # null = not asked, true = configured, false = skipped/failed WindowsTerminal = $null @@ -292,11 +472,6 @@ $results = @{ $totalSteps = 4 # Required installations + extensions $currentStep = 0 -Write-Host "`nStarting installation..." -ForegroundColor Cyan -Write-Host "Note: Some installations may take a few minutes." -ForegroundColor Gray -Write-Host "" - -# Progress bar helper function Write-ProgressIndicator { param( [string]$Activity, @@ -307,6 +482,34 @@ function Write-ProgressIndicator { Write-Progress -Activity $Activity -Status $Status -PercentComplete $PercentComplete } +function Should-Install { + param( + [string]$ToolName, + [string]$UserChoice, + [hashtable]$Prereqs + ) + + $tool = $Prereqs[$ToolName] + + switch ($UserChoice) { + "CloneOnly" { + return $false + } + "OptionalOnly" { + return $ToolName -eq "WindowsTerminal" + } + "InstallMissing" { + return -not ($tool.Installed -and $tool.Sufficient) + } + "InstallAll" { + return $true + } + default { + return -not ($tool.Installed -and $tool.Sufficient) + } + } +} + function Install-VSCodeExtension { param( [string]$ExtensionId, @@ -400,87 +603,127 @@ function Set-VSCodePowerShellIntegration { } } -#region Required Installations +#region Installation Based on User Choice -# Install PowerShell 7 -$currentStep++ -Write-ProgressIndicator -Activity "Installing Required Tools" -Status "Installing PowerShell 7 (1/3)" -PercentComplete (($currentStep / $totalSteps) * 100) -$results.PowerShell = Install-Package ` - -Name "PowerShell 7" ` - -WingetId "Microsoft.PowerShell" ` - -CheckCommand "pwsh" - -# Install Git -$currentStep++ -Write-ProgressIndicator -Activity "Installing Required Tools" -Status "Installing Git (2/3)" -PercentComplete (($currentStep / $totalSteps) * 100) -$results.Git = Install-Package ` - -Name "Git" ` - -WingetId "Git.Git" ` - -CheckCommand "git" ` - -MinVersion "2.23" ` - -AdditionalArgs "-e" - -# Verify Git version specifically -if ($results.Git) { - if (-not (Test-GitVersion)) { - Write-Warning "Git is installed but version may be below 2.23" - $results.Git = $false - } -} - -# Install Visual Studio Code -$currentStep++ -Write-ProgressIndicator -Activity "Installing Required Tools" -Status "Installing Visual Studio Code (3/4)" -PercentComplete (($currentStep / $totalSteps) * 100) -$results.VSCode = Install-Package ` - -Name "Visual Studio Code" ` - -WingetId "Microsoft.VisualStudioCode" ` - -CheckCommand "code" - -# Install VSCode Extensions and configure PowerShell integration -if ($results.VSCode) { - $currentStep++ - Write-ProgressIndicator -Activity "Installing Required Tools" -Status "Installing VSCode Extensions (4/4)" -PercentComplete (($currentStep / $totalSteps) * 100) - +if ($userChoice -ne "CloneOnly") { + Write-Host "`nStarting installation based on your choice..." -ForegroundColor Cyan + Write-Host "Note: Some installations may take a few minutes." -ForegroundColor Gray Write-Host "" - Write-Step "Configuring VSCode" - # Install PowerShell extension - $powershellExtensionResult = Install-VSCodeExtension -ExtensionId "ms-vscode.PowerShell" -ExtensionName "PowerShell" + # Calculate steps needed + $neededSteps = 0 + if (Should-Install -ToolName "PowerShell" -UserChoice $userChoice -Prereqs $prereqs) { $neededSteps++ } + if (Should-Install -ToolName "Git" -UserChoice $userChoice -Prereqs $prereqs) { $neededSteps++ } + if (Should-Install -ToolName "VSCode" -UserChoice $userChoice -Prereqs $prereqs) { $neededSteps++ } + if (Should-Install -ToolName "WindowsTerminal" -UserChoice $userChoice -Prereqs $prereqs) { $neededSteps++ } + if ($neededSteps -eq 0) { $neededSteps = 1 } # At least for progress bar + if ($prereqs.VSCode.Installed -or Should-Install -ToolName "VSCode" -UserChoice $userChoice -Prereqs $prereqs) { $neededSteps++ } # For VSCode extensions + $currentStep = 0 + $totalSteps = $neededSteps + #region Required Installations - # Configure PowerShell 7 integration (optional but recommended) - $powershellIntegrationResult = Set-VSCodePowerShellIntegration - $results.VSCodePowerShellIntegration = $powershellIntegrationResult + # Install PowerShell 7 + if (Should-Install -ToolName "PowerShell" -UserChoice $userChoice -Prereqs $prereqs) { + $currentStep++ + Write-ProgressIndicator -Activity "Installing Tools" -Status "Installing PowerShell 7 ($currentStep/$totalSteps)" -PercentComplete (($currentStep / $totalSteps) * 100) + $results.PowerShell = Install-Package ` + -Name "PowerShell 7" ` + -WingetId "Microsoft.PowerShell" ` + -CheckCommand "pwsh" + } else { + Write-Success "PowerShell 7 already installed and sufficient" + } - $results.VSCodeExtensions = $powershellExtensionResult -} -else { - $results.VSCodeExtensions = $false -} - -# Clear progress bar -Write-Progress -Activity "Installing Required Tools" -Completed - -#endregion - -#region Optional Installations - - - -# Windows Terminal (optional) -Write-Host "" -if (Get-UserConfirmation "Do you want to install Windows Terminal? (Highly recommended for better terminal experience)") { - Write-ProgressIndicator -Activity "Installing Optional Tools" -Status "Installing Windows Terminal" -PercentComplete 50 - $results.WindowsTerminal = Install-Package ` - -Name "Windows Terminal" ` - -WingetId "Microsoft.WindowsTerminal" ` - -CheckCommand "wt" - Write-Progress -Activity "Installing Optional Tools" -Completed -} -else { - Write-Host " Skipping Windows Terminal installation." -ForegroundColor Gray - $results.WindowsTerminal = $null + # Install Git + if (Should-Install -ToolName "Git" -UserChoice $userChoice -Prereqs $prereqs) { + $currentStep++ + Write-ProgressIndicator -Activity "Installing Tools" -Status "Installing Git ($currentStep/$totalSteps)" -PercentComplete (($currentStep / $totalSteps) * 100) + $results.Git = Install-Package ` + -Name "Git" ` + -WingetId "Git.Git" ` + -CheckCommand "git" ` + -MinVersion "2.23" ` + -AdditionalArgs "-e" + + # Verify Git version specifically + if ($results.Git) { + if (-not (Test-GitVersion)) { + Write-Warning "Git is installed but version may be below 2.23" + $results.Git = $false + } + } + } else { + Write-Success "Git already installed and sufficient" + } + + # Install Visual Studio Code + if (Should-Install -ToolName "VSCode" -UserChoice $userChoice -Prereqs $prereqs) { + $currentStep++ + Write-ProgressIndicator -Activity "Installing Tools" -Status "Installing Visual Studio Code ($currentStep/$totalSteps)" -PercentComplete (($currentStep / $totalSteps) * 100) + $results.VSCode = Install-Package ` + -Name "Visual Studio Code" ` + -WingetId "Microsoft.VisualStudioCode" ` + -CheckCommand "code" + } else { + Write-Success "Visual Studio Code already installed" + } + + #endregion + + #region VSCode Extensions and Configuration + + if (($prereqs.VSCode.Installed -or $results.VSCode) -and $userChoice -ne "CloneOnly") { + $currentStep++ + Write-ProgressIndicator -Activity "Installing Tools" -Status "Installing VSCode Extensions ($currentStep/$totalSteps)" -PercentComplete (($currentStep / $totalSteps) * 100) + + Write-Host "" + Write-Step "Configuring VSCode" + + # Install PowerShell extension + $powershellExtensionResult = Install-VSCodeExtension -ExtensionId "ms-vscode.PowerShell" -ExtensionName "PowerShell" + + # Configure PowerShell 7 integration (optional but recommended) + if ($userChoice -eq "InstallAll" -or $userChoice -eq "InstallMissing") { + $powershellIntegrationResult = Set-VSCodePowerShellIntegration + $results.VSCodePowerShellIntegration = $powershellIntegrationResult + } else { + $results.VSCodePowerShellIntegration = $null + } + + $results.VSCodeExtensions = $powershellExtensionResult + } + + # Clear progress bar + Write-Progress -Activity "Installing Tools" -Completed + + #endregion + + #region Optional Installations + + # Windows Terminal (optional) + if (Should-Install -ToolName "WindowsTerminal" -UserChoice $userChoice -Prereqs $prereqs) { + Write-Host "" + if ($userChoice -eq "OptionalOnly" -or (Get-UserConfirmation "Do you want to install Windows Terminal? (Highly recommended for better terminal experience)")) { + Write-ProgressIndicator -Activity "Installing Optional Tools" -Status "Installing Windows Terminal" -PercentComplete 50 + $results.WindowsTerminal = Install-Package ` + -Name "Windows Terminal" ` + -WingetId "Microsoft.WindowsTerminal" ` + -CheckCommand "wt" + Write-Progress -Activity "Installing Optional Tools" -Completed + } else { + Write-Host " Skipping Windows Terminal installation." -ForegroundColor Gray + $results.WindowsTerminal = $null + } + } elseif ($prereqs.WindowsTerminal.Installed) { + Write-Success "Windows Terminal already installed" + } + + #endregion +} else { + Write-Host "`nSkipping tool installation as requested." -ForegroundColor Gray + Write-Host "Proceeding directly to workshop repository setup..." -ForegroundColor Cyan } #endregion @@ -489,7 +732,14 @@ else { Write-Step "Installation Summary" -$allRequired = $results.PowerShell -and $results.Git -and $results.VSCode +# For CloneOnly, check if tools were already installed +if ($userChoice -eq "CloneOnly") { + $allRequired = $prereqs.PowerShell.Installed -and $prereqs.PowerShell.Sufficient -and + $prereqs.Git.Installed -and $prereqs.Git.Sufficient -and + $prereqs.VSCode.Installed -and $prereqs.VSCode.Sufficient +} else { + $allRequired = $results.PowerShell -and $results.Git -and $results.VSCode +} Write-Host "" Write-Host "Required Tools:" -ForegroundColor White