kutils: recursively remove/extract when paths contain directory

this also makes it match the behaviour of KArchive::add() which recurses
into directories and adds the files that the specified directory holds

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2022-12-24 01:56:00 +02:00
parent 7a4a048bdb
commit 4c16e7c0d5
2 changed files with 56 additions and 13 deletions

View file

@ -739,10 +739,25 @@ bool KArchive::remove(const QStringList &paths) const
return result;
}
QStringList recursivepaths;
foreach (const QString &path, paths) {
if (path.endsWith(QLatin1Char('/'))) {
const QByteArray pathbytes = QFile::encodeName(path);
foreach (const KArchiveEntry &karchiveentry, KArchive::list(path)) {
if (karchiveentry.pathname.startsWith(pathbytes)) {
recursivepaths.append(QFile::decodeName(karchiveentry.pathname));
}
}
} else {
recursivepaths << path;
}
}
recursivepaths.removeDuplicates();
QStringList notfound = paths;
qreal progressvalue = 0.0;
const qreal progessstep = (qreal(1.0) / qreal(paths.size()));
const qreal progessstep = (qreal(1.0) / qreal(recursivepaths.size()));
struct archive_entry* entry = archive_entry_new();
int ret = archive_read_next_header(readarchive, &entry);
@ -758,7 +773,7 @@ bool KArchive::remove(const QStringList &paths) const
const QByteArray pathname = archive_entry_pathname(entry);
const QString pathnamestring = QFile::decodeName(pathname);
if (paths.contains(pathnamestring)) {
if (recursivepaths.contains(pathnamestring)) {
kDebug() << "Removing" << pathname;
notfound.removeAll(pathname);
archive_read_data_skip(readarchive);
@ -853,10 +868,25 @@ bool KArchive::extract(const QStringList &paths, const QString &destination, con
return result;
}
QStringList recursivepaths;
foreach (const QString &path, paths) {
if (path.endsWith(QLatin1Char('/'))) {
const QByteArray pathbytes = QFile::encodeName(path);
foreach (const KArchiveEntry &karchiveentry, KArchive::list(path)) {
if (karchiveentry.pathname.startsWith(pathbytes)) {
recursivepaths.append(QFile::decodeName(karchiveentry.pathname));
}
}
} else {
recursivepaths << path;
}
}
recursivepaths.removeDuplicates();
QStringList notfound = paths;
qreal progressvalue = 0.0;
const qreal progessstep = (qreal(1.0) / qreal(paths.size()));
const qreal progessstep = (qreal(1.0) / qreal(recursivepaths.size()));
struct archive_entry* entry = archive_entry_new();
int ret = archive_read_next_header(readarchive, &entry);
@ -872,7 +902,7 @@ bool KArchive::extract(const QStringList &paths, const QString &destination, con
const QByteArray pathname = archive_entry_pathname(entry);
const QString pathnamestring = QFile::decodeName(pathname);
if (!paths.contains(pathnamestring)) {
if (!recursivepaths.contains(pathnamestring)) {
archive_read_data_skip(readarchive);
ret = archive_read_next_header(readarchive, &entry);
continue;

View file

@ -56,6 +56,8 @@ private Q_SLOTS:
void remove_data();
void remove();
// TODO: extract tests
void error_data();
void error();
@ -152,15 +154,26 @@ void KArchiveTest::remove()
QVERIFY(karchive.isWritable());
QList<KArchiveEntry> karchiveentries = karchive.list();
QCOMPARE(karchiveentries.size(), 3);
QStringList toremove = QStringList()
<< QFile::decodeName("tests/CMakeLists.txt");
QVERIFY(karchive.remove(toremove));
QList<KArchiveEntry> karchiveentries2 = karchive.list();
QCOMPARE(karchiveentries2.size(), 2);
QCOMPARE(karchiveentries2.at(0).pathname, QByteArray("tests/"));
QVERIFY(S_ISDIR(karchiveentries2.at(0).mode));
QCOMPARE(karchiveentries2.at(1).pathname, QByteArray("tests/karchivetest.cpp"));
QVERIFY(S_ISREG(karchiveentries2.at(1).mode));
{
QStringList toremove = QStringList()
<< QFile::decodeName("tests/CMakeLists.txt");
QVERIFY(karchive.remove(toremove));
QList<KArchiveEntry> karchiveentries2 = karchive.list();
QCOMPARE(karchiveentries2.size(), 2);
QCOMPARE(karchiveentries2.at(0).pathname, QByteArray("tests/"));
QVERIFY(S_ISDIR(karchiveentries2.at(0).mode));
QCOMPARE(karchiveentries2.at(1).pathname, QByteArray("tests/karchivetest.cpp"));
QVERIFY(S_ISREG(karchiveentries2.at(1).mode));
}
{
QStringList toremove = QStringList()
<< QFile::decodeName("tests/");
QVERIFY(karchive.remove(toremove));
QList<KArchiveEntry> karchiveentries3 = karchive.list();
QCOMPARE(karchiveentries3.size(), 0);
}
}
void KArchiveTest::error_data()