Skip to content

Fix Windows response file temp ownership#55

Merged
zackees merged 1 commit intomainfrom
fix/issue-45-response-file-temp-dir
Apr 17, 2026
Merged

Fix Windows response file temp ownership#55
zackees merged 1 commit intomainfrom
fix/issue-45-response-file-temp-dir

Conversation

@zackees
Copy link
Copy Markdown
Member

@zackees zackees commented Apr 17, 2026

Summary

  • move Windows response-file fallback paths under ~/.fbuild/{dev|prod}/tmp/response-files
  • add best-effort cleanup for stale fbuild_*.rsp files before writing new response files
  • cover the owned-path and cleanup behavior with focused unit tests

Fixes #45.

Verification

  • cargo test -p fbuild-core
  • cargo test -p fbuild-build --lib compiler::tests
  • cargo fmt --check

Summary by CodeRabbit

Release Notes

  • Improvements
    • Response files are now stored in a dedicated application directory
    • Automatic cleanup removes response files older than 7 days, reducing disk usage

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 17, 2026

📝 Walkthrough

Walkthrough

The windows_temp_dir() function was modified to return a path under ~/.fbuild/{dev|prod}/tmp/response-files instead of using LOCALAPPDATA/Temp. New helper functions compute the app-owned response-files directory. A stale response file cleanup mechanism was added to automatically delete fbuild_*.rsp files older than 7 days before writing new response files.

Changes

Cohort / File(s) Summary
Response File Storage and Cleanup
crates/fbuild-core/src/response_file.rs
Modified windows_temp_dir() to use app-owned directory under ~/.fbuild/{dev|prod}/tmp/response-files. Added helper functions to derive response-files root path from environment variables and fixed directory layout. Introduced cleanup_stale_response_files() to scan and delete fbuild_*.rsp files older than 7 days. Added constants for response-file naming and staleness threshold (7 days). Expanded test coverage for path computation and stale file deletion logic.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A fluffy solution hops into view,
No more response files scattered through!
Seven days old? Time to go—
Cleanup sweeps make .fbuild glow. ✨🗑️

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Fix Windows response file temp ownership' directly describes the main change: moving Windows response files from global temp to app-owned directory.
Linked Issues check ✅ Passed The PR fully addresses all coding requirements from issue #45: moves response files to app-owned ~/.fbuild/{dev|prod}/tmp/response-files, adds stale-file cleanup, and includes test coverage.
Out of Scope Changes check ✅ Passed All changes in response_file.rs are directly scoped to the response-file temp directory management and stale-file cleanup objectives from issue #45.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/issue-45-response-file-temp-dir

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
crates/fbuild-core/src/response_file.rs (2)

127-135: Run stale cleanup once per process, not on every write.

write_response_file is invoked for every compile/link command. On large builds (hundreds to thousands of TUs) this re-scans temp_dir and re-stats every entry on each call, plus causes redundant filesystem churn. Since the staleness window is 7 days, running this a single time per process is sufficient and avoids O(N·M) behavior.

♻️ Gate with a std::sync::Once (or OnceLock) per directory
-use std::time::{Duration, SystemTime};
+use std::sync::Once;
+use std::time::{Duration, SystemTime};
@@
-    let _ = cleanup_stale_response_files(temp_dir, RESPONSE_FILE_STALE_AFTER, SystemTime::now());
+    static CLEANUP_ONCE: Once = Once::new();
+    CLEANUP_ONCE.call_once(|| {
+        let _ = cleanup_stale_response_files(
+            temp_dir,
+            RESPONSE_FILE_STALE_AFTER,
+            SystemTime::now(),
+        );
+    });

