Implement QDir::removeRecursively
Task-number: QTBUG-4592 Change-Id: I363e2c24d1c0ada975b8b927d7c6e776b8aae579 Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@nokia.com>
This commit is contained in:
parent
8c74fe5c7a
commit
1bb51cb8b1
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user