Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,73 @@ if ($pathUpdate.MachineStatus -eq 'Updated') {
Write-Success "Successfully installed git-ai into $installDir"
Write-Success "You can now run 'git-ai' from your terminal"

# Configure Git Bash shell profiles so git-ai takes precedence over /mingw64/bin/git
# Git Bash (MSYS2/MinGW) prepends its own directories to PATH, which shadows
# the Windows PATH entry we set above. Writing to ~/.bashrc ensures git-ai's
# bin directory is prepended after Git Bash's own PATH setup.
$gitBashConfigured = $false
$gitBashAlreadyConfigured = $false
try {
$bashrcPath = Join-Path $HOME '.bashrc'
$bashProfilePath = Join-Path $HOME '.bash_profile'
$pathCmd = 'export PATH="$HOME/.git-ai/bin:$PATH"'
$markerString = '.git-ai/bin'

# Detect if Git Bash is installed
$gitBashInstalled = $false
$gitForWindowsPaths = @(
(Join-Path $env:ProgramFiles 'Git\bin\bash.exe'),
(Join-Path ${env:ProgramFiles(x86)} 'Git\bin\bash.exe'),
(Join-Path $env:LOCALAPPDATA 'Programs\Git\bin\bash.exe')
)
Comment on lines +451 to +455
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Eager Join-Path evaluation with null env var aborts entire Git Bash config block

If ${env:ProgramFiles(x86)} is $null (e.g., on 32-bit Windows), the Join-Path call on line 453 throws a ParameterBindingValidationException during array construction, before the loop on line 456 ever executes. This causes the entire try block to jump to catch, skipping Git Bash configuration entirely — even if Git Bash is installed at one of the other checked paths ($env:ProgramFiles\Git\bin\bash.exe or $env:LOCALAPPDATA\Programs\Git\bin\bash.exe).

Root Cause

All three Join-Path calls on lines 452-454 are evaluated eagerly when constructing the $gitForWindowsPaths array. The null-guard $p -and on line 457 was intended to handle null paths, but it never gets reached because the exception occurs during array initialization.

$gitForWindowsPaths = @(
    (Join-Path $env:ProgramFiles 'Git\bin\bash.exe'),
    (Join-Path ${env:ProgramFiles(x86)} 'Git\bin\bash.exe'),  # throws if null
    (Join-Path $env:LOCALAPPDATA 'Programs\Git\bin\bash.exe')
)

With Set-StrictMode -Version Latest (line 2), Join-Path with a $null -Path parameter throws a terminating error. The fix is to guard each path construction against null, e.g., by only adding non-null paths to the array, or by using if checks before Join-Path.

Impact: On 32-bit Windows (rare but possible), Git Bash shell profile configuration is silently skipped with only a warning message, even when Git Bash is installed.

Suggested change
$gitForWindowsPaths = @(
(Join-Path $env:ProgramFiles 'Git\bin\bash.exe'),
(Join-Path ${env:ProgramFiles(x86)} 'Git\bin\bash.exe'),
(Join-Path $env:LOCALAPPDATA 'Programs\Git\bin\bash.exe')
)
$gitForWindowsPaths = @()
if ($env:ProgramFiles) { $gitForWindowsPaths += Join-Path $env:ProgramFiles 'Git\bin\bash.exe' }
if (${env:ProgramFiles(x86)}) { $gitForWindowsPaths += Join-Path ${env:ProgramFiles(x86)} 'Git\bin\bash.exe' }
if ($env:LOCALAPPDATA) { $gitForWindowsPaths += Join-Path $env:LOCALAPPDATA 'Programs\Git\bin\bash.exe' }
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

foreach ($p in $gitForWindowsPaths) {
if ($p -and (Test-Path -LiteralPath $p)) {
$gitBashInstalled = $true
break
}
}

if ($gitBashInstalled) {
# Determine which config file to update (prefer .bashrc, fall back to .bash_profile)
$targetBashConfig = $null
if (Test-Path -LiteralPath $bashrcPath) {
$targetBashConfig = $bashrcPath
} elseif (Test-Path -LiteralPath $bashProfilePath) {
$targetBashConfig = $bashProfilePath
} else {
# No existing config; create .bashrc
$targetBashConfig = $bashrcPath
}

# Check if already configured
$alreadyPresent = $false
if (Test-Path -LiteralPath $targetBashConfig) {
$content = Get-Content -LiteralPath $targetBashConfig -Raw -ErrorAction SilentlyContinue
if ($content -and $content.Contains($markerString)) {
$alreadyPresent = $true
}
}

if ($alreadyPresent) {
$gitBashAlreadyConfigured = $true
} else {
$timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
$appendContent = "`n# Added by git-ai installer on $timestamp`n$pathCmd`n"
$utf8NoBom = New-Object System.Text.UTF8Encoding($false)
[System.IO.File]::AppendAllText($targetBashConfig, $appendContent, $utf8NoBom)
$gitBashConfigured = $true
}
}
} catch {
Write-Host "Warning: Failed to configure Git Bash: $($_.Exception.Message)" -ForegroundColor Yellow
}

if ($gitBashConfigured) {
Write-Success "Successfully configured Git Bash ($targetBashConfig)"
} elseif ($gitBashAlreadyConfigured) {
Write-Success "Git Bash already configured ($targetBashConfig)"
}

# Write JSON config at %USERPROFILE%\.git-ai\config.json (only if it doesn't exist)
try {
$configDir = Join-Path $HOME '.git-ai'
Expand Down
Loading