@@ -119,6 +119,26 @@ function New-ClaudeEnvJson
119119 $claudeEnv [" IS_TEAMCITY_AGENT" ] = $env: IS_TEAMCITY_AGENT
120120 }
121121
122+ # Git identity - read from host git config if not set in environment
123+ $gitUserName = $env: GIT_USER_NAME
124+ $gitUserEmail = $env: GIT_USER_EMAIL
125+ if (-not $gitUserName )
126+ {
127+ $gitUserName = git config -- global user.name
128+ }
129+ if (-not $gitUserEmail )
130+ {
131+ $gitUserEmail = git config -- global user.email
132+ }
133+ if ($gitUserName )
134+ {
135+ $claudeEnv [" GIT_USER_NAME" ] = $gitUserName
136+ }
137+ if ($gitUserEmail )
138+ {
139+ $claudeEnv [" GIT_USER_EMAIL" ] = $gitUserEmail
140+ }
141+
122142 # Convert to JSON and save
123143 $jsonPath = Join-Path $dockerContextDirectory " env.g.json"
124144
@@ -367,6 +387,22 @@ $MountPoints = $MountPoints | ForEach-Object { Get-ContainerPath $_ }
367387$GitDirectories = $GitDirectories | ForEach-Object { Get-ContainerPath $_ }
368388$ContainerSourceDir = Get-ContainerPath $SourceDirName
369389
390+ # Add both the unmapped (C:\X\...) and mapped (X:\...) paths to GitDirectories for safe.directory
391+ # Git may resolve paths differently depending on how it's invoked
392+ $expandedGitDirectories = @ ()
393+ foreach ($dir in $GitDirectories )
394+ {
395+ $expandedGitDirectories += $dir
396+ # If path is C:\<letter>\... (unmapped subst path), also add <letter>:\... (mapped path)
397+ if ($dir -match ' ^C:\\([A-Za-z])\\(.*)$' )
398+ {
399+ $letter = $Matches [1 ].ToUpper()
400+ $rest = $Matches [2 ]
401+ $expandedGitDirectories += " ${letter} :\$rest "
402+ }
403+ }
404+ $GitDirectories = $expandedGitDirectories
405+
370406# Build subst commands string for inline execution in docker run
371407$substCommandsInline = " "
372408foreach ($letter in $driveLetters.Keys | Sort-Object )
@@ -378,9 +414,23 @@ if ($driveLetters.Count -gt 0)
378414 Write-Host " Drive letter mappings for container: $ ( $driveLetters.Keys -join ' , ' ) " - ForegroundColor Cyan
379415}
380416
381- # Create empty Init.g.ps1 for Dockerfile COPY (required by Dockerfile but not used for drive mapping)
417+ # Create Init.g.ps1 with git safe.directory configuration
382418$initScript = Join-Path $dockerContextDirectory " Init.g.ps1"
383- " # Drive mappings are handled inline in docker run command" | Set-Content - Path $initScript - Encoding UTF8
419+ $initScriptContent = @"
420+ # Auto-generated initialization script for container startup
421+ # Configure git safe.directory for all mounted directories
422+ `$ gitDirectories = @(
423+ $ ( ($GitDirectories | ForEach-Object { " '$_ '" }) -join " ,`n " )
424+ )
425+
426+ foreach (`$ dir in `$ gitDirectories) {
427+ if (`$ dir) {
428+ `$ normalizedDir = (`$ dir -replace '\\\\', '/').TrimEnd('/') + '/'
429+ git config --global --add safe.directory `$ normalizedDir
430+ }
431+ }
432+ "@
433+ $initScriptContent | Set-Content - Path $initScript - Encoding UTF8
384434
385435$mountPointsAsString = $MountPoints -Join " ;"
386436$gitDirectoriesAsString = $GitDirectories -Join " ;"
@@ -410,7 +460,7 @@ if (-not $NoBuildImage)
410460 exit 1
411461 }
412462
413- Get-Content - Raw Dockerfile.claude | docker build - t $ImageTag -- build-arg GITDIRS = " $gitDirectoriesAsString " -- build-arg MOUNTPOINTS= " $mountPointsAsString " -f - $dockerContextDirectory
463+ Get-Content - Raw Dockerfile.claude | docker build - t $ImageTag -- build-arg MOUNTPOINTS= " $mountPointsAsString " -f - $dockerContextDirectory
414464 if ($LASTEXITCODE -ne 0 )
415465 {
416466 Write-Host " Docker build (Claude) failed with exit code $LASTEXITCODE " - ForegroundColor Red
@@ -421,7 +471,7 @@ if (-not $NoBuildImage)
421471 {
422472 # Build base image
423473 Write-Host " Building the base image with tag: $ImageTag " - ForegroundColor Green
424- Get-Content - Raw Dockerfile | docker build - t $ImageTag -- build-arg GITDIRS = " $gitDirectoriesAsString " -- build-arg MOUNTPOINTS= " $mountPointsAsString " -f - $dockerContextDirectory
474+ Get-Content - Raw Dockerfile | docker build - t $ImageTag -- build-arg MOUNTPOINTS= " $mountPointsAsString " -f - $dockerContextDirectory
425475 if ($LASTEXITCODE -ne 0 )
426476 {
427477 Write-Host " Docker build failed with exit code $LASTEXITCODE " - ForegroundColor Red
@@ -498,13 +548,13 @@ if (-not $BuildImage)
498548 {
499549 # Non-interactive mode with prompt - no -it flags
500550 $dockerArgs = @ ()
501- $inlineScript = " ${substCommandsInline}${copyClaudeJsonScript} cd '$SourceDirName '; & .\eng\RunClaude.g.ps1 -Prompt `" $ClaudePrompt `" "
551+ $inlineScript = " ${substCommandsInline} & c:\Init.g.ps1; ${copyClaudeJsonScript} cd '$SourceDirName '; & .\eng\RunClaude.g.ps1 -Prompt `" $ClaudePrompt `" "
502552 }
503553 else
504554 {
505555 # Interactive mode - requires TTY
506556 $dockerArgs = @ (" -it" )
507- $inlineScript = " ${substCommandsInline}${copyClaudeJsonScript} cd '$SourceDirName '; & .\eng\RunClaude.g.ps1"
557+ $inlineScript = " ${substCommandsInline} & c:\Init.g.ps1; ${copyClaudeJsonScript} cd '$SourceDirName '; & .\eng\RunClaude.g.ps1"
508558 }
509559
510560 $dockerArgsAsString = $dockerArgs -join " "
@@ -552,8 +602,8 @@ if (-not $BuildImage)
552602 $VolumeMappingsAsString = $VolumeMappings -join " "
553603 $dockerArgsAsString = $dockerArgs -join " "
554604
555- # Build inline script: subst drives, cd to source, run build
556- $inlineScript = " ${substCommandsInline} cd '$SourceDirName '; & .\$Script $buildArgsString ; $pwshExitCommand "
605+ # Build inline script: subst drives, run init, cd to source, run build
606+ $inlineScript = " ${substCommandsInline} & c:\Init.g.ps1; cd '$SourceDirName '; & .\$Script $buildArgsString ; $pwshExitCommand "
557607
558608 $pwshPath = ' C:\Program Files\PowerShell\7\pwsh.exe'
559609 Write-Host " Executing: `` docker run --rm --memory=12g $dockerArgsAsString $VolumeMappingsAsString -w $ContainerSourceDir $ImageTag `" $pwshPath `" $pwshArgs -Command `" $inlineScript `" " - ForegroundColor Cyan
0 commit comments