Compare commits

2 Commits

Author SHA1 Message Date
Bjarke Sporring
09f25d6eae Add repository cloning and VSCode opening to install.ps1
- Ask user if they want to clone workshop to Documents/git-workshop
- Automatically clone repository to Documents folder for convenience
- Open VSCode in the workshop directory after cloning
- Handle existing repositories (update if already cloned)
- Provide quick start commands for VSCode terminal
- Fallback to manual instructions if user declines or cloning fails
- Complete end-to-end setup experience
2026-01-14 17:03:04 +01:00
Bjarke Sporring
cbefeaf4d2 refactor: move install-prerequisites to install.ps1 2026-01-14 17:00:02 +01:00
2 changed files with 612 additions and 809 deletions

View File

@@ -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 ""
}
}

View File

@@ -1,33 +1,35 @@
#!/usr/bin/env pwsh #!/usr/bin/env pwsh
<# <#
.SYNOPSIS .SYNOPSIS
Oneshot Git Workshop installer - Downloads and runs the prerequisites installation. Installs all prerequisites for the Git Workshop using winget.
.DESCRIPTION .DESCRIPTION
This script downloads the Git Workshop repository and runs the prerequisites This script automates the installation of required tools for the Git Workshop:
installation script. It's designed to be run directly from the web: - 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: The script checks for existing installations, shows clear progress, and verifies
1. Create a temporary working directory each installation succeeded. At the end, it displays Git configuration instructions.
2. Download the Git Workshop repository
3. Run the install-prerequisites.ps1 script
4. Clean up temporary files
.EXAMPLE .EXAMPLE
PS> irm https://git.frod.dk/floppydiscen/git-workshop/raw/branch/main/install.ps1 | iex PS> .\install-prerequisites.ps1
Downloads and runs the Git Workshop installer. Runs the installation script with interactive prompts.
.NOTES .NOTES
Requires Windows 11 with PowerShell and internet access. Requires Windows 11 with winget (App Installer) available.
Some installations may require administrator privileges.
#> #>
[CmdletBinding()] [CmdletBinding()]
param() param()
Set-StrictMode -Version Latest Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop' $ErrorActionPreference = 'Continue' # Continue on errors to show all results
#region Helper Functions #region Helper Functions
@@ -59,207 +61,641 @@ function Write-Error {
Write-ColorMessage "$Message" -Color Red 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 #endregion
#region Main Script #region Main Script
Write-Host @" Write-Host @"
Git Workshop - Oneshot Installation Script Git Workshop - Prerequisites Installation Script
"@ -ForegroundColor Cyan "@ -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 "" Write-Host ""
# Check PowerShell version # Check for winget
Write-Step "Checking PowerShell Version" Write-Step "Checking Prerequisites"
$psVersion = $PSVersionTable.PSVersion
Write-Success "PowerShell $psVersion"
if ($psVersion.Major -lt 7) { if (-not (Test-WingetAvailable)) {
Write-Warning "PowerShell 7+ is recommended for best compatibility" Write-Host "`nInstallation cannot continue without winget." -ForegroundColor Red
Write-Host " Continuing with PowerShell $($psVersion.Major)..." -ForegroundColor Gray return
} }
# Create temporary working directory Write-Success "winget is available"
Write-Step "Creating Working Directory"
$tempDir = Join-Path $env:TEMP "git-workshop-$(Get-Date -Format 'yyyyMMdd-HHmmss')"
try { # Track installation results
New-Item -Path $tempDir -ItemType Directory -Force | Out-Null $results = @{
Write-Success "Created temporary directory: $tempDir" PowerShell = $false
} Git = $false
catch { VSCode = $false
Write-Error "Failed to create temporary directory: $_" VSCodeExtensions = $false
exit 1 VSCodePowerShellIntegration = $null # null = not asked, true = configured, false = skipped/failed
Python = $null # null = not attempted, true = success, false = failed
WindowsTerminal = $null
} }
# Download the repository # Progress tracking
Write-Step "Downloading Git Workshop Repository" $totalSteps = 4 # Required installations + extensions
$currentStep = 0
$repoUrl = "https://git.frod.dk/floppydiscen/git-workshop/archive/main.zip" Write-Host "`nStarting installation..." -ForegroundColor Cyan
$zipPath = Join-Path $tempDir "git-workshop.zip" Write-Host "Note: Some installations may take a few minutes." -ForegroundColor Gray
Write-Host ""
try { # Progress bar helper
Write-Host " Downloading from: $repoUrl" -ForegroundColor Gray function Write-ProgressIndicator {
Invoke-WebRequest -Uri $repoUrl -OutFile $zipPath -UseBasicParsing param(
Write-Success "Repository downloaded successfully" [string]$Activity,
} [string]$Status,
catch { [int]$PercentComplete
Write-Error "Failed to download repository: $_" )
Write-Host ""
Write-Host "Troubleshooting:" -ForegroundColor Yellow Write-Progress -Activity $Activity -Status $Status -PercentComplete $PercentComplete
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 function Install-VSCodeExtension {
Write-Step "Extracting Repository" param(
[string]$ExtensionId,
[string]$ExtensionName
)
try { Write-Host " Installing VSCode extension: $ExtensionName" -ForegroundColor Cyan
Write-Host " Extracting to: $tempDir" -ForegroundColor Gray
Expand-Archive -Path $zipPath -DestinationPath $tempDir -Force
# Find the extracted directory (should be git-workshop-main) try {
$extractedDir = Get-ChildItem -Path $tempDir -Directory | Where-Object { $_.Name -like "git-workshop-*" } | Select-Object -First 1 # Refresh environment to ensure code command is available
$env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
if (-not $extractedDir) { $result = & code --install-extension $ExtensionId 2>&1
throw "Could not find extracted repository directory"
}
Write-Success "Repository extracted to: $($extractedDir.FullName)" if ($LASTEXITCODE -eq 0) {
} Write-Success "VSCode extension '$ExtensionName' installed successfully"
catch { return $true
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 { else {
Write-Warning "Prerequisites installation completed with warnings (exit code: $installerExitCode)" 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 { catch {
Write-Error "Failed to run prerequisites installer: $_" Write-Warning "Could not install VSCode extension '$ExtensionName`: $_"
exit 1 Write-Host " You can install it manually later: Ctrl+Shift+X → Search '$ExtensionName'" -ForegroundColor Gray
} return $false
finally {
if (Get-Location -ErrorAction SilentlyContinue) {
Pop-Location -ErrorAction SilentlyContinue
} }
} }
# Clean up function Set-VSCodePowerShellIntegration {
Write-Step "Cleaning Up" # 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)"
try { if (-not $setAsDefault) {
Write-Host " Removing temporary directory: $tempDir" -ForegroundColor Gray Write-Host " Skipping PowerShell 7 terminal configuration." -ForegroundColor Gray
Remove-Item -Path $tempDir -Recurse -Force return $false
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-Host " Configuring PowerShell 7 integration with VSCode..." -ForegroundColor Cyan
Write-Step "Cloning Git Workshop Repository"
$cloneDir = Join-Path $HOME "git-workshop" try {
# Set PowerShell 7 as the default terminal in VSCode
$vscodeSettingsPath = Join-Path $env:APPDATA "Code\User\settings.json"
$vscodeSettingsDir = Split-Path $vscodeSettingsPath -Parent
try { # Create directory if it doesn't exist
if (Test-Path $cloneDir) { if (-not (Test-Path $vscodeSettingsDir)) {
Write-Warning "Directory already exists: $cloneDir" New-Item -Path $vscodeSettingsDir -ItemType Directory -Force | Out-Null
$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 # Read existing settings or create new
Write-Host " Removed existing directory" -ForegroundColor Gray if (Test-Path $vscodeSettingsPath) {
$settings = Get-Content $vscodeSettingsPath -Raw | ConvertFrom-Json
} }
else { else {
Write-Host " Skipping clone - using existing directory" -ForegroundColor Gray $settings = @{}
}
} }
if (-not (Test-Path $cloneDir)) { # Set PowerShell 7 as default terminal
Write-Host " Cloning to: $cloneDir" -ForegroundColor Gray if (-not $settings.PSObject.Properties.Name -contains "terminal.integrated.defaultProfile.windows") {
git clone "https://git.frod.dk/floppydiscen/git-workshop.git" $cloneDir $settings | Add-Member -NotePropertyName "terminal.integrated.defaultProfile.windows" -NotePropertyValue "PowerShell"
Write-Success "Repository cloned successfully!" }
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
} }
} }
catch {
Write-Error "Failed to clone repository: $_" #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-Host ""
Write-Host "You can clone manually:" -ForegroundColor Yellow Write-Step "Configuring VSCode"
Write-Host " git clone https://git.frod.dk/floppydiscen/git-workshop.git ~/git-workshop" -ForegroundColor White
exit 1 # 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
} }
# Final instructions # Clear progress bar
Write-Step "Installation Complete" Write-Progress -Activity "Installing Required Tools" -Completed
Write-Host ""
Write-Success "Git Workshop installation is complete!"
Write-Host ""
Write-Host "Repository cloned to: $cloneDir" -ForegroundColor Green
Write-Host ""
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 ""
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 ""
Write-Host "Enjoy learning Git!" -ForegroundColor Green
#endregion #endregion
exit 0 #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 ""
# Ask user if they want to clone the workshop repository
Write-Step "Workshop Setup"
if (Get-UserConfirmation "Clone the Git Workshop repository to Documents\git-workshop and open in VSCode?") {
try {
$documentsPath = [System.Environment]::GetFolderPath("MyDocuments")
$workshopPath = Join-Path $documentsPath "git-workshop"
Write-Host " Cloning to: $workshopPath" -ForegroundColor Gray
# Create directory if it doesn't exist
$documentsDir = Split-Path $workshopPath -Parent
if (-not (Test-Path $documentsDir)) {
New-Item -Path $documentsDir -ItemType Directory -Force | Out-Null
}
# Clone or update the repository
if (Test-Path $workshopPath) {
Write-Host " Directory already exists. Checking if it's a git repository..." -ForegroundColor Yellow
Push-Location $workshopPath
if (Get-Command git -ErrorAction SilentlyContinue) {
$remoteResult = git remote get-url origin 2>$null
if ($LASTEXITCODE -eq 0 -and $remoteResult -like "*git-workshop*") {
Write-Host " Repository already exists. Updating..." -ForegroundColor Cyan
git pull origin main
} else {
Write-Warning " Directory exists but is not the git-workshop repository"
Write-Host " Please remove the directory manually and run again" -ForegroundColor Yellow
Pop-Location
return
}
}
Pop-Location
} else {
git clone "https://git.frod.dk/floppydiscen/git-workshop.git" $workshopPath
Write-Success "Repository cloned successfully!"
}
# Open in VSCode
Write-Host " Opening in VSCode..." -ForegroundColor Cyan
if (Get-Command code -ErrorAction SilentlyContinue) {
& code $workshopPath
Write-Success "VSCode opened with the workshop repository"
} else {
Write-Warning "VSCode command not found. Please open manually:"
Write-Host " code '$workshopPath'" -ForegroundColor White
}
Write-Host ""
Write-Host "Quick start commands (run in VSCode terminal):" -ForegroundColor Cyan
Write-Host " cd 01-essentials\01-basics" -ForegroundColor White
Write-Host " .\setup.ps1" -ForegroundColor White
Write-Host ""
} 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 ~/Documents/git-workshop" -ForegroundColor White
Write-Host " code ~/Documents/git-workshop" -ForegroundColor White
}
} else {
Write-Host " Skipping repository clone." -ForegroundColor Gray
Write-Host ""
Write-Host "Manual setup:" -ForegroundColor Cyan
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 ""
}
}