Skip to content

Fix ProjectImports.zip regression from shared FileUtilities statics#13382

Merged
JanProvaznik merged 3 commits intodotnet:mainfrom
JanProvaznik:fix/project-imports-zip-regression
Mar 16, 2026
Merged

Fix ProjectImports.zip regression from shared FileUtilities statics#13382
JanProvaznik merged 3 commits intodotnet:mainfrom
JanProvaznik:fix/project-imports-zip-regression

Conversation

@JanProvaznik
Copy link
Member

Summary

Fixes the ProjectImports.zip regression introduced by #13364.

Problem

After #13364, all 9 VMR scenario tests fail across all platforms with:

Unhandled exception: Could not find a part of the path
  '.../MSBuildTemp.../MSBuild<PID>-1/run-dotnet-run.ProjectImports.zip'

Reported in: dotnet/dotnet#5433 (comment)

Root Cause

#13364 moved FileUtilities from src/Shared/ (compiled into each assembly with independent statics) to src/Framework/ (single shared assembly). Before, ClearCacheDirectory() in XMake.cs used MSBuild.exe's own cacheDirectory static — a different directory than the one ProjectImportsCollector used. After, they share the same static, so ClearCacheDirectory() destroys the ProjectImports.zip archive.

Fix

  • Store the temporary ProjectImports archive in TempFileDirectory (parent, not wiped) instead of GetCacheDirectory() (child, wiped by ClearCacheDirectory()).
  • Make DeleteArchive() resilient to IO errors.
  • Added regression test.

Open Question

Before #13364, ClearCacheDirectory() at XMake.cs:1735 was a no-op for the real build cache. Now it actually cleans result cache files. This is new behavior that may need its own investigation.

JanProvaznik and others added 2 commits March 13, 2026 15:37
After FileUtilities moved from Shared to Framework (dotnet#13364), all assemblies
share the same cacheDirectory static. ClearCacheDirectory() in XMake.cs now
deletes the same directory that ProjectImportsCollector uses for its temporary
archive, causing 'Could not find a part of the path' errors during binlog
finalization.

Fix: Store the temporary ProjectImports archive in TempFileDirectory (the
parent) rather than GetCacheDirectory() (the child that gets wiped). Also
make DeleteArchive resilient to the archive already being cleaned up.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The previous test simulated ProjectImportsCollector + ClearCacheDirectory
in isolation. Replace with a real build through MSBuild CLI (ExecMSBuild
with -bl:), which exercises the full XMake.Execute → EndBuild →
ClearCacheDirectory code path. Verify the binlog still contains
embedded project imports by replaying with ArchiveFileEncountered.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@JanProvaznik JanProvaznik force-pushed the fix/project-imports-zip-regression branch from 4e0c79d to 1d02dca Compare March 13, 2026 15:35
@JanProvaznik JanProvaznik marked this pull request as ready for review March 13, 2026 15:44
Copilot AI review requested due to automatic review settings March 13, 2026 15:44
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a regression where ClearCacheDirectory() could delete the temporary *.ProjectImports.zip archive before the binary logger embeds it, due to FileUtilities statics becoming shared after #13364.

Changes:

  • Store temporary ProjectImports archives under FileUtilities.TempFileDirectory instead of FileUtilities.GetCacheDirectory(), avoiding deletion during shutdown cache cleanup.
  • Make ProjectImportsCollector.DeleteArchive() best-effort by swallowing IO-related exceptions.
  • Add a regression unit test ensuring ClearCacheDirectory() does not break reading/embedding the imports archive.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/Build/Logging/BinaryLogger/ProjectImportsCollector.cs Moves temp archive location out of the cache directory and makes archive deletion resilient to IO failures.
src/Build.UnitTests/BinaryLogger_Tests.cs Adds regression coverage to ensure ProjectImports archives survive ClearCacheDirectory().

You can also share your feedback on Copilot code review. Take the survey.

Copy link
Member

@DustinCampbell DustinCampbell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me!

FWIW, this issue was pretty subtle and is a good example of why it's important to avoid static state in files compiled across binaries. For the future, it'd be good to audit the cache/temp path lifetimes.

(Note: Please wait for more legitimate MSBuild reviewers before taking my ✅.)

Co-authored-by: Dustin Campbell <dustin@teamcampbell.org>
@JanProvaznik JanProvaznik enabled auto-merge (squash) March 16, 2026 09:17
@JanProvaznik JanProvaznik merged commit 1cbd743 into dotnet:main Mar 16, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants