fix: hint users to enable Developer Mode on Windows symlink extraction failure#2454
fix: hint users to enable Developer Mode on Windows symlink extraction failure#2454pb01ka wants to merge 12 commits into
Conversation
…raction failure When extracting a tar archive on Windows fails (e.g. due to symlinks requiring elevated privileges), check whether Developer Mode is enabled via the registry. If it is not, append an actionable hint pointing the user to Settings > System > For developers > Developer Mode.
|
|
||
| /// Wraps a tar unpack error, appending a Windows Developer Mode hint when on Windows and | ||
| /// Developer Mode is detected as disabled. | ||
| fn tar_unpack_error(context: &str, e: std::io::Error) -> CacheError { |
There was a problem hiding this comment.
I assume this is also a specific io error that we are looking for? Permission denied or something?
There was a problem hiding this comment.
Not reliably. The error code when symlink creation fails on Windows with Developer Mode disabled is not consistent. ERROR_PRIVILEGE_NOT_HELD (1314) is the most common (as per my observation), but it can't reliably help in identifying a "symlink failed" error from the error alone, we instead gate the hint on the Developer Mode registry check: if Developer Mode is off and tar extraction fails for any reason, we surface the hint. The hint copy uses "may contain symbolic links" to reflect this uncertainty.
|
Having a clear error is nice, but maybe even just continuing would be even nicer. In rattler/pixi we try to unpack symlinks, and if they fail, we simply ignore them and issue a warning. I think that behavior would also be fine here. If it's a problem that they are missing, you will find out soon enough during the build itself. Another option that we could pursue instead is to create a symlink, and if that fails, we simply materialize/create a copy of the file. |
|
@baszalmstra I think both alternatives are better UX than a hard failure.
It is simpler to implement - the
This approach is more robust - if the symlink target exists in the archive, we can materialise it as a regular file. The extracted tree is functionally complete even without actual symlinks. I'd lean towards the copy fallback since it's transparent to the build, but it does require iterating tar entries manually and tracking regular files as they're extracted so we can copy them when a symlink to them is encountered. Happy to implement whichever approach you prefer. |
Problem
Refer - #940 (comment)
When rattler-build tries to extract a source archive (e.g. a
.tar.gz) that contains symbolic links on Windows without Developer Mode enabled, the extraction fails with an error such as (with no hint or actionable information):Solution
This PR detects the failure scenario and surfaces an actionable hint:
Registry check - a new
is_windows_developer_mode_enabled()function checks whether Developer Mode is enabled by reading the registry keyHKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock→AllowDevelopmentWithoutDevLicenseusing thewinregcrate. This is safe Rust with nounsafeblocks.Improved error message - a new
tar_unpack_error()helper wraps every tar.unpack()failure. On Windows, when Developer Mode is detected as disabled, the error is extended with a clear hint:Test coverage - a Windows-only unit test (
test_symlink_extraction_error_message) builds a minimal.tar.gzcontaining a symlink entry and asserts that:"Developer Mode".Notes
tar_unpack_errorcompiles to a simpleCacheError::ExtractionErrorwrapper on non-Windows targets.winregcrate is added as a new Windows-only dependency; it provides safe, idiomatic Rust access to the Windows registry with nounsafecode.This is my first contribution to rattler-build. I've done my best to follow the project's conventions, but I'm very much looking forward to feedback and suggestions for improvement - please feel free to point out anything that could be done better!