Implement QDir::removeRecursively

Task-number: QTBUG-4592
Change-Id: I363e2c24d1c0ada975b8b927d7c6e776b8aae579
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@nokia.com>
This commit is contained in:
David Faure 2011-12-02 10:39:19 +01:00 committed by Qt by Nokia
parent 8c74fe5c7a
commit 1bb51cb8b1
3 changed files with 131 additions and 0 deletions

View File

@ -1470,6 +1470,52 @@ bool QDir::rmpath(const QString &dirPath) const
return d->fileEngine->rmdir(fn, true);
}
/*!
Removes the directory, including all its contents.
Returns true if successful, otherwise false.
If a file or directory cannot be removed, removeRecursively() keeps going
and attempts to delete as many files and sub-directories as possible,
then returns false.
If the directory was already removed, the method returns true
(expected result already reached).
Note: this function is meant for removing a small application-internal
directory (such as a temporary directory), but not user-visible
directories. For user-visible operations, it is rather recommended
to report errors more precisely to the user, to offer solutions
in case of errors, to show progress during the deletion since it
could take several minutes, etc.
*/
bool QDir::removeRecursively()
{
if (!d_ptr->exists())
return true;
bool success = true;
const QString dirPath = path();
// not empty -- we must empty it first
QDirIterator di(dirPath, QDir::AllEntries | QDir::Hidden | QDir::System | QDir::NoDotAndDotDot);
while (di.hasNext()) {
di.next();
const QFileInfo& fi = di.fileInfo();
bool ok;
if (fi.isDir())
ok = QDir(di.filePath()).removeRecursively(); // recursive
else
ok = QFile::remove(di.filePath());
if (!ok)
success = false;
}
if (success)
success = rmdir(absolutePath());
return success;
}
/*!
Returns true if the directory is readable \e and we can open files
by name; otherwise returns false.

View File

@ -166,6 +166,8 @@ public:
bool mkpath(const QString &dirPath) const;
bool rmpath(const QString &dirPath) const;
bool removeRecursively();
bool isReadable() const;
bool exists() const;
bool isRoot() const;

View File

@ -76,6 +76,7 @@ Q_OBJECT
private slots:
void init();
void cleanupTestCase();
void getSetCheck();
void construction();
@ -99,6 +100,10 @@ private slots:
void rmdir_data();
void rmdir();
void removeRecursively_data();
void removeRecursively();
void removeRecursivelyFailure();
void exists_data();
void exists();
@ -201,6 +206,11 @@ void tst_QDir::init()
QVERIFY2(QDir::setCurrent(m_dataPath), qPrintable("Could not chdir to " + m_dataPath));
}
void tst_QDir::cleanupTestCase()
{
QDir(QDir::currentPath() + "/tmpdir").removeRecursively();
}
// Testing get/set functions
void tst_QDir::getSetCheck()
{
@ -332,6 +342,79 @@ void tst_QDir::rmdir()
QVERIFY(!fi.exists());
}
void tst_QDir::removeRecursively_data()
{
QTest::addColumn<QString>("path");
// Create dirs and files
const QString tmpdir = QDir::currentPath() + "/tmpdir/";
QStringList dirs;
dirs << tmpdir + "empty"
<< tmpdir + "one"
<< tmpdir + "two/three"
<< "relative";
QDir dir;
for (int i = 0; i < dirs.count(); ++i)
dir.mkpath(dirs.at(i));
QStringList files;
files << tmpdir + "one/file";
files << tmpdir + "two/three/file";
for (int i = 0; i < files.count(); ++i) {
QFile file(files.at(i));
QVERIFY(file.open(QIODevice::WriteOnly));
file.write("Hello");
}
QTest::newRow("empty") << tmpdir + "empty";
QTest::newRow("one") << tmpdir + "one";
QTest::newRow("two") << tmpdir + "two";
QTest::newRow("does not exist") << tmpdir + "doesnotexist";
QTest::newRow("relative") << "relative";
}
void tst_QDir::removeRecursively()
{
QFETCH(QString, path);
QDir dir(path);
QVERIFY(dir.removeRecursively());
//make sure it really doesn't exist (ie that remove worked)
QVERIFY(!dir.exists());
}
void tst_QDir::removeRecursivelyFailure()
{
const QString tmpdir = QDir::currentPath() + "/tmpdir/";
const QString path = tmpdir + "undeletable";
QDir().mkpath(path);
// Need a file in there, otherwise rmdir works even w/o permissions
QFile file(path + "/file");
QVERIFY(file.open(QIODevice::WriteOnly));
file.write("Hello");
file.close();
#ifdef Q_OS_UNIX
QFile dirAsFile(path); // yay, I have to use QFile to change a dir's permissions...
QVERIFY(dirAsFile.setPermissions(QFile::Permissions(0))); // no permissions
#else
QVERIFY(file.setPermissions(QFile::ReadOwner));
#endif
QVERIFY(!QDir().rmdir(path));
QDir dir(path);
QVERIFY(!dir.removeRecursively()); // didn't work
QVERIFY(dir.exists()); // still exists
#ifdef Q_OS_UNIX
QVERIFY(dirAsFile.setPermissions(QFile::Permissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner)));
#else
QVERIFY(file.setPermissions(QFile::ReadOwner | QFile::WriteOwner));
#endif
QVERIFY(dir.removeRecursively());
QVERIFY(!dir.exists());
}
void tst_QDir::exists_data()
{
QTest::addColumn<QString>("path");