diff --git a/src/Build.UnitTests/BinaryLogger_Tests.cs b/src/Build.UnitTests/BinaryLogger_Tests.cs index 098d237bd8e..3edb919e695 100644 --- a/src/Build.UnitTests/BinaryLogger_Tests.cs +++ b/src/Build.UnitTests/BinaryLogger_Tests.cs @@ -542,6 +542,39 @@ public void BinaryLoggerShouldNotThrowWhenMetadataCannotBeExpanded() ObjectModelHelpers.BuildProjectExpectSuccess(project, binaryLogger); } + /// + /// Regression test for dotnet/dotnet#5433 — ClearCacheDirectory must not destroy the + /// ProjectImports archive before it is embedded in the binlog. + /// + [Fact] + public void BinlogEmbeddedImportsSurviveClearCacheDirectory() + { + string logFilePath = Path.Combine(_env.DefaultTestDirectory.Path, "test.binlog"); + + var collector = new ProjectImportsCollector(logFilePath, createFile: false, runOnBackground: false); + collector.AddFileFromMemory("testfile.proj", ""); + + // This is what XMake.cs does after EndBuild — wipes the cache directory. + FileUtilities.ClearCacheDirectory(); + + // ProcessResult must still read the archive after the cache dir is gone. + bool archiveRead = false; + collector.ProcessResult( + stream => + { + stream.Length.ShouldBeGreaterThan(0); + archiveRead = true; + }, + error => throw new InvalidOperationException(error)); + archiveRead.ShouldBeTrue("Archive must be readable after ClearCacheDirectory"); + + // DeleteArchive must not throw (directory must still exist). + collector.DeleteArchive(); + + // Satisfy the fixture's expectation that _logFile exists. + File.WriteAllText(_logFile, string.Empty); + } + /// /// Regression test for https://github.com/dotnet/msbuild/issues/6323. /// diff --git a/src/Build/Logging/BinaryLogger/ProjectImportsCollector.cs b/src/Build/Logging/BinaryLogger/ProjectImportsCollector.cs index a537f8025f6..c42e54a26a8 100644 --- a/src/Build/Logging/BinaryLogger/ProjectImportsCollector.cs +++ b/src/Build/Logging/BinaryLogger/ProjectImportsCollector.cs @@ -63,15 +63,12 @@ public ProjectImportsCollector( } else { - string cacheDirectory = FileUtilities.GetCacheDirectory(); - if (!FileSystems.Default.DirectoryExists(cacheDirectory)) - { - Directory.CreateDirectory(cacheDirectory); - } + // Store the temporary archive in TempFileDirectory rather than GetCacheDirectory() + // because ClearCacheDirectory() wipes the cache dir during build shutdown. + string tempDirectory = FileUtilities.TempFileDirectory; - // Archive file will be temporarily stored in MSBuild cache folder and deleted when no longer needed _archiveFilePath = Path.Combine( - cacheDirectory, + tempDirectory, GetArchiveFilePath( Path.GetFileName(logFilePath), sourcesArchiveExtension)); @@ -304,7 +301,9 @@ public void Close() public void DeleteArchive() { Close(); - File.Delete(_archiveFilePath); + + // Best effort — the archive may already have been cleaned up. + FileUtilities.DeleteNoThrow(_archiveFilePath); } } }