fix(claude-do): merge GitService stderr matches are English-only, same locale bug

ClaudeDo-Task: 66b7ad7b-ffc4-4ebd-8b21-54bba28e5b04
This commit is contained in:
mika kuns
2026-09-10 13:56:14 +02:00
2 changed files with 60 additions and 0 deletions
+5
View File
@@ -704,6 +704,11 @@ public sealed class GitService
// (mktree "input format error") and would prepend to stdin commit messages. // (mktree "input format error") and would prepend to stdin commit messages.
StandardInputEncoding = stdinData is not null ? new UTF8Encoding(false) : null, StandardInputEncoding = stdinData is not null ? new UTF8Encoding(false) : null,
}; };
// Force English stderr/stdout so the English-only substring matches below
// (e.g. "ambiguous argument 'HEAD'", "tell me who you are") work regardless
// of the OS locale git for Windows picks up.
psi.Environment["LC_ALL"] = "C";
psi.Environment["LANGUAGE"] = "C";
psi.ArgumentList.Add("-C"); psi.ArgumentList.Add("-C");
psi.ArgumentList.Add(workDir); psi.ArgumentList.Add(workDir);
foreach (var a in args) psi.ArgumentList.Add(a); foreach (var a in args) psi.ArgumentList.Add(a);
@@ -122,6 +122,61 @@ public class GitServiceBootstrapTests : IDisposable
Assert.Equal("ClaudeDo <claudedo@local>", author); Assert.Equal("ClaudeDo <claudedo@local>", author);
} }
[Fact]
public async Task RevParseHead_EmptyRepo_FriendlyMessage_EvenUnderNonEnglishLocale()
{
if (!GitAvailable) { Assert.True(true, "git not available -- skipping"); return; }
var dir = InitEmptyRepo();
var previousLanguage = Environment.GetEnvironmentVariable("LANGUAGE");
var previousLcAll = Environment.GetEnvironmentVariable("LC_ALL");
// Simulate a non-English OS/git locale on the *ambient* process environment.
// GitService must override it per-call so its English-only stderr matches
// (e.g. "ambiguous argument 'HEAD'") keep working regardless.
Environment.SetEnvironmentVariable("LANGUAGE", "de");
Environment.SetEnvironmentVariable("LC_ALL", "de_DE.UTF-8");
try
{
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => _git.RevParseHeadAsync(dir));
Assert.Contains("no commits yet", ex.Message);
}
finally
{
Environment.SetEnvironmentVariable("LANGUAGE", previousLanguage);
Environment.SetEnvironmentVariable("LC_ALL", previousLcAll);
}
}
[Fact]
public async Task CommitAsync_MissingIdentity_FallsBackToClaudeDoIdentity_EvenUnderNonEnglishLocale()
{
if (!GitAvailable) { Assert.True(true, "git not available -- skipping"); return; }
var dir = InitEmptyRepo();
GitRepoFixture.RunGit(dir, "-c", "user.name=t", "-c", "user.email=t@t", "commit", "--allow-empty", "-m", "seed");
GitRepoFixture.RunGit(dir, "config", "user.name", "");
GitRepoFixture.RunGit(dir, "config", "user.email", "");
File.WriteAllText(Path.Combine(dir, "work.txt"), "content\n");
await _git.AddAllAsync(dir);
var previousLanguage = Environment.GetEnvironmentVariable("LANGUAGE");
var previousLcAll = Environment.GetEnvironmentVariable("LC_ALL");
Environment.SetEnvironmentVariable("LANGUAGE", "de");
Environment.SetEnvironmentVariable("LC_ALL", "de_DE.UTF-8");
try
{
await _git.CommitAsync(dir, "feat(test): identity fallback under non-English locale");
var author = GitRepoFixture.RunGit(dir, "log", "-1", "--format=%an <%ae>").Trim();
Assert.Equal("ClaudeDo <claudedo@local>", author);
}
finally
{
Environment.SetEnvironmentVariable("LANGUAGE", previousLanguage);
Environment.SetEnvironmentVariable("LC_ALL", previousLcAll);
}
}
public void Dispose() public void Dispose()
{ {
foreach (var dir in _tempDirs) foreach (var dir in _tempDirs)