QFileSystemEngine: add rmpath()
removeDirectory() acts in two mode, rmdir (one entry) and rmpath (the entry and all empty parent directories). This is irregular behavior, and API with a very specific use-case (in unittests, where you create a dir tree and want to cleanup after the test finishes). So, split the code into rmdir() and rmpath(), which matches QDir::rmdir() and QDir::rmpath(). On Unix, a further optimization pointed out by Thiago in review, remove the stat() call, ::rmdir() will fail with ENOTDIR if we try to remove anything that isn't a dir. Change-Id: I1bbb6e6c1ce49ba6d73d3c510b449223498612fb Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
46737c0bc0
commit
ead72a1155
@ -1552,7 +1552,7 @@ bool QDir::rmdir(const QString &dirName) const
|
||||
|
||||
QString fn = filePath(dirName);
|
||||
if (!d->fileEngine)
|
||||
return QFileSystemEngine::removeDirectory(QFileSystemEntry(fn), false);
|
||||
return QFileSystemEngine::rmdir(QFileSystemEntry(fn));
|
||||
|
||||
return d->fileEngine->rmdir(fn, false);
|
||||
}
|
||||
@ -1606,7 +1606,7 @@ bool QDir::rmpath(const QString &dirPath) const
|
||||
|
||||
QString fn = filePath(dirPath);
|
||||
if (!d->fileEngine)
|
||||
return QFileSystemEngine::removeDirectory(QFileSystemEntry(fn), true);
|
||||
return QFileSystemEngine::rmpath(QFileSystemEntry(fn));
|
||||
return d->fileEngine->rmdir(fn, true);
|
||||
}
|
||||
|
||||
|
@ -117,7 +117,15 @@ public:
|
||||
|
||||
static bool createDirectory(const QFileSystemEntry &entry, bool createParents,
|
||||
std::optional<QFile::Permissions> permissions = std::nullopt);
|
||||
static bool removeDirectory(const QFileSystemEntry &entry, bool removeEmptyParents);
|
||||
static bool removeDirectory(const QFileSystemEntry &entry, bool removeEmptyParents)
|
||||
{
|
||||
if (removeEmptyParents)
|
||||
return rmpath(entry);
|
||||
return rmdir(entry);
|
||||
}
|
||||
|
||||
static bool rmdir(const QFileSystemEntry &entry);
|
||||
static bool rmpath(const QFileSystemEntry &entry);
|
||||
|
||||
static bool createLink(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error);
|
||||
|
||||
|
@ -1189,30 +1189,28 @@ bool QFileSystemEngine::createDirectory(const QFileSystemEntry &entry, bool crea
|
||||
return createDirectoryWithParents(dirName, mode, false);
|
||||
}
|
||||
|
||||
//static
|
||||
bool QFileSystemEngine::removeDirectory(const QFileSystemEntry &entry, bool removeEmptyParents)
|
||||
bool QFileSystemEngine::rmdir(const QFileSystemEntry &entry)
|
||||
{
|
||||
Q_CHECK_FILE_NAME(entry, false);
|
||||
const QByteArray path = entry.nativeFilePath();
|
||||
Q_CHECK_FILE_NAME(path, false);
|
||||
return ::rmdir(path.constData()) == 0;
|
||||
}
|
||||
|
||||
if (removeEmptyParents) {
|
||||
QString dirName = QDir::cleanPath(entry.filePath());
|
||||
for (qsizetype oldslash = 0, slash=dirName.size(); slash > 0; oldslash = slash) {
|
||||
const QByteArray chunk = QFile::encodeName(dirName.left(slash));
|
||||
QT_STATBUF st;
|
||||
if (QT_STAT(chunk.constData(), &st) != -1) {
|
||||
if ((st.st_mode & S_IFMT) != S_IFDIR)
|
||||
return false;
|
||||
bool QFileSystemEngine::rmpath(const QFileSystemEntry &entry)
|
||||
{
|
||||
const QString path = QDir::cleanPath(entry.filePath());
|
||||
Q_CHECK_FILE_NAME(path, false);
|
||||
|
||||
for (qsizetype oldslash = 0, slash = path.size(); slash > 0; oldslash = slash) {
|
||||
const QByteArray chunk = QFile::encodeName(path.left(slash));
|
||||
if (::rmdir(chunk.constData()) != 0)
|
||||
return oldslash != 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
slash = dirName.lastIndexOf(QDir::separator(), oldslash-1);
|
||||
|
||||
slash = path.lastIndexOf(QDir::separator(), oldslash - 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return rmdir(QFile::encodeName(entry.filePath()).constData()) == 0;
|
||||
}
|
||||
|
||||
//static
|
||||
bool QFileSystemEngine::createLink(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
|
||||
|
@ -1554,31 +1554,36 @@ bool QFileSystemEngine::createDirectory(const QFileSystemEntry &entry, bool crea
|
||||
return createDirectoryWithParents(dirName, securityAttributes, false);
|
||||
}
|
||||
|
||||
//static
|
||||
bool QFileSystemEngine::removeDirectory(const QFileSystemEntry &entry, bool removeEmptyParents)
|
||||
bool QFileSystemEngine::rmdir(const QFileSystemEntry &entry)
|
||||
{
|
||||
QString dirName = entry.filePath();
|
||||
Q_CHECK_FILE_NAME(dirName, false);
|
||||
|
||||
if (removeEmptyParents) {
|
||||
dirName = QDir::toNativeSeparators(QDir::cleanPath(dirName));
|
||||
for (int oldslash = 0, slash=dirName.length(); slash > 0; oldslash = slash) {
|
||||
return rmDir(dirName);
|
||||
}
|
||||
|
||||
bool QFileSystemEngine::rmpath(const QFileSystemEntry &entry)
|
||||
{
|
||||
const QString dirName = QDir::toNativeSeparators(QDir::cleanPath(entry.filePath()));
|
||||
Q_CHECK_FILE_NAME(dirName, false);
|
||||
|
||||
for (int oldslash = 0, slash = dirName.size(); slash > 0; oldslash = slash) {
|
||||
const auto chunkRef = QStringView{dirName}.left(slash);
|
||||
if (chunkRef.length() == 2 && chunkRef.at(0).isLetter()
|
||||
&& chunkRef.at(1) == u':') {
|
||||
break;
|
||||
}
|
||||
const QString chunk = chunkRef.toString();
|
||||
// TODO: get isDirPath() and rmDir() to accept QStringView
|
||||
if (!isDirPath(chunk, nullptr))
|
||||
return false;
|
||||
if (!rmDir(chunk))
|
||||
return oldslash != 0;
|
||||
slash = dirName.lastIndexOf(QDir::separator(), oldslash - 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return rmDir(entry.filePath());
|
||||
}
|
||||
|
||||
//static
|
||||
QString QFileSystemEngine::rootPath()
|
||||
|
Loading…
x
Reference in New Issue
Block a user