Merge pull request #2025 from mischajonker/mjonker_828

Fix ninja -t clean for directories on Windows
This commit is contained in:
Jan Niklas Hasse
2021-09-16 14:53:34 +02:00
committed by GitHub
2 changed files with 32 additions and 7 deletions

View File

@@ -279,14 +279,31 @@ int RealDiskInterface::RemoveFile(const string& path) {
// Skip error checking. If this fails, accept whatever happens below.
SetFileAttributes(path.c_str(), attributes & ~FILE_ATTRIBUTE_READONLY);
}
if (!DeleteFile(path.c_str())) {
DWORD win_err = GetLastError();
if (win_err == ERROR_FILE_NOT_FOUND || win_err == ERROR_PATH_NOT_FOUND) {
return 1;
if (attributes & FILE_ATTRIBUTE_DIRECTORY) {
// remove() deletes both files and directories. On Windows we have to
// select the correct function (DeleteFile will yield Permission Denied when
// used on a directory)
// This fixes the behavior of ninja -t clean in some cases
// https://github.com/ninja-build/ninja/issues/828
if (!RemoveDirectory(path.c_str())) {
DWORD win_err = GetLastError();
if (win_err == ERROR_FILE_NOT_FOUND || win_err == ERROR_PATH_NOT_FOUND) {
return 1;
}
// Report remove(), not RemoveDirectory(), for cross-platform consistency.
Error("remove(%s): %s", path.c_str(), GetLastErrorString().c_str());
return -1;
}
} else {
if (!DeleteFile(path.c_str())) {
DWORD win_err = GetLastError();
if (win_err == ERROR_FILE_NOT_FOUND || win_err == ERROR_PATH_NOT_FOUND) {
return 1;
}
// Report as remove(), not DeleteFile(), for cross-platform consistency.
Error("remove(%s): %s", path.c_str(), GetLastErrorString().c_str());
return -1;
}
// Report as remove(), not DeleteFile(), for cross-platform consistency.
Error("remove(%s): %s", path.c_str(), GetLastErrorString().c_str());
return -1;
}
#else
if (remove(path.c_str()) < 0) {

View File

@@ -219,6 +219,14 @@ TEST_F(DiskInterfaceTest, RemoveFile) {
#endif
}
TEST_F(DiskInterfaceTest, RemoveDirectory) {
const char* kDirectoryName = "directory-to-remove";
EXPECT_TRUE(disk_.MakeDir(kDirectoryName));
EXPECT_EQ(0, disk_.RemoveFile(kDirectoryName));
EXPECT_EQ(1, disk_.RemoveFile(kDirectoryName));
EXPECT_EQ(1, disk_.RemoveFile("does not exist"));
}
struct StatTest : public StateTestWithBuiltinRules,
public DiskInterface {
StatTest() : scan_(&state_, NULL, NULL, this, NULL) {}