Skip to content

Detect stale runfiles on Windows when symlinks fall back to copies#29566

Open
olbapmar wants to merge 1 commit into
bazelbuild:masterfrom
olbapmar:windows-stale-runfiles
Open

Detect stale runfiles on Windows when symlinks fall back to copies#29566
olbapmar wants to merge 1 commit into
bazelbuild:masterfrom
olbapmar:windows-stale-runfiles

Conversation

@olbapmar
Copy link
Copy Markdown

@olbapmar olbapmar commented May 18, 2026

Description

Add --experimental_detect_stale_runfiles flag (default off). When enabled, RunfilesTreeUpdater probes the on-disk type of the first non-empty manifest entry before short-circuiting: if it's a real symlink the optimization applies; if it's a regular file (the Files.copy fallback on Windows without symlink privileges), the tree is re-synced.

Also hardens WindowsFileSystem.createSymbolicLink's copy fallback with REPLACE_EXISTING and COPY_ATTRIBUTES.

This also fixes a test that has been skipped for windows until now.

Motivation

On Windows without symlink privileges, WindowsFileSystem.createSymbolicLink silently falls back to Files.copy. The runfiles short-circuit in RunfilesTreeUpdater compares manifest digests to decide the tree is up to date, which is safe for real symlinks (which auto-follow source content), but not for copies, where byte-equal manifests say nothing about content freshness. The result is runfiles getting stale on every incremental build until bazel clean.

Build API Changes

New experimental flag: --experimental_detect_stale_runfiles (boolean, default false). No breaking changes, as the behavior is identical to current master when the flag is off.

Checklist

  • I have added tests for the new use cases (if any).
  • I have updated the documentation (if applicable).

Release Notes

RELNOTES[NEW]: New --experimental_detect_stale_runfiles flag detects stale
runfiles on Windows when symlink privileges are unavailable and the runfiles
tree is materialized as copies rather than symlinks.

On Windows without symlink privileges, `WindowsFileSystem.createSymbolicLink`
silently falls back to `Files.copy`. The runfiles short-circuit in
`RunfilesTreeUpdater` compares input/output manifest digests to decide the tree
is up to date — this is sound for real symlinks (which auto-follow source
content) but not for copies, where byte-equal manifests say nothing about
content freshness. The result is silently stale runfiles until `bazel clean`.

This adds `--experimental_detect_stale_runfiles` (default off). When enabled,
the short-circuit probes the on-disk type of the first non-empty manifest entry:
if it's a real symlink, the optimization applies; if it's a regular file (the
copy fallback), the tree is re-synced.

Also hardens the `Files.copy` fallback with `REPLACE_EXISTING` and
`COPY_ATTRIBUTES`.

- New flag: `--experimental_detect_stale_runfiles`
- New method: `RunfilesTreeUpdater.runfilesUseRealSymlinks`
- Unit tests for the new helper
- Unskips `test_runfiles_updated_correctly_with_nobuild_runfile_links` on Windows
@olbapmar olbapmar marked this pull request as ready for review May 18, 2026 14:40
@github-actions github-actions Bot added area-Windows Windows-specific issues and feature requests awaiting-review PR is awaiting review from an assigned reviewer labels May 18, 2026
@olbapmar
Copy link
Copy Markdown
Author

The failed test looks like a flake unrelated to my changes. Please correct me if I'm wrong and I'll double check.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-Windows Windows-specific issues and feature requests awaiting-review PR is awaiting review from an assigned reviewer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant