diff options
author | David Faure <faure@kde.org> | 2011-12-02 10:39:19 +0100 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-12-02 15:59:58 +0100 |
commit | 1bb51cb8b1de3ac795d408757812fc57fbf0a902 (patch) | |
tree | 59904e3e52f8fe307b292a4b3c8955a0952edebd | |
parent | 8c74fe5c7a754a072349fe4cb88834e6efdd5593 (diff) |
Implement QDir::removeRecursively
Task-number: QTBUG-4592
Change-Id: I363e2c24d1c0ada975b8b927d7c6e776b8aae579
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@nokia.com>
-rw-r--r-- | src/corelib/io/qdir.cpp | 46 | ||||
-rw-r--r-- | src/corelib/io/qdir.h | 2 | ||||
-rw-r--r-- | tests/auto/corelib/io/qdir/tst_qdir.cpp | 83 |
3 files changed, 131 insertions, 0 deletions
diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index 32fd81981b..44992fcd14 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -1471,6 +1471,52 @@ bool QDir::rmpath(const QString &dirPath) const } /*! + 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. diff --git a/src/corelib/io/qdir.h b/src/corelib/io/qdir.h index 822173dfc8..e246f2f1aa 100644 --- a/src/corelib/io/qdir.h +++ b/src/corelib/io/qdir.h @@ -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; diff --git a/tests/auto/corelib/io/qdir/tst_qdir.cpp b/tests/auto/corelib/io/qdir/tst_qdir.cpp index 339eb55154..e6592a1174 100644 --- a/tests/auto/corelib/io/qdir/tst_qdir.cpp +++ b/tests/auto/corelib/io/qdir/tst_qdir.cpp @@ -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"); |