Delete read-only files on Windows, too

Fixes main complaint of #1886.
This commit is contained in:
Jan Niklas Hasse 2020-12-07 19:46:10 +01:00
parent 58f77f972b
commit 2d7f7e55c0
2 changed files with 25 additions and 2 deletions

View File

@ -265,6 +265,23 @@ FileReader::Status RealDiskInterface::ReadFile(const string& path,
}
int RealDiskInterface::RemoveFile(const string& path) {
#ifdef _WIN32
DWORD attributes = GetFileAttributes(path.c_str());
if (attributes == INVALID_FILE_ATTRIBUTES &&
GetLastError() == ERROR_FILE_NOT_FOUND) {
return 1;
}
if (attributes & FILE_ATTRIBUTE_READONLY) {
// On non-Windows systems remove will happily delete read-only files. On
// Windows Ninja should behave the same. See
// https://github.com/ninja-build/ninja/issues/1886
SetFileAttributes(path.c_str(), attributes & ~FILE_ATTRIBUTE_READONLY);
}
if (!DeleteFile(path.c_str())) {
Error("remove(%s): %s", path.c_str(), GetLastErrorString().c_str());
return -1;
}
#else
if (remove(path.c_str()) < 0) {
switch (errno) {
case ENOENT:
@ -273,9 +290,9 @@ int RealDiskInterface::RemoveFile(const string& path) {
Error("remove(%s): %s", path.c_str(), strerror(errno));
return -1;
}
} else {
return 0;
}
#endif
return 0;
}
void RealDiskInterface::AllowStatCache(bool allow) {

View File

@ -211,6 +211,12 @@ TEST_F(DiskInterfaceTest, RemoveFile) {
EXPECT_EQ(0, disk_.RemoveFile(kFileName));
EXPECT_EQ(1, disk_.RemoveFile(kFileName));
EXPECT_EQ(1, disk_.RemoveFile("does not exist"));
#ifdef _WIN32
ASSERT_TRUE(Touch(kFileName));
EXPECT_EQ(0, system((std::string("attrib +R ") + kFileName).c_str()));
EXPECT_EQ(0, disk_.RemoveFile(kFileName));
EXPECT_EQ(1, disk_.RemoveFile(kFileName));
#endif
}
struct StatTest : public StateTestWithBuiltinRules,