diff --git a/install.ps1 b/install.ps1 index cdc0b8c..4e75057 100644 --- a/install.ps1 +++ b/install.ps1 @@ -50,6 +50,35 @@ function Ensure-Cargo { } } +function Ensure-Git { + if (Get-Command git -ErrorAction SilentlyContinue) { + return + } + if (-not (Get-Command winget -ErrorAction SilentlyContinue)) { + throw "git not found and winget is unavailable; install Git from https://git-scm.com/download/win or set DOSH_USE_PREBUILT=1" + } + Write-Info "git not found; installing Git with winget" + winget install --id Git.Git -e --accept-package-agreements --accept-source-agreements + $gitBins = @() + if ($env:ProgramFiles) { + $gitBins += (Join-Path $env:ProgramFiles "Git\cmd") + } + if (${env:ProgramFiles(x86)}) { + $gitBins += (Join-Path ${env:ProgramFiles(x86)} "Git\cmd") + } + if ($env:LOCALAPPDATA) { + $gitBins += (Join-Path $env:LOCALAPPDATA "Programs\Git\cmd") + } + foreach ($gitBin in $gitBins) { + if ((Test-Path $gitBin) -and -not (PathList-Contains $env:Path $gitBin)) { + $env:Path = "$gitBin;$env:Path" + } + } + if (-not (Get-Command git -ErrorAction SilentlyContinue)) { + throw "git was installed but is not available in this terminal yet; open a new terminal and rerun dosh update" + } +} + function Normalize-Arch { $arch = if ($env:PROCESSOR_ARCHITEW6432) { $env:PROCESSOR_ARCHITEW6432 } else { $env:PROCESSOR_ARCHITECTURE } switch ($arch) { @@ -433,7 +462,7 @@ function Install-FromSource { if (-not $Repo) { throw "DOSH_REPO is required when running the installer from irm/iex" } - Require-Command git + Ensure-Git $sourceCache = Assert-SafeUpdateCache $UpdateCache $parent = Split-Path -Parent $sourceCache New-Item -ItemType Directory -Force -Path $parent | Out-Null diff --git a/tests/release_scripts.rs b/tests/release_scripts.rs index 5f0f727..d10f60a 100644 --- a/tests/release_scripts.rs +++ b/tests/release_scripts.rs @@ -219,6 +219,22 @@ fn windows_installer_bootstraps_rust_for_source_fallback_like_unix() { assert!(!ps1.contains("Require-Command cargo")); } +#[test] +fn windows_installer_bootstraps_git_for_source_fallback_like_unix() { + let ps1 = include_str!("../install.ps1"); + assert!(ps1.contains("function Ensure-Git")); + assert!(ps1.contains("git not found; installing Git with winget")); + assert!(ps1.contains("winget install --id Git.Git")); + assert!(ps1.contains("--accept-package-agreements --accept-source-agreements")); + assert!(ps1.contains("Join-Path $env:ProgramFiles \"Git\\cmd\"")); + assert!(ps1.contains("Join-Path ${env:ProgramFiles(x86)} \"Git\\cmd\"")); + assert!(ps1.contains("Join-Path $env:LOCALAPPDATA \"Programs\\Git\\cmd\"")); + assert!(ps1.contains("PathList-Contains $env:Path $gitBin")); + assert!(ps1.contains("$env:Path = \"$gitBin;$env:Path\"")); + assert!(ps1.contains("Ensure-Git")); + assert!(!ps1.contains("Require-Command git")); +} + #[test] fn windows_installer_honors_quiet_update_mode() { let ps1 = include_str!("../install.ps1");