From cbefeaf4d2258b48bee6b556ec5f88b9df91063d Mon Sep 17 00:00:00 2001 From: Bjarke Sporring Date: Wed, 14 Jan 2026 17:00:02 +0100 Subject: [PATCH] refactor: move install-prerequisites to install.ps1 --- install-prerequisites.ps1 | 633 --------------------------------- install.ps1 | 720 ++++++++++++++++++++++++++++---------- 2 files changed, 544 insertions(+), 809 deletions(-) delete mode 100644 install-prerequisites.ps1 diff --git a/install-prerequisites.ps1 b/install-prerequisites.ps1 deleted file mode 100644 index 74ceec2..0000000 --- a/install-prerequisites.ps1 +++ /dev/null @@ -1,633 +0,0 @@ -#!/usr/bin/env pwsh -<# -.SYNOPSIS -Installs all prerequisites for the Git Workshop using winget. - -.DESCRIPTION -This script automates the installation of required tools for the Git Workshop: -- PowerShell 7 (cross-platform PowerShell) -- Git 2.23+ (version control system) -- Visual Studio Code (code editor with Git integration) - -Optional tools (with user prompts): -- Python 3.12 (for Module 08: Multiplayer Git) -- Windows Terminal (modern terminal experience) - -The script checks for existing installations, shows clear progress, and verifies -each installation succeeded. At the end, it displays Git configuration instructions. - -.EXAMPLE -PS> .\install-prerequisites.ps1 -Runs the installation script with interactive prompts. - -.NOTES -Requires Windows 11 with winget (App Installer) available. -Some installations may require administrator privileges. -#> - -[CmdletBinding()] -param() - -Set-StrictMode -Version Latest -$ErrorActionPreference = 'Continue' # Continue on errors to show all results - -#region Helper Functions - -function Write-ColorMessage { - param( - [string]$Message, - [string]$Color = 'White' - ) - Write-Host $Message -ForegroundColor $Color -} - -function Write-Step { - param([string]$Message) - Write-ColorMessage "`n=== $Message ===" -Color Cyan -} - -function Write-Success { - param([string]$Message) - Write-ColorMessage " ✓ $Message" -Color Green -} - -function Write-Warning { - param([string]$Message) - Write-ColorMessage " ⚠ $Message" -Color Yellow -} - -function Write-Error { - param([string]$Message) - Write-ColorMessage " ✗ $Message" -Color Red -} - -function Test-CommandExists { - param([string]$Command) - - $oldPreference = $ErrorActionPreference - $ErrorActionPreference = 'SilentlyContinue' - - try { - if (Get-Command $Command -ErrorAction SilentlyContinue) { - return $true - } - return $false - } - finally { - $ErrorActionPreference = $oldPreference - } -} - -function Get-InstalledVersion { - param( - [string]$Command, - [string]$VersionArg = '--version' - ) - - try { - $output = & $Command $VersionArg 2>&1 | Select-Object -First 1 - return $output.ToString().Trim() - } - catch { - return $null - } -} - -function Test-WingetAvailable { - if (-not (Test-CommandExists 'winget')) { - Write-Error "winget is not available on this system." - Write-Host "`nTo fix this:" -ForegroundColor Yellow - Write-Host " 1. Update Windows 11 to the latest version (Settings → Windows Update)" -ForegroundColor White - Write-Host " 2. Install 'App Installer' from the Microsoft Store" -ForegroundColor White - Write-Host " 3. Restart your computer and run this script again" -ForegroundColor White - return $false - } - return $true -} - -function Install-Package { - param( - [string]$Name, - [string]$WingetId, - [string]$CheckCommand, - [string]$MinVersion = $null, - [string]$AdditionalArgs = '' - ) - - Write-Step "Installing $Name" - - # Check if already installed - if (Test-CommandExists $CheckCommand) { - $version = Get-InstalledVersion $CheckCommand - Write-Success "$Name is already installed: $version" - - if ($MinVersion -and $version) { - # Basic version check (not perfect but good enough for common cases) - if ($version -match '(\d+\.[\d.]+)') { - $installedVersion = $matches[1] - if ([version]$installedVersion -lt [version]$MinVersion) { - Write-Warning "Version $installedVersion is below minimum required version $MinVersion" - Write-Host " Attempting to upgrade..." -ForegroundColor Cyan - } - else { - return $true - } - } - } - else { - return $true - } - } - - # Install using winget - Write-Host " Installing via winget: $WingetId" -ForegroundColor Cyan - - $installCmd = "winget install --id $WingetId --source winget --silent $AdditionalArgs".Trim() - Write-Host " Running: $installCmd" -ForegroundColor Gray - - try { - # Show progress during installation - Write-Progress -Activity "Installing $Name" -Status "Downloading and installing..." -PercentComplete 25 - - $result = Invoke-Expression $installCmd 2>&1 - - Write-Progress -Activity "Installing $Name" -Status "Verifying installation..." -PercentComplete 75 - - # Check if installation succeeded - Start-Sleep -Seconds 2 # Give the system time to register the new command - - # Refresh environment variables in current session - $env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User") - - if (Test-CommandExists $CheckCommand) { - $version = Get-InstalledVersion $CheckCommand - Write-Success "$Name installed successfully: $version" - Write-Progress -Activity "Installing $Name" -Completed - return $true - } - else { - Write-Warning "$Name installation completed, but command '$CheckCommand' not found." - Write-Host " You may need to restart your terminal or computer." -ForegroundColor Yellow - Write-Progress -Activity "Installing $Name" -Completed - return $false - } - } - catch { - Write-Error "Failed to install $Name`: $_" - Write-Progress -Activity "Installing $Name" -Completed - return $false - } -} - -function Test-GitVersion { - if (-not (Test-CommandExists 'git')) { - return $false - } - - $version = Get-InstalledVersion 'git' - - # Parse Git version from various formats: - # "git version 2.52.0", "git version 2.52.0.windows.1", etc. - if ($version -match 'git version (\d+)\.(\d+)') { - $majorVersion = [int]$matches[1] - $minorVersion = [int]$matches[2] - - # Check if version is 2.23 or higher - if ($majorVersion -gt 2 -or ($majorVersion -eq 2 -and $minorVersion -ge 23)) { - return $true - } - else { - Write-Warning "Git version $majorVersion.$minorVersion is below required version 2.23" - return $false - } - } - - Write-Warning "Could not parse Git version from: $version" - return $false -} - -function Get-UserConfirmation { - param([string]$Prompt) - - while ($true) { - $response = Read-Host "$Prompt (y/n)" - $response = $response.Trim().ToLower() - - if ($response -eq 'y' -or $response -eq 'yes') { - return $true - } - elseif ($response -eq 'n' -or $response -eq 'no') { - return $false - } - else { - Write-Host "Please enter 'y' or 'n'" -ForegroundColor Yellow - } - } -} - -#endregion - -#region Main Script - -Write-Host @" - -╔═══════════════════════════════════════════════════════════╗ -║ ║ -║ Git Workshop - Prerequisites Installation Script ║ -║ ║ -╚═══════════════════════════════════════════════════════════╝ - -"@ -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 " • Python 3.12 (for Module 08: Multiplayer Git)" -ForegroundColor White -Write-Host " • Windows Terminal (modern terminal experience)" -ForegroundColor White -Write-Host "" - -# Check for winget -Write-Step "Checking Prerequisites" - -if (-not (Test-WingetAvailable)) { - Write-Host "`nInstallation cannot continue without winget." -ForegroundColor Red - return -} - -Write-Success "winget is available" - -# Track installation results -$results = @{ - PowerShell = $false - Git = $false - VSCode = $false - VSCodeExtensions = $false - VSCodePowerShellIntegration = $null # null = not asked, true = configured, false = skipped/failed - Python = $null # null = not attempted, true = success, false = failed - WindowsTerminal = $null -} - -# Progress tracking -$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, - [string]$Status, - [int]$PercentComplete - ) - - Write-Progress -Activity $Activity -Status $Status -PercentComplete $PercentComplete -} - -function Install-VSCodeExtension { - param( - [string]$ExtensionId, - [string]$ExtensionName - ) - - Write-Host " Installing VSCode extension: $ExtensionName" -ForegroundColor Cyan - - try { - # Refresh environment to ensure code command is available - $env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User") - - $result = & code --install-extension $ExtensionId 2>&1 - - if ($LASTEXITCODE -eq 0) { - Write-Success "VSCode extension '$ExtensionName' installed successfully" - return $true - } - else { - Write-Warning "Failed to install VSCode extension '$ExtensionName'" - Write-Host " You can install it manually later: Ctrl+Shift+X → Search '$ExtensionName'" -ForegroundColor Gray - return $false - } - } - catch { - Write-Warning "Could not install VSCode extension '$ExtensionName`: $_" - Write-Host " You can install it manually later: Ctrl+Shift+X → Search '$ExtensionName'" -ForegroundColor Gray - return $false - } -} - -function Set-VSCodePowerShellIntegration { - # Ask user if they want to set PowerShell 7 as default terminal - $setAsDefault = Get-UserConfirmation "Set PowerShell 7 as the default terminal in VSCode? (Recommended for this workshop)" - - if (-not $setAsDefault) { - Write-Host " Skipping PowerShell 7 terminal configuration." -ForegroundColor Gray - return $false - } - - Write-Host " Configuring PowerShell 7 integration with VSCode..." -ForegroundColor Cyan - - try { - # Set PowerShell 7 as the default terminal in VSCode - $vscodeSettingsPath = Join-Path $env:APPDATA "Code\User\settings.json" - $vscodeSettingsDir = Split-Path $vscodeSettingsPath -Parent - - # Create directory if it doesn't exist - if (-not (Test-Path $vscodeSettingsDir)) { - New-Item -Path $vscodeSettingsDir -ItemType Directory -Force | Out-Null - } - - # Read existing settings or create new - if (Test-Path $vscodeSettingsPath) { - $settings = Get-Content $vscodeSettingsPath -Raw | ConvertFrom-Json - } - else { - $settings = @{} - } - - # Set PowerShell 7 as default terminal - if (-not $settings.PSObject.Properties.Name -contains "terminal.integrated.defaultProfile.windows") { - $settings | Add-Member -NotePropertyName "terminal.integrated.defaultProfile.windows" -NotePropertyValue "PowerShell" - } - else { - $settings."terminal.integrated.defaultProfile.windows" = "PowerShell" - } - - # Add terminal profiles if not present - if (-not $settings.PSObject.Properties.Name -contains "terminal.integrated.profiles.windows") { - $profiles = @{ - "PowerShell" = @{ - "source" = "PowerShell" - "icon" = "terminal-powershell" - "path" = "pwsh.exe" - } - } - $settings | Add-Member -NotePropertyName "terminal.integrated.profiles.windows" -NotePropertyValue $profiles - } - - # Save settings - $settings | ConvertTo-Json -Depth 10 | Set-Content $vscodeSettingsPath - - Write-Success "VSCode configured to use PowerShell 7 as default terminal" - return $true - } - catch { - Write-Warning "Could not configure VSCode PowerShell integration automatically" - Write-Host " You can configure it manually in VSCode: Ctrl+Shift+P → Terminal: Select Default Profile → PowerShell" -ForegroundColor Gray - return $false - } -} - -#region Required Installations - -# 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) - - 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) - $powershellIntegrationResult = Set-VSCodePowerShellIntegration - $results.VSCodePowerShellIntegration = $powershellIntegrationResult - - $results.VSCodeExtensions = $powershellExtensionResult -} -else { - $results.VSCodeExtensions = $false -} - -# Clear progress bar -Write-Progress -Activity "Installing Required Tools" -Completed - -#endregion - -#region Optional Installations - -# Python 3.12 (optional) -Write-Host "" -if (Get-UserConfirmation "Do you want to install Python 3.12? (Required for Module 08: Multiplayer Git)") { - Write-ProgressIndicator -Activity "Installing Optional Tools" -Status "Installing Python 3.12" -PercentComplete 50 - $results.Python = Install-Package ` - -Name "Python 3.12" ` - -WingetId "Python.Python.3.12" ` - -CheckCommand "python" - Write-Progress -Activity "Installing Optional Tools" -Completed -} -else { - Write-Host " Skipping Python installation." -ForegroundColor Gray - $results.Python = $null -} - -# 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 -} - -#endregion - -#region Installation Summary - -Write-Step "Installation Summary" - -$allRequired = $results.PowerShell -and $results.Git -and $results.VSCode - -Write-Host "" -Write-Host "Required Tools:" -ForegroundColor White - -if ($results.PowerShell) { - Write-Success "PowerShell 7" -} -else { - Write-Error "PowerShell 7 - Installation failed or needs restart" -} - -if ($results.Git) { - Write-Success "Git 2.23+" -} -else { - Write-Error "Git 2.23+ - Installation failed or needs restart" -} - -if ($results.VSCode) { - Write-Success "Visual Studio Code" - - if ($results.VSCodeExtensions) { - Write-Success " • PowerShell extension" - } - else { - Write-Warning " • VSCode PowerShell extension may need manual installation" - } - - if ($results.VSCodePowerShellIntegration -eq $true) { - Write-Success " • PowerShell 7 terminal integration" - } - elseif ($results.VSCodePowerShellIntegration -eq $false) { - Write-Host " • PowerShell 7 terminal integration: Skipped" -ForegroundColor Gray - } -} -else { - Write-Error "Visual Studio Code - Installation failed or needs restart" -} - -if ($results.Python -ne $null) { - Write-Host "" - Write-Host "Optional Tools:" -ForegroundColor White - - if ($results.Python) { - Write-Success "Python 3.12" - } - else { - Write-Error "Python 3.12 - Installation failed or needs restart" - } -} - -if ($results.WindowsTerminal -ne $null) { - if ($results.Python -eq $null) { - Write-Host "" - Write-Host "Optional Tools:" -ForegroundColor White - } - - if ($results.WindowsTerminal) { - Write-Success "Windows Terminal" - } - else { - Write-Error "Windows Terminal - Installation failed or needs restart" - } -} - -#endregion - -#region Next Steps - -Write-Step "Next Steps" - -if ($allRequired) { - Write-Host "" - Write-Success "All required tools installed successfully!" - Write-Host "" - - Write-Host "IMPORTANT: Configure Git before your first commit:" -ForegroundColor Yellow - Write-Host "" - Write-Host " git config --global user.name `"Your Name`"" -ForegroundColor White - Write-Host " git config --global user.email `"your.email@example.com`"" -ForegroundColor White - Write-Host "" - - Write-Host "Optional: Set VS Code as Git's default editor:" -ForegroundColor Cyan - Write-Host " git config --global core.editor `"code --wait`"" -ForegroundColor White - Write-Host "" - - Write-Host "Verify your installation:" -ForegroundColor Cyan - Write-Host " pwsh --version" -ForegroundColor White - Write-Host " git --version" -ForegroundColor White - Write-Host " code --version" -ForegroundColor White - if ($results.Python) { - Write-Host " python --version" -ForegroundColor White - } - Write-Host "" - - Write-Host "Set PowerShell execution policy (if needed):" -ForegroundColor Cyan - Write-Host " Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser" -ForegroundColor White - Write-Host "" - - Write-Host "Recommended VS Code Extensions:" -ForegroundColor Cyan - Write-Host " • GitLens - Supercharge Git capabilities" -ForegroundColor White - Write-Host " • Git Graph - View Git history visually" -ForegroundColor White - Write-Host " • PowerShell - Better PowerShell support (from Microsoft)" -ForegroundColor White - Write-Host "" - Write-Host " Install via: Ctrl+Shift+X in VS Code" -ForegroundColor Gray - Write-Host "" - - Write-Host "You're ready to start the workshop!" -ForegroundColor Green - Write-Host " cd path\to\git-workshop" -ForegroundColor White - Write-Host " cd 01-essentials\01-basics" -ForegroundColor White - Write-Host " .\setup.ps1" -ForegroundColor White - Write-Host "" -} -else { - Write-Host "" - Write-Warning "Some required installations failed or need verification." - Write-Host "" - Write-Host "Troubleshooting steps:" -ForegroundColor Yellow - Write-Host " 1. Close and reopen your terminal (or restart your computer)" -ForegroundColor White - Write-Host " 2. Run this script again: .\install-prerequisites.ps1" -ForegroundColor White - Write-Host " 3. If issues persist, try manual installation:" -ForegroundColor White - Write-Host " See INSTALLATION.md for detailed instructions" -ForegroundColor White - Write-Host "" - - if (-not $results.Git) { - Write-Host "For Git issues:" -ForegroundColor Yellow - Write-Host " • Restart terminal after installation (PATH needs to refresh)" -ForegroundColor White - Write-Host " • Manual download: https://git-scm.com/downloads" -ForegroundColor White - Write-Host "" - } - - if (-not $results.VSCode) { - Write-Host "For VS Code issues:" -ForegroundColor Yellow - Write-Host " • Ensure 'Add to PATH' option is enabled during installation" -ForegroundColor White - Write-Host " • Manual download: https://code.visualstudio.com/" -ForegroundColor White - Write-Host "" - } - - if (-not $results.PowerShell) { - Write-Host "For PowerShell 7 issues:" -ForegroundColor Yellow - Write-Host " • Manual download: https://github.com/PowerShell/PowerShell/releases/latest" -ForegroundColor White - Write-Host " • Download the file ending in '-win-x64.msi'" -ForegroundColor White - Write-Host "" - } - -} diff --git a/install.ps1 b/install.ps1 index 41f1ce7..74ceec2 100644 --- a/install.ps1 +++ b/install.ps1 @@ -1,33 +1,35 @@ #!/usr/bin/env pwsh <# .SYNOPSIS -Oneshot Git Workshop installer - Downloads and runs the prerequisites installation. +Installs all prerequisites for the Git Workshop using winget. .DESCRIPTION -This script downloads the Git Workshop repository and runs the prerequisites -installation script. It's designed to be run directly from the web: +This script automates the installation of required tools for the Git Workshop: +- PowerShell 7 (cross-platform PowerShell) +- Git 2.23+ (version control system) +- Visual Studio Code (code editor with Git integration) - irm https://git.frod.dk/floppydiscen/git-workshop/raw/branch/main/install.ps1 | iex +Optional tools (with user prompts): +- Python 3.12 (for Module 08: Multiplayer Git) +- Windows Terminal (modern terminal experience) -The script will: -1. Create a temporary working directory -2. Download the Git Workshop repository -3. Run the install-prerequisites.ps1 script -4. Clean up temporary files +The script checks for existing installations, shows clear progress, and verifies +each installation succeeded. At the end, it displays Git configuration instructions. .EXAMPLE -PS> irm https://git.frod.dk/floppydiscen/git-workshop/raw/branch/main/install.ps1 | iex -Downloads and runs the Git Workshop installer. +PS> .\install-prerequisites.ps1 +Runs the installation script with interactive prompts. .NOTES -Requires Windows 11 with PowerShell and internet access. +Requires Windows 11 with winget (App Installer) available. +Some installations may require administrator privileges. #> [CmdletBinding()] param() Set-StrictMode -Version Latest -$ErrorActionPreference = 'Stop' +$ErrorActionPreference = 'Continue' # Continue on errors to show all results #region Helper Functions @@ -59,207 +61,573 @@ function Write-Error { Write-ColorMessage " ✗ $Message" -Color Red } +function Test-CommandExists { + param([string]$Command) + + $oldPreference = $ErrorActionPreference + $ErrorActionPreference = 'SilentlyContinue' + + try { + if (Get-Command $Command -ErrorAction SilentlyContinue) { + return $true + } + return $false + } + finally { + $ErrorActionPreference = $oldPreference + } +} + +function Get-InstalledVersion { + param( + [string]$Command, + [string]$VersionArg = '--version' + ) + + try { + $output = & $Command $VersionArg 2>&1 | Select-Object -First 1 + return $output.ToString().Trim() + } + catch { + return $null + } +} + +function Test-WingetAvailable { + if (-not (Test-CommandExists 'winget')) { + Write-Error "winget is not available on this system." + Write-Host "`nTo fix this:" -ForegroundColor Yellow + Write-Host " 1. Update Windows 11 to the latest version (Settings → Windows Update)" -ForegroundColor White + Write-Host " 2. Install 'App Installer' from the Microsoft Store" -ForegroundColor White + Write-Host " 3. Restart your computer and run this script again" -ForegroundColor White + return $false + } + return $true +} + +function Install-Package { + param( + [string]$Name, + [string]$WingetId, + [string]$CheckCommand, + [string]$MinVersion = $null, + [string]$AdditionalArgs = '' + ) + + Write-Step "Installing $Name" + + # Check if already installed + if (Test-CommandExists $CheckCommand) { + $version = Get-InstalledVersion $CheckCommand + Write-Success "$Name is already installed: $version" + + if ($MinVersion -and $version) { + # Basic version check (not perfect but good enough for common cases) + if ($version -match '(\d+\.[\d.]+)') { + $installedVersion = $matches[1] + if ([version]$installedVersion -lt [version]$MinVersion) { + Write-Warning "Version $installedVersion is below minimum required version $MinVersion" + Write-Host " Attempting to upgrade..." -ForegroundColor Cyan + } + else { + return $true + } + } + } + else { + return $true + } + } + + # Install using winget + Write-Host " Installing via winget: $WingetId" -ForegroundColor Cyan + + $installCmd = "winget install --id $WingetId --source winget --silent $AdditionalArgs".Trim() + Write-Host " Running: $installCmd" -ForegroundColor Gray + + try { + # Show progress during installation + Write-Progress -Activity "Installing $Name" -Status "Downloading and installing..." -PercentComplete 25 + + $result = Invoke-Expression $installCmd 2>&1 + + Write-Progress -Activity "Installing $Name" -Status "Verifying installation..." -PercentComplete 75 + + # Check if installation succeeded + Start-Sleep -Seconds 2 # Give the system time to register the new command + + # Refresh environment variables in current session + $env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User") + + if (Test-CommandExists $CheckCommand) { + $version = Get-InstalledVersion $CheckCommand + Write-Success "$Name installed successfully: $version" + Write-Progress -Activity "Installing $Name" -Completed + return $true + } + else { + Write-Warning "$Name installation completed, but command '$CheckCommand' not found." + Write-Host " You may need to restart your terminal or computer." -ForegroundColor Yellow + Write-Progress -Activity "Installing $Name" -Completed + return $false + } + } + catch { + Write-Error "Failed to install $Name`: $_" + Write-Progress -Activity "Installing $Name" -Completed + return $false + } +} + +function Test-GitVersion { + if (-not (Test-CommandExists 'git')) { + return $false + } + + $version = Get-InstalledVersion 'git' + + # Parse Git version from various formats: + # "git version 2.52.0", "git version 2.52.0.windows.1", etc. + if ($version -match 'git version (\d+)\.(\d+)') { + $majorVersion = [int]$matches[1] + $minorVersion = [int]$matches[2] + + # Check if version is 2.23 or higher + if ($majorVersion -gt 2 -or ($majorVersion -eq 2 -and $minorVersion -ge 23)) { + return $true + } + else { + Write-Warning "Git version $majorVersion.$minorVersion is below required version 2.23" + return $false + } + } + + Write-Warning "Could not parse Git version from: $version" + return $false +} + +function Get-UserConfirmation { + param([string]$Prompt) + + while ($true) { + $response = Read-Host "$Prompt (y/n)" + $response = $response.Trim().ToLower() + + if ($response -eq 'y' -or $response -eq 'yes') { + return $true + } + elseif ($response -eq 'n' -or $response -eq 'no') { + return $false + } + else { + Write-Host "Please enter 'y' or 'n'" -ForegroundColor Yellow + } + } +} + #endregion #region Main Script Write-Host @" + ╔═══════════════════════════════════════════════════════════╗ ║ ║ -║ Git Workshop - Oneshot Installation Script ║ +║ Git Workshop - Prerequisites Installation Script ║ ║ ║ ╚═══════════════════════════════════════════════════════════╝ "@ -ForegroundColor Cyan -Write-Host "This script will download and install all prerequisites for the Git Workshop." -ForegroundColor White +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 " • Python 3.12 (for Module 08: Multiplayer Git)" -ForegroundColor White +Write-Host " • Windows Terminal (modern terminal experience)" -ForegroundColor White Write-Host "" -# Check PowerShell version -Write-Step "Checking PowerShell Version" -$psVersion = $PSVersionTable.PSVersion -Write-Success "PowerShell $psVersion" +# Check for winget +Write-Step "Checking Prerequisites" -if ($psVersion.Major -lt 7) { - Write-Warning "PowerShell 7+ is recommended for best compatibility" - Write-Host " Continuing with PowerShell $($psVersion.Major)..." -ForegroundColor Gray +if (-not (Test-WingetAvailable)) { + Write-Host "`nInstallation cannot continue without winget." -ForegroundColor Red + return } -# Create temporary working directory -Write-Step "Creating Working Directory" -$tempDir = Join-Path $env:TEMP "git-workshop-$(Get-Date -Format 'yyyyMMdd-HHmmss')" +Write-Success "winget is available" -try { - New-Item -Path $tempDir -ItemType Directory -Force | Out-Null - Write-Success "Created temporary directory: $tempDir" -} -catch { - Write-Error "Failed to create temporary directory: $_" - exit 1 +# Track installation results +$results = @{ + PowerShell = $false + Git = $false + VSCode = $false + VSCodeExtensions = $false + VSCodePowerShellIntegration = $null # null = not asked, true = configured, false = skipped/failed + Python = $null # null = not attempted, true = success, false = failed + WindowsTerminal = $null } -# Download the repository -Write-Step "Downloading Git Workshop Repository" +# Progress tracking +$totalSteps = 4 # Required installations + extensions +$currentStep = 0 -$repoUrl = "https://git.frod.dk/floppydiscen/git-workshop/archive/main.zip" -$zipPath = Join-Path $tempDir "git-workshop.zip" +Write-Host "`nStarting installation..." -ForegroundColor Cyan +Write-Host "Note: Some installations may take a few minutes." -ForegroundColor Gray +Write-Host "" -try { - Write-Host " Downloading from: $repoUrl" -ForegroundColor Gray - Invoke-WebRequest -Uri $repoUrl -OutFile $zipPath -UseBasicParsing - Write-Success "Repository downloaded successfully" -} -catch { - Write-Error "Failed to download repository: $_" - Write-Host "" - Write-Host "Troubleshooting:" -ForegroundColor Yellow - Write-Host " • Check your internet connection" -ForegroundColor White - Write-Host " • Verify the repository URL is correct" -ForegroundColor White - Write-Host " • Try running the script again" -ForegroundColor White - exit 1 -} - -# Extract the repository -Write-Step "Extracting Repository" - -try { - Write-Host " Extracting to: $tempDir" -ForegroundColor Gray - Expand-Archive -Path $zipPath -DestinationPath $tempDir -Force +# Progress bar helper +function Write-ProgressIndicator { + param( + [string]$Activity, + [string]$Status, + [int]$PercentComplete + ) - # Find the extracted directory (should be git-workshop-main) - $extractedDir = Get-ChildItem -Path $tempDir -Directory | Where-Object { $_.Name -like "git-workshop-*" } | Select-Object -First 1 + Write-Progress -Activity $Activity -Status $Status -PercentComplete $PercentComplete +} + +function Install-VSCodeExtension { + param( + [string]$ExtensionId, + [string]$ExtensionName + ) - if (-not $extractedDir) { - throw "Could not find extracted repository directory" - } + Write-Host " Installing VSCode extension: $ExtensionName" -ForegroundColor Cyan - Write-Success "Repository extracted to: $($extractedDir.FullName)" -} -catch { - Write-Error "Failed to extract repository: $_" - exit 1 -} - -# Run the prerequisites installer -Write-Step "Running Prerequisites Installation" - -$installerScript = Join-Path $extractedDir.FullName "install-prerequisites.ps1" - -if (-not (Test-Path $installerScript)) { - Write-Error "Installation script not found: $installerScript" - Write-Host "" - Write-Host "Expected file structure:" -ForegroundColor Yellow - Write-Host " git-workshop-main/" -ForegroundColor White - Write-Host " ├── install-prerequisites.ps1" -ForegroundColor White - Write-Host " ├── README.md" -ForegroundColor White - Write-Host " └── ..." -ForegroundColor White - exit 1 -} - -try { - Write-Host " Running: $installerScript" -ForegroundColor Gray - Write-Host "" - - # Change to the extracted directory and run the installer - Push-Location $extractedDir.FullName - & $installerScript - - $installerExitCode = $LASTEXITCODE - Pop-Location - - if ($installerExitCode -eq 0) { - Write-Success "Prerequisites installation completed successfully!" - } - else { - Write-Warning "Prerequisites installation completed with warnings (exit code: $installerExitCode)" - } -} -catch { - Write-Error "Failed to run prerequisites installer: $_" - exit 1 -} -finally { - if (Get-Location -ErrorAction SilentlyContinue) { - Pop-Location -ErrorAction SilentlyContinue - } -} - -# Clean up -Write-Step "Cleaning Up" - -try { - Write-Host " Removing temporary directory: $tempDir" -ForegroundColor Gray - Remove-Item -Path $tempDir -Recurse -Force - Write-Success "Temporary files cleaned up" -} -catch { - Write-Warning "Failed to clean up temporary files: $_" - Write-Host " You can manually delete: $tempDir" -ForegroundColor Yellow -} - -# Clone the repository locally -Write-Step "Cloning Git Workshop Repository" - -$cloneDir = Join-Path $HOME "git-workshop" - -try { - if (Test-Path $cloneDir) { - Write-Warning "Directory already exists: $cloneDir" - $response = Read-Host " Do you want to remove it and clone fresh? (y/n)" - if ($response.Trim().ToLower() -eq 'y' -or $response.Trim().ToLower() -eq 'yes') { - Remove-Item -Path $cloneDir -Recurse -Force - Write-Host " Removed existing directory" -ForegroundColor Gray + try { + # Refresh environment to ensure code command is available + $env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User") + + $result = & code --install-extension $ExtensionId 2>&1 + + if ($LASTEXITCODE -eq 0) { + Write-Success "VSCode extension '$ExtensionName' installed successfully" + return $true } else { - Write-Host " Skipping clone - using existing directory" -ForegroundColor Gray + Write-Warning "Failed to install VSCode extension '$ExtensionName'" + Write-Host " You can install it manually later: Ctrl+Shift+X → Search '$ExtensionName'" -ForegroundColor Gray + return $false } } - - if (-not (Test-Path $cloneDir)) { - Write-Host " Cloning to: $cloneDir" -ForegroundColor Gray - git clone "https://git.frod.dk/floppydiscen/git-workshop.git" $cloneDir - Write-Success "Repository cloned successfully!" + catch { + Write-Warning "Could not install VSCode extension '$ExtensionName`: $_" + Write-Host " You can install it manually later: Ctrl+Shift+X → Search '$ExtensionName'" -ForegroundColor Gray + return $false } } -catch { - Write-Error "Failed to clone repository: $_" - Write-Host "" - Write-Host "You can clone manually:" -ForegroundColor Yellow - Write-Host " git clone https://git.frod.dk/floppydiscen/git-workshop.git ~/git-workshop" -ForegroundColor White - exit 1 + +function Set-VSCodePowerShellIntegration { + # Ask user if they want to set PowerShell 7 as default terminal + $setAsDefault = Get-UserConfirmation "Set PowerShell 7 as the default terminal in VSCode? (Recommended for this workshop)" + + if (-not $setAsDefault) { + Write-Host " Skipping PowerShell 7 terminal configuration." -ForegroundColor Gray + return $false + } + + Write-Host " Configuring PowerShell 7 integration with VSCode..." -ForegroundColor Cyan + + try { + # Set PowerShell 7 as the default terminal in VSCode + $vscodeSettingsPath = Join-Path $env:APPDATA "Code\User\settings.json" + $vscodeSettingsDir = Split-Path $vscodeSettingsPath -Parent + + # Create directory if it doesn't exist + if (-not (Test-Path $vscodeSettingsDir)) { + New-Item -Path $vscodeSettingsDir -ItemType Directory -Force | Out-Null + } + + # Read existing settings or create new + if (Test-Path $vscodeSettingsPath) { + $settings = Get-Content $vscodeSettingsPath -Raw | ConvertFrom-Json + } + else { + $settings = @{} + } + + # Set PowerShell 7 as default terminal + if (-not $settings.PSObject.Properties.Name -contains "terminal.integrated.defaultProfile.windows") { + $settings | Add-Member -NotePropertyName "terminal.integrated.defaultProfile.windows" -NotePropertyValue "PowerShell" + } + else { + $settings."terminal.integrated.defaultProfile.windows" = "PowerShell" + } + + # Add terminal profiles if not present + if (-not $settings.PSObject.Properties.Name -contains "terminal.integrated.profiles.windows") { + $profiles = @{ + "PowerShell" = @{ + "source" = "PowerShell" + "icon" = "terminal-powershell" + "path" = "pwsh.exe" + } + } + $settings | Add-Member -NotePropertyName "terminal.integrated.profiles.windows" -NotePropertyValue $profiles + } + + # Save settings + $settings | ConvertTo-Json -Depth 10 | Set-Content $vscodeSettingsPath + + Write-Success "VSCode configured to use PowerShell 7 as default terminal" + return $true + } + catch { + Write-Warning "Could not configure VSCode PowerShell integration automatically" + Write-Host " You can configure it manually in VSCode: Ctrl+Shift+P → Terminal: Select Default Profile → PowerShell" -ForegroundColor Gray + return $false + } } -# Final instructions -Write-Step "Installation Complete" +#region Required Installations -Write-Host "" -Write-Success "Git Workshop installation is complete!" -Write-Host "" +# 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" -Write-Host "Repository cloned to: $cloneDir" -ForegroundColor Green -Write-Host "" +# 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" -Write-Host "Next steps:" -ForegroundColor Cyan -Write-Host " 1. Configure Git if you haven't already:" -ForegroundColor White -Write-Host " git config --global user.name `"Your Name`"" -ForegroundColor Gray -Write-Host " git config --global user.email `"your.email@example.com`"" -ForegroundColor Gray -Write-Host "" -Write-Host " 2. Navigate to the workshop:" -ForegroundColor White -Write-Host " cd $cloneDir" -ForegroundColor Gray -Write-Host "" -Write-Host " 3. Start with the first module:" -ForegroundColor White -Write-Host " cd 01-essentials\01-basics" -ForegroundColor Gray -Write-Host " .\setup.ps1" -ForegroundColor Gray -Write-Host "" +# 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 + } +} -Write-Host "For help and documentation:" -ForegroundColor Cyan -Write-Host " • README.md - Workshop overview" -ForegroundColor White -Write-Host " • GIT-CHEATSHEET.md - Git command reference" -ForegroundColor White -Write-Host " • AGENDA.md - Workshop schedule (Danish)" -ForegroundColor White -Write-Host "" +# 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" -Write-Host "Enjoy learning Git!" -ForegroundColor Green +# 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) + + 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) + $powershellIntegrationResult = Set-VSCodePowerShellIntegration + $results.VSCodePowerShellIntegration = $powershellIntegrationResult + + $results.VSCodeExtensions = $powershellExtensionResult +} +else { + $results.VSCodeExtensions = $false +} + +# Clear progress bar +Write-Progress -Activity "Installing Required Tools" -Completed #endregion -exit 0 \ No newline at end of file +#region Optional Installations + +# Python 3.12 (optional) +Write-Host "" +if (Get-UserConfirmation "Do you want to install Python 3.12? (Required for Module 08: Multiplayer Git)") { + Write-ProgressIndicator -Activity "Installing Optional Tools" -Status "Installing Python 3.12" -PercentComplete 50 + $results.Python = Install-Package ` + -Name "Python 3.12" ` + -WingetId "Python.Python.3.12" ` + -CheckCommand "python" + Write-Progress -Activity "Installing Optional Tools" -Completed +} +else { + Write-Host " Skipping Python installation." -ForegroundColor Gray + $results.Python = $null +} + +# 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 +} + +#endregion + +#region Installation Summary + +Write-Step "Installation Summary" + +$allRequired = $results.PowerShell -and $results.Git -and $results.VSCode + +Write-Host "" +Write-Host "Required Tools:" -ForegroundColor White + +if ($results.PowerShell) { + Write-Success "PowerShell 7" +} +else { + Write-Error "PowerShell 7 - Installation failed or needs restart" +} + +if ($results.Git) { + Write-Success "Git 2.23+" +} +else { + Write-Error "Git 2.23+ - Installation failed or needs restart" +} + +if ($results.VSCode) { + Write-Success "Visual Studio Code" + + if ($results.VSCodeExtensions) { + Write-Success " • PowerShell extension" + } + else { + Write-Warning " • VSCode PowerShell extension may need manual installation" + } + + if ($results.VSCodePowerShellIntegration -eq $true) { + Write-Success " • PowerShell 7 terminal integration" + } + elseif ($results.VSCodePowerShellIntegration -eq $false) { + Write-Host " • PowerShell 7 terminal integration: Skipped" -ForegroundColor Gray + } +} +else { + Write-Error "Visual Studio Code - Installation failed or needs restart" +} + +if ($results.Python -ne $null) { + Write-Host "" + Write-Host "Optional Tools:" -ForegroundColor White + + if ($results.Python) { + Write-Success "Python 3.12" + } + else { + Write-Error "Python 3.12 - Installation failed or needs restart" + } +} + +if ($results.WindowsTerminal -ne $null) { + if ($results.Python -eq $null) { + Write-Host "" + Write-Host "Optional Tools:" -ForegroundColor White + } + + if ($results.WindowsTerminal) { + Write-Success "Windows Terminal" + } + else { + Write-Error "Windows Terminal - Installation failed or needs restart" + } +} + +#endregion + +#region Next Steps + +Write-Step "Next Steps" + +if ($allRequired) { + Write-Host "" + Write-Success "All required tools installed successfully!" + Write-Host "" + + Write-Host "IMPORTANT: Configure Git before your first commit:" -ForegroundColor Yellow + Write-Host "" + Write-Host " git config --global user.name `"Your Name`"" -ForegroundColor White + Write-Host " git config --global user.email `"your.email@example.com`"" -ForegroundColor White + Write-Host "" + + Write-Host "Optional: Set VS Code as Git's default editor:" -ForegroundColor Cyan + Write-Host " git config --global core.editor `"code --wait`"" -ForegroundColor White + Write-Host "" + + Write-Host "Verify your installation:" -ForegroundColor Cyan + Write-Host " pwsh --version" -ForegroundColor White + Write-Host " git --version" -ForegroundColor White + Write-Host " code --version" -ForegroundColor White + if ($results.Python) { + Write-Host " python --version" -ForegroundColor White + } + Write-Host "" + + Write-Host "Set PowerShell execution policy (if needed):" -ForegroundColor Cyan + Write-Host " Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser" -ForegroundColor White + Write-Host "" + + Write-Host "Recommended VS Code Extensions:" -ForegroundColor Cyan + Write-Host " • GitLens - Supercharge Git capabilities" -ForegroundColor White + Write-Host " • Git Graph - View Git history visually" -ForegroundColor White + Write-Host " • PowerShell - Better PowerShell support (from Microsoft)" -ForegroundColor White + Write-Host "" + Write-Host " Install via: Ctrl+Shift+X in VS Code" -ForegroundColor Gray + Write-Host "" + + Write-Host "You're ready to start the workshop!" -ForegroundColor Green + Write-Host " cd path\to\git-workshop" -ForegroundColor White + Write-Host " cd 01-essentials\01-basics" -ForegroundColor White + Write-Host " .\setup.ps1" -ForegroundColor White + Write-Host "" +} +else { + Write-Host "" + Write-Warning "Some required installations failed or need verification." + Write-Host "" + Write-Host "Troubleshooting steps:" -ForegroundColor Yellow + Write-Host " 1. Close and reopen your terminal (or restart your computer)" -ForegroundColor White + Write-Host " 2. Run this script again: .\install-prerequisites.ps1" -ForegroundColor White + Write-Host " 3. If issues persist, try manual installation:" -ForegroundColor White + Write-Host " See INSTALLATION.md for detailed instructions" -ForegroundColor White + Write-Host "" + + if (-not $results.Git) { + Write-Host "For Git issues:" -ForegroundColor Yellow + Write-Host " • Restart terminal after installation (PATH needs to refresh)" -ForegroundColor White + Write-Host " • Manual download: https://git-scm.com/downloads" -ForegroundColor White + Write-Host "" + } + + if (-not $results.VSCode) { + Write-Host "For VS Code issues:" -ForegroundColor Yellow + Write-Host " • Ensure 'Add to PATH' option is enabled during installation" -ForegroundColor White + Write-Host " • Manual download: https://code.visualstudio.com/" -ForegroundColor White + Write-Host "" + } + + if (-not $results.PowerShell) { + Write-Host "For PowerShell 7 issues:" -ForegroundColor Yellow + Write-Host " • Manual download: https://github.com/PowerShell/PowerShell/releases/latest" -ForegroundColor White + Write-Host " • Download the file ending in '-win-x64.msi'" -ForegroundColor White + Write-Host "" + } + +}