Skip to content

Commit 94afadd

Browse files
Fix test failures when HOME is not a valid directory (issue #2227)
Co-authored-by: marekzmyslowski <1062877+marekzmyslowski@users.noreply.github.com>
1 parent 557ab47 commit 94afadd

File tree

2 files changed

+68
-42
lines changed

2 files changed

+68
-42
lines changed

src/shared/Core.Tests/GitConfigurationTests.cs

Lines changed: 37 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -324,63 +324,58 @@ public void GitConfiguration_Set_All_ThrowsException()
324324
public void GitConfiguration_Unset_Global_UnsetsGlobalConfig()
325325
{
326326
string repoPath = CreateRepository(out string workDirPath);
327-
try
328-
{
329-
ExecGit(repoPath, workDirPath, "config --global core.foobar alice").AssertSuccess();
330-
ExecGit(repoPath, workDirPath, "config --local core.foobar bob").AssertSuccess();
331327

332-
string gitPath = GetGitPath();
333-
var trace = new NullTrace();
334-
var trace2 = new NullTrace2();
335-
var processManager = new TestProcessManager();
336-
var git = new GitProcess(trace, trace2, processManager, gitPath, repoPath);
337-
IGitConfiguration config = git.GetConfiguration();
328+
// Use an isolated global config file so tests work even when HOME is not set
329+
// to a valid directory (e.g., in package build environments like AUR).
330+
using var _ = new GitTestUtilities.EnvVarScope(
331+
"GIT_CONFIG_GLOBAL", Path.Combine(workDirPath, ".gitconfig-global"));
338332

339-
config.Unset(GitConfigurationLevel.Global, "core.foobar");
333+
ExecGit(repoPath, workDirPath, "config --global core.foobar alice").AssertSuccess();
334+
ExecGit(repoPath, workDirPath, "config --local core.foobar bob").AssertSuccess();
340335

341-
GitResult globalResult = ExecGit(repoPath, workDirPath, "config --global core.foobar");
342-
GitResult localResult = ExecGit(repoPath, workDirPath, "config --local core.foobar");
336+
string gitPath = GetGitPath();
337+
var trace = new NullTrace();
338+
var trace2 = new NullTrace2();
339+
var processManager = new TestProcessManager();
340+
var git = new GitProcess(trace, trace2, processManager, gitPath, repoPath);
341+
IGitConfiguration config = git.GetConfiguration();
343342

344-
Assert.Equal(string.Empty, globalResult.StandardOutput.Trim());
345-
Assert.Equal("bob", localResult.StandardOutput.Trim());
346-
}
347-
finally
348-
{
349-
// Cleanup global config changes
350-
ExecGit(repoPath, workDirPath, "config --global --unset core.foobar");
351-
}
343+
config.Unset(GitConfigurationLevel.Global, "core.foobar");
344+
345+
GitResult globalResult = ExecGit(repoPath, workDirPath, "config --global core.foobar");
346+
GitResult localResult = ExecGit(repoPath, workDirPath, "config --local core.foobar");
347+
348+
Assert.Equal(string.Empty, globalResult.StandardOutput.Trim());
349+
Assert.Equal("bob", localResult.StandardOutput.Trim());
352350
}
353351

354352
[Fact]
355353
public void GitConfiguration_Unset_Local_UnsetsLocalConfig()
356354
{
357355
string repoPath = CreateRepository(out string workDirPath);
358356

359-
try
360-
{
361-
ExecGit(repoPath, workDirPath, "config --global core.foobar alice").AssertSuccess();
362-
ExecGit(repoPath, workDirPath, "config --local core.foobar bob").AssertSuccess();
357+
// Use an isolated global config file so tests work even when HOME is not set
358+
// to a valid directory (e.g., in package build environments like AUR).
359+
using var _ = new GitTestUtilities.EnvVarScope(
360+
"GIT_CONFIG_GLOBAL", Path.Combine(workDirPath, ".gitconfig-global"));
361+
362+
ExecGit(repoPath, workDirPath, "config --global core.foobar alice").AssertSuccess();
363+
ExecGit(repoPath, workDirPath, "config --local core.foobar bob").AssertSuccess();
363364

364-
string gitPath = GetGitPath();
365-
var trace = new NullTrace();
366-
var trace2 = new NullTrace2();
367-
var processManager = new TestProcessManager();
368-
var git = new GitProcess(trace, trace2, processManager, gitPath, repoPath);
369-
IGitConfiguration config = git.GetConfiguration();
365+
string gitPath = GetGitPath();
366+
var trace = new NullTrace();
367+
var trace2 = new NullTrace2();
368+
var processManager = new TestProcessManager();
369+
var git = new GitProcess(trace, trace2, processManager, gitPath, repoPath);
370+
IGitConfiguration config = git.GetConfiguration();
370371

371-
config.Unset(GitConfigurationLevel.Local, "core.foobar");
372+
config.Unset(GitConfigurationLevel.Local, "core.foobar");
372373

373-
GitResult globalResult = ExecGit(repoPath, workDirPath, "config --global core.foobar");
374-
GitResult localResult = ExecGit(repoPath, workDirPath, "config --local core.foobar");
374+
GitResult globalResult = ExecGit(repoPath, workDirPath, "config --global core.foobar");
375+
GitResult localResult = ExecGit(repoPath, workDirPath, "config --local core.foobar");
375376

376-
Assert.Equal("alice", globalResult.StandardOutput.Trim());
377-
Assert.Equal(string.Empty, localResult.StandardOutput.Trim());
378-
}
379-
finally
380-
{
381-
// Cleanup global config changes
382-
ExecGit(repoPath, workDirPath, "config --global --unset core.foobar");
383-
}
377+
Assert.Equal("alice", globalResult.StandardOutput.Trim());
378+
Assert.Equal(string.Empty, localResult.StandardOutput.Trim());
384379
}
385380

386381
[Fact]

src/shared/TestInfrastructure/GitTestUtilities.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ public static GitResult ExecGit(string repositoryPath, string workingDirectory,
8080

8181
procInfo.Environment["GIT_DIR"] = repositoryPath;
8282

83+
// Use an isolated global config file in the test's working directory to avoid
84+
// failures when HOME is not set to a valid directory (e.g., in package build
85+
// environments). This also prevents tests from polluting the user's real global config.
86+
procInfo.Environment["GIT_CONFIG_GLOBAL"] = Path.Combine(workingDirectory, ".gitconfig-global");
87+
8388
var proc = ChildProcess.Start(new NullTrace2(), procInfo, Trace2ProcessClass.None);
8489
if (proc is null)
8590
{
@@ -109,5 +114,31 @@ public void AssertSuccess()
109114
Assert.Equal(0, ExitCode);
110115
}
111116
}
117+
118+
/// <summary>
119+
/// Sets an environment variable for the scope of a using block, restoring the original value on dispose.
120+
/// </summary>
121+
/// <remarks>
122+
/// This class modifies the process-level environment, which is shared across all threads.
123+
/// To avoid interference, tests using this class should not run concurrently. Tests within
124+
/// the same xUnit test class are guaranteed to run serially by default.
125+
/// </remarks>
126+
public sealed class EnvVarScope : IDisposable
127+
{
128+
private readonly string _name;
129+
private readonly string _previousValue;
130+
131+
public EnvVarScope(string name, string value)
132+
{
133+
_name = name;
134+
_previousValue = Environment.GetEnvironmentVariable(name);
135+
Environment.SetEnvironmentVariable(name, value);
136+
}
137+
138+
public void Dispose()
139+
{
140+
Environment.SetEnvironmentVariable(_name, _previousValue);
141+
}
142+
}
112143
}
113144
}

0 commit comments

Comments
 (0)