Repository navigation
Use a real rename for File.Move(overwrite) polyfill - #664
Merged
Merged
Conversation
This was referenced Oct 12, 2026
This was referenced Oct 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bug
Below netcoreapp3.0 the
File.Move(sourceFileName, destFileName, overwrite: true)polyfill wasFile.Copyfollowed byFile.Delete:UnauthorizedAccessException, leaving both files behind.name.txttoNAME.txt) failed with a sharing violation, because the copy opened the same file twice.FileNotFoundException.Fix
Do a real rename that replaces the destination, as the BCL does:
MoveFileExwithMOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED. Paths of 260 characters or more get the\\?\prefix.rename(2), falling back to copy and delete only forEXDEV(a move across file systems).Exceptions follow the BCL, which I checked against net10 on Windows: null or empty arguments,
FileNotFoundExceptionfor a missing source (checked first, so it also applies when both paths are the same),DirectoryNotFoundExceptionfor a missing destination directory,UnauthorizedAccessExceptionfor access denied (for example a read-only destination),IOExceptionotherwise.The Unix path was not executed: I only had Windows available, and the repo's tests run on Windows CI.
Tests
New
Move_Overwrite_*tests inFilePolyfillTests, each in its own temp directory: read-only source, case-only rename, same missing path, same existing path, missing source keeps the destination, missing destination directory keeps the source, and read-only destination keeps both (Windows only).ReadOnlySource,CaseOnlyRenameandSameMissingPathfail on net48 without the fix. All pass on net48 (Tests and NoRefsTests) and on net10.0 (BCL), and the wholeFilePolyfillTestsclass passes on net48.