If multiple distinct temp_dir values are expected per process, swap Once for a Mutex<HashSet<PathBuf>> guard keyed on the directory.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/fbuild-core/src/response_file.rs` around lines 127 - 135, The
stale-file cleanup is currently run on every call to write_response_file
(calling cleanup_stale_response_files(temp_dir, RESPONSE_FILE_STALE_AFTER,
SystemTime::now())), causing expensive repeated scans; change this so cleanup
runs once per process (or once per distinct temp_dir) by gating the call with a
one-time guard (e.g. a static std::sync::Once or a
OnceLock/Mutex<HashSet<PathBuf>> keyed by temp_dir) and only invoke
cleanup_stale_response_files when the guard for that directory has not yet run;
leave write_response_file, RESPONSE_FILE_STALE_AFTER, and the
cleanup_stale_response_files function intact, only add the one-time registration
check around the cleanup invocation.

11-13: Use the new constants when constructing the response-file path.

RESPONSE_FILE_PREFIX and RESPONSE_FILE_SUFFIX were introduced so the cleanup scanner and the writer agree on the naming scheme, but line 171 still hardcodes "fbuild_" and ".rsp". A future rename would silently break cleanup.

♻️ Proposed fix
-    let path = temp_dir.join(format!("fbuild_{}_{}.rsp", prefix, hash));
+    let path = temp_dir.join(format!(
+        "{}{}_{}{}",
+        RESPONSE_FILE_PREFIX, prefix, hash, RESPONSE_FILE_SUFFIX
+    ));

Also applies to: 161-171

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/fbuild-core/src/response_file.rs` around lines 11 - 13, Replace the
hardcoded "fbuild_" and ".rsp" string literals used when constructing
response-file paths with the new constants RESPONSE_FILE_PREFIX and
RESPONSE_FILE_SUFFIX so the writer and cleanup scanner stay in sync; find the
code that builds the response-file name (the block around where the path is
constructed—previously using "fbuild_" and ".rsp", referenced in the diff around
lines 161–171) and change it to compose the filename using RESPONSE_FILE_PREFIX
and RESPONSE_FILE_SUFFIX (e.g., prefix + base + suffix) so any future rename
only requires updating the constants.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@crates/fbuild-core/src/response_file.rs`:
- Around line 40-45: The home_dir() function currently falls back to
std::env::temp_dir() which on Windows is the unwanted %LOCALAPPDATA%\Temp;
instead modify home_dir() to avoid returning the raw temp dir by nesting the
fallback under a deterministic fbuild-owned subdirectory (e.g.
std::env::temp_dir().join("fbuild") or ".fbuild") so cleanup/ownership can be
applied; update the implementation in the home_dir function (and any docs/tests)
to return that nested PathBuf rather than the raw temp_dir(), preserving the
current signature to avoid wider API changes.

---

Nitpick comments:
In `@crates/fbuild-core/src/response_file.rs`:
- Around line 127-135: The stale-file cleanup is currently run on every call to
write_response_file (calling cleanup_stale_response_files(temp_dir,
RESPONSE_FILE_STALE_AFTER, SystemTime::now())), causing expensive repeated
scans; change this so cleanup runs once per process (or once per distinct
temp_dir) by gating the call with a one-time guard (e.g. a static
std::sync::Once or a OnceLock/Mutex<HashSet<PathBuf>> keyed by temp_dir) and
only invoke cleanup_stale_response_files when the guard for that directory has
not yet run; leave write_response_file, RESPONSE_FILE_STALE_AFTER, and the
cleanup_stale_response_files function intact, only add the one-time registration
check around the cleanup invocation.
- Around line 11-13: Replace the hardcoded "fbuild_" and ".rsp" string literals
used when constructing response-file paths with the new constants
RESPONSE_FILE_PREFIX and RESPONSE_FILE_SUFFIX so the writer and cleanup scanner
stay in sync; find the code that builds the response-file name (the block around
where the path is constructed—previously using "fbuild_" and ".rsp", referenced
in the diff around lines 161–171) and change it to compose the filename using
RESPONSE_FILE_PREFIX and RESPONSE_FILE_SUFFIX (e.g., prefix + base + suffix) so
any future rename only requires updating the constants.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 786478b3-4705-41e7-a765-3621efb2ff54

📥 Commits

Reviewing files that changed from the base of the PR and between fbf39f3 and c911a49.

📒 Files selected for processing (1)
  • crates/fbuild-core/src/response_file.rs

Comment on lines +40 to +45
fn home_dir() -> PathBuf {
std::env::var("HOME")
.or_else(|_| std::env::var("USERPROFILE"))
.map(PathBuf::from)
.unwrap_or_else(|_| std::env::temp_dir())
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

home_dir() silently falls back to the old broken location.

When neither HOME nor USERPROFILE is set, this returns std::env::temp_dir(), which on Windows is exactly %LOCALAPPDATA%\Temp — the location issue #45 is trying to move away from. In practice Windows always sets USERPROFILE, so this is a minor/edge concern, but the fallback defeats the fix if it ever triggers. Consider either erroring out or at least nesting under a deterministic fbuild-owned subdirectory so cleanup still applies.

🛡️ Suggested change
 fn home_dir() -> PathBuf {
     std::env::var("HOME")
         .or_else(|_| std::env::var("USERPROFILE"))
         .map(PathBuf::from)
-        .unwrap_or_else(|_| std::env::temp_dir())
+        .unwrap_or_else(|_| std::env::temp_dir().join("fbuild-home"))
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/fbuild-core/src/response_file.rs` around lines 40 - 45, The home_dir()
function currently falls back to std::env::temp_dir() which on Windows is the
unwanted %LOCALAPPDATA%\Temp; instead modify home_dir() to avoid returning the
raw temp dir by nesting the fallback under a deterministic fbuild-owned
subdirectory (e.g. std::env::temp_dir().join("fbuild") or ".fbuild") so
cleanup/ownership can be applied; update the implementation in the home_dir
function (and any docs/tests) to return that nested PathBuf rather than the raw
temp_dir(), preserving the current signature to avoid wider API changes.

@zackees zackees merged commit e012748 into main Apr 17, 2026
76 checks passed
@zackees zackees deleted the fix/issue-45-response-file-temp-dir branch April 17, 2026 06:09
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.

Windows: response files accumulate in %LOCALAPPDATA%\Temp instead of a .fbuild-managed temp dir

1 participant