Hello community, here is the log from the commit of package karchive for openSUSE:Factory checked in at 2018-10-01 08:03:59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/karchive (Old) and /work/SRC/openSUSE:Factory/.karchive.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "karchive" Mon Oct 1 08:03:59 2018 rev:57 rq:635975 version:5.50.0 Changes: -------- --- /work/SRC/openSUSE:Factory/karchive/karchive.changes 2018-08-24 16:51:55.281206994 +0200 +++ /work/SRC/openSUSE:Factory/.karchive.new/karchive.changes 2018-10-01 08:04:59.630398461 +0200 @@ -1,0 +2,16 @@ +Thu Sep 13 21:58:44 UTC 2018 - [email protected] + +- Update to 5.50.0 + * New feature release + * For more details please see: + * https://www.kde.org/announcements/kde-frameworks-5.50.0.php +- Changes since 5.49.0: + * Actual gz file, the other was empty + * handle non-ASCII encodings of file names in tar archives (kde#266141) + * KCompressionDevice: don't call write after WriteError (kde#397545) + * autotests: adjust expected value for Windows... + * Add missing Q_OBJECT macros for QIODevice subclasses + * KCompressionDevice: propagate errors from QIODevice::close() (kde#397545) + * Fix bzip main page + +------------------------------------------------------------------- Old: ---- karchive-5.49.0.tar.xz New: ---- karchive-5.50.0.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ karchive.spec ++++++ --- /var/tmp/diff_new_pack.i53eX0/_old 2018-10-01 08:05:00.442398026 +0200 +++ /var/tmp/diff_new_pack.i53eX0/_new 2018-10-01 08:05:00.446398024 +0200 @@ -17,13 +17,13 @@ %define lname libKF5Archive5 -%define _tar_path 5.49 +%define _tar_path 5.50 # Full KF5 version (e.g. 5.33.0) %{!?_kf5_version: %global _kf5_version %{version}} # Last major and minor KF5 version (e.g. 5.33) %{!?_kf5_bugfix_version: %define _kf5_bugfix_version %(echo %{_kf5_version} | awk -F. '{print $1"."$2}')} Name: karchive -Version: 5.49.0 +Version: 5.50.0 Release: 0 Summary: Qt 5 addon providing access to numerous types of archives License: LGPL-2.1-or-later ++++++ karchive-5.49.0.tar.xz -> karchive-5.50.0.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/karchive-5.49.0/CMakeLists.txt new/karchive-5.50.0/CMakeLists.txt --- old/karchive-5.49.0/CMakeLists.txt 2018-08-04 10:41:56.000000000 +0200 +++ new/karchive-5.50.0/CMakeLists.txt 2018-09-01 00:19:36.000000000 +0200 @@ -1,10 +1,10 @@ cmake_minimum_required(VERSION 3.0) -set(KF5_VERSION "5.49.0") # handled by release scripts +set(KF5_VERSION "5.50.0") # handled by release scripts project(KArchive VERSION ${KF5_VERSION}) include(FeatureSummary) -find_package(ECM 5.49.0 NO_MODULE) +find_package(ECM 5.50.0 NO_MODULE) set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake Modules." URL "https://projects.kde.org/projects/kdesupport/extra-cmake-modules") feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND FATAL_ON_MISSING_REQUIRED_PACKAGES) @@ -31,7 +31,7 @@ find_package(BZip2) set_package_properties(BZip2 PROPERTIES - URL "http://www.bzip.org" + URL "https://sourceware.org/bzip2/" DESCRIPTION "Support for BZip2 compressed files and data streams" TYPE RECOMMENDED PURPOSE "Support for BZip2 compressed files and data streams" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/karchive-5.49.0/autotests/karchivetest.cpp new/karchive-5.50.0/autotests/karchivetest.cpp --- old/karchive-5.49.0/autotests/karchivetest.cpp 2018-08-04 10:41:56.000000000 +0200 +++ new/karchive-5.50.0/autotests/karchivetest.cpp 2018-09-01 00:19:36.000000000 +0200 @@ -769,6 +769,55 @@ QCOMPARE(listing.count(), 10); } +void KArchiveTest::testTarLongNonASCIINames() // bug 266141 +{ + const QString tarName = QString("karchive-long-non-ascii-names.tar"); + const QString longName = + QString("раз-два-три-четыре-пять-вышел-зайчик-погулять-вдруг-охотник-" + "выбегает-прямо-в-зайчика.txt"); + + { + KTar tar(tarName); + QVERIFY(tar.open(QIODevice::WriteOnly)); + QVERIFY(tar.writeFile(longName, "", 0644, "user", "users")); + QVERIFY(tar.close()); + } + + { + KTar tar(tarName); + + QVERIFY(tar.open(QIODevice::ReadOnly)); + const KArchiveDirectory *dir = tar.directory(); + QVERIFY(dir != nullptr); + + const QStringList listing = recursiveListEntries(dir, QString(""), 0); + + const QString expectedListingEntry = + QString("mode=644 path=") + longName + QString(" type=file size=0"); + + QCOMPARE(listing.count(), 1); + + QCOMPARE(listing[0], expectedListingEntry); + QVERIFY(tar.close()); + } +} + +void KArchiveTest::testTarShortNonASCIINames() // bug 266141 +{ + KTar tar(QFINDTESTDATA(QString("tar_non_ascii_file_name.tar.gz"))); + + QVERIFY(tar.open(QIODevice::ReadOnly)); + const KArchiveDirectory *dir = tar.directory(); + QVERIFY(dir != nullptr); + + const QStringList listing = recursiveListEntries(dir, QString(""), 0); + + QCOMPARE(listing.count(), 1); + QCOMPARE(listing[0], QString("mode=644 path=абвгдеёжзийклмнопрстуфхцчшщъыьэюя.txt" + " type=file size=0")); + QVERIFY(tar.close()); +} + void KArchiveTest::testTarDirectoryTwice() // bug 206994 { KTar tar(QFINDTESTDATA(QLatin1String("tar_directory_twice.tar.gz"))); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/karchive-5.49.0/autotests/karchivetest.h new/karchive-5.50.0/autotests/karchivetest.h --- old/karchive-5.49.0/autotests/karchivetest.h 2018-08-04 10:41:56.000000000 +0200 +++ new/karchive-5.50.0/autotests/karchivetest.h 2018-09-01 00:19:36.000000000 +0200 @@ -77,6 +77,8 @@ void testTarRootDir(); void testTarDirectoryTwice(); void testTarIgnoreRelativePathOutsideArchive(); + void testTarLongNonASCIINames(); + void testTarShortNonASCIINames(); void testCreateZip(); void testCreateZipError(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/karchive-5.49.0/autotests/kcompressiondevicetest.cpp new/karchive-5.50.0/autotests/kcompressiondevicetest.cpp --- old/karchive-5.49.0/autotests/kcompressiondevicetest.cpp 2018-08-04 10:41:56.000000000 +0200 +++ new/karchive-5.50.0/autotests/kcompressiondevicetest.cpp 2018-09-01 00:19:36.000000000 +0200 @@ -91,6 +91,7 @@ void KCompressionDeviceTest::testExtraction() { QTemporaryDir temp; + QString oldCurrentDir = QDir::currentPath(); QDir::setCurrent(temp.path()); QVERIFY(archive->open(QIODevice::ReadOnly)); @@ -113,13 +114,14 @@ << QLatin1String("examples/unzipper/CMakeLists.txt") << QLatin1String("examples/unzipper/main.cpp"); - foreach (const QString s, fileList) { + foreach (const QString& s, fileList) { QFileInfo extractedFile(s); QFileInfo sourceFile(QFINDTESTDATA("../" + s)); QVERIFY(extractedFile.exists()); QCOMPARE(extractedFile.size(), sourceFile.size()); } + QDir::setCurrent(oldCurrentDir); } void KCompressionDeviceTest::regularKTarUsage() @@ -152,3 +154,39 @@ QSKIP("This test needs xz support"); #endif } + +void KCompressionDeviceTest::testWriteErrorOnOpen() +{ + // GIVEN + QString fileName("/I/dont/exist/kcompressiondevicetest-write.gz"); + KCompressionDevice dev(fileName, KCompressionDevice::GZip); + // WHEN + QVERIFY(!dev.open(QIODevice::WriteOnly)); + // THEN + QCOMPARE(dev.error(), QFileDevice::OpenError); +#ifdef Q_OS_WIN + QCOMPARE(dev.errorString(), QStringLiteral("The system cannot find the path specified.")); +#else + QCOMPARE(dev.errorString(), QStringLiteral("No such file or directory")); +#endif +} + +void KCompressionDeviceTest::testWriteErrorOnClose() +{ + // GIVEN + QFile file("kcompressiondevicetest-write.gz"); + KCompressionDevice dev(&file, false, KCompressionDevice::GZip); + QVERIFY(dev.open(QIODevice::WriteOnly)); + const QByteArray data = "Hello world"; + QCOMPARE(dev.write(data), data.size()); + // This is nasty, it's just a way to try and trigger an error on flush, without filling up a partition first ;) + file.close(); + QVERIFY(file.open(QIODevice::ReadOnly)); + QTest::ignoreMessage(QtWarningMsg, "QIODevice::write (QFile, \"kcompressiondevicetest-write.gz\"): ReadOnly device"); + + // WHEN + dev.close(); // I want a QVERIFY here... https://bugreports.qt.io/browse/QTBUG-70033 + + // THEN + QCOMPARE(int(dev.error()), int(QFileDevice::WriteError)); +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/karchive-5.49.0/autotests/kcompressiondevicetest.h new/karchive-5.50.0/autotests/kcompressiondevicetest.h --- old/karchive-5.49.0/autotests/kcompressiondevicetest.h 2018-08-04 10:41:56.000000000 +0200 +++ new/karchive-5.50.0/autotests/kcompressiondevicetest.h 2018-09-01 00:19:36.000000000 +0200 @@ -54,6 +54,9 @@ void testGZipBufferedDevice(); void testBZip2BufferedDevice(); void testXzBufferedDevice(); + + void testWriteErrorOnOpen(); + void testWriteErrorOnClose(); }; #endif Binary files old/karchive-5.49.0/autotests/tar_non_ascii_file_name.tar.gz and new/karchive-5.50.0/autotests/tar_non_ascii_file_name.tar.gz differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/karchive-5.49.0/src/kcompressiondevice.cpp new/karchive-5.50.0/src/kcompressiondevice.cpp --- old/karchive-5.49.0/src/kcompressiondevice.cpp 2018-08-04 10:41:56.000000000 +0200 +++ new/karchive-5.50.0/src/kcompressiondevice.cpp 2018-09-01 00:19:36.000000000 +0200 @@ -43,15 +43,20 @@ class KCompressionDevicePrivate { public: - KCompressionDevicePrivate() + KCompressionDevicePrivate(KCompressionDevice *q) : bNeedHeader(true) , bSkipHeaders(false) , bOpenedUnderlyingDevice(false) , bIgnoreData(false) , type(KCompressionDevice::None) + , errorCode(QFileDevice::NoError) , deviceReadPos(0) + , q(q) { } + + void propagateErrorCode(); + bool bNeedHeader; bool bSkipHeaders; bool bOpenedUnderlyingDevice; @@ -61,9 +66,23 @@ KFilterBase::Result result; KFilterBase *filter; KCompressionDevice::CompressionType type; + QFileDevice::FileError errorCode; qint64 deviceReadPos; + KCompressionDevice *q; }; +void KCompressionDevicePrivate::propagateErrorCode() +{ + QIODevice *dev = filter->device(); + if (QFileDevice *fileDev = qobject_cast<QFileDevice *>(dev)) { + if (fileDev->error() != QFileDevice::NoError) { + errorCode = fileDev->error(); + q->setErrorString(dev->errorString()); + } + } + // ... we have no generic way to propagate errors from other kinds of iodevices. Sucks, heh? :( +} + KFilterBase *KCompressionDevice::filterForCompressionType(KCompressionDevice::CompressionType type) { switch (type) { @@ -88,7 +107,7 @@ } KCompressionDevice::KCompressionDevice(QIODevice *inputDevice, bool autoDeleteInputDevice, CompressionType type) - : d(new KCompressionDevicePrivate) + : d(new KCompressionDevicePrivate(this)) { assert(inputDevice); d->filter = filterForCompressionType(type); @@ -99,7 +118,7 @@ } KCompressionDevice::KCompressionDevice(const QString &fileName, CompressionType type) - : d(new KCompressionDevicePrivate) + : d(new KCompressionDevicePrivate(this)) { QFile *f = new QFile(fileName); d->filter = filterForCompressionType(type); @@ -142,6 +161,7 @@ if (!d->filter->device()->isOpen()) { if (!d->filter->device()->open(mode)) { //qCWarning(KArchiveLog) << "KCompressionDevice::open: Couldn't open underlying device"; + d->propagateErrorCode(); return false; } d->bOpenedUnderlyingDevice = true; @@ -161,27 +181,35 @@ if (!isOpen()) { return; } - if (d->filter->mode() == QIODevice::WriteOnly) { + if (d->filter->mode() == QIODevice::WriteOnly && d->errorCode == QFileDevice::NoError) { write(nullptr, 0); // finish writing } //qCDebug(KArchiveLog) << "Calling terminate()."; if (!d->filter->terminate()) { //qCWarning(KArchiveLog) << "KCompressionDevice::close: terminate returned an error"; + d->errorCode = QFileDevice::UnspecifiedError; } if (d->bOpenedUnderlyingDevice) { - d->filter->device()->close(); + QIODevice *dev = d->filter->device(); + dev->close(); + d->propagateErrorCode(); } setOpenMode(QIODevice::NotOpen); } +QFileDevice::FileError KCompressionDevice::error() const +{ + return d->errorCode; +} + bool KCompressionDevice::seek(qint64 pos) { if (d->deviceReadPos == pos) { return QIODevice::seek(pos); } - //qCDebug(KArchiveLog) << "seek(" << pos << ") called, current pos=" << ioIndex; + //qCDebug(KArchiveLog) << "seek(" << pos << ") called, current pos=" << QIODevice::pos(); Q_ASSERT(d->filter->mode() == QIODevice::ReadOnly); @@ -374,7 +402,9 @@ int size = filter->device()->write(d->buffer.data(), towrite); if (size != towrite) { //qCWarning(KArchiveLog) << "KCompressionDevice::write. Could only write " << size << " out of " << towrite << " bytes"; - return 0; // indicate an error (happens on disk full) + d->errorCode = QFileDevice::WriteError; + setErrorString(tr("Could not write. Partition full?")); + return 0; // indicate an error } //qCDebug(KArchiveLog) << " wrote " << size << " bytes"; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/karchive-5.49.0/src/kcompressiondevice.h new/karchive-5.50.0/src/kcompressiondevice.h --- old/karchive-5.49.0/src/kcompressiondevice.h 2018-08-04 10:41:56.000000000 +0200 +++ new/karchive-5.50.0/src/kcompressiondevice.h 2018-09-01 00:19:36.000000000 +0200 @@ -21,6 +21,7 @@ #include <karchive_export.h> #include <QIODevice> +#include <QFileDevice> #include <QString> #include <QMetaType> class KCompressionDevicePrivate; @@ -36,8 +37,9 @@ * Use this class to read/write compressed files. */ -class KARCHIVE_EXPORT KCompressionDevice : public QIODevice +class KARCHIVE_EXPORT KCompressionDevice : public QIODevice // KF6 TODO: consider inheriting from QFileDevice, so apps can use error() generically ? { + Q_OBJECT public: enum CompressionType { GZip, @@ -113,6 +115,14 @@ */ static KFilterBase *filterForCompressionType(CompressionType type); + /** + * Returns the error code from the last failing operation. + * This is especially useful after calling close(), which unfortunately returns void + * (see https://bugreports.qt.io/browse/QTBUG-70033), to see if the flushing done by close + * was able to write all the data to disk. + */ + QFileDevice::FileError error() const; + protected: friend class K7Zip; @@ -121,6 +131,7 @@ KFilterBase *filterBase(); private: + friend KCompressionDevicePrivate; KCompressionDevicePrivate *const d; }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/karchive-5.49.0/src/klimitediodevice_p.h new/karchive-5.50.0/src/klimitediodevice_p.h --- old/karchive-5.49.0/src/klimitediodevice_p.h 2018-08-04 10:41:56.000000000 +0200 +++ new/karchive-5.50.0/src/klimitediodevice_p.h 2018-09-01 00:19:36.000000000 +0200 @@ -30,6 +30,7 @@ */ class KLimitedIODevice : public QIODevice { + Q_OBJECT public: /** * Creates a new KLimitedIODevice. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/karchive-5.49.0/src/ktar.cpp new/karchive-5.50.0/src/ktar.cpp --- old/karchive-5.49.0/src/ktar.cpp 2018-08-04 10:41:56.000000000 +0200 +++ new/karchive-5.50.0/src/ktar.cpp 2018-09-01 00:19:36.000000000 +0200 @@ -196,12 +196,12 @@ int check = 0; for (uint j = 0; j < 0x200; ++j) { - check += buffer[j]; + check += static_cast<unsigned char>(buffer[j]); } // adjust checksum to count the checksum fields as blanks for (uint j = 0; j < 8 /*size of the checksum field including the \0 and the space*/; j++) { - check -= buffer[148 + j]; + check -= static_cast<unsigned char>(buffer[148 + j]); } check += 8 * ' '; @@ -698,7 +698,7 @@ // Header check sum int check = 32; for (uint j = 0; j < 0x200; ++j) { - check += buffer[j]; + check += static_cast<unsigned char>(buffer[j]); } s = QByteArray::number(check, 8); // octal s = s.rightJustified(6, '0'); @@ -773,8 +773,8 @@ const QByteArray uname = user.toLocal8Bit(); const QByteArray gname = group.toLocal8Bit(); - // If more than 100 chars, we need to use the LongLink trick - if (fileName.length() > 99) { + // If more than 100 bytes, we need to use the LongLink trick + if (encodedFileName.length() > 99) { d->writeLonglink(buffer, encodedFileName, 'L', uname.constData(), gname.constData()); } @@ -838,8 +838,8 @@ QByteArray uname = user.toLocal8Bit(); QByteArray gname = group.toLocal8Bit(); - // If more than 100 chars, we need to use the LongLink trick - if (dirName.length() > 99) { + // If more than 100 bytes, we need to use the LongLink trick + if (encodedDirname.length() > 99) { d->writeLonglink(buffer, encodedDirname, 'L', uname.constData(), gname.constData()); } @@ -894,11 +894,11 @@ QByteArray uname = user.toLocal8Bit(); QByteArray gname = group.toLocal8Bit(); - // If more than 100 chars, we need to use the LongLink trick - if (target.length() > 99) { + // If more than 100 bytes, we need to use the LongLink trick + if (encodedTarget.length() > 99) { d->writeLonglink(buffer, encodedTarget, 'K', uname.constData(), gname.constData()); } - if (fileName.length() > 99) { + if (encodedFileName.length() > 99) { d->writeLonglink(buffer, encodedFileName, 'L', uname.constData(), gname.constData()); }
