Skip to content
Merged
Show file tree
Hide file tree
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
3 changes: 2 additions & 1 deletion samples/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
<IsPackable>false</IsPackable>

<!-- Suppress documentation and API visibility warnings for sample projects -->
<NoWarn>$(NoWarn);CA2007;CS1591;CA1515;CA1816;CA1062</NoWarn>
<!-- CA5394: Random is acceptable for non-security flaky-test simulation in samples -->
<NoWarn>$(NoWarn);CA2007;CS1591;CA1515;CA1816;CA1062;CA5394</NoWarn>

<!-- Allow some relaxed rules for samples -->
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -732,10 +732,38 @@ private static void CollectLocalGitMetadata(Dictionary<string, string> propertie
}

private static string? ReadGitConfigUserName(string gitDir)
{
// Check local repo config first, then fall back to global git config (~/.gitconfig or
// XDG_CONFIG_HOME/git/config), which is where most users set their name.
string localConfig = Path.Combine(gitDir, "config");
string? result = ReadUserNameFromFile(localConfig);
if (result is not null)
return result;

// Global config: $HOME/.gitconfig
string? home = System.Environment.GetEnvironmentVariable("HOME")
?? System.Environment.GetFolderPath(System.Environment.SpecialFolder.UserProfile);
if (!string.IsNullOrEmpty(home))
{
result = ReadUserNameFromFile(Path.Combine(home, ".gitconfig"));
if (result is not null)
return result;

// XDG-compliant location: $XDG_CONFIG_HOME/git/config (defaults to ~/.config/git/config)
string xdgConfigHome = System.Environment.GetEnvironmentVariable("XDG_CONFIG_HOME")
?? Path.Combine(home, ".config");
result = ReadUserNameFromFile(Path.Combine(xdgConfigHome, "git", "config"));
if (result is not null)
return result;
}

return null;
}

private static string? ReadUserNameFromFile(string configPath)
{
try
{
string configPath = Path.Combine(gitDir, "config");
if (!File.Exists(configPath))
return null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,39 @@ public async Task BuildEnvironmentInfoAsync_InsideGitRepositoryWithUserConfig_Se
Assert.Equal("Jane Doe", info.CustomProperties["Git.Actor"]);
}

[Fact]
public async Task BuildEnvironmentInfoAsync_NoLocalUserConfig_FallsBackToGlobalGitConfig()
{
using var clearedCiVariables = ClearEnvironmentVariables(_environmentVariables);
using var tempGit = new TempGitDirectory();
tempGit.WriteHead("ref: refs/heads/main");
tempGit.WriteRef("main", "0000000000000000000000000000000000000001");
// No local [user] in .git/config — only write an unrelated section
tempGit.WriteConfig("[core]\n\trepositoryformatversion = 0\n");
using var dirRestorer = new WorkingDirectoryRestorer(tempGit.WorkingDirectory);

// Create a temporary HOME directory that contains only a .gitconfig with the user name
string tempHome = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
Directory.CreateDirectory(tempHome);
string? originalHome = System.Environment.GetEnvironmentVariable("HOME");
try
{
await File.WriteAllTextAsync(Path.Combine(tempHome, ".gitconfig"),
"[user]\n\tname = Global Author\n\temail = global@example.com\n");
System.Environment.SetEnvironmentVariable("HOME", tempHome);

IEnvironmentDetector detector = CreateDetector(new XpingConfiguration { CollectLocalGitAuthor = true });
EnvironmentInfo info = await detector.BuildEnvironmentInfoAsync();

Assert.Equal("Global Author", info.CustomProperties["Git.Actor"]);
}
finally
{
System.Environment.SetEnvironmentVariable("HOME", originalHome);
try { Directory.Delete(tempHome, recursive: true); } catch { /* best effort */ }
}
}

[Fact]
public async Task BuildEnvironmentInfoAsync_WithUserConfigButAuthorCollectionDisabled_OmitsActor()
{
Expand Down
Loading