Skip to content

Commit

Permalink
Windows: Remove read-only attribute for directory before deleting
Browse files Browse the repository at this point in the history
If some directory is set to read-only on Windows, DeletePath will fail
to delete that directory even when no one else is using it.

Previously, we only remove the read-only attribute for files before
deleting, we should also do the same for deleting directory.

Fixes bazelbuild/continuous-integration#1012

Closes #11982.

PiperOrigin-RevId: 327774854
  • Loading branch information
meteorcloudy authored and copybara-github committed Aug 21, 2020
1 parent d683688 commit faecd05
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 8 deletions.
17 changes: 9 additions & 8 deletions src/main/native/windows/file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,15 @@ int DeletePath(const wstring& path, wstring* error) {
GetLastError(), error);
}

if (attr & FILE_ATTRIBUTE_READONLY) {
// Remove the read-only attribute.
attr &= ~FILE_ATTRIBUTE_READONLY;
if (!SetFileAttributesW(wpath, attr)) {
return GetResultFromErrorCode(L"SetFileAttributesW", path, GetLastError(),
error);
}
}

if (attr & FILE_ATTRIBUTE_DIRECTORY) {
// It's a directory or a junction, RemoveDirectoryW should be used.
//
Expand Down Expand Up @@ -700,14 +709,6 @@ int DeletePath(const wstring& path, wstring* error) {
}
} else {
// It's a regular file or symlink, DeleteFileW should be used.
if (attr & FILE_ATTRIBUTE_READONLY) {
// Remove the read-only attribute.
attr &= ~FILE_ATTRIBUTE_READONLY;
if (!SetFileAttributesW(wpath, attr)) {
return GetResultFromErrorCode(L"SetFileAttributesW", path,
GetLastError(), error);
}
}
if (!DeleteFileW(wpath)) {
// Failed to delete the file or symlink.
return GetResultFromErrorCode(L"DeleteFileW", path,
Expand Down
22 changes: 22 additions & 0 deletions src/test/py/bazel/bazel_windows_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,28 @@ def testBuildNonCcRuleWithoutVCInstalled(self):
)
self.AssertExitCode(exit_code, 0, stderr)

def testDeleteReadOnlyFileAndDirectory(self):
self.CreateWorkspaceWithDefaultRepos('WORKSPACE')
self.ScratchFile('BUILD', [
'genrule(',
' name = "gen_read_only_dir",',
' cmd_bat = "mkdir $@ && attrib +r $@",',
' outs = ["dir_foo"],',
')',
'',
'genrule(',
' name = "gen_read_only_file",',
' cmd_bat = "echo hello > $@ && attrib +r $@",',
' outs = ["file_foo"],',
')',
])

exit_code, _, stderr = self.RunBazel(['build', '//...'])
self.AssertExitCode(exit_code, 0, stderr)

exit_code, _, stderr = self.RunBazel(['clean'])
self.AssertExitCode(exit_code, 0, stderr)


if __name__ == '__main__':
unittest.main()

0 comments on commit faecd05

Please sign in to comment.